Merge commit 'e5bed7ac380b6adb54b60a2a72a2a8f07f50d6c1' as 'bridges'

This commit is contained in:
Hernando Castano
2021-04-21 11:56:23 -04:00
339 changed files with 71658 additions and 0 deletions
@@ -0,0 +1,59 @@
[package]
name = "pallet-bridge-grandpa"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
finality-grandpa = { version = "0.14.0", default-features = false }
log = { version = "0.4.14", default-features = false }
num-traits = { version = "0.2", default-features = false }
serde = { version = "1.0", optional = true }
# Bridge Dependencies
bp-runtime = { path = "../../primitives/runtime", default-features = false }
bp-header-chain = { path = "../../primitives/header-chain", default-features = false }
# Substrate Dependencies
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
# Optional Benchmarking Dependencies
bp-test-utils = { path = "../../primitives/test-utils", default-features = false, optional = true }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
[dev-dependencies]
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
[features]
default = ["std"]
std = [
"bp-header-chain/std",
"bp-runtime/std",
"bp-test-utils/std",
"codec/std",
"finality-grandpa/std",
"frame-support/std",
"frame-system/std",
"log/std",
"num-traits/std",
"serde",
"sp-finality-grandpa/std",
"sp-runtime/std",
"sp-std/std",
"sp-trie/std",
]
runtime-benchmarks = [
"bp-test-utils",
"frame-benchmarking",
]
@@ -0,0 +1,272 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Benchmarks for the GRANDPA Pallet.
//!
//! The main dispatchable for the GRANDPA pallet is `submit_finality_proof`, so these benchmarks are
//! based around that. There are to main factors which affect finality proof verification:
//!
//! 1. The number of `votes-ancestries` in the justification
//! 2. The number of `pre-commits` in the justification
//!
//! Vote ancestries are the headers between (`finality_target`, `head_of_chain`], where
//! `header_of_chain` is a decendant of `finality_target`.
//!
//! Pre-commits are messages which are signed by validators at the head of the chain they think is
//! the best.
//!
//! Consider the following:
//!
//! / [B'] <- [C']
//! [A] <- [B] <- [C]
//!
//! The common ancestor of both forks is block A, so this is what GRANDPA will finalize. In order to
//! verify this we will have vote ancestries of [B, C, B', C'] and pre-commits [C, C'].
//!
//! Note that the worst case scenario here would be a justification where each validator has it's
//! own fork which is `SESSION_LENGTH` blocks long.
//!
//! As far as benchmarking results go, the only benchmark that should be used in
//! `pallet-bridge-grandpa` to annotate weights is the `submit_finality_proof` one. The others are
//! looking at the effects of specific code paths and do not actually reflect the overall worst case
//! scenario.
use crate::*;
use bp_test_utils::{
accounts, authority_list, make_justification_for_header, test_keyring, JustificationGeneratorParams, ALICE,
TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID,
};
use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller};
use frame_system::RawOrigin;
use sp_finality_grandpa::AuthorityId;
use sp_runtime::traits::{One, Zero};
use sp_std::{vec, vec::Vec};
// The maximum number of vote ancestries to include in a justification.
//
// In practice this would be limited by the session length (number of blocks a single authority set
// can produce) of a given chain.
const MAX_VOTE_ANCESTRIES: u32 = 1000;
// The maximum number of pre-commits to include in a justification. In practice this scales with the
// number of validators.
const MAX_VALIDATOR_SET_SIZE: u32 = 1024;
benchmarks_instance_pallet! {
// This is the "gold standard" benchmark for this extrinsic, and it's what should be used to
// annotate the weight in the pallet.
//
// The other benchmarks related to `submit_finality_proof` are looking at the effect of specific
// parameters and are there mostly for seeing how specific codepaths behave.
submit_finality_proof {
let v in 1..MAX_VOTE_ANCESTRIES;
let p in 1..MAX_VALIDATOR_SET_SIZE;
let caller: T::AccountId = whitelisted_caller();
let authority_list = accounts(p as u16)
.iter()
.map(|id| (AuthorityId::from(*id), 1))
.collect::<Vec<_>>();
let init_data = InitializationData {
header: bp_test_utils::test_header(Zero::zero()),
authority_list,
set_id: TEST_GRANDPA_SET_ID,
is_halted: false,
};
initialize_bridge::<T, I>(init_data);
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
let params = JustificationGeneratorParams {
header: header.clone(),
round: TEST_GRANDPA_ROUND,
set_id: TEST_GRANDPA_SET_ID,
authorities: accounts(p as u16).iter().map(|k| (*k, 1)).collect::<Vec<_>>(),
votes: v,
forks: 1,
};
let justification = make_justification_for_header(params);
}: _(RawOrigin::Signed(caller), header, justification)
verify {
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
let expected_hash = header.hash();
assert_eq!(<BestFinalized<T, I>>::get(), expected_hash);
assert!(<ImportedHeaders<T, I>>::contains_key(expected_hash));
}
// What we want to check here is the effect of vote ancestries on justification verification
// do this by varying the number of headers between `finality_target` and `header_of_chain`.
submit_finality_proof_on_single_fork {
let v in 1..MAX_VOTE_ANCESTRIES;
let caller: T::AccountId = whitelisted_caller();
let init_data = InitializationData {
header: bp_test_utils::test_header(Zero::zero()),
authority_list: authority_list(),
set_id: TEST_GRANDPA_SET_ID,
is_halted: false,
};
initialize_bridge::<T, I>(init_data);
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
let params = JustificationGeneratorParams {
header: header.clone(),
round: TEST_GRANDPA_ROUND,
set_id: TEST_GRANDPA_SET_ID,
authorities: test_keyring(),
votes: v,
forks: 1,
};
let justification = make_justification_for_header(params);
}: submit_finality_proof(RawOrigin::Signed(caller), header, justification)
verify {
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
let expected_hash = header.hash();
assert_eq!(<BestFinalized<T, I>>::get(), expected_hash);
assert!(<ImportedHeaders<T, I>>::contains_key(expected_hash));
}
// What we want to check here is the effect of many pre-commits on justification verification.
// We do this by creating many forks, whose head will be used as a signed pre-commit in the
// final justification.
submit_finality_proof_on_many_forks {
let p in 1..MAX_VALIDATOR_SET_SIZE;
let caller: T::AccountId = whitelisted_caller();
let authority_list = accounts(p as u16)
.iter()
.map(|id| (AuthorityId::from(*id), 1))
.collect::<Vec<_>>();
let init_data = InitializationData {
header: bp_test_utils::test_header(Zero::zero()),
authority_list,
set_id: TEST_GRANDPA_SET_ID,
is_halted: false,
};
initialize_bridge::<T, I>(init_data);
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
let params = JustificationGeneratorParams {
header: header.clone(),
round: TEST_GRANDPA_ROUND,
set_id: TEST_GRANDPA_SET_ID,
authorities: accounts(p as u16).iter().map(|k| (*k, 1)).collect::<Vec<_>>(),
votes: p,
forks: p,
};
let justification = make_justification_for_header(params);
}: submit_finality_proof(RawOrigin::Signed(caller), header, justification)
verify {
let header: BridgedHeader<T, I> = bp_test_utils::test_header(One::one());
let expected_hash = header.hash();
assert_eq!(<BestFinalized<T, I>>::get(), expected_hash);
assert!(<ImportedHeaders<T, I>>::contains_key(expected_hash));
}
// Here we want to find out the overheaded of looking through consensus digests found in a
// header. As the number of logs in a header grows, how much more work do we require to look
// through them?
//
// Note that this should be the same for looking through scheduled changes and forces changes,
// which is why we only have one benchmark for this.
find_scheduled_change {
// Not really sure what a good bound for this is.
let n in 1..1000;
let mut logs = vec![];
for i in 0..n {
// We chose a non-consensus log on purpose since that way we have to look through all
// the logs in the header
logs.push(sp_runtime::DigestItem::Other(vec![]));
}
let mut header: BridgedHeader<T, I> = bp_test_utils::test_header(Zero::zero());
let digest = header.digest_mut();
*digest = sp_runtime::Digest {
logs,
};
}: {
crate::find_scheduled_change(&header)
}
// What we want to check here is how long it takes to read and write the authority set tracked
// by the pallet as the number of authorities grows.
read_write_authority_sets {
// The current max target number of validators on Polkadot/Kusama
let n in 1..1000;
let mut authorities = vec![];
for i in 0..n {
authorities.push((ALICE, 1));
}
let authority_set = bp_header_chain::AuthoritySet {
authorities: authorities.iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect(),
set_id: 0
};
<CurrentAuthoritySet<T, I>>::put(&authority_set);
}: {
let authority_set = <CurrentAuthoritySet<T, I>>::get();
<CurrentAuthoritySet<T, I>>::put(&authority_set);
}
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::assert_ok;
#[test]
fn finality_proof_is_valid() {
mock::run_test(|| {
assert_ok!(test_benchmark_submit_finality_proof::<mock::TestRuntime>());
});
}
#[test]
fn single_fork_finality_proof_is_valid() {
mock::run_test(|| {
assert_ok!(test_benchmark_submit_finality_proof_on_single_fork::<mock::TestRuntime>());
});
}
#[test]
fn multi_fork_finality_proof_is_valid() {
mock::run_test(|| {
assert_ok!(test_benchmark_submit_finality_proof_on_many_forks::<mock::TestRuntime>());
});
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,113 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
// From construct_runtime macro
#![allow(clippy::from_over_into)]
use bp_runtime::Chain;
use frame_support::{construct_runtime, parameter_types, weights::Weight};
use sp_runtime::{
testing::{Header, H256},
traits::{BlakeTwo256, IdentityLookup},
Perbill,
};
pub type AccountId = u64;
pub type TestHeader = crate::BridgedHeader<TestRuntime, ()>;
pub type TestNumber = crate::BridgedBlockNumber<TestRuntime, ()>;
pub type TestHash = crate::BridgedBlockHash<TestRuntime, ()>;
type Block = frame_system::mocking::MockBlock<TestRuntime>;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
use crate as grandpa;
construct_runtime! {
pub enum TestRuntime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Grandpa: grandpa::{Pallet},
}
}
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
impl frame_system::Config for TestRuntime {
type Origin = Origin;
type Index = u64;
type Call = Call;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type BaseCallFilter = ();
type SystemWeightInfo = ();
type DbWeight = ();
type BlockWeights = ();
type BlockLength = ();
type SS58Prefix = ();
type OnSetCode = ();
}
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 = ();
}
#[derive(Debug)]
pub struct TestBridgedChain;
impl Chain for TestBridgedChain {
type BlockNumber = <TestRuntime as frame_system::Config>::BlockNumber;
type Hash = <TestRuntime as frame_system::Config>::Hash;
type Hasher = <TestRuntime as frame_system::Config>::Hashing;
type Header = <TestRuntime as frame_system::Config>::Header;
}
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
sp_io::TestExternalities::new(Default::default()).execute_with(test)
}
pub fn test_header(num: TestNumber) -> TestHeader {
// We wrap the call to avoid explicit type annotations in our tests
bp_test_utils::test_header(num)
}
@@ -0,0 +1,121 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for pallet_bridge_grandpa
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
//! DATE: 2021-04-14, STEPS: [50, ], REPEAT: 20
//! LOW RANGE: [], HIGH RANGE: []
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
//! CHAIN: Some("dev"), DB CACHE: 128
// Executed Command:
// target/release/rialto-bridge-node
// benchmark
// --chain=dev
// --steps=50
// --repeat=20
// --pallet=pallet_bridge_grandpa
// --extrinsic=*
// --execution=wasm
// --wasm-execution=Compiled
// --heap-pages=4096
// --output=./modules/grandpa/src/weights.rs
// --template=./.maintain/rialto-weight-template.hbs
#![allow(clippy::all)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{
traits::Get,
weights::{constants::RocksDbWeight, Weight},
};
use sp_std::marker::PhantomData;
/// Weight functions needed for pallet_bridge_grandpa.
pub trait WeightInfo {
fn submit_finality_proof(v: u32, p: u32) -> Weight;
fn submit_finality_proof_on_single_fork(v: u32) -> Weight;
fn submit_finality_proof_on_many_forks(p: u32) -> Weight;
fn find_scheduled_change(n: u32) -> Weight;
fn read_write_authority_sets(n: u32) -> Weight;
}
/// Weights for pallet_bridge_grandpa using the Rialto node and recommended hardware.
pub struct RialtoWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for RialtoWeight<T> {
fn submit_finality_proof(v: u32, p: u32) -> Weight {
(0 as Weight)
.saturating_add((837_084_000 as Weight).saturating_mul(v as Weight))
.saturating_add((874_929_000 as Weight).saturating_mul(p as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
fn submit_finality_proof_on_single_fork(v: u32) -> Weight {
(276_463_000 as Weight)
.saturating_add((14_149_000 as Weight).saturating_mul(v as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
fn submit_finality_proof_on_many_forks(p: u32) -> Weight {
(10_676_019_000 as Weight)
.saturating_add((97_598_000 as Weight).saturating_mul(p as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
fn find_scheduled_change(n: u32) -> Weight {
(618_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight))
}
fn read_write_authority_sets(n: u32) -> Weight {
(8_582_000 as Weight)
.saturating_add((234_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
fn submit_finality_proof(v: u32, p: u32) -> Weight {
(0 as Weight)
.saturating_add((837_084_000 as Weight).saturating_mul(v as Weight))
.saturating_add((874_929_000 as Weight).saturating_mul(p as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
fn submit_finality_proof_on_single_fork(v: u32) -> Weight {
(276_463_000 as Weight)
.saturating_add((14_149_000 as Weight).saturating_mul(v as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
fn submit_finality_proof_on_many_forks(p: u32) -> Weight {
(10_676_019_000 as Weight)
.saturating_add((97_598_000 as Weight).saturating_mul(p as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
fn find_scheduled_change(n: u32) -> Weight {
(618_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight))
}
fn read_write_authority_sets(n: u32) -> Weight {
(8_582_000 as Weight)
.saturating_add((234_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
}