mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 21:21:11 +00:00
Move proof generation to the type system level (#8185)
* Start * Finish!!!! * Update client/basic-authorship/src/basic_authorship.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Review comments Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
@@ -179,7 +179,7 @@ pub fn start_aura<B, C, SC, E, I, P, SO, CAW, BS, Error>(
|
||||
&inherent_data_providers,
|
||||
slot_duration.slot_duration()
|
||||
)?;
|
||||
Ok(sc_consensus_slots::start_slot_worker::<_, _, _, _, _, AuraSlotCompatible, _>(
|
||||
Ok(sc_consensus_slots::start_slot_worker::<_, _, _, _, _, AuraSlotCompatible, _, _>(
|
||||
slot_duration,
|
||||
select_chain,
|
||||
worker,
|
||||
@@ -877,7 +877,9 @@ pub fn import_queue<B, I, C, P, S, CAW>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_consensus::{NoNetwork as DummyOracle, Proposal, RecordProof, AlwaysCanAuthor};
|
||||
use sp_consensus::{
|
||||
NoNetwork as DummyOracle, Proposal, AlwaysCanAuthor, DisableProofRecording,
|
||||
};
|
||||
use sc_network_test::{Block as TestBlock, *};
|
||||
use sp_runtime::traits::{Block as BlockT, DigestFor};
|
||||
use sc_network::config::ProtocolConfig;
|
||||
@@ -916,20 +918,21 @@ mod tests {
|
||||
substrate_test_runtime_client::Backend,
|
||||
TestBlock
|
||||
>;
|
||||
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
|
||||
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction, ()>, Error>>;
|
||||
type ProofRecording = DisableProofRecording;
|
||||
type Proof = ();
|
||||
|
||||
fn propose(
|
||||
self,
|
||||
_: InherentData,
|
||||
digests: DigestFor<TestBlock>,
|
||||
_: Duration,
|
||||
_: RecordProof,
|
||||
) -> Self::Proposal {
|
||||
let r = self.1.new_block(digests).unwrap().build().map_err(|e| e.into());
|
||||
|
||||
future::ready(r.map(|b| Proposal {
|
||||
block: b.block,
|
||||
proof: b.proof,
|
||||
proof: (),
|
||||
storage_changes: b.storage_changes,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -32,11 +32,10 @@ use sp_consensus_babe::{AuthorityPair, Slot, AllowedSlots, make_transcript, make
|
||||
use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging;
|
||||
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
||||
use sp_consensus::{
|
||||
NoNetwork as DummyOracle, Proposal, RecordProof, AlwaysCanAuthor,
|
||||
NoNetwork as DummyOracle, Proposal, DisableProofRecording, AlwaysCanAuthor,
|
||||
import_queue::{BoxBlockImport, BoxJustificationImport},
|
||||
};
|
||||
use sc_network_test::*;
|
||||
use sc_network_test::{Block as TestBlock, PeersClient};
|
||||
use sc_network_test::{Block as TestBlock, *};
|
||||
use sc_network::config::ProtocolConfig;
|
||||
use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}};
|
||||
use sc_client_api::{BlockchainEvents, backend::TransactionFor};
|
||||
@@ -44,8 +43,7 @@ use log::debug;
|
||||
use std::{time::Duration, cell::RefCell, task::Poll};
|
||||
use rand::RngCore;
|
||||
use rand_chacha::{
|
||||
rand_core::SeedableRng,
|
||||
ChaChaRng,
|
||||
rand_core::SeedableRng, ChaChaRng,
|
||||
};
|
||||
use sc_keystore::LocalKeystore;
|
||||
use sp_application_crypto::key_types::BABE;
|
||||
@@ -112,7 +110,8 @@ impl DummyProposer {
|
||||
Result<
|
||||
Proposal<
|
||||
TestBlock,
|
||||
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>
|
||||
sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>,
|
||||
()
|
||||
>,
|
||||
Error
|
||||
>
|
||||
@@ -163,21 +162,22 @@ impl DummyProposer {
|
||||
// mutate the block header according to the mutator.
|
||||
(self.factory.mutator)(&mut block.header, Stage::PreSeal);
|
||||
|
||||
future::ready(Ok(Proposal { block, proof: None, storage_changes: Default::default() }))
|
||||
future::ready(Ok(Proposal { block, proof: (), storage_changes: Default::default() }))
|
||||
}
|
||||
}
|
||||
|
||||
impl Proposer<TestBlock> for DummyProposer {
|
||||
type Error = Error;
|
||||
type Transaction = sc_client_api::TransactionFor<substrate_test_runtime_client::Backend, TestBlock>;
|
||||
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction>, Error>>;
|
||||
type Proposal = future::Ready<Result<Proposal<TestBlock, Self::Transaction, ()>, Error>>;
|
||||
type ProofRecording = DisableProofRecording;
|
||||
type Proof = ();
|
||||
|
||||
fn propose(
|
||||
mut self,
|
||||
_: InherentData,
|
||||
pre_digests: DigestFor<TestBlock>,
|
||||
_: Duration,
|
||||
_: RecordProof,
|
||||
) -> Self::Proposal {
|
||||
self.propose_with(pre_digests)
|
||||
}
|
||||
|
||||
@@ -123,8 +123,11 @@ pub async fn seal_block<B, BI, SC, C, E, P>(
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let proposal = proposer.propose(id.clone(), digest, Duration::from_secs(MAX_PROPOSAL_DURATION), false.into())
|
||||
.map_err(|err| Error::StringError(format!("{:?}", err))).await?;
|
||||
let proposal = proposer.propose(
|
||||
id.clone(),
|
||||
digest,
|
||||
Duration::from_secs(MAX_PROPOSAL_DURATION),
|
||||
).map_err(|err| Error::StringError(format!("{:?}", err))).await?;
|
||||
|
||||
if proposal.block.extrinsics().len() == inherents_len && !create_empty {
|
||||
return Err(Error::EmptyTransactionPool)
|
||||
|
||||
@@ -52,8 +52,7 @@ use sp_consensus_pow::{Seal, TotalDifficulty, POW_ENGINE_ID};
|
||||
use sp_inherents::{InherentDataProviders, InherentData};
|
||||
use sp_consensus::{
|
||||
BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer,
|
||||
SelectChain, Error as ConsensusError, CanAuthorWith, RecordProof, BlockImport,
|
||||
BlockCheckParams, ImportResult,
|
||||
SelectChain, Error as ConsensusError, CanAuthorWith, BlockImport, BlockCheckParams, ImportResult,
|
||||
};
|
||||
use sp_consensus::import_queue::{
|
||||
BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport,
|
||||
@@ -549,7 +548,10 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
timeout: Duration,
|
||||
build_time: Duration,
|
||||
can_author_with: CAW,
|
||||
) -> (Arc<Mutex<MiningWorker<Block, Algorithm, C>>>, impl Future<Output = ()>) where
|
||||
) -> (
|
||||
Arc<Mutex<MiningWorker<Block, Algorithm, C, <E::Proposer as Proposer<Block>>::Proof>>>,
|
||||
impl Future<Output = ()>,
|
||||
) where
|
||||
Block: BlockT,
|
||||
C: ProvideRuntimeApi<Block> + BlockchainEvents<Block> + 'static,
|
||||
S: SelectChain<Block> + 'static,
|
||||
@@ -566,7 +568,7 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
}
|
||||
|
||||
let timer = UntilImportedOrTimeout::new(client.import_notification_stream(), timeout);
|
||||
let worker = Arc::new(Mutex::new(MiningWorker::<Block, Algorithm, C> {
|
||||
let worker = Arc::new(Mutex::new(MiningWorker::<Block, Algorithm, C, _> {
|
||||
build: None,
|
||||
algorithm: algorithm.clone(),
|
||||
block_import,
|
||||
@@ -664,7 +666,6 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
inherent_data,
|
||||
inherent_digest,
|
||||
build_time.clone(),
|
||||
RecordProof::No,
|
||||
).await {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
@@ -678,7 +679,7 @@ pub fn start_mining_worker<Block, C, S, Algorithm, E, SO, CAW>(
|
||||
},
|
||||
};
|
||||
|
||||
let build = MiningBuild::<Block, Algorithm, C> {
|
||||
let build = MiningBuild::<Block, Algorithm, C, _> {
|
||||
metadata: MiningMetadata {
|
||||
best_hash,
|
||||
pre_hash: proposal.block.header().hash(),
|
||||
|
||||
@@ -40,21 +40,31 @@ pub struct MiningMetadata<H, D> {
|
||||
}
|
||||
|
||||
/// A build of mining, containing the metadata and the block proposal.
|
||||
pub struct MiningBuild<Block: BlockT, Algorithm: PowAlgorithm<Block>, C: sp_api::ProvideRuntimeApi<Block>> {
|
||||
pub struct MiningBuild<
|
||||
Block: BlockT,
|
||||
Algorithm: PowAlgorithm<Block>,
|
||||
C: sp_api::ProvideRuntimeApi<Block>,
|
||||
Proof
|
||||
> {
|
||||
/// Mining metadata.
|
||||
pub metadata: MiningMetadata<Block::Hash, Algorithm::Difficulty>,
|
||||
/// Mining proposal.
|
||||
pub proposal: Proposal<Block, sp_api::TransactionFor<C, Block>>,
|
||||
pub proposal: Proposal<Block, sp_api::TransactionFor<C, Block>, Proof>,
|
||||
}
|
||||
|
||||
/// Mining worker that exposes structs to query the current mining build and submit mined blocks.
|
||||
pub struct MiningWorker<Block: BlockT, Algorithm: PowAlgorithm<Block>, C: sp_api::ProvideRuntimeApi<Block>> {
|
||||
pub(crate) build: Option<MiningBuild<Block, Algorithm, C>>,
|
||||
pub struct MiningWorker<
|
||||
Block: BlockT,
|
||||
Algorithm: PowAlgorithm<Block>,
|
||||
C: sp_api::ProvideRuntimeApi<Block>,
|
||||
Proof
|
||||
> {
|
||||
pub(crate) build: Option<MiningBuild<Block, Algorithm, C, Proof>>,
|
||||
pub(crate) algorithm: Algorithm,
|
||||
pub(crate) block_import: BoxBlockImport<Block, sp_api::TransactionFor<C, Block>>,
|
||||
}
|
||||
|
||||
impl<Block, Algorithm, C> MiningWorker<Block, Algorithm, C> where
|
||||
impl<Block, Algorithm, C, Proof> MiningWorker<Block, Algorithm, C, Proof> where
|
||||
Block: BlockT,
|
||||
C: sp_api::ProvideRuntimeApi<Block>,
|
||||
Algorithm: PowAlgorithm<Block>,
|
||||
@@ -72,7 +82,7 @@ impl<Block, Algorithm, C> MiningWorker<Block, Algorithm, C> where
|
||||
|
||||
pub(crate) fn on_build(
|
||||
&mut self,
|
||||
build: MiningBuild<Block, Algorithm, C>,
|
||||
build: MiningBuild<Block, Algorithm, C, Proof>,
|
||||
) {
|
||||
self.build = Some(build);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ use log::{debug, error, info, warn};
|
||||
use parking_lot::Mutex;
|
||||
use sp_api::{ProvideRuntimeApi, ApiRef};
|
||||
use sp_arithmetic::traits::BaseArithmetic;
|
||||
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData, RecordProof};
|
||||
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData};
|
||||
use sp_consensus_slots::Slot;
|
||||
use sp_inherents::{InherentData, InherentDataProviders};
|
||||
use sp_runtime::{
|
||||
@@ -57,20 +57,18 @@ pub type StorageChanges<Transaction, Block> =
|
||||
|
||||
/// The result of [`SlotWorker::on_slot`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SlotResult<Block: BlockT> {
|
||||
pub struct SlotResult<Block: BlockT, Proof> {
|
||||
/// The block that was built.
|
||||
pub block: Block,
|
||||
/// The optional storage proof that was calculated while building the block.
|
||||
///
|
||||
/// This needs to be enabled for the proposer to get this storage proof.
|
||||
pub storage_proof: Option<sp_trie::StorageProof>,
|
||||
/// The storage proof that was recorded while building the block.
|
||||
pub storage_proof: Proof,
|
||||
}
|
||||
|
||||
/// A worker that should be invoked at every new slot.
|
||||
///
|
||||
/// The implementation should not make any assumptions of the slot being bound to the time or
|
||||
/// similar. The only valid assumption is that the slot number is always increasing.
|
||||
pub trait SlotWorker<B: BlockT> {
|
||||
pub trait SlotWorker<B: BlockT, Proof> {
|
||||
/// Called when a new slot is triggered.
|
||||
///
|
||||
/// Returns a future that resolves to a [`SlotResult`] iff a block was successfully built in
|
||||
@@ -79,7 +77,7 @@ pub trait SlotWorker<B: BlockT> {
|
||||
&mut self,
|
||||
chain_head: B::Header,
|
||||
slot_info: SlotInfo,
|
||||
) -> Pin<Box<dyn Future<Output = Option<SlotResult<B>>> + Send>>;
|
||||
) -> Pin<Box<dyn Future<Output = Option<SlotResult<B, Proof>>> + Send>>;
|
||||
}
|
||||
|
||||
/// A skeleton implementation for `SlotWorker` which tries to claim a slot at
|
||||
@@ -206,7 +204,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
&mut self,
|
||||
chain_head: B::Header,
|
||||
slot_info: SlotInfo,
|
||||
) -> Pin<Box<dyn Future<Output = Option<SlotResult<B>>> + Send>>
|
||||
) -> Pin<Box<dyn Future<Output = Option<SlotResult<B, <Self::Proposer as Proposer<B>>::Proof>>> + Send>>
|
||||
where
|
||||
<Self::Proposer as Proposer<B>>::Proposal: Unpin + Send + 'static,
|
||||
{
|
||||
@@ -307,7 +305,6 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
logs,
|
||||
},
|
||||
slot_remaining_duration,
|
||||
RecordProof::No,
|
||||
).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e))));
|
||||
|
||||
let proposal_work =
|
||||
@@ -384,12 +381,13 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, T: SimpleSlotWorker<B>> SlotWorker<B> for T {
|
||||
impl<B: BlockT, T: SimpleSlotWorker<B>> SlotWorker<B, <T::Proposer as Proposer<B>>::Proof> for T
|
||||
{
|
||||
fn on_slot(
|
||||
&mut self,
|
||||
chain_head: B::Header,
|
||||
slot_info: SlotInfo,
|
||||
) -> Pin<Box<dyn Future<Output = Option<SlotResult<B>>> + Send>> {
|
||||
) -> Pin<Box<dyn Future<Output = Option<SlotResult<B, <T::Proposer as Proposer<B>>::Proof>>> + Send>> {
|
||||
SimpleSlotWorker::on_slot(self, chain_head, slot_info)
|
||||
}
|
||||
}
|
||||
@@ -407,7 +405,7 @@ pub trait SlotCompatible {
|
||||
///
|
||||
/// Every time a new slot is triggered, `worker.on_slot` is called and the future it returns is
|
||||
/// polled until completion, unless we are major syncing.
|
||||
pub fn start_slot_worker<B, C, W, T, SO, SC, CAW>(
|
||||
pub fn start_slot_worker<B, C, W, T, SO, SC, CAW, Proof>(
|
||||
slot_duration: SlotDuration<T>,
|
||||
client: C,
|
||||
mut worker: W,
|
||||
@@ -419,7 +417,7 @@ pub fn start_slot_worker<B, C, W, T, SO, SC, CAW>(
|
||||
where
|
||||
B: BlockT,
|
||||
C: SelectChain<B>,
|
||||
W: SlotWorker<B>,
|
||||
W: SlotWorker<B, Proof>,
|
||||
SO: SyncOracle + Send,
|
||||
SC: SlotCompatible + Unpin,
|
||||
T: SlotData + Clone,
|
||||
|
||||
Reference in New Issue
Block a user