mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 13:21:10 +00:00
Disallow Duplicate Best Headers (#653)
* Add test proving bug * Add checks for duplicate headers * Fix Clippy error
This commit is contained in:
committed by
Bastian Köcher
parent
507edb950c
commit
6cd4f5edf1
@@ -521,7 +521,12 @@ impl<T: Config> BridgeStorage for PalletStorage<T> {
|
|||||||
|
|
||||||
match current_height.cmp(&best_height) {
|
match current_height.cmp(&best_height) {
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
<BestHeaders<T>>::append(hash);
|
// Want to avoid duplicates in the case where we're writing a finalized header to
|
||||||
|
// storage which also happens to be at the best height the best height
|
||||||
|
let not_duplicate = !<ImportedHeaders<T>>::contains_key(hash);
|
||||||
|
if not_duplicate {
|
||||||
|
<BestHeaders<T>>::append(hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
<BestHeaders<T>>::kill();
|
<BestHeaders<T>>::kill();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange};
|
use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange};
|
||||||
use crate::BridgeStorage;
|
use crate::BridgeStorage;
|
||||||
|
|
||||||
use bp_header_chain::justification::verify_justification;
|
use bp_header_chain::justification::verify_justification;
|
||||||
use finality_grandpa::voter_set::VoterSet;
|
use finality_grandpa::voter_set::VoterSet;
|
||||||
use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID};
|
use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID};
|
||||||
@@ -545,8 +546,23 @@ mod tests {
|
|||||||
run_test(|| {
|
run_test(|| {
|
||||||
let mut storage = PalletStorage::<TestRuntime>::new();
|
let mut storage = PalletStorage::<TestRuntime>::new();
|
||||||
|
|
||||||
|
// We want to write the genesis header to storage
|
||||||
|
let _ = write_headers(&mut storage, vec![]);
|
||||||
|
|
||||||
// Write two headers at the same height to storage.
|
// Write two headers at the same height to storage.
|
||||||
let imported_headers = write_default_headers(&mut storage, vec![1, 1]);
|
let best_header = test_header(1);
|
||||||
|
let mut also_best_header = test_header(1);
|
||||||
|
|
||||||
|
// We need to change _something_ to make it a different header
|
||||||
|
also_best_header.state_root = [1; 32].into();
|
||||||
|
|
||||||
|
let mut verifier = Verifier {
|
||||||
|
storage: storage.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// It should be fine to import both
|
||||||
|
assert_ok!(verifier.import_header(best_header.hash(), best_header.clone()));
|
||||||
|
assert_ok!(verifier.import_header(also_best_header.hash(), also_best_header));
|
||||||
|
|
||||||
// The headers we manually imported should have been marked as the best
|
// The headers we manually imported should have been marked as the best
|
||||||
// upon writing to storage. Let's confirm that.
|
// upon writing to storage. Let's confirm that.
|
||||||
@@ -555,11 +571,8 @@ mod tests {
|
|||||||
|
|
||||||
// Now let's build something at a better height.
|
// Now let's build something at a better height.
|
||||||
let mut better_header = test_header(2);
|
let mut better_header = test_header(2);
|
||||||
better_header.parent_hash = imported_headers[1].hash();
|
better_header.parent_hash = best_header.hash();
|
||||||
|
|
||||||
let mut verifier = Verifier {
|
|
||||||
storage: storage.clone(),
|
|
||||||
};
|
|
||||||
assert_ok!(verifier.import_header(better_header.hash(), better_header.clone()));
|
assert_ok!(verifier.import_header(better_header.hash(), better_header.clone()));
|
||||||
|
|
||||||
// Since `better_header` is the only one at height = 2 we should only have
|
// Since `better_header` is the only one at height = 2 we should only have
|
||||||
@@ -577,6 +590,39 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn doesnt_write_best_header_twice_upon_finalization() {
|
||||||
|
run_test(|| {
|
||||||
|
let mut storage = PalletStorage::<TestRuntime>::new();
|
||||||
|
let _imported_headers = write_default_headers(&mut storage, vec![1]);
|
||||||
|
|
||||||
|
let set_id = 1;
|
||||||
|
let authorities = authority_list();
|
||||||
|
let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id);
|
||||||
|
storage.update_current_authority_set(initial_authority_set);
|
||||||
|
|
||||||
|
// Let's import our header
|
||||||
|
let header = test_header(2);
|
||||||
|
let mut verifier = Verifier {
|
||||||
|
storage: storage.clone(),
|
||||||
|
};
|
||||||
|
assert_ok!(verifier.import_header(header.hash(), header.clone()));
|
||||||
|
|
||||||
|
// Our header should be the only best header we have
|
||||||
|
assert_eq!(storage.best_headers()[0].hash, header.hash());
|
||||||
|
assert_eq!(storage.best_headers().len(), 1);
|
||||||
|
|
||||||
|
// Now lets finalize our best header
|
||||||
|
let grandpa_round = 1;
|
||||||
|
let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode();
|
||||||
|
assert_ok!(verifier.import_finality_proof(header.hash(), justification.into()));
|
||||||
|
|
||||||
|
// Our best header should only appear once in the list of best headers
|
||||||
|
assert_eq!(storage.best_headers()[0].hash, header.hash());
|
||||||
|
assert_eq!(storage.best_headers().len(), 1);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn related_headers_are_ancestors() {
|
fn related_headers_are_ancestors() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
|
|||||||
Reference in New Issue
Block a user