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

Commit

Permalink
Implement consensus hook for aura-ext
Browse files Browse the repository at this point in the history
  • Loading branch information
slumber committed May 9, 2023
1 parent 86b5d3d commit 3e20e1a
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 3 deletions.
63 changes: 63 additions & 0 deletions pallets/aura-ext/src/consensus_hook.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2023 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.

// Cumulus 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.

// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.

//! The definition of a [`ConsensusHook`] trait for consensus logic to manage
//! block velocity.
//!
//! The velocity `V` refers to the rate of block processing by the relay chain.
use sp_std::num::NonZeroU32;

/// Block processing velocity, essentially defining the limit of block production per
/// aura slot.
#[derive(Debug, Copy, Clone)]
pub struct BlockProcessingVelocity(NonZeroU32);

impl BlockProcessingVelocity {
pub(crate) fn get(&self) -> u32 {
self.0.get()
}
}

impl From<NonZeroU32> for BlockProcessingVelocity {
fn from(value: NonZeroU32) -> Self {
Self(value)
}
}

/// The consensus hook for managing number of blocks authored per slot.
pub trait ConsensusHook {
/// This hook is called on each block initialization to determine if it's valid to author
/// another block.
fn block_processing_velocity() -> BlockProcessingVelocity;
}

/// A consensus hook for a fixed block processing velocity.
///
/// Since it is illegal to provide zero-velocity, this sets a minimum of 1.
pub struct FixedVelocityConsensusHook<const N: u32>;

impl<const N: u32> ConsensusHook for FixedVelocityConsensusHook<N> {
fn block_processing_velocity() -> BlockProcessingVelocity {
NonZeroU32::new(sp_std::cmp::max(N, 1))
.expect("1 is the minimum value and non-zero; qed")
.into()
}
}

/// A fixed-velocity consensus hook, which assumes there's only single core
/// assigned to parachain.
pub type DefaultBlockProcessingVelocity = FixedVelocityConsensusHook<1>;
46 changes: 43 additions & 3 deletions pallets/aura-ext/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@

use frame_support::traits::{ExecuteBlock, FindAuthor};
use sp_application_crypto::RuntimeAppPublic;
use sp_consensus_aura::digests::CompatibleDigestItem;
use sp_consensus_aura::{digests::CompatibleDigestItem, Slot};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};

pub mod consensus_hook;
pub use consensus_hook::ConsensusHook;

type Aura<T> = pallet_aura::Pallet<T>;

pub use pallet::*;
Expand All @@ -52,7 +55,13 @@ pub mod pallet {

/// The configuration trait.
#[pallet::config]
pub trait Config: pallet_aura::Config + frame_system::Config {}
pub trait Config: pallet_aura::Config + frame_system::Config {
/// Hook used to determine current velocity of block processing
/// by the relay chain.
///
/// Defines the limit of blocks authored per slot to `V`.
type ConsensusHook: ConsensusHook;
}

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand All @@ -68,7 +77,32 @@ pub mod pallet {
// Fetch the authorities once to get them into the storage proof of the PoV.
Authorities::<T>::get();

T::DbWeight::get().reads_writes(2, 1)
let new_slot = Aura::<T>::current_slot();
let velocity = T::ConsensusHook::block_processing_velocity();

let (new_slot, authored) = match SlotInfo::<T>::get() {
Some((slot, authored)) if slot == new_slot => {
// New slot is the same as previous one, increment the
// the counter if within the limit.
if authored < velocity.get() {
(slot, authored + 1)
} else {
panic!("not allowed to author another block in the current slot")
}
},
Some((slot, _)) if slot < new_slot => {
// Velocity is non-zero, always within the limit.
(new_slot, 1)
},
Some(..) => {
panic!("slot moved backwards")
},
None => (new_slot, 1),
};

SlotInfo::<T>::put((new_slot, authored));

T::DbWeight::get().reads_writes(5, 2)
}
}

Expand All @@ -84,6 +118,12 @@ pub mod pallet {
ValueQuery,
>;

/// Current slot paired with a number of authored blocks.
///
/// Updated on each block initialization.
#[pallet::storage]
pub(crate) type SlotInfo<T: Config> = StorageValue<_, (Slot, u32), OptionQuery>;

#[pallet::genesis_config]
#[derive(Default)]
pub struct GenesisConfig;
Expand Down

0 comments on commit 3e20e1a

Please sign in to comment.