Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
parachain_head_hash: head_data(1, 5).hash(),
}),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UntrackedParachainRejected {
parachain: ParaId(UNTRACKED_PARACHAIN_ID),
}),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UpdatedParachainHead {
parachain: ParaId(2),
parachain_head_hash: head_data(1, 5).hash(),
}),
topics: vec![],
}
],
);
#[test]
fn does_nothing_when_already_imported_this_head_at_previous_relay_header() {
Svyatoslav Nikolsky
committed
let (state_root, proof, parachains) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]);
run_test(|| {
// import head#0 of parachain#1 at relay block#0
initialize(state_root);
Svyatoslav Nikolsky
committed
assert_ok!(import_parachain_1_head(0, state_root, parachains.clone(), proof.clone()));
assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1)));
assert_eq!(
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UpdatedParachainHead {
parachain: ParaId(1),
parachain_head_hash: initial_best_head(1).best_head_hash.head_hash,
}),
topics: vec![],
}],
);
// try to import head#0 of parachain#1 at relay block#1
// => call succeeds, but nothing is changed
proceed(1, state_root);
Svyatoslav Nikolsky
committed
assert_ok!(import_parachain_1_head(1, state_root, parachains, proof));
assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1)));
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
assert_eq!(
System::<TestRuntime>::events(),
vec![
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UpdatedParachainHead {
parachain: ParaId(1),
parachain_head_hash: initial_best_head(1).best_head_hash.head_hash,
}),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::RejectedObsoleteParachainHead {
parachain: ParaId(1),
parachain_head_hash: initial_best_head(1).best_head_hash.head_hash,
}),
topics: vec![],
}
],
);
});
}
#[test]
fn does_nothing_when_already_imported_head_at_better_relay_header() {
Svyatoslav Nikolsky
committed
let (state_root_5, proof_5, parachains_5) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
let (state_root_10, proof_10, parachains_10) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]);
run_test(|| {
// start with relay block #0
initialize(state_root_5);
// head#10 of parachain#1 at relay block#1
proceed(1, state_root_10);
Svyatoslav Nikolsky
committed
assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10));
ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(ParaInfo {
best_head_hash: BestParaHeadHash {
at_relay_block_number: 1,
head_hash: head_data(1, 10).hash()
},
next_imported_hash_position: 1,
})
);
assert_eq!(
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UpdatedParachainHead {
parachain: ParaId(1),
parachain_head_hash: head_data(1, 10).hash(),
}),
topics: vec![],
}],
);
Svyatoslav Nikolsky
committed
// now try to import head#5 at relay block#0
// => nothing is changed, because better head has already been imported
Svyatoslav Nikolsky
committed
assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5));
ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(ParaInfo {
best_head_hash: BestParaHeadHash {
at_relay_block_number: 1,
head_hash: head_data(1, 10).hash()
},
next_imported_hash_position: 1,
})
);
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
assert_eq!(
System::<TestRuntime>::events(),
vec![
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UpdatedParachainHead {
parachain: ParaId(1),
parachain_head_hash: head_data(1, 10).hash(),
}),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::RejectedObsoleteParachainHead {
parachain: ParaId(1),
parachain_head_hash: head_data(1, 5).hash(),
}),
topics: vec![],
}
],
);
#[test]
fn does_nothing_when_parachain_head_is_too_large() {
let (state_root, proof, parachains) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (2, large_head_data(1, 5))]);
run_test(|| {
// start with relay block #0 and try to import head#5 of parachain#1 and untracked
// parachain
initialize(state_root);
let result = Pallet::<TestRuntime>::submit_parachain_heads(
RuntimeOrigin::signed(1),
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
(0, test_relay_header(0, state_root).hash()),
parachains,
proof,
);
assert_ok!(result);
assert_eq!(
ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(ParaInfo {
best_head_hash: BestParaHeadHash {
at_relay_block_number: 0,
head_hash: head_data(1, 5).hash()
},
next_imported_hash_position: 1,
})
);
assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(2)), None);
assert_eq!(
System::<TestRuntime>::events(),
vec![
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::UpdatedParachainHead {
parachain: ParaId(1),
parachain_head_hash: head_data(1, 5).hash(),
}),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::RejectedLargeParachainHead {
parachain: ParaId(2),
parachain_head_hash: large_head_data(1, 5).hash(),
parachain_head_size: large_head_data(1, 5).encoded_size() as u32,
}),
topics: vec![],
},
],
);
});
}
#[test]
fn prunes_old_heads() {
run_test(|| {
let heads_to_keep = crate::mock::HeadsToKeep::get();
// import exactly `HeadsToKeep` headers
for i in 0..heads_to_keep {
Svyatoslav Nikolsky
committed
let (state_root, proof, parachains) =
prepare_parachain_heads_proof(vec![(1, head_data(1, i))]);
if i == 0 {
initialize(state_root);
} else {
proceed(i, state_root);
}
let expected_weight = weight_of_import_parachain_1_head(&proof, false);
Svyatoslav Nikolsky
committed
let result = import_parachain_1_head(i, state_root, parachains, proof);
assert_ok!(result);
assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight));
}
// nothing is pruned yet
for i in 0..heads_to_keep {
assert!(ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, i).hash())
.is_some());
}
// import next relay chain header and next parachain head
Svyatoslav Nikolsky
committed
let (state_root, proof, parachains) =
prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]);
proceed(heads_to_keep, state_root);
let expected_weight = weight_of_import_parachain_1_head(&proof, true);
Svyatoslav Nikolsky
committed
let result = import_parachain_1_head(heads_to_keep, state_root, parachains, proof);
assert_ok!(result);
assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight));
// and the head#0 is pruned
assert!(
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 0).hash()).is_none()
);
for i in 1..=heads_to_keep {
assert!(ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, i).hash())
.is_some());
}
});
}
#[test]
fn fails_on_unknown_relay_chain_block() {
Svyatoslav Nikolsky
committed
let (state_root, proof, parachains) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
run_test(|| {
// start with relay block #0
initialize(state_root);
// try to import head#5 of parachain#1 at unknown relay chain block #1
assert_noop!(
Svyatoslav Nikolsky
committed
import_parachain_1_head(1, state_root, parachains, proof),
Error::<TestRuntime>::UnknownRelayChainBlock
);
});
}
#[test]
fn fails_on_invalid_storage_proof() {
Svyatoslav Nikolsky
committed
let (_state_root, proof, parachains) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
run_test(|| {
// start with relay block #0
initialize(Default::default());
// try to import head#5 of parachain#1 at relay chain block #0
assert_noop!(
Svyatoslav Nikolsky
committed
import_parachain_1_head(0, Default::default(), parachains, proof),
Error::<TestRuntime>::InvalidStorageProof
);
});
}
#[test]
fn is_not_rewriting_existing_head_if_failed_to_read_updated_head() {
Svyatoslav Nikolsky
committed
let (state_root_5, proof_5, parachains_5) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]);
let (state_root_10_at_20, proof_10_at_20, parachains_10_at_20) =
prepare_parachain_heads_proof(vec![(2, head_data(2, 10))]);
Svyatoslav Nikolsky
committed
let (state_root_10_at_30, proof_10_at_30, parachains_10_at_30) =
prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]);
run_test(|| {
// we've already imported head#5 of parachain#1 at relay block#10
initialize(state_root_5);
Svyatoslav Nikolsky
committed
import_parachain_1_head(0, state_root_5, parachains_5, proof_5).expect("ok");
assert_eq!(
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
Some(head_data(1, 5))
);
// then if someone is pretending to provide updated head#10 of parachain#1 at relay
// block#20, but fails to do that
//
// => we'll leave previous value
proceed(20, state_root_10_at_20);
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
RuntimeOrigin::signed(1),
(20, test_relay_header(20, state_root_10_at_20).hash()),
Svyatoslav Nikolsky
committed
parachains_10_at_20,
proof_10_at_20,
),);
assert_eq!(
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
Some(head_data(1, 5))
);
// then if someone is pretending to provide updated head#10 of parachain#1 at relay
// block#30, and actualy provides it
//
// => we'll update value
proceed(30, state_root_10_at_30);
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
RuntimeOrigin::signed(1),
(30, test_relay_header(30, state_root_10_at_30).hash()),
Svyatoslav Nikolsky
committed
parachains_10_at_30,
proof_10_at_30,
),);
assert_eq!(
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
Some(head_data(1, 10))
);
});
}
#[test]
fn storage_keys_computed_properly() {
assert_eq!(
ParasInfo::<TestRuntime>::storage_map_final_key(ParaId(42)).to_vec(),
ParasInfoKeyProvider::final_key("Parachains", &ParaId(42)).0
);
assert_eq!(
ImportedParaHeads::<TestRuntime>::storage_double_map_final_key(
ParaId(42),
ParaHash::from([21u8; 32])
)
.to_vec(),
ImportedParaHeadsKeyProvider::final_key(
&ParaId(42),
&ParaHash::from([21u8; 32])
#[test]
fn ignores_parachain_head_if_it_is_missing_from_storage_proof() {
let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]);
let parachains = vec![(ParaId(2), Default::default())];
run_test(|| {
initialize(state_root);
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
RuntimeOrigin::signed(1),
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
(0, test_relay_header(0, state_root).hash()),
parachains,
proof,
));
assert_eq!(
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::MissingParachainHead {
parachain: ParaId(2),
}),
topics: vec![],
}],
);
});
}
#[test]
fn ignores_parachain_head_if_parachain_head_hash_is_wrong() {
let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]);
let parachains = vec![(ParaId(1), head_data(1, 10).hash())];
run_test(|| {
initialize(state_root);
assert_ok!(Pallet::<TestRuntime>::submit_parachain_heads(
RuntimeOrigin::signed(1),
(0, test_relay_header(0, state_root).hash()),
parachains,
proof,
));
assert_eq!(
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Parachains(Event::IncorrectParachainHeadHash {
parachain: ParaId(1),
parachain_head_hash: head_data(1, 10).hash(),
actual_parachain_head_hash: head_data(1, 0).hash(),
}),
topics: vec![],
}],
);
});
}
generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted);