Newer
Older
// Make sure that our header is the best finalized
Svyatoslav Nikolsky
committed
assert_eq!(<BestFinalized<TestRuntime>>::get().unwrap().1, header.hash());
assert!(<ImportedHeaders<TestRuntime>>::contains_key(header.hash()));
// Make sure that the authority set actually changed upon importing our header
assert_eq!(
<CurrentAuthoritySet<TestRuntime>>::get(),
Svyatoslav Nikolsky
committed
StoredAuthoritySet::<TestRuntime, ()>::try_new(next_authorities, next_set_id)
.unwrap(),
);
})
}
#[test]
fn importing_header_rejects_header_with_scheduled_change_delay() {
run_test(|| {
initialize_substrate_bridge();
// Need to update the header digest to indicate that our header signals an authority set
// change. However, the change doesn't happen until the next block.
let mut header = test_header(2);
header.digest = change_log(1);
// Create a valid justification for the header
let justification = make_default_justification(&header);
// Should not be allowed to import this header
assert_err!(
RuntimeOrigin::signed(1),
<Error<TestRuntime>>::UnsupportedScheduledChange
);
})
}
#[test]
fn importing_header_rejects_header_with_forced_changes() {
run_test(|| {
initialize_substrate_bridge();
// Need to update the header digest to indicate that it signals a forced authority set
// change.
let mut header = test_header(2);
header.digest = forced_change_log(0);
// Create a valid justification for the header
let justification = make_default_justification(&header);
// Should not be allowed to import this header
assert_err!(
RuntimeOrigin::signed(1),
<Error<TestRuntime>>::UnsupportedScheduledChange
);
})
}
Svyatoslav Nikolsky
committed
#[test]
fn importing_header_rejects_header_with_too_many_authorities() {
run_test(|| {
initialize_substrate_bridge();
// Need to update the header digest to indicate that our header signals an authority set
// change. However, the change doesn't happen until the next block.
let mut header = test_header(2);
header.digest = many_authorities_log();
// Create a valid justification for the header
let justification = make_default_justification(&header);
// Should not be allowed to import this header
assert_err!(
Pallet::<TestRuntime>::submit_finality_proof(
RuntimeOrigin::signed(1),
Svyatoslav Nikolsky
committed
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
Box::new(header),
justification
),
<Error<TestRuntime>>::TooManyAuthoritiesInSet
);
});
}
#[test]
fn importing_header_rejects_header_if_it_is_too_large() {
run_test(|| {
initialize_substrate_bridge();
// Need to update the header digest to indicate that our header signals an authority set
// change. However, the change doesn't happen until the next block.
let mut header = test_header(2);
header.digest = large_digest();
// Create a valid justification for the header
let justification = make_default_justification(&header);
// Should not be allowed to import this header
assert_err!(
Pallet::<TestRuntime>::submit_finality_proof(
RuntimeOrigin::signed(1),
Svyatoslav Nikolsky
committed
Box::new(header),
justification
),
<Error<TestRuntime>>::TooLargeHeader
);
});
}
#[test]
fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() {
run_test(|| {
assert_noop!(
Pallet::<TestRuntime>::parse_finalized_storage_proof(
Default::default(),
sp_trie::StorageProof::new(vec![]),
|_| (),
),
Error::<TestRuntime>::UnknownHeader,
);
});
}
#[test]
fn parse_finalized_storage_accepts_valid_proof() {
run_test(|| {
let (state_root, storage_proof) = bp_runtime::craft_valid_storage_proof();
let mut header = test_header(2);
header.set_state_root(state_root);
let hash = header.hash();
Svyatoslav Nikolsky
committed
<BestFinalized<TestRuntime>>::put((2, hash));
Svyatoslav Nikolsky
committed
<ImportedHeaders<TestRuntime>>::insert(
hash,
StoredBridgedHeader::<TestRuntime, ()>::try_from_inner(header).unwrap(),
Svyatoslav Nikolsky
committed
);
Pallet::<TestRuntime>::parse_finalized_storage_proof(hash, storage_proof, |_| (),),
(),
);
});
}
#[test]
fn rate_limiter_disallows_imports_once_limit_is_hit_in_single_block() {
run_test(|| {
initialize_substrate_bridge();
assert_ok!(submit_finality_proof(1));
assert_ok!(submit_finality_proof(2));
assert_err!(submit_finality_proof(3), <Error<TestRuntime>>::TooManyRequests);
})
}
#[test]
fn rate_limiter_invalid_requests_do_not_count_towards_request_count() {
run_test(|| {
let submit_invalid_request = || {
let mut invalid_justification = make_default_justification(&header);
invalid_justification.round = 42;
RuntimeOrigin::signed(1),
Box::new(header),
invalid_justification,
)
};
initialize_substrate_bridge();
for _ in 0..<TestRuntime as Config>::MaxRequests::get() + 1 {
// Notice that the error here *isn't* `TooManyRequests`
assert_err!(submit_invalid_request(), <Error<TestRuntime>>::InvalidJustification);
}
// Can still submit `MaxRequests` requests afterwards
assert_ok!(submit_finality_proof(1));
assert_ok!(submit_finality_proof(2));
assert_err!(submit_finality_proof(3), <Error<TestRuntime>>::TooManyRequests);
fn rate_limiter_allows_request_after_new_block_has_started() {
run_test(|| {
initialize_substrate_bridge();
assert_ok!(submit_finality_proof(1));
assert_ok!(submit_finality_proof(2));
assert_ok!(submit_finality_proof(3));
fn rate_limiter_disallows_imports_once_limit_is_hit_across_different_blocks() {
run_test(|| {
initialize_substrate_bridge();
assert_ok!(submit_finality_proof(1));
assert_ok!(submit_finality_proof(2));
assert_ok!(submit_finality_proof(3));
assert_err!(submit_finality_proof(4), <Error<TestRuntime>>::TooManyRequests);
fn rate_limiter_allows_max_requests_after_long_time_with_no_activity() {
run_test(|| {
initialize_substrate_bridge();
assert_ok!(submit_finality_proof(1));
assert_ok!(submit_finality_proof(2));
next_block();
next_block();
next_block();
assert_ok!(submit_finality_proof(5));
assert_ok!(submit_finality_proof(7));
#[test]
fn should_prune_headers_over_headers_to_keep_parameter() {
run_test(|| {
initialize_substrate_bridge();
assert_ok!(submit_finality_proof(1));
let first_header = Pallet::<TestRuntime>::best_finalized().unwrap();
next_block();
assert_ok!(submit_finality_proof(2));
next_block();
assert_ok!(submit_finality_proof(3));
next_block();
assert_ok!(submit_finality_proof(4));
next_block();
assert_ok!(submit_finality_proof(5));
next_block();
assert_ok!(submit_finality_proof(6));
assert!(
!Pallet::<TestRuntime>::is_known_header(first_header.hash()),
"First header should be pruned."
);
})
}
Svyatoslav Nikolsky
committed
#[test]
fn storage_keys_computed_properly() {
Svyatoslav Nikolsky
committed
assert_eq!(
PalletOperatingMode::<TestRuntime>::storage_value_final_key().to_vec(),
bp_header_chain::storage_keys::pallet_operating_mode_key("Grandpa").0,
Svyatoslav Nikolsky
committed
);
Svyatoslav Nikolsky
committed
assert_eq!(
BestFinalized::<TestRuntime>::storage_value_final_key().to_vec(),
Svyatoslav Nikolsky
committed
bp_header_chain::storage_keys::best_finalized_key("Grandpa").0,
Svyatoslav Nikolsky
committed
);
}
generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted);