Skip to content

Commit dd7efa3

Browse files
authored
babe: report equivocations (#6362)
* slots: create primitives crate for consensus slots * offences: add method to check if an offence is unknown * babe: initial equivocation reporting implementation * babe: organize imports * babe: working equivocation reporting * babe: add slot number to equivocation proof * session: move duplicate traits to session primitives * babe: move equivocation stuff to its own file * offences: fix test * session: don't have primitives depend on frame_support * babe: use opaque type for key owner proof * babe: cleanup client equivocation reporting * babe: cleanup equivocation code in pallet * babe: allow sending signed equivocation reports * node: fix compilation * fix test compilation * babe: return bool on check_equivocation_proof * babe: add test for equivocation reporting * babe: add more tests * babe: add test for validate unsigned * babe: take slot number in generate_key_ownership_proof API * babe: add benchmark for equivocation proof checking * session: add benchmark for membership proof checking * offences: fix babe benchmark * babe: add weights based on benchmark results * babe: adjust weights after benchmarking on reference hardware * babe: reorder checks in check_and_report_equivocation
1 parent 0eacd75 commit dd7efa3

File tree

2 files changed

+102
-7
lines changed

2 files changed

+102
-7
lines changed

benchmarking/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ targets = ["x86_64-unknown-linux-gnu"]
1313

1414
[dependencies]
1515
sp-std = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/std" }
16+
sp-session = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/session" }
1617
sp-runtime = { version = "2.0.0-rc4", default-features = false, path = "../../../primitives/runtime" }
1718
frame-system = { version = "2.0.0-rc4", default-features = false, path = "../../system" }
1819
frame-benchmarking = { version = "2.0.0-rc4", default-features = false, path = "../../benchmarking" }
1920
frame-support = { version = "2.0.0-rc4", default-features = false, path = "../../support" }
2021
pallet-staking = { version = "2.0.0-rc4", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" }
2122
pallet-session = { version = "2.0.0-rc4", default-features = false, path = "../../session" }
23+
rand = { version = "0.7.2", default-features = false }
2224

2325
[dev-dependencies]
2426
serde = { version = "1.0.101" }
@@ -33,6 +35,7 @@ pallet-balances = { version = "2.0.0-rc4", path = "../../balances" }
3335
default = ["std"]
3436
std = [
3537
"sp-std/std",
38+
"sp-session/std",
3639
"sp-runtime/std",
3740
"frame-system/std",
3841
"frame-benchmarking/std",

benchmarking/src/lib.rs

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,30 @@ mod mock;
2525
use sp_std::prelude::*;
2626
use sp_std::vec;
2727

28-
use frame_system::RawOrigin;
2928
use frame_benchmarking::benchmarks;
30-
31-
use pallet_session::*;
32-
use pallet_session::Module as Session;
33-
29+
use frame_support::{
30+
codec::Decode,
31+
storage::StorageValue,
32+
traits::{KeyOwnerProofSystem, OnInitialize},
33+
};
34+
use frame_system::RawOrigin;
35+
use pallet_session::{historical::Module as Historical, Module as Session, *};
3436
use pallet_staking::{
37+
benchmarking::create_validator_with_nominators, testing_utils::create_validators,
3538
MAX_NOMINATIONS,
36-
benchmarking::create_validator_with_nominators,
3739
};
40+
use sp_runtime::traits::{One, StaticLookup};
41+
42+
const MAX_VALIDATORS: u32 = 1000;
3843

3944
pub struct Module<T: Trait>(pallet_session::Module<T>);
45+
pub trait Trait: pallet_session::Trait + pallet_session::historical::Trait + pallet_staking::Trait {}
4046

41-
pub trait Trait: pallet_session::Trait + pallet_staking::Trait {}
47+
impl<T: Trait> OnInitialize<T::BlockNumber> for Module<T> {
48+
fn on_initialize(n: T::BlockNumber) -> frame_support::weights::Weight {
49+
pallet_session::Module::<T>::on_initialize(n)
50+
}
51+
}
4252

4353
benchmarks! {
4454
_ { }
@@ -59,6 +69,88 @@ benchmarks! {
5969
let proof: Vec<u8> = vec![0,1,2,3];
6070
Session::<T>::set_keys(RawOrigin::Signed(v_controller.clone()).into(), keys, proof)?;
6171
}: _(RawOrigin::Signed(v_controller))
72+
73+
check_membership_proof_current_session {
74+
let n in 2 .. MAX_VALIDATORS as u32;
75+
76+
let (key, key_owner_proof1) = check_membership_proof_setup::<T>(n);
77+
let key_owner_proof2 = key_owner_proof1.clone();
78+
}: {
79+
Historical::<T>::check_proof(key, key_owner_proof1);
80+
}
81+
verify {
82+
assert!(Historical::<T>::check_proof(key, key_owner_proof2).is_some());
83+
}
84+
85+
check_membership_proof_historical_session {
86+
let n in 2 .. MAX_VALIDATORS as u32;
87+
88+
let (key, key_owner_proof1) = check_membership_proof_setup::<T>(n);
89+
90+
// skip to the next session so that the session is historical
91+
// and the membership merkle proof must be checked.
92+
Session::<T>::rotate_session();
93+
94+
let key_owner_proof2 = key_owner_proof1.clone();
95+
}: {
96+
Historical::<T>::check_proof(key, key_owner_proof1);
97+
}
98+
verify {
99+
assert!(Historical::<T>::check_proof(key, key_owner_proof2).is_some());
100+
}
101+
}
102+
103+
/// Sets up the benchmark for checking a membership proof. It creates the given
104+
/// number of validators, sets random session keys and then creates a membership
105+
/// proof for the first authority and returns its key and the proof.
106+
fn check_membership_proof_setup<T: Trait>(
107+
n: u32,
108+
) -> (
109+
(sp_runtime::KeyTypeId, &'static [u8; 32]),
110+
sp_session::MembershipProof,
111+
) {
112+
pallet_staking::ValidatorCount::put(n);
113+
114+
// create validators and set random session keys
115+
for (n, who) in create_validators::<T>(n, 1000)
116+
.unwrap()
117+
.into_iter()
118+
.enumerate()
119+
{
120+
use rand::RngCore;
121+
use rand::SeedableRng;
122+
123+
let validator = T::Lookup::lookup(who).unwrap();
124+
let controller = pallet_staking::Module::<T>::bonded(validator).unwrap();
125+
126+
let keys = {
127+
let mut keys = [0u8; 128];
128+
129+
// we keep the keys for the first validator as 0x00000...
130+
if n > 0 {
131+
let mut rng = rand::rngs::StdRng::seed_from_u64(n as u64);
132+
rng.fill_bytes(&mut keys);
133+
}
134+
135+
keys
136+
};
137+
138+
let keys: T::Keys = Decode::decode(&mut &keys[..]).unwrap();
139+
let proof: Vec<u8> = vec![];
140+
141+
Session::<T>::set_keys(RawOrigin::Signed(controller).into(), keys, proof).unwrap();
142+
}
143+
144+
Module::<T>::on_initialize(T::BlockNumber::one());
145+
146+
// skip sessions until the new validator set is enacted
147+
while Session::<T>::validators().len() < n as usize {
148+
Session::<T>::rotate_session();
149+
}
150+
151+
let key = (sp_runtime::KeyTypeId(*b"babe"), &[0u8; 32]);
152+
153+
(key, Historical::<T>::prove(key).unwrap())
62154
}
63155

64156
#[cfg(test)]

0 commit comments

Comments
 (0)