Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Generate storage info for pallet babe (#9760)
Browse files Browse the repository at this point in the history
* Adding MaxEncodedLen for:
* NextConfigDescriptor
* AllowedSlots
* BabeEpochConfiguration

In prepation for adding storage information on pallet babe

* Adding stotage_info to pallet babe

Refactored UNDER_CONSTRUCTION_SEGMENT_LENGTH to become a runtime
parameter MaxSegmentLength

* Reinstate Slice as opposed to Vec

* Refactoring code to make it neater

* Replace `MaxSegmentLength` by
`UNDER_CONSTRUCTION_SEGMENT_LENGTH`
Stop exposing the bounds to the runtime

* Removing extra line

Co-authored-by: thiolliere <[email protected]>
  • Loading branch information
Georges and gui1117 authored Sep 22, 2021
1 parent 1361206 commit eded990
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 30 deletions.
3 changes: 2 additions & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ impl pallet_babe::Config for Runtime {
pallet_babe::EquivocationHandler<Self::KeyOwnerIdentification, Offences, ReportLongevity>;

type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
}

parameter_types! {
Expand Down Expand Up @@ -1441,7 +1442,7 @@ impl_runtime_apis! {
slot_duration: Babe::slot_duration(),
epoch_length: EpochDuration::get(),
c: BABE_GENESIS_EPOCH_CONFIG.c,
genesis_authorities: Babe::authorities(),
genesis_authorities: Babe::authorities().to_vec(),
randomness: Babe::randomness(),
allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots,
}
Expand Down
86 changes: 64 additions & 22 deletions frame/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ use codec::{Decode, Encode};
use frame_support::{
dispatch::DispatchResultWithPostInfo,
traits::{
DisabledValidators, FindAuthor, Get, KeyOwnerProofSystem, OnTimestampSet, OneSessionHandler,
ConstU32, DisabledValidators, FindAuthor, Get, KeyOwnerProofSystem, OnTimestampSet,
OneSessionHandler,
},
weights::{Pays, Weight},
BoundedVec, WeakBoundedVec,
};
use sp_application_crypto::Public;
use sp_application_crypto::{Public, TryFrom};
use sp_runtime::{
generic::DigestItem,
traits::{IsMember, One, SaturatedConversion, Saturating, Zero},
Expand Down Expand Up @@ -100,7 +102,7 @@ impl EpochChangeTrigger for SameAuthoritiesForever {
}
}

const UNDER_CONSTRUCTION_SEGMENT_LENGTH: usize = 256;
const UNDER_CONSTRUCTION_SEGMENT_LENGTH: u32 = 256;

type MaybeRandomness = Option<schnorrkel::Randomness>;

Expand All @@ -113,6 +115,7 @@ pub mod pallet {
/// The BABE Pallet
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::generate_storage_info]
pub struct Pallet<T>(_);

#[pallet::config]
Expand Down Expand Up @@ -169,6 +172,10 @@ pub mod pallet {
type HandleEquivocation: HandleEquivocation<Self>;

type WeightInfo: WeightInfo;

/// Max number of authorities allowed
#[pallet::constant]
type MaxAuthorities: Get<u32>;
}

#[pallet::error]
Expand All @@ -189,7 +196,11 @@ pub mod pallet {
/// Current epoch authorities.
#[pallet::storage]
#[pallet::getter(fn authorities)]
pub type Authorities<T> = StorageValue<_, Vec<(AuthorityId, BabeAuthorityWeight)>, ValueQuery>;
pub type Authorities<T: Config> = StorageValue<
_,
WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities>,
ValueQuery,
>;

/// The slot at which the first epoch actually started. This is 0
/// until the first block of the chain.
Expand Down Expand Up @@ -229,8 +240,11 @@ pub mod pallet {

/// Next epoch authorities.
#[pallet::storage]
pub(super) type NextAuthorities<T> =
StorageValue<_, Vec<(AuthorityId, BabeAuthorityWeight)>, ValueQuery>;
pub(super) type NextAuthorities<T: Config> = StorageValue<
_,
WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities>,
ValueQuery,
>;

/// Randomness under construction.
///
Expand All @@ -246,8 +260,13 @@ pub mod pallet {

/// TWOX-NOTE: `SegmentIndex` is an increasing integer, so this is okay.
#[pallet::storage]
pub(super) type UnderConstruction<T> =
StorageMap<_, Twox64Concat, u32, Vec<schnorrkel::Randomness>, ValueQuery>;
pub(super) type UnderConstruction<T: Config> = StorageMap<
_,
Twox64Concat,
u32,
BoundedVec<schnorrkel::Randomness, ConstU32<UNDER_CONSTRUCTION_SEGMENT_LENGTH>>,
ValueQuery,
>;

/// Temporary value (cleared at block finalization) which is `Some`
/// if per-block initialization has already been called for current block.
Expand Down Expand Up @@ -503,8 +522,8 @@ impl<T: Config> Pallet<T> {
/// Typically, this is not handled directly by the user, but by higher-level validator-set
/// manager logic like `pallet-session`.
pub fn enact_epoch_change(
authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
next_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
authorities: WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities>,
next_authorities: WeakBoundedVec<(AuthorityId, BabeAuthorityWeight), T::MaxAuthorities>,
) {
// PRECONDITION: caller has done initialization and is guaranteed
// by the session module to be called before this.
Expand Down Expand Up @@ -541,8 +560,10 @@ impl<T: Config> Pallet<T> {
// so that nodes can track changes.
let next_randomness = NextRandomness::<T>::get();

let next_epoch =
NextEpochDescriptor { authorities: next_authorities, randomness: next_randomness };
let next_epoch = NextEpochDescriptor {
authorities: next_authorities.to_vec(),
randomness: next_randomness,
};
Self::deposit_consensus(ConsensusLog::NextEpochData(next_epoch));

if let Some(next_config) = NextEpochConfig::<T>::get() {
Expand Down Expand Up @@ -571,7 +592,7 @@ impl<T: Config> Pallet<T> {
epoch_index: EpochIndex::<T>::get(),
start_slot: Self::current_epoch_start(),
duration: T::EpochDuration::get(),
authorities: Self::authorities(),
authorities: Self::authorities().to_vec(),
randomness: Self::randomness(),
config: EpochConfig::<T>::get()
.expect("EpochConfig is initialized in genesis; we never `take` or `kill` it; qed"),
Expand All @@ -590,7 +611,7 @@ impl<T: Config> Pallet<T> {
epoch_index: next_epoch_index,
start_slot: Self::epoch_start(next_epoch_index),
duration: T::EpochDuration::get(),
authorities: NextAuthorities::<T>::get(),
authorities: NextAuthorities::<T>::get().to_vec(),
randomness: NextRandomness::<T>::get(),
config: NextEpochConfig::<T>::get().unwrap_or_else(|| {
EpochConfig::<T>::get().expect(
Expand Down Expand Up @@ -619,14 +640,18 @@ impl<T: Config> Pallet<T> {
fn deposit_randomness(randomness: &schnorrkel::Randomness) {
let segment_idx = SegmentIndex::<T>::get();
let mut segment = UnderConstruction::<T>::get(&segment_idx);
if segment.len() < UNDER_CONSTRUCTION_SEGMENT_LENGTH {
if segment.try_push(*randomness).is_ok() {
// push onto current segment: not full.
segment.push(*randomness);
UnderConstruction::<T>::insert(&segment_idx, &segment);
} else {
// move onto the next segment and update the index.
let segment_idx = segment_idx + 1;
UnderConstruction::<T>::insert(&segment_idx, &vec![randomness.clone()]);
let bounded_randomness =
BoundedVec::<_, ConstU32<UNDER_CONSTRUCTION_SEGMENT_LENGTH>>::try_from(vec![
randomness.clone(),
])
.expect("UNDER_CONSTRUCTION_SEGMENT_LENGTH >= 1");
UnderConstruction::<T>::insert(&segment_idx, bounded_randomness);
SegmentIndex::<T>::put(&segment_idx);
}
}
Expand Down Expand Up @@ -667,7 +692,7 @@ impl<T: Config> Pallet<T> {
// we use the same values as genesis because we haven't collected any
// randomness yet.
let next = NextEpochDescriptor {
authorities: Self::authorities(),
authorities: Self::authorities().to_vec(),
randomness: Self::randomness(),
};

Expand Down Expand Up @@ -732,7 +757,7 @@ impl<T: Config> Pallet<T> {
let segment_idx: u32 = SegmentIndex::<T>::mutate(|s| sp_std::mem::replace(s, 0));

// overestimate to the segment being full.
let rho_size = segment_idx.saturating_add(1) as usize * UNDER_CONSTRUCTION_SEGMENT_LENGTH;
let rho_size = (segment_idx.saturating_add(1) * UNDER_CONSTRUCTION_SEGMENT_LENGTH) as usize;

let next_randomness = compute_randomness(
this_randomness,
Expand All @@ -747,8 +772,11 @@ impl<T: Config> Pallet<T> {
fn initialize_authorities(authorities: &[(AuthorityId, BabeAuthorityWeight)]) {
if !authorities.is_empty() {
assert!(Authorities::<T>::get().is_empty(), "Authorities are already initialized!");
Authorities::<T>::put(authorities);
NextAuthorities::<T>::put(authorities);
let bounded_authorities =
WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.to_vec())
.expect("Initial number of authorities should be lower than T::MaxAuthorities");
Authorities::<T>::put(&bounded_authorities);
NextAuthorities::<T>::put(&bounded_authorities);
}
}

Expand Down Expand Up @@ -878,10 +906,24 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
I: Iterator<Item = (&'a T::AccountId, AuthorityId)>,
{
let authorities = validators.map(|(_account, k)| (k, 1)).collect::<Vec<_>>();
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::force_from(
authorities,
Some(
"Warning: The session has more validators than expected. \
A runtime configuration adjustment may be needed.",
),
);

let next_authorities = queued_validators.map(|(_account, k)| (k, 1)).collect::<Vec<_>>();
let next_bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::force_from(
next_authorities,
Some(
"Warning: The session has more queued validators than expected. \
A runtime configuration adjustment may be needed.",
),
);

Self::enact_epoch_change(authorities, next_authorities)
Self::enact_epoch_change(bounded_authorities, next_bounded_authorities)
}

fn on_disabled(i: usize) {
Expand Down
3 changes: 3 additions & 0 deletions frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ parameter_types! {
pub const ExpectedBlockTime: u64 = 1;
pub const ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get();
pub const MaxAuthorities: u32 = 10;
pub const MaxSegmentLength: u32 = 256;
}

impl Config for Test {
Expand All @@ -252,6 +254,7 @@ impl Config for Test {
super::EquivocationHandler<Self::KeyOwnerIdentification, Offences, ReportLongevity>;

type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
}

pub fn go_to_block(n: u64, s: u64) {
Expand Down
2 changes: 1 addition & 1 deletion frame/babe/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn first_block_epoch_zero_start() {

let consensus_log = sp_consensus_babe::ConsensusLog::NextEpochData(
sp_consensus_babe::digests::NextEpochDescriptor {
authorities: Babe::authorities(),
authorities: Babe::authorities().to_vec(),
randomness: Babe::randomness(),
},
);
Expand Down
6 changes: 4 additions & 2 deletions primitives/consensus/babe/src/digests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{
AllowedSlots, AuthorityId, AuthorityIndex, AuthoritySignature, BabeAuthorityWeight,
BabeEpochConfiguration, Slot, BABE_ENGINE_ID,
};
use codec::{Codec, Decode, Encode};
use codec::{Codec, Decode, Encode, MaxEncodedLen};
use sp_runtime::{DigestItem, RuntimeDebug};
use sp_std::vec::Vec;

Expand Down Expand Up @@ -134,7 +134,9 @@ pub struct NextEpochDescriptor {

/// Information about the next epoch config, if changed. This is broadcast in the first
/// block of the epoch, and applies using the same rules as `NextEpochDescriptor`.
#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, scale_info::TypeInfo)]
#[derive(
Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo,
)]
pub enum NextConfigDescriptor {
/// Version 1.
#[codec(index = 1)]
Expand Down
6 changes: 3 additions & 3 deletions primitives/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub use sp_consensus_vrf::schnorrkel::{
Randomness, RANDOMNESS_LENGTH, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH,
};

use codec::{Decode, Encode};
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -214,7 +214,7 @@ pub struct BabeGenesisConfiguration {
}

/// Types of allowed slots.
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum AllowedSlots {
/// Only allow primary slots.
Expand Down Expand Up @@ -247,7 +247,7 @@ impl sp_consensus::SlotData for BabeGenesisConfiguration {
}

/// Configuration data used by the BABE consensus engine.
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct BabeEpochConfiguration {
/// A constant value that is used in the threshold calculation formula.
Expand Down
4 changes: 3 additions & 1 deletion test-utils/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ impl pallet_timestamp::Config for Runtime {
parameter_types! {
pub const EpochDuration: u64 = 6;
pub const ExpectedBlockTime: u64 = 10_000;
pub const MaxAuthorities: u32 = 10;
}

impl pallet_babe::Config for Runtime {
Expand All @@ -596,8 +597,9 @@ impl pallet_babe::Config for Runtime {
)>>::IdentificationTuple;

type HandleEquivocation = ();

type WeightInfo = ();

type MaxAuthorities = MaxAuthorities;
}

/// Adds one to the given input and returns the final result.
Expand Down

0 comments on commit eded990

Please sign in to comment.