Skip to content

Commit

Permalink
Grandpa Pallet Pruning (paritytech#890)
Browse files Browse the repository at this point in the history
* Pruning.

* Add tests.

* Address review.
  • Loading branch information
tomusdrw authored and serban300 committed Apr 8, 2024
1 parent dcc36c9 commit ed98bcf
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 0 deletions.
8 changes: 8 additions & 0 deletions bridges/bin/millau/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand All @@ -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>;
Expand Down
7 changes: 7 additions & 0 deletions bridges/bin/rialto/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}

Expand Down
53 changes: 53 additions & 0 deletions bridges/modules/grandpa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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 = ()> =
Expand Down Expand Up @@ -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 changes: 2 additions & 0 deletions bridges/modules/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@ 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;
}

impl grandpa::Config for TestRuntime {
type BridgedChain = TestBridgedChain;
type MaxRequests = MaxRequests;
type HeadersToKeep = HeadersToKeep;
type WeightInfo = ();
}

Expand Down

0 comments on commit ed98bcf

Please sign in to comment.