Wrap Proposer so we can add the SeraiPreExecutionDigest (timestamps)

This commit is contained in:
Luke Parker
2025-11-14 08:02:18 -05:00
parent cde0f753c2
commit 82ca889ed3
3 changed files with 64 additions and 4 deletions

View File

@@ -253,7 +253,7 @@ mod substrate {
for log in header.consensus.digest.logs() { for log in header.consensus.digest.logs() {
match log { match log {
DigestItem::PreRuntime(consensus, encoded) DigestItem::PreRuntime(consensus, encoded)
if *consensus == SeraiExecutionDigest::CONSENSUS_ID => if *consensus == SeraiPreExecutionDigest::CONSENSUS_ID =>
{ {
pre_execution_digest = pre_execution_digest =
SeraiPreExecutionDigest::deserialize_reader(&mut encoded.as_slice()).ok(); SeraiPreExecutionDigest::deserialize_reader(&mut encoded.as_slice()).ok();

View File

@@ -22,6 +22,8 @@ use serai_runtime::RuntimeApi;
use sc_consensus_babe::{self, SlotProportion}; use sc_consensus_babe::{self, SlotProportion};
use sc_consensus_grandpa as grandpa; use sc_consensus_grandpa as grandpa;
mod proposer;
#[cfg(not(feature = "runtime-benchmarks"))] #[cfg(not(feature = "runtime-benchmarks"))]
pub type Executor = WasmExecutor<ExtendedHostFunctions<SubstrateHostFunctions, ()>>; pub type Executor = WasmExecutor<ExtendedHostFunctions<SubstrateHostFunctions, ()>>;
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
@@ -32,6 +34,8 @@ pub type Executor = WasmExecutor<
type FullBackend = sc_service::TFullBackend<Block>; type FullBackend = sc_service::TFullBackend<Block>;
pub type FullClient = TFullClient<Block, RuntimeApi, Executor>; pub type FullClient = TFullClient<Block, RuntimeApi, Executor>;
pub type TransactionPool = sc_transaction_pool::TransactionPoolWrapper<Block, FullClient>;
type SelectChain = sc_consensus::LongestChain<FullBackend, Block>; type SelectChain = sc_consensus::LongestChain<FullBackend, Block>;
type GrandpaBlockImport = grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, SelectChain>; type GrandpaBlockImport = grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, SelectChain>;
type BabeBlockImport<CIDP> = type BabeBlockImport<CIDP> =
@@ -42,7 +46,7 @@ type PartialComponents<CIDP> = sc_service::PartialComponents<
FullBackend, FullBackend,
SelectChain, SelectChain,
sc_consensus::DefaultImportQueue<Block>, sc_consensus::DefaultImportQueue<Block>,
sc_transaction_pool::TransactionPoolWrapper<Block, FullClient>, TransactionPool,
( (
BabeBlockImport<CIDP>, BabeBlockImport<CIDP>,
sc_consensus_babe::BabeLink<Block>, sc_consensus_babe::BabeLink<Block>,
@@ -391,13 +395,13 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
keystore: keystore.clone(), keystore: keystore.clone(),
client: client.clone(), client: client.clone(),
select_chain, select_chain,
env: sc_basic_authorship::ProposerFactory::new( env: proposer::ProposerFactory(sc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(), task_manager.spawn_handle(),
client, client,
transaction_pool.clone(), transaction_pool.clone(),
prometheus_registry.as_ref(), prometheus_registry.as_ref(),
telemetry.as_ref().map(Telemetry::handle), telemetry.as_ref().map(Telemetry::handle),
), )),
block_import, block_import,
sync_oracle: sync_service.clone(), sync_oracle: sync_service.clone(),
justification_sync_link: sync_service.clone(), justification_sync_link: sync_service.clone(),

View File

@@ -0,0 +1,56 @@
use std::time::Duration;
use sp_runtime::Digest;
use sp_consensus::{InherentData, DisableProofRecording};
use serai_abi::{SeraiPreExecutionDigest, SubstrateHeader as Header, SubstrateBlock as Block};
use super::{FullClient, TransactionPool};
type UnderlyingProposer =
sc_basic_authorship::Proposer<Block, FullClient, TransactionPool, DisableProofRecording>;
pub struct Proposer(UnderlyingProposer);
impl sp_consensus::Proposer<Block> for Proposer {
type Error = <UnderlyingProposer as sp_consensus::Proposer<Block>>::Error;
type Proposal = <UnderlyingProposer as sp_consensus::Proposer<Block>>::Proposal;
type ProofRecording = DisableProofRecording;
type Proof = ();
fn propose(
self,
inherent_data: InherentData,
mut inherent_digests: Digest,
max_duration: Duration,
block_size_limit: Option<usize>,
) -> Self::Proposal {
Box::pin(async move {
// Insert our expected digest
inherent_digests.logs.push(sp_runtime::generic::DigestItem::PreRuntime(
SeraiPreExecutionDigest::CONSENSUS_ID,
borsh::to_vec(&SeraiPreExecutionDigest {
unix_time_in_millis: inherent_data
.get_data::<sp_timestamp::Timestamp>(&sp_timestamp::INHERENT_IDENTIFIER)
.map_err(|err| sp_blockchain::Error::Application(err.into()))?
.ok_or(sp_blockchain::Error::Application("missing timestamp inherent".into()))?
.as_millis(),
})
.unwrap(),
));
// Call the underlying propose function
self.0.propose(inherent_data, inherent_digests, max_duration, block_size_limit).await
})
}
}
type UnderlyingFactory =
sc_basic_authorship::ProposerFactory<TransactionPool, FullClient, DisableProofRecording>;
pub struct ProposerFactory(pub UnderlyingFactory);
impl sp_consensus::Environment<Block> for ProposerFactory {
type CreateProposer = core::future::Ready<Result<Proposer, Self::Error>>;
type Proposer = Proposer;
type Error = <UnderlyingFactory as sp_consensus::Environment<Block>>::Error;
fn init(&mut self, parent_header: &Header) -> Self::CreateProposer {
core::future::ready(self.0.init(parent_header).into_inner().map(Proposer))
}
}