mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
sc-consensus-manual-seal uses Finalizer trait for finalization instead of Backend. (#5469)
* manual-seal uses Finalizer trait for finalization instead of Backend * fix tests * use Transaction type * refactor import_queue * ugh * line-width * Update client/consensus/manual-seal/src/lib.rs Co-Authored-By: Joshy Orndorff <JoshOrndorff@users.noreply.github.com> * fix tests * update docs * Update client/consensus/manual-seal/src/seal_new_block.rs Co-Authored-By: André Silva <123550+andresilva@users.noreply.github.com> * Don't auto-finalize on verification * Explicity don't finalize on import. Co-authored-by: Joshy Orndorff <JoshOrndorff@users.noreply.github.com> Co-authored-by: Joshy Orndorff <admin@joshyorndorff.com> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
@@ -17,66 +17,32 @@
|
||||
//! A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks.
|
||||
//! This is suitable for a testing environment.
|
||||
|
||||
use futures::prelude::*;
|
||||
use sp_consensus::{
|
||||
self, BlockImport, Environment, Proposer, BlockCheckParams,
|
||||
ForkChoiceStrategy, BlockImportParams, BlockOrigin,
|
||||
ImportResult, SelectChain,
|
||||
import_queue::{
|
||||
BasicQueue,
|
||||
CacheKeyId,
|
||||
Verifier,
|
||||
BoxBlockImport,
|
||||
},
|
||||
Environment, Proposer, ForkChoiceStrategy, BlockImportParams, BlockOrigin, SelectChain,
|
||||
import_queue::{BasicQueue, CacheKeyId, Verifier, BoxBlockImport},
|
||||
};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_inherents::InherentDataProviders;
|
||||
use sp_runtime::{traits::Block as BlockT, Justification};
|
||||
use sc_client_api::backend::Backend as ClientBackend;
|
||||
use futures::prelude::*;
|
||||
use sc_client_api::backend::{Backend as ClientBackend, Finalizer};
|
||||
use sc_transaction_pool::txpool;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::{sync::Arc, marker::PhantomData};
|
||||
|
||||
pub mod rpc;
|
||||
mod error;
|
||||
mod finalize_block;
|
||||
mod seal_new_block;
|
||||
use finalize_block::{finalize_block, FinalizeBlockParams};
|
||||
use seal_new_block::{seal_new_block, SealBlockParams};
|
||||
pub use error::Error;
|
||||
pub use rpc::{EngineCommand, CreatedBlock};
|
||||
pub mod rpc;
|
||||
|
||||
/// The synchronous block-import worker of the engine.
|
||||
pub struct ManualSealBlockImport<I> {
|
||||
inner: I,
|
||||
}
|
||||
|
||||
impl<I> From<I> for ManualSealBlockImport<I> {
|
||||
fn from(i: I) -> Self {
|
||||
ManualSealBlockImport { inner: i }
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, I> BlockImport<B> for ManualSealBlockImport<I>
|
||||
where
|
||||
B: BlockT,
|
||||
I: BlockImport<B, Transaction = ()>,
|
||||
{
|
||||
type Error = I::Error;
|
||||
type Transaction = ();
|
||||
|
||||
fn check_block(&mut self, block: BlockCheckParams<B>) -> Result<ImportResult, Self::Error>
|
||||
{
|
||||
self.inner.check_block(block)
|
||||
}
|
||||
|
||||
fn import_block(
|
||||
&mut self,
|
||||
block: BlockImportParams<B, Self::Transaction>,
|
||||
cache: HashMap<CacheKeyId, Vec<u8>>,
|
||||
) -> Result<ImportResult, Self::Error> {
|
||||
self.inner.import_block(block, cache)
|
||||
}
|
||||
}
|
||||
use self::{
|
||||
finalize_block::{finalize_block, FinalizeBlockParams},
|
||||
seal_new_block::{seal_new_block, SealBlockParams},
|
||||
};
|
||||
pub use self::{
|
||||
error::Error,
|
||||
rpc::{EngineCommand, CreatedBlock},
|
||||
};
|
||||
use sc_client_api::{TransactionFor, Backend};
|
||||
|
||||
/// The verifier for the manual seal engine; instantly finalizes.
|
||||
struct ManualSealVerifier;
|
||||
@@ -92,7 +58,7 @@ impl<B: BlockT> Verifier<B> for ManualSealVerifier {
|
||||
let mut import_params = BlockImportParams::new(origin, header);
|
||||
import_params.justification = justification;
|
||||
import_params.body = body;
|
||||
import_params.finalized = true;
|
||||
import_params.finalized = false;
|
||||
import_params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
|
||||
|
||||
Ok((import_params, None))
|
||||
@@ -100,37 +66,43 @@ impl<B: BlockT> Verifier<B> for ManualSealVerifier {
|
||||
}
|
||||
|
||||
/// Instantiate the import queue for the manual seal consensus engine.
|
||||
pub fn import_queue<B: BlockT>(block_import: BoxBlockImport<B, ()>) -> BasicQueue<B, ()>
|
||||
pub fn import_queue<Block, B>(
|
||||
block_import: BoxBlockImport<Block, TransactionFor<B, Block>>
|
||||
) -> BasicQueue<Block, TransactionFor<B, Block>>
|
||||
where
|
||||
Block: BlockT,
|
||||
B: Backend<Block> + 'static,
|
||||
{
|
||||
BasicQueue::new(
|
||||
ManualSealVerifier,
|
||||
block_import,
|
||||
Box::new(block_import),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates the background authorship task for the manual seal engine.
|
||||
pub async fn run_manual_seal<B, CB, E, A, C, S, T>(
|
||||
pub async fn run_manual_seal<B, CB, E, C, A, SC, S, T>(
|
||||
mut block_import: BoxBlockImport<B, T>,
|
||||
mut env: E,
|
||||
backend: Arc<CB>,
|
||||
client: Arc<C>,
|
||||
pool: Arc<txpool::Pool<A>>,
|
||||
mut seal_block_channel: S,
|
||||
select_chain: C,
|
||||
mut commands_stream: S,
|
||||
select_chain: SC,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
)
|
||||
where
|
||||
A: txpool::ChainApi<Block=B, Hash=<B as BlockT>::Hash> + 'static,
|
||||
B: BlockT + 'static,
|
||||
C: HeaderBackend<B> + Finalizer<B, CB> + 'static,
|
||||
CB: ClientBackend<B> + 'static,
|
||||
E: Environment<B> + 'static,
|
||||
E::Error: std::fmt::Display,
|
||||
<E::Proposer as Proposer<B>>::Error: std::fmt::Display,
|
||||
A: txpool::ChainApi<Block=B, Hash=<B as BlockT>::Hash> + 'static,
|
||||
S: Stream<Item=EngineCommand<<B as BlockT>::Hash>> + Unpin + 'static,
|
||||
C: SelectChain<B> + 'static,
|
||||
SC: SelectChain<B> + 'static,
|
||||
{
|
||||
while let Some(command) = seal_block_channel.next().await {
|
||||
while let Some(command) = commands_stream.next().await {
|
||||
match command {
|
||||
EngineCommand::SealNewBlock {
|
||||
create_empty,
|
||||
@@ -149,7 +121,7 @@ pub async fn run_manual_seal<B, CB, E, A, C, S, T>(
|
||||
block_import: &mut block_import,
|
||||
inherent_data_provider: &inherent_data_providers,
|
||||
pool: pool.clone(),
|
||||
backend: backend.clone(),
|
||||
client: client.clone(),
|
||||
}
|
||||
).await;
|
||||
}
|
||||
@@ -159,7 +131,8 @@ pub async fn run_manual_seal<B, CB, E, A, C, S, T>(
|
||||
hash,
|
||||
sender,
|
||||
justification,
|
||||
backend: backend.clone(),
|
||||
finalizer: client.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
).await
|
||||
}
|
||||
@@ -170,26 +143,28 @@ pub async fn run_manual_seal<B, CB, E, A, C, S, T>(
|
||||
/// runs the background authorship task for the instant seal engine.
|
||||
/// instant-seal creates a new block for every transaction imported into
|
||||
/// the transaction pool.
|
||||
pub async fn run_instant_seal<B, CB, E, A, C, T>(
|
||||
pub async fn run_instant_seal<B, CB, E, C, A, SC, T>(
|
||||
block_import: BoxBlockImport<B, T>,
|
||||
env: E,
|
||||
backend: Arc<CB>,
|
||||
client: Arc<C>,
|
||||
pool: Arc<txpool::Pool<A>>,
|
||||
select_chain: C,
|
||||
select_chain: SC,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
)
|
||||
where
|
||||
A: txpool::ChainApi<Block=B, Hash=<B as BlockT>::Hash> + 'static,
|
||||
B: BlockT + 'static,
|
||||
C: HeaderBackend<B> + Finalizer<B, CB> + 'static,
|
||||
CB: ClientBackend<B> + 'static,
|
||||
E: Environment<B> + 'static,
|
||||
E::Error: std::fmt::Display,
|
||||
<E::Proposer as Proposer<B>>::Error: std::fmt::Display,
|
||||
C: SelectChain<B> + 'static
|
||||
SC: SelectChain<B> + 'static
|
||||
{
|
||||
// instant-seal creates blocks as soon as transactions are imported
|
||||
// into the transaction pool.
|
||||
let seal_block_channel = pool.validated_pool().import_notification_stream()
|
||||
let commands_stream = pool.validated_pool()
|
||||
.import_notification_stream()
|
||||
.map(|_| {
|
||||
EngineCommand::SealNewBlock {
|
||||
create_empty: false,
|
||||
@@ -202,9 +177,9 @@ pub async fn run_instant_seal<B, CB, E, A, C, T>(
|
||||
run_manual_seal(
|
||||
block_import,
|
||||
env,
|
||||
backend,
|
||||
client,
|
||||
pool,
|
||||
seal_block_channel,
|
||||
commands_stream,
|
||||
select_chain,
|
||||
inherent_data_providers,
|
||||
).await
|
||||
@@ -226,9 +201,7 @@ mod tests {
|
||||
use substrate_test_runtime_transaction_pool::{TestApi, uxt};
|
||||
use sp_transaction_pool::{TransactionPool, MaintainedTransactionPool, TransactionSource};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_consensus::ImportedAux;
|
||||
use sc_client::LongestChain;
|
||||
use sp_inherents::InherentDataProviders;
|
||||
use sc_basic_authorship::ProposerFactory;
|
||||
|
||||
@@ -241,9 +214,8 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn instant_seal() {
|
||||
let builder = TestClientBuilder::new();
|
||||
let backend = builder.backend();
|
||||
let client = Arc::new(builder.build());
|
||||
let select_chain = LongestChain::new(backend.clone());
|
||||
let (client, select_chain) = builder.build_with_longest_chain();
|
||||
let client = Arc::new(client);
|
||||
let inherent_data_providers = InherentDataProviders::new();
|
||||
let pool = Arc::new(BasicPool::new(Options::default(), api()).0);
|
||||
let env = ProposerFactory::new(
|
||||
@@ -268,7 +240,7 @@ mod tests {
|
||||
let future = run_manual_seal(
|
||||
Box::new(client.clone()),
|
||||
env,
|
||||
backend.clone(),
|
||||
client.clone(),
|
||||
pool.pool().clone(),
|
||||
stream,
|
||||
select_chain,
|
||||
@@ -300,15 +272,14 @@ mod tests {
|
||||
}
|
||||
);
|
||||
// assert that there's a new block in the db.
|
||||
assert!(backend.blockchain().header(BlockId::Number(1)).unwrap().is_some())
|
||||
assert!(client.header(&BlockId::Number(1)).unwrap().is_some())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn manual_seal_and_finalization() {
|
||||
let builder = TestClientBuilder::new();
|
||||
let backend = builder.backend();
|
||||
let client = Arc::new(builder.build());
|
||||
let select_chain = LongestChain::new(backend.clone());
|
||||
let (client, select_chain) = builder.build_with_longest_chain();
|
||||
let client = Arc::new(client);
|
||||
let inherent_data_providers = InherentDataProviders::new();
|
||||
let pool = Arc::new(BasicPool::new(Options::default(), api()).0);
|
||||
let env = ProposerFactory::new(
|
||||
@@ -320,7 +291,7 @@ mod tests {
|
||||
let future = run_manual_seal(
|
||||
Box::new(client.clone()),
|
||||
env,
|
||||
backend.clone(),
|
||||
client.clone(),
|
||||
pool.pool().clone(),
|
||||
stream,
|
||||
select_chain,
|
||||
@@ -360,7 +331,7 @@ mod tests {
|
||||
}
|
||||
);
|
||||
// assert that there's a new block in the db.
|
||||
let header = backend.blockchain().header(BlockId::Number(1)).unwrap().unwrap();
|
||||
let header = client.header(&BlockId::Number(1)).unwrap().unwrap();
|
||||
let (tx, rx) = futures::channel::oneshot::channel();
|
||||
sink.send(EngineCommand::FinalizeBlock {
|
||||
sender: Some(tx),
|
||||
@@ -374,9 +345,8 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn manual_seal_fork_blocks() {
|
||||
let builder = TestClientBuilder::new();
|
||||
let backend = builder.backend();
|
||||
let client = Arc::new(builder.build());
|
||||
let select_chain = LongestChain::new(backend.clone());
|
||||
let (client, select_chain) = builder.build_with_longest_chain();
|
||||
let client = Arc::new(client);
|
||||
let inherent_data_providers = InherentDataProviders::new();
|
||||
let pool_api = api();
|
||||
let pool = Arc::new(BasicPool::new(Options::default(), pool_api.clone()).0);
|
||||
@@ -389,7 +359,7 @@ mod tests {
|
||||
let future = run_manual_seal(
|
||||
Box::new(client.clone()),
|
||||
env,
|
||||
backend.clone(),
|
||||
client.clone(),
|
||||
pool.pool().clone(),
|
||||
stream,
|
||||
select_chain,
|
||||
@@ -431,12 +401,12 @@ mod tests {
|
||||
}
|
||||
);
|
||||
// assert that there's a new block in the db.
|
||||
assert!(backend.blockchain().header(BlockId::Number(0)).unwrap().is_some());
|
||||
assert!(client.header(&BlockId::Number(0)).unwrap().is_some());
|
||||
assert!(pool.submit_one(&BlockId::Number(1), SOURCE, uxt(Alice, 1)).await.is_ok());
|
||||
|
||||
pool.maintain(sp_transaction_pool::ChainEvent::NewBlock {
|
||||
id: BlockId::Number(1),
|
||||
header: backend.blockchain().header(BlockId::Number(1)).expect("db error").expect("imported above"),
|
||||
header: client.header(&BlockId::Number(1)).expect("db error").expect("imported above"),
|
||||
is_new_best: true,
|
||||
retracted: vec![],
|
||||
}).await;
|
||||
@@ -452,7 +422,7 @@ mod tests {
|
||||
rx1.await.expect("should be no error receiving"),
|
||||
Ok(_)
|
||||
);
|
||||
assert!(backend.blockchain().header(BlockId::Number(1)).unwrap().is_some());
|
||||
assert!(client.header(&BlockId::Number(1)).unwrap().is_some());
|
||||
pool_api.increment_nonce(Alice.into());
|
||||
|
||||
assert!(pool.submit_one(&BlockId::Number(2), SOURCE, uxt(Alice, 2)).await.is_ok());
|
||||
@@ -465,6 +435,6 @@ mod tests {
|
||||
}).await.is_ok());
|
||||
let imported = rx2.await.unwrap().unwrap();
|
||||
// assert that fork block is in the db
|
||||
assert!(backend.blockchain().header(BlockId::Hash(imported.hash)).unwrap().is_some())
|
||||
assert!(client.header(&BlockId::Hash(imported.hash)).unwrap().is_some())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user