Grandpa Pallet Pruning (#890)

* Pruning.

* Add tests.

* Address review.
This commit is contained in:
Tomasz Drwięga
2021-04-13 17:30:39 +02:00
committed by Bastian Köcher
parent a783775ca5
commit f92449a461
4 changed files with 70 additions and 0 deletions
+8
View File
@@ -309,12 +309,19 @@ parameter_types! {
// call per block.
pub const MaxRequests: u32 = 50;
pub const WestendValidatorCount: u32 = 255;
// Number of headers to keep.
//
// Assuming the worst case of every header being finalized, we will keep headers for at least a
// week.
pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32;
}
pub type RialtoGrandpaInstance = ();
impl pallet_bridge_grandpa::Config for Runtime {
type BridgedChain = bp_rialto::Rialto;
type MaxRequests = MaxRequests;
type HeadersToKeep = HeadersToKeep;
// TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones.
type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight<Runtime>;
@@ -324,6 +331,7 @@ pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1;
impl pallet_bridge_grandpa::Config<WestendGrandpaInstance> for Runtime {
type BridgedChain = bp_westend::Westend;
type MaxRequests = MaxRequests;
type HeadersToKeep = HeadersToKeep;
// TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones.
type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight<Runtime>;
+7
View File
@@ -414,11 +414,18 @@ parameter_types! {
// Note that once this is hit the pallet will essentially throttle incoming requests down to one
// call per block.
pub const MaxRequests: u32 = 50;
// Number of headers to keep.
//
// Assuming the worst case of every header being finalized, we will keep headers at least for a
// week.
pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32;
}
impl pallet_bridge_grandpa::Config for Runtime {
type BridgedChain = bp_millau::Millau;
type MaxRequests = MaxRequests;
type HeadersToKeep = HeadersToKeep;
type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight<Runtime>;
}
+53
View File
@@ -91,6 +91,14 @@ pub mod pallet {
#[pallet::constant]
type MaxRequests: Get<u32>;
/// Maximal number of finalized headers to keep in the storage.
///
/// The setting is there to prevent growing the on-chain state indefinitely. Note
/// the setting does not relate to block numbers - we will simply keep as much items
/// in the storage, so it doesn't guarantee any fixed timeframe for finality headers.
#[pallet::constant]
type HeadersToKeep: Get<u32>;
/// Weights gathered through benchmarking.
type WeightInfo: WeightInfo;
}
@@ -153,10 +161,20 @@ pub mod pallet {
verify_justification::<T, I>(&justification, hash, *number, authority_set)?;
let _enacted = try_enact_authority_change::<T, I>(&finality_target, set_id)?;
let index = <ImportedHashesPointer<T, I>>::get();
let pruning = <ImportedHashes<T, I>>::try_get(index);
<BestFinalized<T, I>>::put(hash);
<ImportedHeaders<T, I>>::insert(hash, finality_target);
<ImportedHashes<T, I>>::insert(index, hash);
<RequestCount<T, I>>::mutate(|count| *count += 1);
// Update ring buffer pointer and remove old header.
<ImportedHashesPointer<T, I>>::put((index + 1) % T::HeadersToKeep::get());
if let Ok(hash) = pruning {
log::debug!(target: "runtime::bridge-grandpa", "Pruning old header: {:?}.", hash);
<ImportedHeaders<T, I>>::remove(hash);
}
log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash);
Ok(().into())
@@ -248,6 +266,15 @@ pub mod pallet {
#[pallet::storage]
pub(super) type BestFinalized<T: Config<I>, I: 'static = ()> = StorageValue<_, BridgedBlockHash<T, I>, ValueQuery>;
/// A ring buffer of imported hashes. Ordered by the insertion time.
#[pallet::storage]
pub(super) type ImportedHashes<T: Config<I>, I: 'static = ()> =
StorageMap<_, Identity, u32, BridgedBlockHash<T, I>>;
/// Current ring buffer position.
#[pallet::storage]
pub(super) type ImportedHashesPointer<T: Config<I>, I: 'static = ()> = StorageValue<_, u32, ValueQuery>;
/// Headers which have been imported into the pallet.
#[pallet::storage]
pub(super) type ImportedHeaders<T: Config<I>, I: 'static = ()> =
@@ -999,4 +1026,30 @@ mod tests {
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();
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."
);
})
}
}
+2
View File
@@ -81,6 +81,7 @@ impl frame_system::Config for TestRuntime {
parameter_types! {
pub const MaxRequests: u32 = 2;
pub const HeadersToKeep: u32 = 5;
pub const SessionLength: u64 = 5;
pub const NumValidators: u32 = 5;
}
@@ -88,6 +89,7 @@ parameter_types! {
impl grandpa::Config for TestRuntime {
type BridgedChain = TestBridgedChain;
type MaxRequests = MaxRequests;
type HeadersToKeep = HeadersToKeep;
type WeightInfo = ();
}