Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beefy: add benchmarks for report_fork_voting() #5188

Merged
merged 21 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0ae1e63
Fix report_future_block_voting weight
serban300 Jul 25, 2024
15a18ec
Add empty benchmarks for pallet-beefy-mmr
serban300 Jul 26, 2024
91b34da
[MMR] Make offchain set/get work in benchmarks
serban300 Jul 29, 2024
8e0ea6f
Ancestry proof benchmarks
serban300 Jul 26, 2024
e6599ea
Compute report_fork_voting() weight
serban300 Jul 30, 2024
3f8272e
Remove impl_benchmark_test_suite!() for the MMR pallet
serban300 Jul 30, 2024
928201f
Update TODO comment
serban300 Aug 13, 2024
0ec5164
Merge branch 'master' into beefy-equivocation-runtime
serban300 Aug 13, 2024
efad090
Generate weights locally
serban300 Aug 13, 2024
e1a1140
Add prdoc
serban300 Aug 13, 2024
9270d80
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Aug 13, 2024
be8a25a
".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime…
Aug 13, 2024
4a71e72
Add pallet_beefy_mmr benchmarks to kitchensink
serban300 Aug 13, 2024
d1fcb6e
bot bench substrate-pallet --pallet=pallet_beefy_mmr
serban300 Aug 13, 2024
6b17188
Revert "Add pallet_beefy_mmr benchmarks to kitchensink"
serban300 Aug 13, 2024
9fab84a
Call local_storage_set only in offline context
serban300 Aug 13, 2024
1454f87
improvements
serban300 Aug 13, 2024
4d525a1
Update prdoc
serban300 Aug 14, 2024
e044ae4
Merge branch 'master' into beefy-equivocation-runtime
serban300 Aug 14, 2024
c7149cc
Remove is_offchain_db_ext_available()
serban300 Aug 14, 2024
87e474e
Merge remote-tracking branch 'upstream/master' into beefy-equivocatio…
serban300 Aug 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions polkadot/runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,7 @@ impl pallet_beefy_mmr::Config for Runtime {
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type LeafExtra = H256;
type BeefyDataProvider = ParaHeadsRootProvider;
type WeightInfo = ();
}

impl paras_sudo_wrapper::Config for Runtime {}
Expand Down Expand Up @@ -1735,6 +1736,7 @@ mod benches {
// Substrate
[pallet_balances, Balances]
[pallet_balances, NisCounterpartBalances]
[pallet_beefy_mmr, MmrLeaf]
[frame_benchmarking::baseline, Baseline::<Runtime>]
[pallet_bounties, Bounties]
[pallet_child_bounties, ChildBounties]
Expand Down
2 changes: 2 additions & 0 deletions polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ impl pallet_beefy_mmr::Config for Runtime {
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type LeafExtra = H256;
type BeefyDataProvider = ParaHeadsRootProvider;
type WeightInfo = ();
}

parameter_types! {
Expand Down Expand Up @@ -1842,6 +1843,7 @@ mod benches {
// Substrate
[pallet_bags_list, VoterList]
[pallet_balances, Balances]
[pallet_beefy_mmr, BeefyMmrLeaf]
[pallet_conviction_voting, ConvictionVoting]
[pallet_election_provider_multi_phase, ElectionProviderMultiPhase]
[frame_election_provider_support, ElectionProviderBench::<Runtime>]
Expand Down
1 change: 1 addition & 0 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,7 @@ impl pallet_beefy_mmr::Config for Runtime {
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type LeafExtra = Vec<u8>;
type BeefyDataProvider = ();
type WeightInfo = ();
}

parameter_types! {
Expand Down
3 changes: 3 additions & 0 deletions substrate/frame/beefy-mmr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ log = { workspace = true }
scale-info = { features = ["derive"], workspace = true }
serde = { optional = true, workspace = true, default-features = true }
binary-merkle-tree = { workspace = true }
frame-benchmarking = { optional = true, workspace = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-beefy = { workspace = true }
Expand All @@ -40,6 +41,7 @@ std = [
"array-bytes",
"binary-merkle-tree/std",
"codec/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"log/std",
Expand All @@ -65,6 +67,7 @@ try-runtime = [
"sp-runtime/try-runtime",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-mmr/runtime-benchmarks",
Expand Down
111 changes: 111 additions & 0 deletions substrate/frame/beefy-mmr/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Beefy pallet benchmarking.

#![cfg(feature = "runtime-benchmarks")]

use super::*;
use crate::Pallet as BeefyMmr;
use codec::Encode;
use frame_benchmarking::v2::*;
use frame_support::traits::Hooks;
use frame_system::{Config as SystemConfig, Pallet as System};
use pallet_mmr::{Nodes, Pallet as Mmr};
use sp_consensus_beefy::Payload;
use sp_runtime::traits::Zero;

pub trait Config:
pallet_mmr::Config<Hashing = sp_consensus_beefy::MmrHashing> + crate::Config
{
}

impl<T> Config for T where
T: pallet_mmr::Config<Hashing = sp_consensus_beefy::MmrHashing> + crate::Config
{
}

fn init_block<T: Config>(block_num: u32) {
let block_num = block_num.into();
System::<T>::initialize(&block_num, &<T as SystemConfig>::Hash::default(), &Default::default());
Mmr::<T>::on_initialize(block_num);
}

#[benchmarks]
mod benchmarks {
use super::*;

#[benchmark]
fn extract_validation_context() {
init_block::<T>(0);
let header = System::<T>::finalize();
frame_system::BlockHash::<T>::insert(BlockNumberFor::<T>::zero(), header.hash());

let validation_context;
#[block]
{
validation_context =
<BeefyMmr<T> as AncestryHelper<HeaderFor<T>>>::extract_validation_context(header);
}

assert!(validation_context.is_some());
}

#[benchmark]
fn read_peak() {
init_block::<T>(0);

let peak;
#[block]
{
peak = Nodes::<T>::get(0)
}

assert!(peak.is_some());
}

/// Generate ancestry proofs with `n` nodes and benchmark the verification logic.
/// These proofs are inflated, containing all the leafs, so we won't read any peak during
/// the verification. We need to account for the peaks separately.
#[benchmark]
fn n_items_proof_is_non_canonical(n: Linear<2, 512>) {
for block_num in 1..=n {
init_block::<T>(block_num);
}
let proof = Mmr::<T>::generate_mock_ancestry_proof().unwrap();
assert_eq!(proof.items.len(), n as usize);

let is_non_canonical;
#[block]
{
is_non_canonical = <BeefyMmr<T> as AncestryHelper<HeaderFor<T>>>::is_non_canonical(
&Commitment {
payload: Payload::from_single_entry(
known_payloads::MMR_ROOT_ID,
MerkleRootOf::<T>::default().encode(),
),
block_number: n.into(),
validator_set_id: 0,
},
proof,
Mmr::<T>::mmr_root(),
);
};

assert_eq!(is_non_canonical, true);
}
}
43 changes: 38 additions & 5 deletions substrate/frame/beefy-mmr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,34 @@

extern crate alloc;

use sp_runtime::traits::{Convert, Header, Member};
use sp_runtime::{
generic::OpaqueDigestItemId,
traits::{Convert, Header, Member},
SaturatedConversion,
};

use alloc::vec::Vec;
use codec::Decode;
use pallet_mmr::{primitives::AncestryProof, LeafDataProvider, ParentNumberAndHash};
use pallet_mmr::{primitives::AncestryProof, LeafDataProvider, NodesUtils, ParentNumberAndHash};
use sp_consensus_beefy::{
known_payloads,
mmr::{BeefyAuthoritySet, BeefyDataProvider, BeefyNextAuthoritySet, MmrLeaf, MmrLeafVersion},
AncestryHelper, Commitment, ConsensusLog, ValidatorSet as BeefyValidatorSet,
AncestryHelper, AncestryHelperWeightInfo, Commitment, ConsensusLog,
ValidatorSet as BeefyValidatorSet,
};

use frame_support::{crypto::ecdsa::ECDSAExt, traits::Get};
use frame_support::{crypto::ecdsa::ECDSAExt, pallet_prelude::Weight, traits::Get};
use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor};

pub use pallet::*;
use sp_runtime::generic::OpaqueDigestItemId;
use weights::WeightInfo;

mod benchmarking;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
mod weights;

/// A BEEFY consensus digest item with MMR root hash.
pub struct DepositBeefyDigest<T>(core::marker::PhantomData<T>);
Expand Down Expand Up @@ -126,6 +133,8 @@ pub mod pallet {

/// Retrieve arbitrary data that should be added to the mmr leaf
type BeefyDataProvider: BeefyDataProvider<Self::LeafExtra>;

type WeightInfo: WeightInfo;
}

/// Details of current BEEFY authority set.
Expand Down Expand Up @@ -263,6 +272,30 @@ where
}
}

impl<T: Config> AncestryHelperWeightInfo<HeaderFor<T>> for Pallet<T>
where
T: pallet_mmr::Config<Hashing = sp_consensus_beefy::MmrHashing>,
{
fn extract_validation_context() -> Weight {
<T as Config>::WeightInfo::extract_validation_context()
}

fn is_non_canonical(proof: &<Self as AncestryHelper<HeaderFor<T>>>::Proof) -> Weight {
let mmr_utils = NodesUtils::new(proof.leaf_count);
let num_peaks = mmr_utils.number_of_peaks();

// The approximated cost of verifying an ancestry proof with `n` nodes.
// We add the previous peaks to the total number of nodes,
// since they have to be processed as well.
<T as Config>::WeightInfo::n_items_proof_is_non_canonical(
proof.items.len().saturating_add(proof.prev_peaks.len()).saturated_into(),
)
// `n_items_proof_is_non_canonical()` uses inflated proofs that contain all the leafs,
// where no peak needs to be read. So we need to also add the cost of reading the peaks.
.saturating_add(<T as Config>::WeightInfo::read_peak().saturating_mul(num_peaks))
}
}

impl<T: Config> Pallet<T> {
/// Return the currently active BEEFY authority set proof.
pub fn authority_set_proof() -> BeefyAuthoritySet<MerkleRootOf<T>> {
Expand Down
1 change: 1 addition & 0 deletions substrate/frame/beefy-mmr/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ impl pallet_beefy_mmr::Config for Test {
type LeafExtra = Vec<u8>;

type BeefyDataProvider = DummyDataProvider;
type WeightInfo = ();
}

pub struct DummyDataProvider;
Expand Down
6 changes: 2 additions & 4 deletions substrate/frame/beefy-mmr/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ fn init_block(block: u64, maybe_parent_hash: Option<H256>) {
System::initialize(&block, &parent_hash, &Default::default());
Session::on_initialize(block);
Mmr::on_initialize(block);
Beefy::on_initialize(block);
BeefyMmr::on_initialize(block);
}

pub fn beefy_log(log: ConsensusLog<BeefyId>) -> DigestItem {
Expand Down Expand Up @@ -268,7 +266,7 @@ fn is_non_canonical_should_work_correctly() {
ext.register_extension(OffchainWorkerExt::new(offchain));

ext.execute_with(|| {
let valid_proof = Mmr::generate_ancestry_proof(250, None).unwrap();
let valid_proof = BeefyMmr::generate_proof(250, None).unwrap();
let mut invalid_proof = valid_proof.clone();
invalid_proof.items.push((300, Default::default()));

Expand Down Expand Up @@ -343,7 +341,7 @@ fn is_non_canonical_should_work_correctly() {
// - should return false, if the commitment is targeting the canonical chain
// - should return true if the commitment is NOT targeting the canonical chain
for prev_block_number in 1usize..=500 {
let proof = Mmr::generate_ancestry_proof(prev_block_number as u64, None).unwrap();
let proof = BeefyMmr::generate_proof(prev_block_number as u64, None).unwrap();

assert_eq!(
BeefyMmr::is_non_canonical(
Expand Down
Loading
Loading