Skip to content

Commit

Permalink
add: mechainsm to tie inherent data with digest (paritytech#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
AmbientTea authored Mar 7, 2024
1 parent d987613 commit df1a171
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 26 deletions.
37 changes: 21 additions & 16 deletions substrate/client/consensus/aura/src/import_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use sc_consensus::{
block_import::{BlockImport, BlockImportParams, ForkChoiceStrategy},
import_queue::{BasicQueue, BoxJustificationImport, DefaultImportQueue, Verifier},
};
use sc_consensus_slots::{check_equivocation, CheckedHeader};
use sc_consensus_slots::{check_equivocation, CheckedHeader, InherentDigest};
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_TRACE};
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_block_builder::BlockBuilder as BlockBuilderApi;
Expand Down Expand Up @@ -101,16 +101,16 @@ where
}

/// A verifier for Aura blocks.
pub struct AuraVerifier<C, P, CIDP, N> {
pub struct AuraVerifier<C, P, CIDP, N, ID> {
client: Arc<C>,
create_inherent_data_providers: CIDP,
check_for_equivocation: CheckForEquivocation,
telemetry: Option<TelemetryHandle>,
compatibility_mode: CompatibilityMode<N>,
_phantom: PhantomData<fn() -> P>,
_phantom: PhantomData<(fn() -> P, ID)>,
}

impl<C, P, CIDP, N> AuraVerifier<C, P, CIDP, N> {
impl<C, P, CIDP, N, ID> AuraVerifier<C, P, CIDP, N, ID> {
pub(crate) fn new(
client: Arc<C>,
create_inherent_data_providers: CIDP,
Expand All @@ -129,7 +129,7 @@ impl<C, P, CIDP, N> AuraVerifier<C, P, CIDP, N> {
}
}

impl<C, P, CIDP, N> AuraVerifier<C, P, CIDP, N>
impl<C, P, CIDP, N, ID> AuraVerifier<C, P, CIDP, N, ID>
where
CIDP: Send,
{
Expand All @@ -142,7 +142,8 @@ where
where
C: ProvideRuntimeApi<B>,
C::Api: BlockBuilderApi<B>,
CIDP: CreateInherentDataProviders<B, Slot>,
CIDP: CreateInherentDataProviders<B, (Slot, <ID as InherentDigest>::Value)>,
ID: InherentDigest
{
let inherent_data =
create_inherent_data::<B>(&inherent_data_providers).await?;
Expand All @@ -167,14 +168,15 @@ where
}

#[async_trait::async_trait]
impl<B: BlockT, C, P, CIDP> Verifier<B> for AuraVerifier<C, P, CIDP, NumberFor<B>>
impl<B: BlockT, C, P, CIDP, ID> Verifier<B> for AuraVerifier<C, P, CIDP, NumberFor<B>, ID>
where
C: ProvideRuntimeApi<B> + Send + Sync + sc_client_api::backend::AuxStore,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B>,
P: Pair,
P::Public: Codec + Debug,
P::Signature: Codec,
CIDP: CurrentSlotProvider + CreateInherentDataProviders<B, Slot> + Send + Sync,
CIDP: CurrentSlotProvider + CreateInherentDataProviders<B, (Slot, <ID as InherentDigest>::Value)> + Send + Sync,
ID: InherentDigest + Send + Sync + 'static,
{
async fn verify(
&mut self,
Expand Down Expand Up @@ -210,12 +212,14 @@ where
let checked_header = check_header::<C, B, P>(
&self.client,
slot_now + 1,
block.header,
block.header.clone(),
hash,
&authorities[..],
self.check_for_equivocation,
)
.map_err(|e| e.to_string())?;
let inherent_digest = <ID as InherentDigest>::value_from_digest(block.header.digest().logs())
.map_err(|e| format!("Failed to retrieve inherent digest from header at {:?}: {}", parent_hash, e))?;
match checked_header {
CheckedHeader::Checked(pre_header, (slot, seal)) => {
// if the body is passed through, we need to use the runtime
Expand All @@ -228,7 +232,7 @@ where
create_inherent_data_provider(
&self.create_inherent_data_providers,
parent_hash,
slot,
(slot, inherent_digest),
)
.await?;

Expand Down Expand Up @@ -333,7 +337,7 @@ pub struct ImportQueueParams<'a, Block: BlockT, I, C, S, CIDP> {
}

/// Start an import queue for the Aura consensus algorithm.
pub fn import_queue<P, Block, I, C, S, CIDP>(
pub fn import_queue<P, Block, I, C, S, CIDP, ID>(
ImportQueueParams {
block_import,
justification_import,
Expand Down Expand Up @@ -362,9 +366,10 @@ where
P::Public: Codec + Debug,
P::Signature: Codec,
S: sp_core::traits::SpawnEssentialNamed,
CIDP: CurrentSlotProvider + CreateInherentDataProviders<Block, Slot> + Sync + Send + 'static,
CIDP: CurrentSlotProvider + CreateInherentDataProviders<Block, (Slot, <ID as InherentDigest>::Value)> + Sync + Send + 'static,
ID: InherentDigest + Send + Sync + 'static,
{
let verifier = build_verifier::<P, _, _, _>(BuildVerifierParams {
let verifier = build_verifier::<P, _, _, _, ID>(BuildVerifierParams {
client,
create_inherent_data_providers,
check_for_equivocation,
Expand Down Expand Up @@ -392,16 +397,16 @@ pub struct BuildVerifierParams<C, CIDP, N> {
}

/// Build the [`AuraVerifier`]
pub fn build_verifier<P, C, CIDP, N>(
pub fn build_verifier<P, C, CIDP, N, ID>(
BuildVerifierParams {
client,
create_inherent_data_providers,
check_for_equivocation,
telemetry,
compatibility_mode,
}: BuildVerifierParams<C, CIDP, N>,
) -> AuraVerifier<C, P, CIDP, N> {
AuraVerifier::<_, P, _, _>::new(
) -> AuraVerifier<C, P, CIDP, N, ID> {
AuraVerifier::<_, P, _, _, ID>::new(
client,
create_inherent_data_providers,
check_for_equivocation,
Expand Down
21 changes: 13 additions & 8 deletions substrate/client/consensus/aura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use std::{fmt::Debug, marker::PhantomData, pin::Pin, sync::Arc};

use codec::Codec;
use futures::prelude::*;
pub use sc_consensus_slots::InherentDigest;

use sc_client_api::{backend::AuxStore, BlockOf};
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, StateAction};
Expand Down Expand Up @@ -151,7 +152,7 @@ pub struct StartAuraParams<C, SC, I, PF, SO, L, CIDP, BS, N> {
}

/// Start the aura worker. The returned future should be run in a futures executor.
pub fn start_aura<P, B, C, SC, I, PF, SO, L, CIDP, BS, Error>(
pub fn start_aura<P, B, C, SC, I, PF, SO, L, CIDP, BS, Error, ID>(
StartAuraParams {
slot_duration,
client,
Expand Down Expand Up @@ -187,8 +188,9 @@ where
CIDP::InherentDataProviders: InherentDataProviderExt + Send,
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + Sync + 'static,
Error: std::error::Error + Send + From<ConsensusError> + 'static,
ID: InherentDigest + Send + Sync + 'static,
{
let worker = build_aura_worker::<P, _, _, _, _, _, _, _, _>(BuildAuraWorkerParams {
let worker = build_aura_worker::<P, _, _, _, _, _, _, _, _, ID>(BuildAuraWorkerParams {
client,
block_import,
proposer_factory,
Expand Down Expand Up @@ -250,7 +252,7 @@ pub struct BuildAuraWorkerParams<C, I, PF, SO, L, BS, N> {
/// Build the aura worker.
///
/// The caller is responsible for running this worker, otherwise it will do nothing.
pub fn build_aura_worker<P, B, C, PF, I, SO, L, BS, Error>(
pub fn build_aura_worker<P, B, C, PF, I, SO, L, BS, Error, ID>(
BuildAuraWorkerParams {
client,
block_import,
Expand Down Expand Up @@ -288,6 +290,7 @@ where
SO: SyncOracle + Send + Sync + Clone,
L: sc_consensus::JustificationSyncLink<B>,
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + Sync + 'static,
ID: InherentDigest + Send + Sync + 'static,
{
AuraWorker {
client,
Expand All @@ -302,11 +305,11 @@ where
block_proposal_slot_portion,
max_block_proposal_slot_portion,
compatibility_mode,
_phantom: PhantomData::<fn() -> P>,
_phantom: PhantomData::<(fn() -> P, ID)>,
}
}

struct AuraWorker<C, E, I, P, SO, L, BS, N> {
struct AuraWorker<C, E, I, P, SO, L, BS, N, ID> {
client: Arc<C>,
block_import: I,
env: E,
Expand All @@ -319,12 +322,12 @@ struct AuraWorker<C, E, I, P, SO, L, BS, N> {
max_block_proposal_slot_portion: Option<SlotProportion>,
telemetry: Option<TelemetryHandle>,
compatibility_mode: CompatibilityMode<N>,
_phantom: PhantomData<fn() -> P>,
_phantom: PhantomData<(fn() -> P, ID)>,
}

#[async_trait::async_trait]
impl<B, C, E, I, P, Error, SO, L, BS> sc_consensus_slots::SimpleSlotWorker<B>
for AuraWorker<C, E, I, P, SO, L, BS, NumberFor<B>>
impl<B, C, E, I, P, Error, SO, L, BS, ID> sc_consensus_slots::SimpleSlotWorker<B>
for AuraWorker<C, E, I, P, SO, L, BS, NumberFor<B>, ID>
where
B: BlockT,
C: ProvideRuntimeApi<B> + BlockOf + HeaderBackend<B> + Sync,
Expand All @@ -339,6 +342,7 @@ where
L: sc_consensus::JustificationSyncLink<B>,
BS: BackoffAuthoringBlocksStrategy<NumberFor<B>> + Send + Sync + 'static,
Error: std::error::Error + Send + From<ConsensusError> + 'static,
ID: InherentDigest + Send + Sync + 'static,
{
type BlockImport = I;
type SyncOracle = SO;
Expand All @@ -348,6 +352,7 @@ where
type Proposer = E::Proposer;
type Claim = P::Public;
type AuxData = Vec<AuthorityId<P>>;
type InherentDigest = ID;

fn logging_target(&self) -> &'static str {
"aura"
Expand Down
1 change: 1 addition & 0 deletions substrate/client/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ where
type Proposer = E::Proposer;
type BlockImport = I;
type AuxData = ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>;
type InherentDigest = ();

fn logging_target(&self) -> &'static str {
LOG_TARGET
Expand Down
49 changes: 47 additions & 2 deletions substrate/client/consensus/slots/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ use sp_arithmetic::traits::BaseArithmetic;
use sp_consensus::{Proposal, Proposer, SelectChain, SyncOracle};
use sp_consensus_slots::{Slot, SlotDuration};
use sp_inherents::CreateInherentDataProviders;
use sp_runtime::traits::{Block as BlockT, HashingFor, Header as HeaderT};
use sp_runtime::{
traits::{Block as BlockT, HashingFor, Header as HeaderT},
DigestItem,
};
use std::{
error::Error,
fmt::Debug,
ops::Deref,
time::{Duration, Instant},
Expand Down Expand Up @@ -77,6 +81,36 @@ pub trait SlotWorker<B: BlockT, Proof> {
async fn on_slot(&mut self, slot_info: SlotInfo<B>) -> Option<SlotResult<B, Proof>>;
}

/// Defines parts of inherent data that should be included in header digest
pub trait InherentDigest {
/// Rust type of the inherent digest value
type Value: Send + Sync + 'static;

/// Construct digest items from block's inherent data
fn from_inherent_data(
inherent_data: &sp_consensus::InherentData,
) -> Result<Vec<sp_runtime::DigestItem>, Box<dyn Error + Send + Sync>>;

/// Retrieve value from digests
fn value_from_digest(
digests: &[DigestItem],
) -> Result<Self::Value, Box<dyn Error + Send + Sync>>;
}

impl InherentDigest for () {
type Value = ();

fn from_inherent_data(
_inherent_data: &sp_consensus::InherentData,
) -> Result<Vec<sp_runtime::DigestItem>, Box<dyn Error + Send + Sync>> {
Ok(vec![])
}

fn value_from_digest(_digests: &[DigestItem]) -> Result<(), Box<dyn Error + Send + Sync>> {
Ok(())
}
}

/// A skeleton implementation for `SlotWorker` which tries to claim a slot at
/// its beginning and tries to produce a block if successfully claimed, timing
/// out if block production takes too long.
Expand Down Expand Up @@ -107,6 +141,9 @@ pub trait SimpleSlotWorker<B: BlockT> {
/// Auxiliary data necessary for authoring.
type AuxData: Send + Sync + 'static;

/// Definition of inherent data that should be put in the digest
type InherentDigest: InherentDigest + Send + Sync + 'static;

/// The logging target to use when logging messages.
fn logging_target(&self) -> &'static str;

Expand Down Expand Up @@ -195,7 +232,15 @@ pub trait SimpleSlotWorker<B: BlockT> {

let proposing_remaining_duration =
end_proposing_at.saturating_duration_since(Instant::now());
let logs = self.pre_digest_data(slot, claim);
let mut logs = self.pre_digest_data(slot, claim);
let mut inherent_logs = match Self::InherentDigest::from_inherent_data(&inherent_data) {
Ok(inherent_logs) => inherent_logs,
Err(err) => {
info!("Proposing failed: {err}");
return None;
},
};
logs.append(&mut inherent_logs);

// deadline our production to 98% of the total time left for proposing. As we deadline
// the proposing below to the same total time left, the 2% margin should be enough for
Expand Down

0 comments on commit df1a171

Please sign in to comment.