diff --git a/Cargo.lock b/Cargo.lock index 757b9ad080074..245493986bdd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5615,7 +5615,6 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.10.0", "sc-block-builder", - "sc-client", "sc-client-api", "sc-telemetry", "sc-transaction-pool", @@ -6112,6 +6111,7 @@ dependencies = [ "parking_lot 0.10.0", "pin-project", "rand 0.7.3", + "sc-block-builder", "sc-client", "sc-client-api", "sc-keystore", @@ -6944,6 +6944,7 @@ dependencies = [ "criterion 0.3.1", "parity-scale-codec", "rustversion", + "sc-block-builder", "sp-api", "sp-blockchain", "sp-consensus", diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 6e2a766dc1a4b..7a714d5d7a371 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -93,10 +93,10 @@ pub fn new_full(config: Configuration) .build()?; if participates_in_consensus { - let proposer = sc_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; + let proposer = sc_basic_authorship::ProposerFactory::new( + service.client(), + service.transaction_pool() + ); let client = service.client(); let select_chain = service.select_chain() diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 90090cdf54775..7df266a687add 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -150,10 +150,10 @@ macro_rules! new_full { ($with_startup_data)(&block_import, &babe_link); if participates_in_consensus { - let proposer = sc_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; + let proposer = sc_basic_authorship::ProposerFactory::new( + service.client(), + service.transaction_pool() + ); let client = service.client(); let select_chain = service.select_chain() @@ -501,10 +501,10 @@ mod tests { let parent_header = service.client().header(&parent_id).unwrap().unwrap(); let parent_hash = parent_header.hash(); let parent_number = *parent_header.number(); - let mut proposer_factory = sc_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; + let mut proposer_factory = sc_basic_authorship::ProposerFactory::new( + service.client(), + service.transaction_pool() + ); let epoch = babe_link.epoch_changes().lock().epoch_for_child_of( descendent_query(&*service.client()), diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index c3fb8799bba6f..56bfb57072561 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -16,7 +16,6 @@ sp-api = { version = "2.0.0-alpha.2", path = "../../primitives/api" } sp-runtime = { version = "2.0.0-alpha.2", path = "../../primitives/runtime" } sp-core = { version = "2.0.0-alpha.2", path = "../../primitives/core" } sp-blockchain = { version = "2.0.0-alpha.2", path = "../../primitives/blockchain" } -sc-client = { version = "0.8.0-alpha.2", path = "../" } sc-client-api = { version = "2.0.0-alpha.2", path = "../api" } sp-consensus = { version = "0.8.0-alpha.2", path = "../../primitives/consensus/common" } sp-inherents = { version = "2.0.0-alpha.2", path = "../../primitives/inherents" } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index a99453544e5f6..231d0255919b4 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -19,8 +19,7 @@ // FIXME #1021 move this into sp-consensus use std::{time, sync::Arc}; -use sc_client_api::{CallExecutor, backend}; -use sc_client::Client as SubstrateClient; +use sc_client_api::backend; use codec::Decode; use sp_consensus::{evaluation, Proposal, RecordProof}; use sp_inherents::InherentData; @@ -32,35 +31,47 @@ use sp_runtime::{ }; use sp_transaction_pool::{TransactionPool, InPoolTransaction}; use sc_telemetry::{telemetry, CONSENSUS_INFO}; -use sc_block_builder::BlockBuilderApi; +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; use sp_api::{ProvideRuntimeApi, ApiExt}; use futures::prelude::*; +use sp_blockchain::HeaderBackend; +use std::marker::PhantomData; /// Proposer factory. -pub struct ProposerFactory where A: TransactionPool { +pub struct ProposerFactory { /// The client instance. - pub client: Arc, + client: Arc, /// The transaction pool. - pub transaction_pool: Arc, + transaction_pool: Arc, + /// phantom member to pin the `Backend` type. + _phantom: PhantomData, +} + +impl ProposerFactory { + pub fn new(client: Arc, transaction_pool: Arc) -> Self { + ProposerFactory { + client, + transaction_pool, + _phantom: PhantomData, + } + } } -impl ProposerFactory, A> +impl ProposerFactory where A: TransactionPool + 'static, B: backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: - BlockBuilderApi + - ApiExt>, + C: BlockBuilderProvider + HeaderBackend + ProvideRuntimeApi + + Send + Sync + 'static, + C::Api: ApiExt> + + BlockBuilderApi, { pub fn init_with_now( &mut self, parent_header: &::Header, now: Box time::Instant + Send + Sync>, - ) -> Proposer, A> { + ) -> Proposer { let parent_hash = parent_header.hash(); let id = BlockId::hash(parent_hash); @@ -75,6 +86,7 @@ impl ProposerFactory, A> parent_number: *parent_header.number(), transaction_pool: self.transaction_pool.clone(), now, + _phantom: PhantomData, }), }; @@ -82,21 +94,19 @@ impl ProposerFactory, A> } } -impl sp_consensus::Environment for - ProposerFactory, A> +impl sp_consensus::Environment for + ProposerFactory where A: TransactionPool + 'static, B: backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: - BlockBuilderApi + - ApiExt>, + C: BlockBuilderProvider + HeaderBackend + ProvideRuntimeApi + + Send + Sync + 'static, + C::Api: ApiExt> + + BlockBuilderApi, { type CreateProposer = future::Ready>; - type Proposer = Proposer, A>; + type Proposer = Proposer; type Error = sp_blockchain::Error; fn init( @@ -108,32 +118,31 @@ impl sp_consensus::Environment for } /// The proposer logic. -pub struct Proposer { - inner: Arc>, +pub struct Proposer { + inner: Arc>, } /// Proposer inner, to wrap parameters under Arc. -struct ProposerInner { +struct ProposerInner { client: Arc, parent_hash: ::Hash, parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, transaction_pool: Arc, now: Box time::Instant + Send + Sync>, + _phantom: PhantomData, } -impl sp_consensus::Proposer for - Proposer, A> +impl sp_consensus::Proposer for + Proposer where A: TransactionPool + 'static, B: backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: - BlockBuilderApi + - ApiExt>, + C: BlockBuilderProvider + HeaderBackend + ProvideRuntimeApi + + Send + Sync + 'static, + C::Api: ApiExt> + + BlockBuilderApi, { type Transaction = backend::TransactionFor; type Proposal = tokio_executor::blocking::Blocking< @@ -157,16 +166,15 @@ impl sp_consensus::Proposer for } } -impl ProposerInner, A> where - A: TransactionPool, - B: sc_client_api::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, - Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: - BlockBuilderApi + - ApiExt>, +impl ProposerInner + where + A: TransactionPool, + B: backend::Backend + Send + Sync + 'static, + Block: BlockT, + C: BlockBuilderProvider + HeaderBackend + ProvideRuntimeApi + + Send + Sync + 'static, + C::Api: ApiExt> + + BlockBuilderApi, { fn propose_with( &self, @@ -315,10 +323,7 @@ mod tests { txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)]) ).unwrap(); - let mut proposer_factory = ProposerFactory { - client: client.clone(), - transaction_pool: txpool.clone(), - }; + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); let cell = Mutex::new(time::Instant::now()); let mut proposer = proposer_factory.init_with_now( @@ -359,10 +364,7 @@ mod tests { txpool.submit_at(&BlockId::number(0), vec![extrinsic(0)]), ).unwrap(); - let mut proposer_factory = ProposerFactory { - client: client.clone(), - transaction_pool: txpool.clone(), - }; + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); let mut proposer = proposer_factory.init_with_now( &client.header(&block_id).unwrap().unwrap(), diff --git a/client/basic-authorship/src/lib.rs b/client/basic-authorship/src/lib.rs index e9087c89e07ed..5ec0bc6f9a520 100644 --- a/client/basic-authorship/src/lib.rs +++ b/client/basic-authorship/src/lib.rs @@ -28,10 +28,7 @@ //! # let client = Arc::new(substrate_test_runtime_client::new()); //! # let txpool = Arc::new(BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0); //! // The first step is to create a `ProposerFactory`. -//! let mut proposer_factory = ProposerFactory { -//! client: client.clone(), -//! transaction_pool: txpool.clone(), -//! }; +//! let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); //! //! // From this factory, we create a `Proposer`. //! let proposer = proposer_factory.init( diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index a93ad137835ed..4c14f3716f210 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -63,6 +63,27 @@ impl>> Built } } +/// Block builder provider +pub trait BlockBuilderProvider + where + Block: BlockT, + B: backend::Backend, + Self: Sized, + RA: ProvideRuntimeApi, +{ + /// Create a new block, built on top of `parent`. + /// + /// When proof recording is enabled, all accessed trie nodes are saved. + /// These recorded trie nodes can be used by a third party to proof the + /// output of this block builder without having access to the full storage. + fn new_block_at>( + &self, + parent: &BlockId, + inherent_digests: DigestFor, + record_proof: R, + ) -> sp_blockchain::Result>; +} + /// Utility for building new (valid) blocks from a stream of extrinsics. pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { extrinsics: Vec, diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 4045e18b5c3fb..9331319d55eb6 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -23,7 +23,7 @@ use super::*; use authorship::claim_slot; use sp_consensus_babe::{AuthorityPair, SlotNumber}; -use sc_block_builder::BlockBuilder; +use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sp_consensus::{ NoNetwork as DummyOracle, Proposal, RecordProof, import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport}, diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index c4336485a14ac..18dc91ad34d62 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -244,10 +244,10 @@ mod tests { let select_chain = LongestChain::new(backend.clone()); let inherent_data_providers = InherentDataProviders::new(); let pool = Arc::new(BasicPool::new(Options::default(), api()).0); - let env = ProposerFactory { - transaction_pool: pool.clone(), - client: client.clone(), - }; + let env = ProposerFactory::new( + client.clone(), + pool.clone() + ); // this test checks that blocks are created as soon as transactions are imported into the pool. let (sender, receiver) = futures::channel::oneshot::channel(); let mut sender = Arc::new(Some(sender)); @@ -309,10 +309,10 @@ mod tests { let select_chain = LongestChain::new(backend.clone()); let inherent_data_providers = InherentDataProviders::new(); let pool = Arc::new(BasicPool::new(Options::default(), api()).0); - let env = ProposerFactory { - transaction_pool: pool.clone(), - client: client.clone(), - }; + let env = ProposerFactory::new( + client.clone(), + pool.clone() + ); // this test checks that blocks are created as soon as an engine command is sent over the stream. let (mut sink, stream) = futures::channel::mpsc::channel(1024); let future = run_manual_seal( @@ -378,10 +378,10 @@ mod tests { let inherent_data_providers = InherentDataProviders::new(); let pool_api = api(); let pool = Arc::new(BasicPool::new(Options::default(), pool_api.clone()).0); - let env = ProposerFactory { - transaction_pool: pool.clone(), - client: client.clone(), - }; + let env = ProposerFactory::new( + client.clone(), + pool.clone(), + ); // this test checks that blocks are created as soon as an engine command is sent over the stream. let (mut sink, stream) = futures::channel::mpsc::channel(1024); let future = run_manual_seal( diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index f8774ea2836a6..773cbc23170bd 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -35,6 +35,7 @@ sc-network = { version = "0.8.0-alpha.2", path = "../network" } sc-network-gossip = { version = "0.8.0-alpha.2", path = "../network-gossip" } sp-finality-tracker = { version = "2.0.0-alpha.2", path = "../../primitives/finality-tracker" } sp-finality-grandpa = { version = "2.0.0-alpha.2", path = "../../primitives/finality-grandpa" } +sc-block-builder = { version = "0.8.0-alpha.2", path = "../block-builder" } finality-grandpa = { version = "0.11.1", features = ["derive-codec"] } pin-project = "0.4.6" diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 23c7ec9ba8777..6b9ab5e1f2fa4 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -55,6 +55,7 @@ use finality_proof::{ FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker, }; use consensus_changes::ConsensusChanges; +use sc_block_builder::BlockBuilderProvider; type PeerData = Mutex< diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index d09897e853ec2..8dc8aff14d461 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -35,7 +35,7 @@ use sc_client_api::{ FinalityNotification, backend::{TransactionFor, AuxStore, Backend, Finalizer}, }; -use sc_block_builder::BlockBuilder; +use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sc_client::LongestChain; use sc_network::config::Roles; use sp_consensus::block_validation::DefaultBlockAnnounceValidator; diff --git a/client/src/client.rs b/client/src/client.rs index babbaaf7ef74d..d461a17ded75f 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -60,7 +60,7 @@ use sp_api::{ CallApiAt, ConstructRuntimeApi, Core as CoreApi, ApiExt, ApiRef, ProvideRuntimeApi, CallApiAtParams, }; -use sc_block_builder::BlockBuilderApi; +use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider}; pub use sc_client_api::{ backend::{ @@ -863,33 +863,6 @@ impl Client where ) } - /// Create a new block, built on top of `parent`. - /// - /// When proof recording is enabled, all accessed trie nodes are saved. - /// These recorded trie nodes can be used by a third party to proof the - /// output of this block builder without having access to the full storage. - pub fn new_block_at>( - &self, - parent: &BlockId, - inherent_digests: DigestFor, - record_proof: R, - ) -> sp_blockchain::Result> where - E: Clone + Send + Sync, - RA: Send + Sync, - Self: ProvideRuntimeApi, - >::Api: BlockBuilderApi + - ApiExt> - { - sc_block_builder::BlockBuilder::new( - self, - self.expect_block_hash_from_id(parent)?, - self.expect_block_number_from_id(parent)?, - record_proof.into(), - inherent_digests, - &self.backend - ) - } - /// Apply a checked and validated block to an operation. If a justification is provided /// then `finalized` *must* be true. fn apply_block( @@ -1421,6 +1394,32 @@ impl Client where } } +impl BlockBuilderProvider for Client + where + B: backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static, + Block: BlockT, + Self: ChainHeaderBackend + ProvideRuntimeApi, + >::Api: ApiExt> + + BlockBuilderApi, +{ + fn new_block_at>( + &self, + parent: &BlockId, + inherent_digests: DigestFor, + record_proof: R, + ) -> sp_blockchain::Result> { + sc_block_builder::BlockBuilder::new( + self, + self.expect_block_hash_from_id(parent)?, + self.expect_block_number_from_id(parent)?, + record_proof.into(), + inherent_digests, + &self.backend + ) + } +} + impl HeaderMetadata for Client where B: backend::Backend, E: CallExecutor, diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index 7b018199a5593..dc1600b334e50 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -15,6 +15,7 @@ sp-version = { version = "2.0.0-alpha.2", path = "../../version" } sp-runtime = { version = "2.0.0-alpha.2", path = "../../runtime" } sp-blockchain = { version = "2.0.0-alpha.2", path = "../../blockchain" } sp-consensus = { version = "0.8.0-alpha.2", path = "../../../primitives/consensus/common" } +sc-block-builder = { version = "0.8.0-alpha.2", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "1.0.0" } sp-state-machine = { version = "0.8.0-alpha.2", path = "../../../primitives/state-machine" } trybuild = "1.0.17" diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 66412edae026d..6a3af7469cc0e 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -28,6 +28,7 @@ use sp_state_machine::{ use sp_consensus::SelectChain; use codec::Encode; +use sc_block_builder::BlockBuilderProvider; fn calling_function_with_strat(strat: ExecutionStrategy) { let client = TestClientBuilder::new().set_execution_strategy(strat).build(); diff --git a/test-utils/runtime/client/src/trait_tests.rs b/test-utils/runtime/client/src/trait_tests.rs index 05db43298fd49..5ceab4355d897 100644 --- a/test-utils/runtime/client/src/trait_tests.rs +++ b/test-utils/runtime/client/src/trait_tests.rs @@ -30,6 +30,7 @@ use substrate_test_client::sp_consensus::BlockOrigin; use substrate_test_runtime::{self, Transfer}; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, HasherFor}; +use sc_block_builder::BlockBuilderProvider; /// helper to test the `leaves` implementation for various backends pub fn test_leaves_for_backend(backend: Arc) where