mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 03:31:10 +00:00
Allow for customisation of chain selection systems (#2240)
* move SelectChain trait out of client * Extend SelectChain, move longest chain implementation into it * Bring SelectChain into service * implement LongestChain SelectChain * implement longest chain for node * update Cargo.lock's * in between erroring tests * deprecate ::backend and ::import_lock * Remove unneded space Co-Authored-By: gnunicorn <ben.kampmann@googlemail.com> * Remove unneded space Co-Authored-By: gnunicorn <ben.kampmann@googlemail.com> * Fixes test compilation * remove todo * re-enable client test * add doc * fixing tests * Clarify SelectChain Interface, intended implementation and usage * minor components cleanups * minor cleanups * Update lock files * Implement cleaner interface for SelectChain * addressing comments * Updating tests * bump node runtime impl version * address grumbles
This commit is contained in:
committed by
Gavin Wood
parent
32fdeed21c
commit
18ca0170c3
@@ -127,7 +127,8 @@ pub fn import_blocks<F, E, R>(
|
||||
{
|
||||
let client = new_client::<F>(&config)?;
|
||||
// FIXME #1134 this shouldn't need a mutable config.
|
||||
let queue = components::FullComponents::<F>::build_import_queue(&mut config, client.clone())?;
|
||||
let select_chain = components::FullComponents::<F>::build_select_chain(&mut config, client.clone())?;
|
||||
let queue = components::FullComponents::<F>::build_import_queue(&mut config, client.clone(), select_chain)?;
|
||||
|
||||
let (wait_send, wait_recv) = std::sync::mpsc::channel();
|
||||
let wait_link = WaitLink::new(wait_send);
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
//! Substrate service components.
|
||||
|
||||
use std::{sync::Arc, net::SocketAddr, marker::PhantomData, ops::Deref, ops::DerefMut};
|
||||
use std::{sync::Arc, net::SocketAddr, ops::Deref, ops::DerefMut};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use tokio::runtime::TaskExecutor;
|
||||
use crate::chain_spec::ChainSpec;
|
||||
use client_db;
|
||||
use client::{self, Client, runtime_api};
|
||||
use crate::{error, Service, maybe_start_server};
|
||||
use consensus_common::import_queue::ImportQueue;
|
||||
use consensus_common::{import_queue::ImportQueue, SelectChain};
|
||||
use network::{self, OnDemand};
|
||||
use substrate_executor::{NativeExecutor, NativeExecutionDispatch};
|
||||
use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool};
|
||||
@@ -304,9 +304,11 @@ pub trait ServiceFactory: 'static + Sized {
|
||||
/// Extended light service type.
|
||||
type LightService: ServiceTrait<LightComponents<Self>>;
|
||||
/// ImportQueue for full client
|
||||
type FullImportQueue: consensus_common::import_queue::ImportQueue<Self::Block> + 'static;
|
||||
type FullImportQueue: ImportQueue<Self::Block> + 'static;
|
||||
/// ImportQueue for light clients
|
||||
type LightImportQueue: consensus_common::import_queue::ImportQueue<Self::Block> + 'static;
|
||||
type LightImportQueue: ImportQueue<Self::Block> + 'static;
|
||||
/// The Fork Choice Strategy for the chain
|
||||
type SelectChain: SelectChain<Self::Block> + 'static;
|
||||
|
||||
//TODO: replace these with a constructor trait. that TransactionPool implements. (#1242)
|
||||
/// Extrinsic pool constructor for the full client.
|
||||
@@ -320,6 +322,12 @@ pub trait ServiceFactory: 'static + Sized {
|
||||
fn build_network_protocol(config: &FactoryFullConfiguration<Self>)
|
||||
-> Result<Self::NetworkProtocol, error::Error>;
|
||||
|
||||
/// Build the Fork Choice algorithm for full client
|
||||
fn build_select_chain(
|
||||
config: &mut FactoryFullConfiguration<Self>,
|
||||
client: Arc<FullClient<Self>>,
|
||||
) -> Result<Self::SelectChain, error::Error>;
|
||||
|
||||
/// Build full service.
|
||||
fn new_full(config: FactoryFullConfiguration<Self>, executor: TaskExecutor)
|
||||
-> Result<Self::FullService, error::Error>;
|
||||
@@ -330,7 +338,8 @@ pub trait ServiceFactory: 'static + Sized {
|
||||
/// ImportQueue for a full client
|
||||
fn build_full_import_queue(
|
||||
config: &mut FactoryFullConfiguration<Self>,
|
||||
_client: Arc<FullClient<Self>>
|
||||
_client: Arc<FullClient<Self>>,
|
||||
_select_chain: Self::SelectChain
|
||||
) -> Result<Self::FullImportQueue, error::Error> {
|
||||
if let Some(name) = config.chain_spec.consensus_engine() {
|
||||
match name {
|
||||
@@ -378,6 +387,8 @@ pub trait Components: Sized + 'static {
|
||||
>;
|
||||
/// Our Import Queue
|
||||
type ImportQueue: ImportQueue<FactoryBlock<Self::Factory>> + 'static;
|
||||
/// The Fork Choice Strategy for the chain
|
||||
type SelectChain: SelectChain<FactoryBlock<Self::Factory>>;
|
||||
|
||||
/// Create client.
|
||||
fn build_client(
|
||||
@@ -398,13 +409,20 @@ pub trait Components: Sized + 'static {
|
||||
/// instance of import queue for clients
|
||||
fn build_import_queue(
|
||||
config: &mut FactoryFullConfiguration<Self::Factory>,
|
||||
client: Arc<ComponentClient<Self>>
|
||||
client: Arc<ComponentClient<Self>>,
|
||||
select_chain: Self::SelectChain,
|
||||
) -> Result<Self::ImportQueue, error::Error>;
|
||||
|
||||
/// Build fork choice selector
|
||||
fn build_select_chain(
|
||||
config: &mut FactoryFullConfiguration<Self::Factory>,
|
||||
client: Arc<ComponentClient<Self>>
|
||||
) -> Result<Self::SelectChain, error::Error>;
|
||||
|
||||
}
|
||||
|
||||
/// A struct that implement `Components` for the full client.
|
||||
pub struct FullComponents<Factory: ServiceFactory> {
|
||||
_factory: PhantomData<Factory>,
|
||||
service: Service<FullComponents<Factory>>,
|
||||
}
|
||||
|
||||
@@ -416,7 +434,6 @@ impl<Factory: ServiceFactory> FullComponents<Factory> {
|
||||
) -> Result<Self, error::Error> {
|
||||
Ok(
|
||||
Self {
|
||||
_factory: Default::default(),
|
||||
service: Service::new(config, task_executor)?,
|
||||
}
|
||||
)
|
||||
@@ -445,6 +462,7 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
|
||||
type ImportQueue = Factory::FullImportQueue;
|
||||
type RuntimeApi = Factory::RuntimeApi;
|
||||
type RuntimeServices = Factory::FullService;
|
||||
type SelectChain = Factory::SelectChain;
|
||||
|
||||
fn build_client(
|
||||
config: &FactoryFullConfiguration<Factory>,
|
||||
@@ -469,23 +487,32 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
|
||||
)?), None))
|
||||
}
|
||||
|
||||
fn build_transaction_pool(config: TransactionPoolOptions, client: Arc<ComponentClient<Self>>)
|
||||
-> Result<TransactionPool<Self::TransactionPoolApi>, error::Error>
|
||||
{
|
||||
fn build_transaction_pool(
|
||||
config: TransactionPoolOptions,
|
||||
client: Arc<ComponentClient<Self>>
|
||||
) -> Result<TransactionPool<Self::TransactionPoolApi>, error::Error> {
|
||||
Factory::build_full_transaction_pool(config, client)
|
||||
}
|
||||
|
||||
fn build_import_queue(
|
||||
config: &mut FactoryFullConfiguration<Self::Factory>,
|
||||
client: Arc<ComponentClient<Self>>
|
||||
client: Arc<ComponentClient<Self>>,
|
||||
select_chain: Self::SelectChain,
|
||||
) -> Result<Self::ImportQueue, error::Error> {
|
||||
Factory::build_full_import_queue(config, client)
|
||||
Factory::build_full_import_queue(config, client, select_chain)
|
||||
}
|
||||
|
||||
fn build_select_chain(
|
||||
config: &mut FactoryFullConfiguration<Self::Factory>,
|
||||
client: Arc<ComponentClient<Self>>
|
||||
) -> Result<Self::SelectChain, error::Error> {
|
||||
Self::Factory::build_select_chain(config, client)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// A struct that implement `Components` for the light client.
|
||||
pub struct LightComponents<Factory: ServiceFactory> {
|
||||
_factory: PhantomData<Factory>,
|
||||
service: Service<LightComponents<Factory>>,
|
||||
}
|
||||
|
||||
@@ -497,7 +524,6 @@ impl<Factory: ServiceFactory> LightComponents<Factory> {
|
||||
) -> Result<Self, error::Error> {
|
||||
Ok(
|
||||
Self {
|
||||
_factory: Default::default(),
|
||||
service: Service::new(config, task_executor)?,
|
||||
}
|
||||
)
|
||||
@@ -520,6 +546,7 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
|
||||
type ImportQueue = <Factory as ServiceFactory>::LightImportQueue;
|
||||
type RuntimeApi = Factory::RuntimeApi;
|
||||
type RuntimeServices = Factory::LightService;
|
||||
type SelectChain = Factory::SelectChain;
|
||||
|
||||
fn build_client(
|
||||
config: &FactoryFullConfiguration<Factory>,
|
||||
@@ -554,16 +581,27 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
|
||||
|
||||
fn build_import_queue(
|
||||
config: &mut FactoryFullConfiguration<Self::Factory>,
|
||||
client: Arc<ComponentClient<Self>>
|
||||
client: Arc<ComponentClient<Self>>,
|
||||
_select_chain: Self::SelectChain,
|
||||
) -> Result<Self::ImportQueue, error::Error> {
|
||||
Factory::build_light_import_queue(config, client)
|
||||
}
|
||||
|
||||
/// Build fork choice selector
|
||||
fn build_select_chain(
|
||||
_config: &mut FactoryFullConfiguration<Self::Factory>,
|
||||
_client: Arc<ComponentClient<Self>>
|
||||
) -> Result<Self::SelectChain, error::Error> {
|
||||
Err("Fork choice doesn't happen on light clients.".into())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use consensus_common::BlockOrigin;
|
||||
use client::LongestChain;
|
||||
use substrate_test_client::{self, TestClient, AccountKeyring, runtime::Transfer};
|
||||
|
||||
#[test]
|
||||
@@ -576,8 +614,11 @@ mod tests {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: Default::default(),
|
||||
}.into_signed_tx();
|
||||
let best = LongestChain::new(client.backend().clone(), client.import_lock())
|
||||
.best_chain().unwrap();
|
||||
|
||||
// store the transaction in the pool
|
||||
pool.submit_one(&BlockId::hash(client.best_block_header().unwrap().hash()), transaction.clone()).unwrap();
|
||||
pool.submit_one(&BlockId::hash(best.hash()), transaction.clone()).unwrap();
|
||||
|
||||
// import the block
|
||||
let mut builder = client.new_block().unwrap();
|
||||
|
||||
@@ -42,6 +42,7 @@ use primitives::Pair;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{Header, As};
|
||||
use substrate_executor::NativeExecutor;
|
||||
use consensus_common::SelectChain;
|
||||
use tel::{telemetry, SUBSTRATE_INFO};
|
||||
|
||||
pub use self::error::{ErrorKind, Error};
|
||||
@@ -73,6 +74,7 @@ const DEFAULT_PROTOCOL_ID: &str = "sup";
|
||||
/// Substrate service.
|
||||
pub struct Service<Components: components::Components> {
|
||||
client: Arc<ComponentClient<Components>>,
|
||||
select_chain: <Components as components::Components>::SelectChain,
|
||||
network: Option<Arc<components::NetworkService<Components::Factory>>>,
|
||||
transaction_pool: Arc<TransactionPool<Components::TransactionPoolApi>>,
|
||||
inherents_pool: Arc<InherentsPool<ComponentExtrinsic<Components>>>,
|
||||
@@ -150,8 +152,13 @@ impl<Components: components::Components> Service<Components> {
|
||||
};
|
||||
|
||||
let (client, on_demand) = Components::build_client(&config, executor)?;
|
||||
let import_queue = Box::new(Components::build_import_queue(&mut config, client.clone())?);
|
||||
let best_header = client.best_block_header()?;
|
||||
let select_chain = Components::build_select_chain(&mut config, client.clone())?;
|
||||
let import_queue = Box::new(Components::build_import_queue(
|
||||
&mut config,
|
||||
client.clone(),
|
||||
select_chain.clone()
|
||||
)?);
|
||||
let best_header = select_chain.best_chain()?;
|
||||
|
||||
let version = config.full_version();
|
||||
info!("Best block: #{}", best_header.number());
|
||||
@@ -357,6 +364,7 @@ impl<Components: components::Components> Service<Components> {
|
||||
Ok(Service {
|
||||
client,
|
||||
network: Some(network),
|
||||
select_chain,
|
||||
transaction_pool,
|
||||
inherents_pool,
|
||||
signal: Some(signal),
|
||||
@@ -395,6 +403,11 @@ impl<Components> Service<Components> where Components: components::Components {
|
||||
self.client.clone()
|
||||
}
|
||||
|
||||
/// Get clone of select chain.
|
||||
pub fn select_chain(&self) -> <Components as components::Components>::SelectChain {
|
||||
self.select_chain.clone()
|
||||
}
|
||||
|
||||
/// Get shared network instance.
|
||||
pub fn network(&self) -> Arc<components::NetworkService<Components::Factory>> {
|
||||
self.network.as_ref().expect("self.network always Some").clone()
|
||||
@@ -578,6 +591,8 @@ macro_rules! construct_service_factory {
|
||||
{ $( $full_import_queue_init:tt )* },
|
||||
LightImportQueue = $light_import_queue:ty
|
||||
{ $( $light_import_queue_init:tt )* },
|
||||
SelectChain = $select_chain:ty
|
||||
{ $( $select_chain_init:tt )* },
|
||||
}
|
||||
) => {
|
||||
$( #[$attr] )*
|
||||
@@ -597,6 +612,7 @@ macro_rules! construct_service_factory {
|
||||
type LightService = $light_service;
|
||||
type FullImportQueue = $full_import_queue;
|
||||
type LightImportQueue = $light_import_queue;
|
||||
type SelectChain = $select_chain;
|
||||
|
||||
fn build_full_transaction_pool(
|
||||
config: $crate::TransactionPoolOptions,
|
||||
@@ -620,11 +636,19 @@ macro_rules! construct_service_factory {
|
||||
( $( $protocol_init )* ) (config)
|
||||
}
|
||||
|
||||
fn build_select_chain(
|
||||
config: &mut $crate::FactoryFullConfiguration<Self>,
|
||||
client: Arc<$crate::FullClient<Self>>
|
||||
) -> $crate::Result<Self::SelectChain, $crate::Error> {
|
||||
( $( $select_chain_init )* ) (config, client)
|
||||
}
|
||||
|
||||
fn build_full_import_queue(
|
||||
config: &mut $crate::FactoryFullConfiguration<Self>,
|
||||
client: $crate::Arc<$crate::FullClient<Self>>,
|
||||
select_chain: Self::SelectChain
|
||||
) -> $crate::Result<Self::FullImportQueue, $crate::Error> {
|
||||
( $( $full_import_queue_init )* ) (config, client)
|
||||
( $( $full_import_queue_init )* ) (config, client, select_chain)
|
||||
}
|
||||
|
||||
fn build_light_import_queue(
|
||||
|
||||
Reference in New Issue
Block a user