Skip to content

Commit e75d872

Browse files
svyatonikbkchr
authored andcommitted
MaxValues limit for storage maps in the pallet-bridge-grandpa (#1861)
* MaxValues limit for storage maps in the pallet-bridge-grandpa * remove use from the future PR
1 parent a5a3f80 commit e75d872

File tree

3 files changed

+87
-92
lines changed

3 files changed

+87
-92
lines changed

bridges/modules/grandpa/src/benchmarking.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller};
5050
use frame_support::traits::Get;
5151
use frame_system::RawOrigin;
5252
use sp_finality_grandpa::AuthorityId;
53-
use sp_runtime::traits::Zero;
53+
use sp_runtime::traits::{One, Zero};
5454
use sp_std::vec::Vec;
5555

5656
/// The maximum number of vote ancestries to include in a justification.
@@ -76,14 +76,6 @@ fn validator_set_range_end<T: Config<I>, I: 'static>() -> u32 {
7676
}
7777
}
7878

79-
/// Returns number of first header to be imported.
80-
///
81-
/// Since we bootstrap the pallet with `HeadersToKeep` already imported headers,
82-
/// this function computes the next expected header number to import.
83-
fn header_number<T: Config<I>, I: 'static, N: From<u32>>() -> N {
84-
(T::HeadersToKeep::get() + 1).into()
85-
}
86-
8779
/// Prepare header and its justification to submit using `submit_finality_proof`.
8880
fn prepare_benchmark_data<T: Config<I>, I: 'static>(
8981
precommits: u32,
@@ -94,16 +86,19 @@ fn prepare_benchmark_data<T: Config<I>, I: 'static>(
9486
.map(|id| (AuthorityId::from(*id), 1))
9587
.collect::<Vec<_>>();
9688

89+
let genesis_header: BridgedHeader<T, I> = bp_test_utils::test_header(Zero::zero());
90+
let genesis_hash = genesis_header.hash();
9791
let init_data = InitializationData {
98-
header: Box::new(bp_test_utils::test_header(Zero::zero())),
92+
header: Box::new(genesis_header),
9993
authority_list,
10094
set_id: TEST_GRANDPA_SET_ID,
10195
operating_mode: BasicOperatingMode::Normal,
10296
};
10397

10498
bootstrap_bridge::<T, I>(init_data);
99+
assert!(<ImportedHeaders<T, I>>::contains_key(genesis_hash));
105100

106-
let header: BridgedHeader<T, I> = bp_test_utils::test_header(header_number::<T, I, _>());
101+
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
107102
let params = JustificationGeneratorParams {
108103
header: header.clone(),
109104
round: TEST_GRANDPA_ROUND,
@@ -126,10 +121,15 @@ benchmarks_instance_pallet! {
126121
let (header, justification) = prepare_benchmark_data::<T, I>(p, v);
127122
}: submit_finality_proof(RawOrigin::Signed(caller), Box::new(header), justification)
128123
verify {
129-
let header: BridgedHeader<T, I> = bp_test_utils::test_header(header_number::<T, I, _>());
124+
let genesis_header: BridgedHeader<T, I> = bp_test_utils::test_header(Zero::zero());
125+
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
130126
let expected_hash = header.hash();
131127

128+
// check that the header#1 has been inserted
132129
assert_eq!(<BestFinalized<T, I>>::get().unwrap().1, expected_hash);
133130
assert!(<ImportedHeaders<T, I>>::contains_key(expected_hash));
131+
132+
// check that the header#0 has been pruned
133+
assert!(!<ImportedHeaders<T, I>>::contains_key(genesis_header.hash()));
134134
}
135135
}

bridges/modules/grandpa/src/lib.rs

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,6 @@ pub mod pallet {
104104
#[pallet::constant]
105105
type MaxRequests: Get<u32>;
106106

107-
// Avoid using `HeadersToKeep` directly in the pallet code. Use `headers_to_keep` function
108-
// instead.
109-
110107
/// Maximal number of finalized headers to keep in the storage.
111108
///
112109
/// The setting is there to prevent growing the on-chain state indefinitely. Note
@@ -292,8 +289,14 @@ pub mod pallet {
292289

293290
/// A ring buffer of imported hashes. Ordered by the insertion time.
294291
#[pallet::storage]
295-
pub(super) type ImportedHashes<T: Config<I>, I: 'static = ()> =
296-
StorageMap<_, Identity, u32, BridgedBlockHash<T, I>>;
292+
pub(super) type ImportedHashes<T: Config<I>, I: 'static = ()> = StorageMap<
293+
Hasher = Identity,
294+
Key = u32,
295+
Value = BridgedBlockHash<T, I>,
296+
QueryKind = OptionQuery,
297+
OnEmpty = GetDefault,
298+
MaxValues = MaybeHeadersToKeep<T, I>,
299+
>;
297300

298301
/// Current ring buffer position.
299302
#[pallet::storage]
@@ -302,8 +305,14 @@ pub mod pallet {
302305

303306
/// Relevant fields of imported headers.
304307
#[pallet::storage]
305-
pub type ImportedHeaders<T: Config<I>, I: 'static = ()> =
306-
StorageMap<_, Identity, BridgedBlockHash<T, I>, BridgedStoredHeaderData<T, I>>;
308+
pub type ImportedHeaders<T: Config<I>, I: 'static = ()> = StorageMap<
309+
Hasher = Identity,
310+
Key = BridgedBlockHash<T, I>,
311+
Value = BridgedStoredHeaderData<T, I>,
312+
QueryKind = OptionQuery,
313+
OnEmpty = GetDefault,
314+
MaxValues = MaybeHeadersToKeep<T, I>,
315+
>;
307316

308317
/// The current GRANDPA Authority set.
309318
#[pallet::storage]
@@ -467,20 +476,6 @@ pub mod pallet {
467476
})?)
468477
}
469478

470-
/// Return number of headers to keep in the runtime storage.
471-
#[cfg(not(feature = "runtime-benchmarks"))]
472-
pub(crate) fn headers_to_keep<T: Config<I>, I: 'static>() -> u32 {
473-
T::HeadersToKeep::get()
474-
}
475-
476-
/// Return number of headers to keep in the runtime storage.
477-
#[cfg(feature = "runtime-benchmarks")]
478-
pub(crate) fn headers_to_keep<T: Config<I>, I: 'static>() -> u32 {
479-
// every db operation (significantly) slows down benchmarks, so let's keep as min as
480-
// possible
481-
2
482-
}
483-
484479
/// Import a previously verified header to the storage.
485480
///
486481
/// Note this function solely takes care of updating the storage and pruning old entries,
@@ -496,7 +491,7 @@ pub mod pallet {
496491
<ImportedHashes<T, I>>::insert(index, hash);
497492

498493
// Update ring buffer pointer and remove old header.
499-
<ImportedHashesPointer<T, I>>::put((index + 1) % headers_to_keep::<T, I>());
494+
<ImportedHashesPointer<T, I>>::put((index + 1) % T::HeadersToKeep::get());
500495
if let Ok(hash) = pruning {
501496
log::debug!(target: LOG_TARGET, "Pruning old header: {:?}.", hash);
502497
<ImportedHeaders<T, I>>::remove(hash);
@@ -535,27 +530,35 @@ pub mod pallet {
535530
Ok(())
536531
}
537532

533+
/// Adapter for using `Config::HeadersToKeep` as `MaxValues` bound in our storage maps.
534+
pub struct MaybeHeadersToKeep<T, I>(PhantomData<(T, I)>);
535+
536+
// this implementation is required to use the struct as `MaxValues`
537+
impl<T: Config<I>, I: 'static> Get<Option<u32>> for MaybeHeadersToKeep<T, I> {
538+
fn get() -> Option<u32> {
539+
Some(T::HeadersToKeep::get())
540+
}
541+
}
542+
543+
/// Initialize pallet so that it is ready for inserting new header.
544+
///
545+
/// The function makes sure that the new insertion will cause the pruning of some old header.
546+
///
547+
/// Returns parent header for the new header.
538548
#[cfg(feature = "runtime-benchmarks")]
539549
pub(crate) fn bootstrap_bridge<T: Config<I>, I: 'static>(
540550
init_params: super::InitializationData<BridgedHeader<T, I>>,
541-
) {
542-
let start_number = *init_params.header.number();
543-
let end_number = start_number + headers_to_keep::<T, I>().into();
551+
) -> BridgedHeader<T, I> {
552+
let start_header = init_params.header.clone();
544553
initialize_bridge::<T, I>(init_params).expect("benchmarks are correct");
545554

546-
let mut number = start_number;
547-
while number < end_number {
548-
number = number + sp_runtime::traits::One::one();
549-
let header = <BridgedHeader<T, I>>::new(
550-
number,
551-
Default::default(),
552-
Default::default(),
553-
Default::default(),
554-
Default::default(),
555-
);
556-
let hash = header.hash();
557-
insert_header::<T, I>(header, hash);
558-
}
555+
// the most obvious way to cause pruning during next insertion would be to insert
556+
// `HeadersToKeep` headers. But it'll make our benchmarks slow. So we will just play with
557+
// our pruning ring-buffer.
558+
assert_eq!(ImportedHashesPointer::<T, I>::get(), 1);
559+
ImportedHashesPointer::<T, I>::put(0);
560+
561+
*start_header
559562
}
560563
}
561564

@@ -816,13 +819,9 @@ mod tests {
816819
fn succesfully_imports_header_with_valid_finality() {
817820
run_test(|| {
818821
initialize_substrate_bridge();
819-
assert_ok!(
820-
submit_finality_proof(1),
821-
PostDispatchInfo {
822-
actual_weight: None,
823-
pays_fee: frame_support::dispatch::Pays::Yes,
824-
},
825-
);
822+
let result = submit_finality_proof(1);
823+
assert_ok!(result);
824+
assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes);
826825

827826
let header = test_header(1);
828827
assert_eq!(<BestFinalized<TestRuntime>>::get().unwrap().1, header.hash());
@@ -929,17 +928,13 @@ mod tests {
929928
let justification = make_default_justification(&header);
930929

931930
// Let's import our test header
932-
assert_ok!(
933-
Pallet::<TestRuntime>::submit_finality_proof(
934-
RuntimeOrigin::signed(1),
935-
Box::new(header.clone()),
936-
justification
937-
),
938-
PostDispatchInfo {
939-
actual_weight: None,
940-
pays_fee: frame_support::dispatch::Pays::No,
941-
},
931+
let result = Pallet::<TestRuntime>::submit_finality_proof(
932+
RuntimeOrigin::signed(1),
933+
Box::new(header.clone()),
934+
justification,
942935
);
936+
assert_ok!(result);
937+
assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::No);
943938

944939
// Make sure that our header is the best finalized
945940
assert_eq!(<BestFinalized<TestRuntime>>::get().unwrap().1, header.hash());

bridges/modules/grandpa/src/weights.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! Autogenerated weights for pallet_bridge_grandpa
1818
//!
1919
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
20-
//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
20+
//! DATE: 2023-02-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
2121
//! WORST CASE MAP SIZE: `1000000`
2222
//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz`
2323
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
@@ -85,27 +85,27 @@ impl<T: frame_system::Config> WeightInfo for BridgeWeight<T> {
8585
///
8686
/// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1)
8787
///
88-
/// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: None, max_size: Some(36), added:
89-
/// 2511, mode: MaxEncodedLen)
88+
/// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36),
89+
/// added: 2016, mode: MaxEncodedLen)
9090
///
9191
/// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2)
9292
///
93-
/// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added:
94-
/// 2543, mode: MaxEncodedLen)
93+
/// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
94+
/// added: 2048, mode: MaxEncodedLen)
9595
///
9696
/// The range of component `p` is `[1, 5]`.
9797
///
9898
/// The range of component `v` is `[50, 100]`.
9999
fn submit_finality_proof(p: u32, v: u32) -> Weight {
100100
// Proof Size summary in bytes:
101-
// Measured: `459 + p * (40 ±0)`
102-
// Estimated: `5240`
103-
// Minimum execution time: 368_734 nanoseconds.
104-
Weight::from_parts(64_214_587, 5240)
105-
// Standard Error: 226_504
106-
.saturating_add(Weight::from_ref_time(41_231_918).saturating_mul(p.into()))
107-
// Standard Error: 20_667
108-
.saturating_add(Weight::from_ref_time(2_770_962).saturating_mul(v.into()))
101+
// Measured: `416 + p * (40 ±0)`
102+
// Estimated: `4745`
103+
// Minimum execution time: 221_703 nanoseconds.
104+
Weight::from_parts(39_358_497, 4745)
105+
// Standard Error: 85_573
106+
.saturating_add(Weight::from_ref_time(40_593_280).saturating_mul(p.into()))
107+
// Standard Error: 7_808
108+
.saturating_add(Weight::from_ref_time(1_529_400).saturating_mul(v.into()))
109109
.saturating_add(T::DbWeight::get().reads(6_u64))
110110
.saturating_add(T::DbWeight::get().writes(6_u64))
111111
}
@@ -140,27 +140,27 @@ impl WeightInfo for () {
140140
///
141141
/// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1)
142142
///
143-
/// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: None, max_size: Some(36), added:
144-
/// 2511, mode: MaxEncodedLen)
143+
/// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36),
144+
/// added: 2016, mode: MaxEncodedLen)
145145
///
146146
/// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2)
147147
///
148-
/// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added:
149-
/// 2543, mode: MaxEncodedLen)
148+
/// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
149+
/// added: 2048, mode: MaxEncodedLen)
150150
///
151151
/// The range of component `p` is `[1, 5]`.
152152
///
153153
/// The range of component `v` is `[50, 100]`.
154154
fn submit_finality_proof(p: u32, v: u32) -> Weight {
155155
// Proof Size summary in bytes:
156-
// Measured: `459 + p * (40 ±0)`
157-
// Estimated: `5240`
158-
// Minimum execution time: 368_734 nanoseconds.
159-
Weight::from_parts(64_214_587, 5240)
160-
// Standard Error: 226_504
161-
.saturating_add(Weight::from_ref_time(41_231_918).saturating_mul(p.into()))
162-
// Standard Error: 20_667
163-
.saturating_add(Weight::from_ref_time(2_770_962).saturating_mul(v.into()))
156+
// Measured: `416 + p * (40 ±0)`
157+
// Estimated: `4745`
158+
// Minimum execution time: 221_703 nanoseconds.
159+
Weight::from_parts(39_358_497, 4745)
160+
// Standard Error: 85_573
161+
.saturating_add(Weight::from_ref_time(40_593_280).saturating_mul(p.into()))
162+
// Standard Error: 7_808
163+
.saturating_add(Weight::from_ref_time(1_529_400).saturating_mul(v.into()))
164164
.saturating_add(RocksDbWeight::get().reads(6_u64))
165165
.saturating_add(RocksDbWeight::get().writes(6_u64))
166166
}

0 commit comments

Comments
 (0)