"refund" proof size in GRANDPa pallet (#1863)

* "refund" proof size in GRANDPa pallet

* clippy

* extra_proof_size_bytes_works

* use saturated_into

* fix review comments
This commit is contained in:
Svyatoslav Nikolsky
2023-02-09 14:09:37 +03:00
committed by Bastian Köcher
parent e75d872aa7
commit bae329c66e
3 changed files with 97 additions and 8 deletions
+39 -6
View File
@@ -44,9 +44,12 @@ use bp_header_chain::{
};
use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule};
use finality_grandpa::voter_set::VoterSet;
use frame_support::{ensure, fail};
use frame_support::{dispatch::PostDispatchInfo, ensure, fail};
use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID};
use sp_runtime::traits::{Header as HeaderT, Zero};
use sp_runtime::{
traits::{Header as HeaderT, Zero},
SaturatedConversion,
};
use sp_std::{boxed::Box, convert::TryInto};
mod extension;
@@ -152,8 +155,8 @@ pub mod pallet {
/// pallet.
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::submit_finality_proof(
justification.commit.precommits.len().try_into().unwrap_or(u32::MAX),
justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX),
justification.commit.precommits.len().saturated_into(),
justification.votes_ancestries.len().saturated_into(),
))]
pub fn submit_finality_proof(
_origin: OriginFor<T>,
@@ -189,6 +192,7 @@ pub mod pallet {
ensure!(best_finalized_number < *number, <Error<T, I>>::OldHeader);
let authority_set = <CurrentAuthoritySet<T, I>>::get();
let unused_proof_size = authority_set.unused_proof_size();
let set_id = authority_set.set_id;
verify_justification::<T, I>(&justification, hash, *number, authority_set.into())?;
@@ -210,7 +214,18 @@ pub mod pallet {
let is_mandatory_header = is_authorities_change_enacted;
let pays_fee = if is_mandatory_header { Pays::No } else { Pays::Yes };
Ok(pays_fee.into())
// the proof size component of the call weight assumes that there are
// `MaxBridgedAuthorities` in the `CurrentAuthoritySet` (we use `MaxEncodedLen`
// estimation). But if their number is lower, then we may "refund" some `proof_size`,
// making proof smaller and leaving block space to other useful transactions
let pre_dispatch_weight = T::WeightInfo::submit_finality_proof(
justification.commit.precommits.len().saturated_into(),
justification.votes_ancestries.len().saturated_into(),
);
let actual_weight = pre_dispatch_weight
.set_proof_size(pre_dispatch_weight.proof_size().saturating_sub(unused_proof_size));
Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee })
}
/// Bootstrap the bridge pallet with an initial header and authority set from which to sync.
@@ -819,9 +834,27 @@ mod tests {
fn succesfully_imports_header_with_valid_finality() {
run_test(|| {
initialize_substrate_bridge();
let result = submit_finality_proof(1);
let header_number = 1;
let header = test_header(header_number.into());
let justification = make_default_justification(&header);
let pre_dispatch_weight = <TestRuntime as Config>::WeightInfo::submit_finality_proof(
justification.commit.precommits.len().try_into().unwrap_or(u32::MAX),
justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX),
);
let result = submit_finality_proof(header_number);
assert_ok!(result);
assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes);
// our test config assumes 2048 max authorities and we are just using couple
let pre_dispatch_proof_size = pre_dispatch_weight.proof_size();
let actual_proof_size = result.unwrap().actual_weight.unwrap().proof_size();
assert!(actual_proof_size > 0);
assert!(
actual_proof_size < pre_dispatch_proof_size,
"Actual proof size {actual_proof_size} must be less than the pre-dispatch {pre_dispatch_proof_size}",
);
let header = test_header(1);
assert_eq!(<BestFinalized<TestRuntime>>::get().unwrap().1, header.hash());