mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 19:21:13 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -17,65 +17,52 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
error::Error, MallocSizeOfWasm, RpcHandlers,
|
||||
start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager, SpawnTaskHandle,
|
||||
metrics::MetricsService,
|
||||
build_network_future,
|
||||
client::{light, Client, ClientConfig},
|
||||
config::{Configuration, KeystoreConfig, PrometheusConfig, TransactionStorageMode},
|
||||
error::Error,
|
||||
metrics::MetricsService,
|
||||
start_rpc_servers, MallocSizeOfWasm, RpcHandlers, SpawnTaskHandle, TaskManager,
|
||||
TransactionPoolAdapter,
|
||||
};
|
||||
use sc_client_api::{
|
||||
light::RemoteBlockchain, ForkBlocks, BadBlocks, UsageProvider, ExecutorProvider,
|
||||
};
|
||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
|
||||
use futures::{channel::oneshot, future::ready, FutureExt, StreamExt};
|
||||
use jsonrpc_pubsub::manager::SubscriptionManager;
|
||||
use log::info;
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_chain_spec::get_extension;
|
||||
use sc_client_api::{
|
||||
execution_extensions::ExecutionExtensions, light::RemoteBlockchain,
|
||||
proof_provider::ProofProvider, BadBlocks, BlockBackend, BlockchainEvents, ExecutorProvider,
|
||||
ForkBlocks, StorageProvider, UsageProvider,
|
||||
};
|
||||
use sc_client_db::{Backend, DatabaseSettings};
|
||||
use sc_executor::{NativeExecutionDispatch, NativeExecutor, RuntimeInfo};
|
||||
use sc_keystore::LocalKeystore;
|
||||
use sc_network::{
|
||||
block_request_handler::{self, BlockRequestHandler},
|
||||
config::{OnDemand, Role, SyncMode},
|
||||
light_client_requests::{self, handler::LightClientRequestHandler},
|
||||
state_request_handler::{self, StateRequestHandler},
|
||||
NetworkService,
|
||||
};
|
||||
use sc_telemetry::{telemetry, ConnectionMessage, Telemetry, TelemetryHandle, SUBSTRATE_INFO};
|
||||
use sc_transaction_pool_api::MaintainedTransactionPool;
|
||||
use sp_api::{CallApiAt, ProvideRuntimeApi};
|
||||
use sp_blockchain::{HeaderBackend, HeaderMetadata};
|
||||
use sp_consensus::{
|
||||
block_validation::{BlockAnnounceValidator, DefaultBlockAnnounceValidator, Chain},
|
||||
block_validation::{BlockAnnounceValidator, Chain, DefaultBlockAnnounceValidator},
|
||||
import_queue::ImportQueue,
|
||||
};
|
||||
use jsonrpc_pubsub::manager::SubscriptionManager;
|
||||
use futures::{
|
||||
FutureExt, StreamExt,
|
||||
future::ready,
|
||||
channel::oneshot,
|
||||
};
|
||||
use sc_keystore::LocalKeystore;
|
||||
use log::info;
|
||||
use sc_network::config::{Role, OnDemand, SyncMode};
|
||||
use sc_network::NetworkService;
|
||||
use sc_network::block_request_handler::{self, BlockRequestHandler};
|
||||
use sc_network::state_request_handler::{self, StateRequestHandler};
|
||||
use sc_network::light_client_requests::{self, handler::LightClientRequestHandler};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_runtime::traits::{
|
||||
Block as BlockT, HashFor, Zero, BlockIdTo,
|
||||
};
|
||||
use sp_api::{ProvideRuntimeApi, CallApiAt};
|
||||
use sc_executor::{NativeExecutor, NativeExecutionDispatch, RuntimeInfo};
|
||||
use std::{sync::Arc, str::FromStr};
|
||||
use wasm_timer::SystemTime;
|
||||
use sc_telemetry::{
|
||||
telemetry,
|
||||
ConnectionMessage,
|
||||
Telemetry,
|
||||
TelemetryHandle,
|
||||
SUBSTRATE_INFO,
|
||||
};
|
||||
use sc_transaction_pool_api::MaintainedTransactionPool;
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_client_db::{Backend, DatabaseSettings};
|
||||
use sp_core::traits::{
|
||||
CodeExecutor,
|
||||
SpawnNamed,
|
||||
};
|
||||
use sp_core::traits::{CodeExecutor, SpawnNamed};
|
||||
use sp_keystore::{CryptoStore, SyncCryptoStore, SyncCryptoStorePtr};
|
||||
use sp_runtime::BuildStorage;
|
||||
use sc_client_api::{
|
||||
BlockBackend, BlockchainEvents,
|
||||
StorageProvider,
|
||||
proof_provider::ProofProvider,
|
||||
execution_extensions::ExecutionExtensions
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, BlockIdTo, HashFor, Zero},
|
||||
BuildStorage,
|
||||
};
|
||||
use sp_blockchain::{HeaderMetadata, HeaderBackend};
|
||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
|
||||
use std::{str::FromStr, sync::Arc};
|
||||
use wasm_timer::SystemTime;
|
||||
|
||||
/// A utility trait for building an RPC extension given a `DenyUnsafe` instance.
|
||||
/// This is useful since at service definition time we don't know whether the
|
||||
@@ -95,7 +82,8 @@ pub trait RpcExtensionBuilder {
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<F, R> RpcExtensionBuilder for F where
|
||||
impl<F, R> RpcExtensionBuilder for F
|
||||
where
|
||||
F: Fn(sc_rpc::DenyUnsafe, sc_rpc::SubscriptionTaskExecutor) -> R,
|
||||
R: sc_rpc::RpcExtension<sc_rpc::Metadata>,
|
||||
{
|
||||
@@ -115,7 +103,8 @@ impl<F, R> RpcExtensionBuilder for F where
|
||||
/// `DenyUnsafe` instance and return a static `RpcExtension` instance.
|
||||
pub struct NoopRpcExtensionBuilder<R>(pub R);
|
||||
|
||||
impl<R> RpcExtensionBuilder for NoopRpcExtensionBuilder<R> where
|
||||
impl<R> RpcExtensionBuilder for NoopRpcExtensionBuilder<R>
|
||||
where
|
||||
R: Clone + sc_rpc::RpcExtension<sc_rpc::Metadata>,
|
||||
{
|
||||
type Output = R;
|
||||
@@ -129,7 +118,8 @@ impl<R> RpcExtensionBuilder for NoopRpcExtensionBuilder<R> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<R> for NoopRpcExtensionBuilder<R> where
|
||||
impl<R> From<R> for NoopRpcExtensionBuilder<R>
|
||||
where
|
||||
R: sc_rpc::RpcExtension<sc_rpc::Metadata>,
|
||||
{
|
||||
fn from(e: R) -> NoopRpcExtensionBuilder<R> {
|
||||
@@ -137,58 +127,37 @@ impl<R> From<R> for NoopRpcExtensionBuilder<R> where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Full client type.
|
||||
pub type TFullClient<TBl, TRtApi, TExecDisp> = Client<
|
||||
TFullBackend<TBl>,
|
||||
TFullCallExecutor<TBl, TExecDisp>,
|
||||
TBl,
|
||||
TRtApi,
|
||||
>;
|
||||
pub type TFullClient<TBl, TRtApi, TExecDisp> =
|
||||
Client<TFullBackend<TBl>, TFullCallExecutor<TBl, TExecDisp>, TBl, TRtApi>;
|
||||
|
||||
/// Full client backend type.
|
||||
pub type TFullBackend<TBl> = sc_client_db::Backend<TBl>;
|
||||
|
||||
/// Full client call executor type.
|
||||
pub type TFullCallExecutor<TBl, TExecDisp> = crate::client::LocalCallExecutor<
|
||||
TBl,
|
||||
sc_client_db::Backend<TBl>,
|
||||
NativeExecutor<TExecDisp>,
|
||||
>;
|
||||
pub type TFullCallExecutor<TBl, TExecDisp> =
|
||||
crate::client::LocalCallExecutor<TBl, sc_client_db::Backend<TBl>, NativeExecutor<TExecDisp>>;
|
||||
|
||||
/// Light client type.
|
||||
pub type TLightClient<TBl, TRtApi, TExecDisp> = TLightClientWithBackend<
|
||||
TBl, TRtApi, TExecDisp, TLightBackend<TBl>
|
||||
>;
|
||||
pub type TLightClient<TBl, TRtApi, TExecDisp> =
|
||||
TLightClientWithBackend<TBl, TRtApi, TExecDisp, TLightBackend<TBl>>;
|
||||
|
||||
/// Light client backend type.
|
||||
pub type TLightBackend<TBl> = sc_light::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
HashFor<TBl>,
|
||||
>;
|
||||
pub type TLightBackend<TBl> =
|
||||
sc_light::Backend<sc_client_db::light::LightStorage<TBl>, HashFor<TBl>>;
|
||||
|
||||
/// Light call executor type.
|
||||
pub type TLightCallExecutor<TBl, TExecDisp> = sc_light::GenesisCallExecutor<
|
||||
sc_light::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
HashFor<TBl>
|
||||
>,
|
||||
sc_light::Backend<sc_client_db::light::LightStorage<TBl>, HashFor<TBl>>,
|
||||
crate::client::LocalCallExecutor<
|
||||
TBl,
|
||||
sc_light::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
HashFor<TBl>
|
||||
>,
|
||||
NativeExecutor<TExecDisp>
|
||||
sc_light::Backend<sc_client_db::light::LightStorage<TBl>, HashFor<TBl>>,
|
||||
NativeExecutor<TExecDisp>,
|
||||
>,
|
||||
>;
|
||||
|
||||
type TFullParts<TBl, TRtApi, TExecDisp> = (
|
||||
TFullClient<TBl, TRtApi, TExecDisp>,
|
||||
Arc<TFullBackend<TBl>>,
|
||||
KeystoreContainer,
|
||||
TaskManager,
|
||||
);
|
||||
type TFullParts<TBl, TRtApi, TExecDisp> =
|
||||
(TFullClient<TBl, TRtApi, TExecDisp>, Arc<TFullBackend<TBl>>, KeystoreContainer, TaskManager);
|
||||
|
||||
type TLightParts<TBl, TRtApi, TExecDisp> = (
|
||||
Arc<TLightClient<TBl, TRtApi, TExecDisp>>,
|
||||
@@ -199,10 +168,8 @@ type TLightParts<TBl, TRtApi, TExecDisp> = (
|
||||
);
|
||||
|
||||
/// Light client backend type with a specific hash type.
|
||||
pub type TLightBackendWithHash<TBl, THash> = sc_light::Backend<
|
||||
sc_client_db::light::LightStorage<TBl>,
|
||||
THash,
|
||||
>;
|
||||
pub type TLightBackendWithHash<TBl, THash> =
|
||||
sc_light::Backend<sc_client_db::light::LightStorage<TBl>, THash>;
|
||||
|
||||
/// Light client type with a specific backend.
|
||||
pub type TLightClientWithBackend<TBl, TRtApi, TExecDisp, TBackend> = Client<
|
||||
@@ -220,7 +187,10 @@ trait AsCryptoStoreRef {
|
||||
fn sync_keystore_ref(&self) -> Arc<dyn SyncCryptoStore>;
|
||||
}
|
||||
|
||||
impl<T> AsCryptoStoreRef for Arc<T> where T: CryptoStore + SyncCryptoStore + 'static {
|
||||
impl<T> AsCryptoStoreRef for Arc<T>
|
||||
where
|
||||
T: CryptoStore + SyncCryptoStore + 'static,
|
||||
{
|
||||
fn keystore_ref(&self) -> Arc<dyn CryptoStore> {
|
||||
self.clone()
|
||||
}
|
||||
@@ -239,14 +209,12 @@ impl KeystoreContainer {
|
||||
/// Construct KeystoreContainer
|
||||
pub fn new(config: &KeystoreConfig) -> Result<Self, Error> {
|
||||
let keystore = Arc::new(match config {
|
||||
KeystoreConfig::Path { path, password } => LocalKeystore::open(
|
||||
path.clone(),
|
||||
password.clone(),
|
||||
)?,
|
||||
KeystoreConfig::Path { path, password } =>
|
||||
LocalKeystore::open(path.clone(), password.clone())?,
|
||||
KeystoreConfig::InMemory => LocalKeystore::in_memory(),
|
||||
});
|
||||
|
||||
Ok(Self{remote: Default::default(), local: keystore})
|
||||
Ok(Self { remote: Default::default(), local: keystore })
|
||||
}
|
||||
|
||||
/// Set the remote keystore.
|
||||
@@ -255,7 +223,8 @@ impl KeystoreContainer {
|
||||
/// does not reset any references previously handed out - they will
|
||||
/// stick around.
|
||||
pub fn set_remote_keystore<T>(&mut self, remote: Arc<T>)
|
||||
where T: CryptoStore + SyncCryptoStore + 'static
|
||||
where
|
||||
T: CryptoStore + SyncCryptoStore + 'static,
|
||||
{
|
||||
self.remote = Some(Box::new(remote))
|
||||
}
|
||||
@@ -295,7 +264,8 @@ impl KeystoreContainer {
|
||||
pub fn new_full_client<TBl, TRtApi, TExecDisp>(
|
||||
config: &Configuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
) -> Result<TFullClient<TBl, TRtApi, TExecDisp>, Error> where
|
||||
) -> Result<TFullClient<TBl, TRtApi, TExecDisp>, Error>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TExecDisp: NativeExecutionDispatch + 'static,
|
||||
TBl::Hash: FromStr,
|
||||
@@ -307,7 +277,8 @@ pub fn new_full_client<TBl, TRtApi, TExecDisp>(
|
||||
pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
config: &Configuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
) -> Result<TFullParts<TBl, TRtApi, TExecDisp>, Error> where
|
||||
) -> Result<TFullParts<TBl, TRtApi, TExecDisp>, Error>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TExecDisp: NativeExecutionDispatch + 'static,
|
||||
TBl::Hash: FromStr,
|
||||
@@ -337,15 +308,13 @@ pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
let (client, backend) = {
|
||||
let db_config = sc_client_db::DatabaseSettings {
|
||||
state_cache_size: config.state_cache_size,
|
||||
state_cache_child_ratio:
|
||||
config.state_cache_child_ratio.map(|v| (v, 100)),
|
||||
state_cache_child_ratio: config.state_cache_child_ratio.map(|v| (v, 100)),
|
||||
state_pruning: config.state_pruning.clone(),
|
||||
source: config.database.clone(),
|
||||
keep_blocks: config.keep_blocks.clone(),
|
||||
transaction_storage: config.transaction_storage.clone(),
|
||||
};
|
||||
|
||||
|
||||
let backend = new_db_backend(db_config)?;
|
||||
|
||||
let extensions = sc_client_api::execution_extensions::ExecutionExtensions::new(
|
||||
@@ -354,15 +323,20 @@ pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
sc_offchain::OffchainDb::factory_from_backend(&*backend),
|
||||
);
|
||||
|
||||
let wasm_runtime_substitutes = config.chain_spec.code_substitutes().into_iter().map(|(h, c)| {
|
||||
let hash = TBl::Hash::from_str(&h)
|
||||
.map_err(|_|
|
||||
Error::Application(Box::from(
|
||||
format!("Failed to parse `{}` as block hash for code substitutes.", h)
|
||||
))
|
||||
)?;
|
||||
Ok((hash, c))
|
||||
}).collect::<Result<std::collections::HashMap<_, _>, Error>>()?;
|
||||
let wasm_runtime_substitutes = config
|
||||
.chain_spec
|
||||
.code_substitutes()
|
||||
.into_iter()
|
||||
.map(|(h, c)| {
|
||||
let hash = TBl::Hash::from_str(&h).map_err(|_| {
|
||||
Error::Application(Box::from(format!(
|
||||
"Failed to parse `{}` as block hash for code substitutes.",
|
||||
h
|
||||
)))
|
||||
})?;
|
||||
Ok((hash, c))
|
||||
})
|
||||
.collect::<Result<std::collections::HashMap<_, _>, Error>>()?;
|
||||
|
||||
let client = new_client(
|
||||
backend.clone(),
|
||||
@@ -375,10 +349,13 @@ pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
config.prometheus_config.as_ref().map(|config| config.registry.clone()),
|
||||
telemetry,
|
||||
ClientConfig {
|
||||
offchain_worker_enabled : config.offchain_worker.enabled,
|
||||
offchain_worker_enabled: config.offchain_worker.enabled,
|
||||
offchain_indexing_api: config.offchain_worker.indexing_enabled,
|
||||
wasm_runtime_overrides: config.wasm_runtime_overrides.clone(),
|
||||
no_genesis: matches!(config.network.sync_mode, sc_network::config::SyncMode::Fast {..}),
|
||||
no_genesis: matches!(
|
||||
config.network.sync_mode,
|
||||
sc_network::config::SyncMode::Fast { .. }
|
||||
),
|
||||
wasm_runtime_substitutes,
|
||||
},
|
||||
)?;
|
||||
@@ -386,19 +363,15 @@ pub fn new_full_parts<TBl, TRtApi, TExecDisp>(
|
||||
(client, backend)
|
||||
};
|
||||
|
||||
Ok((
|
||||
client,
|
||||
backend,
|
||||
keystore_container,
|
||||
task_manager,
|
||||
))
|
||||
Ok((client, backend, keystore_container, task_manager))
|
||||
}
|
||||
|
||||
/// Create the initial parts of a light node.
|
||||
pub fn new_light_parts<TBl, TRtApi, TExecDisp>(
|
||||
config: &Configuration,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
) -> Result<TLightParts<TBl, TRtApi, TExecDisp>, Error> where
|
||||
) -> Result<TLightParts<TBl, TRtApi, TExecDisp>, Error>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TExecDisp: NativeExecutionDispatch + 'static,
|
||||
{
|
||||
@@ -417,8 +390,7 @@ pub fn new_light_parts<TBl, TRtApi, TExecDisp>(
|
||||
let db_storage = {
|
||||
let db_settings = sc_client_db::DatabaseSettings {
|
||||
state_cache_size: config.state_cache_size,
|
||||
state_cache_child_ratio:
|
||||
config.state_cache_child_ratio.map(|v| (v, 100)),
|
||||
state_cache_child_ratio: config.state_cache_child_ratio.map(|v| (v, 100)),
|
||||
state_pruning: config.state_pruning.clone(),
|
||||
source: config.database.clone(),
|
||||
keep_blocks: config.keep_blocks.clone(),
|
||||
@@ -427,13 +399,11 @@ pub fn new_light_parts<TBl, TRtApi, TExecDisp>(
|
||||
sc_client_db::light::LightStorage::new(db_settings)?
|
||||
};
|
||||
let light_blockchain = sc_light::new_light_blockchain(db_storage);
|
||||
let fetch_checker = Arc::new(
|
||||
sc_light::new_fetch_checker::<_, TBl, _>(
|
||||
light_blockchain.clone(),
|
||||
executor.clone(),
|
||||
Box::new(task_manager.spawn_handle()),
|
||||
),
|
||||
);
|
||||
let fetch_checker = Arc::new(sc_light::new_fetch_checker::<_, TBl, _>(
|
||||
light_blockchain.clone(),
|
||||
executor.clone(),
|
||||
Box::new(task_manager.spawn_handle()),
|
||||
));
|
||||
let on_demand = Arc::new(sc_network::config::OnDemand::new(fetch_checker));
|
||||
let backend = sc_light::new_light_backend(light_blockchain);
|
||||
let client = Arc::new(light::new_light(
|
||||
@@ -451,7 +421,8 @@ pub fn new_light_parts<TBl, TRtApi, TExecDisp>(
|
||||
/// Create an instance of default DB-backend backend.
|
||||
pub fn new_db_backend<Block>(
|
||||
settings: DatabaseSettings,
|
||||
) -> Result<Arc<Backend<Block>>, sp_blockchain::Error> where
|
||||
) -> Result<Arc<Backend<Block>>, sp_blockchain::Error>
|
||||
where
|
||||
Block: BlockT,
|
||||
{
|
||||
const CANONICALIZATION_DELAY: u64 = 4096;
|
||||
@@ -480,11 +451,16 @@ pub fn new_client<E, Block, RA>(
|
||||
>,
|
||||
sp_blockchain::Error,
|
||||
>
|
||||
where
|
||||
Block: BlockT,
|
||||
E: CodeExecutor + RuntimeInfo,
|
||||
where
|
||||
Block: BlockT,
|
||||
E: CodeExecutor + RuntimeInfo,
|
||||
{
|
||||
let executor = crate::client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone())?;
|
||||
let executor = crate::client::LocalCallExecutor::new(
|
||||
backend.clone(),
|
||||
executor,
|
||||
spawn_handle,
|
||||
config.clone(),
|
||||
)?;
|
||||
Ok(crate::client::Client::new(
|
||||
backend,
|
||||
executor,
|
||||
@@ -534,10 +510,10 @@ pub fn build_offchain_workers<TBl, TCl>(
|
||||
client: Arc<TCl>,
|
||||
network: Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
|
||||
) -> Option<Arc<sc_offchain::OffchainWorkers<TCl, TBl>>>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TCl: Send + Sync + ProvideRuntimeApi<TBl> + BlockchainEvents<TBl> + 'static,
|
||||
<TCl as ProvideRuntimeApi<TBl>>::Api: sc_offchain::OffchainWorkerApi<TBl>,
|
||||
where
|
||||
TBl: BlockT,
|
||||
TCl: Send + Sync + ProvideRuntimeApi<TBl> + BlockchainEvents<TBl> + 'static,
|
||||
<TCl as ProvideRuntimeApi<TBl>>::Api: sc_offchain::OffchainWorkerApi<TBl>,
|
||||
{
|
||||
let offchain_workers = Some(Arc::new(sc_offchain::OffchainWorkers::new(client.clone())));
|
||||
|
||||
@@ -551,7 +527,7 @@ pub fn build_offchain_workers<TBl, TCl>(
|
||||
offchain,
|
||||
Clone::clone(&spawn_handle),
|
||||
network.clone(),
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -562,22 +538,32 @@ pub fn build_offchain_workers<TBl, TCl>(
|
||||
pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
|
||||
params: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
|
||||
) -> Result<RpcHandlers, Error>
|
||||
where
|
||||
TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> +
|
||||
BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> +
|
||||
HeaderBackend<TBl> + BlockchainEvents<TBl> + ExecutorProvider<TBl> + UsageProvider<TBl> +
|
||||
StorageProvider<TBl, TBackend> + CallApiAt<TBl> + Send + 'static,
|
||||
<TCl as ProvideRuntimeApi<TBl>>::Api:
|
||||
sp_api::Metadata<TBl> +
|
||||
sc_offchain::OffchainWorkerApi<TBl> +
|
||||
sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl> +
|
||||
sp_session::SessionKeys<TBl> +
|
||||
sp_api::ApiExt<TBl, StateBackend = TBackend::State>,
|
||||
TBl: BlockT,
|
||||
TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
|
||||
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> +
|
||||
MallocSizeOfWasm + 'static,
|
||||
TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>
|
||||
where
|
||||
TCl: ProvideRuntimeApi<TBl>
|
||||
+ HeaderMetadata<TBl, Error = sp_blockchain::Error>
|
||||
+ Chain<TBl>
|
||||
+ BlockBackend<TBl>
|
||||
+ BlockIdTo<TBl, Error = sp_blockchain::Error>
|
||||
+ ProofProvider<TBl>
|
||||
+ HeaderBackend<TBl>
|
||||
+ BlockchainEvents<TBl>
|
||||
+ ExecutorProvider<TBl>
|
||||
+ UsageProvider<TBl>
|
||||
+ StorageProvider<TBl, TBackend>
|
||||
+ CallApiAt<TBl>
|
||||
+ Send
|
||||
+ 'static,
|
||||
<TCl as ProvideRuntimeApi<TBl>>::Api: sp_api::Metadata<TBl>
|
||||
+ sc_offchain::OffchainWorkerApi<TBl>
|
||||
+ sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl>
|
||||
+ sp_session::SessionKeys<TBl>
|
||||
+ sp_api::ApiExt<TBl, StateBackend = TBackend::State>,
|
||||
TBl: BlockT,
|
||||
TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
|
||||
TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash>
|
||||
+ MallocSizeOfWasm
|
||||
+ 'static,
|
||||
TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>,
|
||||
{
|
||||
let SpawnTasksParams {
|
||||
mut config,
|
||||
@@ -600,17 +586,11 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
|
||||
client.clone(),
|
||||
&BlockId::Hash(chain_info.best_hash),
|
||||
config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
|
||||
).map_err(|e| Error::Application(Box::new(e)))?;
|
||||
)
|
||||
.map_err(|e| Error::Application(Box::new(e)))?;
|
||||
|
||||
let telemetry = telemetry
|
||||
.map(|telemetry| {
|
||||
init_telemetry(
|
||||
&mut config,
|
||||
network.clone(),
|
||||
client.clone(),
|
||||
telemetry,
|
||||
)
|
||||
})
|
||||
.map(|telemetry| init_telemetry(&mut config, network.clone(), client.clone(), telemetry))
|
||||
.transpose()?;
|
||||
|
||||
info!("📦 Highest known block at #{}", chain_info.best_number);
|
||||
@@ -625,63 +605,69 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
|
||||
|
||||
spawn_handle.spawn(
|
||||
"on-transaction-imported",
|
||||
transaction_notifications(
|
||||
transaction_pool.clone(),
|
||||
network.clone(),
|
||||
telemetry.clone(),
|
||||
),
|
||||
transaction_notifications(transaction_pool.clone(), network.clone(), telemetry.clone()),
|
||||
);
|
||||
|
||||
// Prometheus metrics.
|
||||
let metrics_service = if let Some(PrometheusConfig { port, registry }) =
|
||||
config.prometheus_config.clone()
|
||||
{
|
||||
// Set static metrics.
|
||||
let metrics = MetricsService::with_prometheus(telemetry.clone(), ®istry, &config)?;
|
||||
spawn_handle.spawn(
|
||||
"prometheus-endpoint",
|
||||
prometheus_endpoint::init_prometheus(port, registry).map(drop)
|
||||
);
|
||||
let metrics_service =
|
||||
if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() {
|
||||
// Set static metrics.
|
||||
let metrics = MetricsService::with_prometheus(telemetry.clone(), ®istry, &config)?;
|
||||
spawn_handle.spawn(
|
||||
"prometheus-endpoint",
|
||||
prometheus_endpoint::init_prometheus(port, registry).map(drop),
|
||||
);
|
||||
|
||||
metrics
|
||||
} else {
|
||||
MetricsService::new(telemetry.clone())
|
||||
};
|
||||
metrics
|
||||
} else {
|
||||
MetricsService::new(telemetry.clone())
|
||||
};
|
||||
|
||||
// Periodically updated metrics and telemetry updates.
|
||||
spawn_handle.spawn("telemetry-periodic-send",
|
||||
metrics_service.run(
|
||||
client.clone(),
|
||||
transaction_pool.clone(),
|
||||
network.clone(),
|
||||
)
|
||||
spawn_handle.spawn(
|
||||
"telemetry-periodic-send",
|
||||
metrics_service.run(client.clone(), transaction_pool.clone(), network.clone()),
|
||||
);
|
||||
|
||||
// RPC
|
||||
let gen_handler = |
|
||||
deny_unsafe: sc_rpc::DenyUnsafe,
|
||||
rpc_middleware: sc_rpc_server::RpcMiddleware
|
||||
| gen_handler(
|
||||
deny_unsafe, rpc_middleware, &config, task_manager.spawn_handle(),
|
||||
client.clone(), transaction_pool.clone(), keystore.clone(),
|
||||
on_demand.clone(), remote_blockchain.clone(), &*rpc_extensions_builder,
|
||||
backend.offchain_storage(), system_rpc_tx.clone()
|
||||
);
|
||||
let gen_handler = |deny_unsafe: sc_rpc::DenyUnsafe,
|
||||
rpc_middleware: sc_rpc_server::RpcMiddleware| {
|
||||
gen_handler(
|
||||
deny_unsafe,
|
||||
rpc_middleware,
|
||||
&config,
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
transaction_pool.clone(),
|
||||
keystore.clone(),
|
||||
on_demand.clone(),
|
||||
remote_blockchain.clone(),
|
||||
&*rpc_extensions_builder,
|
||||
backend.offchain_storage(),
|
||||
system_rpc_tx.clone(),
|
||||
)
|
||||
};
|
||||
let rpc_metrics = sc_rpc_server::RpcMetrics::new(config.prometheus_registry())?;
|
||||
let rpc = start_rpc_servers(&config, gen_handler, rpc_metrics.clone())?;
|
||||
// This is used internally, so don't restrict access to unsafe RPC
|
||||
let rpc_handlers = RpcHandlers(Arc::new(gen_handler(
|
||||
sc_rpc::DenyUnsafe::No,
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics, "inbrowser")
|
||||
).into()));
|
||||
let rpc_handlers = RpcHandlers(Arc::new(
|
||||
gen_handler(
|
||||
sc_rpc::DenyUnsafe::No,
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics, "inbrowser"),
|
||||
)
|
||||
.into(),
|
||||
));
|
||||
|
||||
// Spawn informant task
|
||||
spawn_handle.spawn("informant", sc_informant::build(
|
||||
client.clone(),
|
||||
network.clone(),
|
||||
transaction_pool.clone(),
|
||||
config.informant_output_format,
|
||||
));
|
||||
spawn_handle.spawn(
|
||||
"informant",
|
||||
sc_informant::build(
|
||||
client.clone(),
|
||||
network.clone(),
|
||||
transaction_pool.clone(),
|
||||
config.informant_output_format,
|
||||
),
|
||||
);
|
||||
|
||||
task_manager.keep_alive((config.base_path, rpc, rpc_handlers.clone()));
|
||||
|
||||
@@ -692,10 +678,9 @@ async fn transaction_notifications<TBl, TExPool>(
|
||||
transaction_pool: Arc<TExPool>,
|
||||
network: Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
)
|
||||
where
|
||||
TBl: BlockT,
|
||||
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash>,
|
||||
) where
|
||||
TBl: BlockT,
|
||||
TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash>,
|
||||
{
|
||||
// transaction notifications
|
||||
transaction_pool
|
||||
@@ -730,9 +715,11 @@ fn init_telemetry<TBl: BlockT, TCl: BlockBackend<TBl>>(
|
||||
chain: config.chain_spec.name().to_owned(),
|
||||
genesis_hash: format!("{:?}", genesis_hash),
|
||||
authority: config.role.is_authority(),
|
||||
startup_time: SystemTime::UNIX_EPOCH.elapsed()
|
||||
startup_time: SystemTime::UNIX_EPOCH
|
||||
.elapsed()
|
||||
.map(|dur| dur.as_millis())
|
||||
.unwrap_or(0).to_string(),
|
||||
.unwrap_or(0)
|
||||
.to_string(),
|
||||
network_id: network.local_peer_id().to_base58(),
|
||||
};
|
||||
|
||||
@@ -753,22 +740,28 @@ fn gen_handler<TBl, TBackend, TExPool, TRpc, TCl>(
|
||||
remote_blockchain: Option<Arc<dyn RemoteBlockchain<TBl>>>,
|
||||
rpc_extensions_builder: &(dyn RpcExtensionBuilder<Output = TRpc> + Send),
|
||||
offchain_storage: Option<<TBackend as sc_client_api::backend::Backend<TBl>>::OffchainStorage>,
|
||||
system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>
|
||||
system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
|
||||
) -> sc_rpc_server::RpcHandler<sc_rpc::Metadata>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TCl: ProvideRuntimeApi<TBl> + BlockchainEvents<TBl> + HeaderBackend<TBl> +
|
||||
HeaderMetadata<TBl, Error=sp_blockchain::Error> + ExecutorProvider<TBl> +
|
||||
CallApiAt<TBl> + ProofProvider<TBl> +
|
||||
StorageProvider<TBl, TBackend> + BlockBackend<TBl> + Send + Sync + 'static,
|
||||
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> + 'static,
|
||||
TBackend: sc_client_api::backend::Backend<TBl> + 'static,
|
||||
TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>,
|
||||
<TCl as ProvideRuntimeApi<TBl>>::Api:
|
||||
sp_session::SessionKeys<TBl> +
|
||||
sp_api::Metadata<TBl>,
|
||||
where
|
||||
TBl: BlockT,
|
||||
TCl: ProvideRuntimeApi<TBl>
|
||||
+ BlockchainEvents<TBl>
|
||||
+ HeaderBackend<TBl>
|
||||
+ HeaderMetadata<TBl, Error = sp_blockchain::Error>
|
||||
+ ExecutorProvider<TBl>
|
||||
+ CallApiAt<TBl>
|
||||
+ ProofProvider<TBl>
|
||||
+ StorageProvider<TBl, TBackend>
|
||||
+ BlockBackend<TBl>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + 'static,
|
||||
TBackend: sc_client_api::backend::Backend<TBl> + 'static,
|
||||
TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>,
|
||||
<TCl as ProvideRuntimeApi<TBl>>::Api: sp_session::SessionKeys<TBl> + sp_api::Metadata<TBl>,
|
||||
{
|
||||
use sc_rpc::{chain, state, author, system, offchain};
|
||||
use sc_rpc::{author, chain, offchain, state, system};
|
||||
|
||||
let system_info = sc_rpc::system::SystemInfo {
|
||||
chain_name: config.chain_spec.name().into(),
|
||||
@@ -781,43 +774,37 @@ fn gen_handler<TBl, TBackend, TExPool, TRpc, TCl>(
|
||||
let task_executor = sc_rpc::SubscriptionTaskExecutor::new(spawn_handle);
|
||||
let subscriptions = SubscriptionManager::new(Arc::new(task_executor.clone()));
|
||||
|
||||
let (chain, state, child_state) = if let (Some(remote_blockchain), Some(on_demand)) =
|
||||
(remote_blockchain, on_demand) {
|
||||
// Light clients
|
||||
let chain = sc_rpc::chain::new_light(
|
||||
client.clone(),
|
||||
subscriptions.clone(),
|
||||
remote_blockchain.clone(),
|
||||
on_demand.clone(),
|
||||
);
|
||||
let (state, child_state) = sc_rpc::state::new_light(
|
||||
client.clone(),
|
||||
subscriptions.clone(),
|
||||
remote_blockchain.clone(),
|
||||
on_demand,
|
||||
deny_unsafe,
|
||||
);
|
||||
(chain, state, child_state)
|
||||
let (chain, state, child_state) =
|
||||
if let (Some(remote_blockchain), Some(on_demand)) = (remote_blockchain, on_demand) {
|
||||
// Light clients
|
||||
let chain = sc_rpc::chain::new_light(
|
||||
client.clone(),
|
||||
subscriptions.clone(),
|
||||
remote_blockchain.clone(),
|
||||
on_demand.clone(),
|
||||
);
|
||||
let (state, child_state) = sc_rpc::state::new_light(
|
||||
client.clone(),
|
||||
subscriptions.clone(),
|
||||
remote_blockchain.clone(),
|
||||
on_demand,
|
||||
deny_unsafe,
|
||||
);
|
||||
(chain, state, child_state)
|
||||
} else {
|
||||
// Full nodes
|
||||
let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone());
|
||||
let (state, child_state) = sc_rpc::state::new_full(
|
||||
client.clone(),
|
||||
subscriptions.clone(),
|
||||
deny_unsafe,
|
||||
config.rpc_max_payload,
|
||||
);
|
||||
(chain, state, child_state)
|
||||
};
|
||||
|
||||
} else {
|
||||
// Full nodes
|
||||
let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone());
|
||||
let (state, child_state) = sc_rpc::state::new_full(
|
||||
client.clone(),
|
||||
subscriptions.clone(),
|
||||
deny_unsafe,
|
||||
config.rpc_max_payload,
|
||||
);
|
||||
(chain, state, child_state)
|
||||
};
|
||||
|
||||
let author = sc_rpc::author::Author::new(
|
||||
client,
|
||||
transaction_pool,
|
||||
subscriptions,
|
||||
keystore,
|
||||
deny_unsafe,
|
||||
);
|
||||
let author =
|
||||
sc_rpc::author::Author::new(client, transaction_pool, subscriptions, keystore, deny_unsafe);
|
||||
let system = system::System::new(system_info, system_rpc_tx, deny_unsafe);
|
||||
|
||||
let maybe_offchain_rpc = offchain_storage.map(|storage| {
|
||||
@@ -835,7 +822,7 @@ fn gen_handler<TBl, TBackend, TExPool, TRpc, TCl>(
|
||||
system::SystemApi::to_delegate(system),
|
||||
rpc_extensions_builder.build(deny_unsafe, task_executor),
|
||||
),
|
||||
rpc_middleware
|
||||
rpc_middleware,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -854,32 +841,42 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> {
|
||||
/// An optional, shared data fetcher for light clients.
|
||||
pub on_demand: Option<Arc<OnDemand<TBl>>>,
|
||||
/// A block announce validator builder.
|
||||
pub block_announce_validator_builder: Option<Box<
|
||||
dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send
|
||||
>>,
|
||||
pub block_announce_validator_builder:
|
||||
Option<Box<dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send>>,
|
||||
}
|
||||
|
||||
/// Build the network service, the network status sinks and an RPC sender.
|
||||
pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
params: BuildNetworkParams<TBl, TExPool, TImpQu, TCl>
|
||||
params: BuildNetworkParams<TBl, TExPool, TImpQu, TCl>,
|
||||
) -> Result<
|
||||
(
|
||||
Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
|
||||
TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
|
||||
NetworkStarter,
|
||||
),
|
||||
Error
|
||||
Error,
|
||||
>
|
||||
where
|
||||
TBl: BlockT,
|
||||
TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> +
|
||||
BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> +
|
||||
HeaderBackend<TBl> + BlockchainEvents<TBl> + 'static,
|
||||
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> + 'static,
|
||||
TImpQu: ImportQueue<TBl> + 'static,
|
||||
where
|
||||
TBl: BlockT,
|
||||
TCl: ProvideRuntimeApi<TBl>
|
||||
+ HeaderMetadata<TBl, Error = sp_blockchain::Error>
|
||||
+ Chain<TBl>
|
||||
+ BlockBackend<TBl>
|
||||
+ BlockIdTo<TBl, Error = sp_blockchain::Error>
|
||||
+ ProofProvider<TBl>
|
||||
+ HeaderBackend<TBl>
|
||||
+ BlockchainEvents<TBl>
|
||||
+ 'static,
|
||||
TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + 'static,
|
||||
TImpQu: ImportQueue<TBl> + 'static,
|
||||
{
|
||||
let BuildNetworkParams {
|
||||
config, client, transaction_pool, spawn_handle, import_queue, on_demand,
|
||||
config,
|
||||
client,
|
||||
transaction_pool,
|
||||
spawn_handle,
|
||||
import_queue,
|
||||
on_demand,
|
||||
block_announce_validator_builder,
|
||||
} = params;
|
||||
|
||||
@@ -906,8 +903,8 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
let (handler, protocol_config) = BlockRequestHandler::new(
|
||||
&protocol_id,
|
||||
client.clone(),
|
||||
config.network.default_peers_set.in_peers as usize
|
||||
+ config.network.default_peers_set.out_peers as usize,
|
||||
config.network.default_peers_set.in_peers as usize +
|
||||
config.network.default_peers_set.out_peers as usize,
|
||||
);
|
||||
spawn_handle.spawn("block_request_handler", handler.run());
|
||||
protocol_config
|
||||
@@ -923,8 +920,8 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
let (handler, protocol_config) = StateRequestHandler::new(
|
||||
&protocol_id,
|
||||
client.clone(),
|
||||
config.network.default_peers_set.in_peers as usize
|
||||
+ config.network.default_peers_set.out_peers as usize,
|
||||
config.network.default_peers_set.in_peers as usize +
|
||||
config.network.default_peers_set.out_peers as usize,
|
||||
);
|
||||
spawn_handle.spawn("state_request_handler", handler.run());
|
||||
protocol_config
|
||||
@@ -937,10 +934,8 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
light_client_requests::generate_protocol_config(&protocol_id)
|
||||
} else {
|
||||
// Allow both outgoing and incoming requests.
|
||||
let (handler, protocol_config) = LightClientRequestHandler::new(
|
||||
&protocol_id,
|
||||
client.clone(),
|
||||
);
|
||||
let (handler, protocol_config) =
|
||||
LightClientRequestHandler::new(&protocol_id, client.clone());
|
||||
spawn_handle.spawn("light_client_request_handler", handler.run());
|
||||
protocol_config
|
||||
}
|
||||
@@ -962,7 +957,7 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
},
|
||||
network_config: config.network.clone(),
|
||||
chain: client.clone(),
|
||||
on_demand: on_demand,
|
||||
on_demand,
|
||||
transaction_pool: transaction_pool_adapter as _,
|
||||
import_queue: Box::new(import_queue),
|
||||
protocol_id,
|
||||
@@ -976,10 +971,8 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
// Storage chains don't keep full block history and can't be synced in full mode.
|
||||
// Force fast sync when storage chain mode is enabled.
|
||||
if matches!(config.transaction_storage, TransactionStorageMode::StorageChain) {
|
||||
network_params.network_config.sync_mode = SyncMode::Fast {
|
||||
storage_chain_mode: true,
|
||||
skip_proofs: false,
|
||||
};
|
||||
network_params.network_config.sync_mode =
|
||||
SyncMode::Fast { storage_chain_mode: true, skip_proofs: false };
|
||||
}
|
||||
|
||||
let has_bootnodes = !network_params.network_config.boot_nodes.is_empty();
|
||||
@@ -1028,7 +1021,7 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
|
||||
);
|
||||
// This `return` might seem unnecessary, but we don't want to make it look like
|
||||
// everything is working as normal even though the user is clearly misusing the API.
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
future.await
|
||||
|
||||
@@ -17,22 +17,20 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::Error;
|
||||
use futures::{future, prelude::*};
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use sp_runtime::generic::BlockId;
|
||||
use codec::Encode;
|
||||
use sp_consensus::import_queue::ImportQueue;
|
||||
use futures::{future, prelude::*};
|
||||
use sc_client_api::{BlockBackend, UsageProvider};
|
||||
use sp_consensus::import_queue::ImportQueue;
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use crate::chain_ops::import_blocks;
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
|
||||
/// Re-validate known block.
|
||||
pub fn check_block<B, IQ, C>(
|
||||
client: Arc<C>,
|
||||
import_queue: IQ,
|
||||
block_id: BlockId<B>
|
||||
block_id: BlockId<B>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>>
|
||||
where
|
||||
C: BlockBackend<B> + UsageProvider<B> + Send + Sync + 'static,
|
||||
@@ -46,7 +44,7 @@ where
|
||||
block.encode_to(&mut buf);
|
||||
let reader = std::io::Cursor::new(buf);
|
||||
import_blocks(client, import_queue, reader, true, true)
|
||||
}
|
||||
},
|
||||
Ok(None) => Box::pin(future::err("Unknown block".into())),
|
||||
Err(e) => Box::pin(future::err(format!("Error reading block: {:?}", e).into())),
|
||||
}
|
||||
|
||||
@@ -17,18 +17,16 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::Error;
|
||||
use log::info;
|
||||
use futures::{future, prelude::*};
|
||||
use sp_runtime::traits::{
|
||||
Block as BlockT, NumberFor, One, Zero, SaturatedConversion
|
||||
};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use codec::Encode;
|
||||
use futures::{future, prelude::*};
|
||||
use log::info;
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, NumberFor, One, SaturatedConversion, Zero},
|
||||
};
|
||||
|
||||
use std::{io::Write, pin::Pin};
|
||||
use sc_client_api::{BlockBackend, UsageProvider};
|
||||
use std::sync::Arc;
|
||||
use std::task::Poll;
|
||||
use std::{io::Write, pin::Pin, sync::Arc, task::Poll};
|
||||
|
||||
/// Performs the blocks export.
|
||||
pub fn export_blocks<B, C>(
|
||||
@@ -36,7 +34,7 @@ pub fn export_blocks<B, C>(
|
||||
mut output: impl Write + 'static,
|
||||
from: NumberFor<B>,
|
||||
to: Option<NumberFor<B>>,
|
||||
binary: bool
|
||||
binary: bool,
|
||||
) -> Pin<Box<dyn Future<Output = Result<(), Error>>>>
|
||||
where
|
||||
C: BlockBackend<B> + UsageProvider<B> + 'static,
|
||||
@@ -63,7 +61,7 @@ where
|
||||
let client = &client;
|
||||
|
||||
if last < block {
|
||||
return Poll::Ready(Err("Invalid block range specified".into()));
|
||||
return Poll::Ready(Err("Invalid block range specified".into()))
|
||||
}
|
||||
|
||||
if !wrote_header {
|
||||
@@ -78,14 +76,13 @@ where
|
||||
}
|
||||
|
||||
match client.block(&BlockId::number(block))? {
|
||||
Some(block) => {
|
||||
Some(block) =>
|
||||
if binary {
|
||||
output.write_all(&block.encode())?;
|
||||
} else {
|
||||
serde_json::to_writer(&mut output, &block)
|
||||
.map_err(|e| format!("Error writing JSON: {}", e))?;
|
||||
}
|
||||
},
|
||||
},
|
||||
// Reached end of the chain.
|
||||
None => return Poll::Ready(Ok(())),
|
||||
}
|
||||
@@ -93,7 +90,7 @@ where
|
||||
info!("#{}", block);
|
||||
}
|
||||
if block == last {
|
||||
return Poll::Ready(Ok(()));
|
||||
return Poll::Ready(Ok(()))
|
||||
}
|
||||
block += One::one();
|
||||
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::Error;
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_core::storage::{StorageKey, well_known_keys, ChildInfo, Storage, StorageChild, StorageMap};
|
||||
use sc_client_api::{StorageProvider, UsageProvider};
|
||||
use sp_core::storage::{well_known_keys, ChildInfo, Storage, StorageChild, StorageKey, StorageMap};
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
@@ -35,9 +34,7 @@ where
|
||||
B: BlockT,
|
||||
BA: sc_client_api::backend::Backend<B>,
|
||||
{
|
||||
let block = block.unwrap_or_else(
|
||||
|| BlockId::Hash(client.usage_info().chain.best_hash)
|
||||
);
|
||||
let block = block.unwrap_or_else(|| BlockId::Hash(client.usage_info().chain.best_hash));
|
||||
|
||||
let empty_key = StorageKey(Vec::new());
|
||||
let mut top_storage = client.storage_pairs(&block, &empty_key)?;
|
||||
@@ -47,12 +44,12 @@ where
|
||||
// pairs.
|
||||
while let Some(pos) = top_storage
|
||||
.iter()
|
||||
.position(|(k, _)| k.0.starts_with(well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX)) {
|
||||
.position(|(k, _)| k.0.starts_with(well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX))
|
||||
{
|
||||
let (key, _) = top_storage.swap_remove(pos);
|
||||
|
||||
let key = StorageKey(
|
||||
key.0[well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX.len()..].to_vec(),
|
||||
);
|
||||
let key =
|
||||
StorageKey(key.0[well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX.len()..].to_vec());
|
||||
let child_info = ChildInfo::new_default(&key.0);
|
||||
|
||||
let keys = client.child_storage_keys(&block, &child_info, &empty_key)?;
|
||||
|
||||
@@ -16,29 +16,31 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error;
|
||||
use crate::error::Error;
|
||||
use sc_chain_spec::ChainSpec;
|
||||
use log::{warn, info};
|
||||
use futures::{future, prelude::*};
|
||||
use sp_runtime::traits::{
|
||||
Block as BlockT, NumberFor, Zero, Header, MaybeSerializeDeserialize,
|
||||
};
|
||||
use sp_runtime::generic::SignedBlock;
|
||||
use crate::{error, error::Error};
|
||||
use codec::{Decode, IoReader as CodecIoReader};
|
||||
use futures::{future, prelude::*};
|
||||
use log::{info, warn};
|
||||
use sc_chain_spec::ChainSpec;
|
||||
use sp_consensus::{
|
||||
import_queue::{BlockImportError, BlockImportResult, ImportQueue, IncomingBlock, Link},
|
||||
BlockOrigin,
|
||||
import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue},
|
||||
};
|
||||
use sp_runtime::{
|
||||
generic::SignedBlock,
|
||||
traits::{Block as BlockT, Header, MaybeSerializeDeserialize, NumberFor, Zero},
|
||||
};
|
||||
|
||||
use std::{io::{Read, Seek}, pin::Pin};
|
||||
use std::time::{Duration, Instant};
|
||||
use futures_timer::Delay;
|
||||
use std::task::Poll;
|
||||
use serde_json::{de::IoRead as JsonIoRead, Deserializer, StreamDeserializer};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use sp_runtime::traits::{CheckedDiv, Saturating};
|
||||
use sc_client_api::UsageProvider;
|
||||
use serde_json::{de::IoRead as JsonIoRead, Deserializer, StreamDeserializer};
|
||||
use sp_runtime::traits::{CheckedDiv, Saturating};
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
io::{Read, Seek},
|
||||
pin::Pin,
|
||||
task::Poll,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
/// Number of blocks we will add to the queue before waiting for the queue to catch up.
|
||||
const MAX_PENDING_BLOCKS: u64 = 1_024;
|
||||
@@ -56,11 +58,11 @@ pub fn build_spec(spec: &dyn ChainSpec, raw: bool) -> error::Result<String> {
|
||||
spec.as_json(raw).map_err(Into::into)
|
||||
}
|
||||
|
||||
|
||||
/// Helper enum that wraps either a binary decoder (from parity-scale-codec), or a JSON decoder
|
||||
/// (from serde_json). Implements the Iterator Trait, calling `next()` will decode the next
|
||||
/// SignedBlock and return it.
|
||||
enum BlockIter<R, B> where
|
||||
enum BlockIter<R, B>
|
||||
where
|
||||
R: std::io::Read + std::io::Seek,
|
||||
{
|
||||
Binary {
|
||||
@@ -79,7 +81,8 @@ enum BlockIter<R, B> where
|
||||
},
|
||||
}
|
||||
|
||||
impl<R, B> BlockIter<R, B> where
|
||||
impl<R, B> BlockIter<R, B>
|
||||
where
|
||||
R: Read + Seek + 'static,
|
||||
B: BlockT + MaybeSerializeDeserialize,
|
||||
{
|
||||
@@ -90,40 +93,32 @@ impl<R, B> BlockIter<R, B> where
|
||||
// of blocks that are going to be decoded. We read it and add it to our enum struct.
|
||||
let num_expected_blocks: u64 = Decode::decode(&mut reader)
|
||||
.map_err(|e| format!("Failed to decode the number of blocks: {:?}", e))?;
|
||||
Ok(BlockIter::Binary {
|
||||
num_expected_blocks,
|
||||
read_block_count: 0,
|
||||
reader,
|
||||
})
|
||||
Ok(BlockIter::Binary { num_expected_blocks, read_block_count: 0, reader })
|
||||
} else {
|
||||
let stream_deser = Deserializer::from_reader(input)
|
||||
.into_iter::<SignedBlock<B>>();
|
||||
Ok(BlockIter::Json {
|
||||
reader: stream_deser,
|
||||
read_block_count: 0,
|
||||
})
|
||||
let stream_deser = Deserializer::from_reader(input).into_iter::<SignedBlock<B>>();
|
||||
Ok(BlockIter::Json { reader: stream_deser, read_block_count: 0 })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of blocks read thus far.
|
||||
fn read_block_count(&self) -> u64 {
|
||||
match self {
|
||||
BlockIter::Binary { read_block_count, .. }
|
||||
| BlockIter::Json { read_block_count, .. }
|
||||
=> *read_block_count,
|
||||
BlockIter::Binary { read_block_count, .. } |
|
||||
BlockIter::Json { read_block_count, .. } => *read_block_count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the total number of blocks to be imported, if possible.
|
||||
fn num_expected_blocks(&self) -> Option<u64> {
|
||||
match self {
|
||||
BlockIter::Binary { num_expected_blocks, ..} => Some(*num_expected_blocks),
|
||||
BlockIter::Json {..} => None
|
||||
BlockIter::Binary { num_expected_blocks, .. } => Some(*num_expected_blocks),
|
||||
BlockIter::Json { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, B> Iterator for BlockIter<R, B> where
|
||||
impl<R, B> Iterator for BlockIter<R, B>
|
||||
where
|
||||
R: Read + Seek + 'static,
|
||||
B: BlockT + MaybeSerializeDeserialize,
|
||||
{
|
||||
@@ -133,20 +128,20 @@ impl<R, B> Iterator for BlockIter<R, B> where
|
||||
match self {
|
||||
BlockIter::Binary { num_expected_blocks, read_block_count, reader } => {
|
||||
if read_block_count < num_expected_blocks {
|
||||
let block_result: Result<SignedBlock::<B>, _> = SignedBlock::<B>::decode(reader)
|
||||
.map_err(|e| e.to_string());
|
||||
let block_result: Result<SignedBlock<B>, _> =
|
||||
SignedBlock::<B>::decode(reader).map_err(|e| e.to_string());
|
||||
*read_block_count += 1;
|
||||
Some(block_result)
|
||||
} else {
|
||||
// `read_block_count` == `num_expected_blocks` so we've read enough blocks.
|
||||
None
|
||||
}
|
||||
}
|
||||
},
|
||||
BlockIter::Json { reader, read_block_count } => {
|
||||
let res = Some(reader.next()?.map_err(|e| e.to_string()));
|
||||
*read_block_count += 1;
|
||||
res
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +150,7 @@ impl<R, B> Iterator for BlockIter<R, B> where
|
||||
fn import_block_to_queue<TBl, TImpQu>(
|
||||
signed_block: SignedBlock<TBl>,
|
||||
queue: &mut TImpQu,
|
||||
force: bool
|
||||
force: bool,
|
||||
) where
|
||||
TBl: BlockT + MaybeSerializeDeserialize,
|
||||
TImpQu: 'static + ImportQueue<TBl>,
|
||||
@@ -163,8 +158,9 @@ fn import_block_to_queue<TBl, TImpQu>(
|
||||
let (header, extrinsics) = signed_block.block.deconstruct();
|
||||
let hash = header.hash();
|
||||
// import queue handles verification and importing it into the client.
|
||||
queue.import_blocks(BlockOrigin::File, vec![
|
||||
IncomingBlock::<TBl> {
|
||||
queue.import_blocks(
|
||||
BlockOrigin::File,
|
||||
vec![IncomingBlock::<TBl> {
|
||||
hash,
|
||||
header: Some(header),
|
||||
body: Some(extrinsics),
|
||||
@@ -175,15 +171,15 @@ fn import_block_to_queue<TBl, TImpQu>(
|
||||
import_existing: force,
|
||||
state: None,
|
||||
skip_execution: false,
|
||||
}
|
||||
]);
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns true if we have imported every block we were supposed to import, else returns false.
|
||||
fn importing_is_done(
|
||||
num_expected_blocks: Option<u64>,
|
||||
read_block_count: u64,
|
||||
imported_blocks: u64
|
||||
imported_blocks: u64,
|
||||
) -> bool {
|
||||
if let Some(num_expected_blocks) = num_expected_blocks {
|
||||
imported_blocks >= num_expected_blocks
|
||||
@@ -209,7 +205,7 @@ impl<B: BlockT> Speedometer<B> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates `(best_number - last_number) / (now - last_update)` and
|
||||
/// Calculates `(best_number - last_number) / (now - last_update)` and
|
||||
/// logs the speed of import.
|
||||
fn display_speed(&self) {
|
||||
// Number of milliseconds elapsed since last time.
|
||||
@@ -223,24 +219,28 @@ impl<B: BlockT> Speedometer<B> {
|
||||
// Number of blocks that have been imported since last time.
|
||||
let diff = match self.last_number {
|
||||
None => return,
|
||||
Some(n) => self.best_number.saturating_sub(n)
|
||||
Some(n) => self.best_number.saturating_sub(n),
|
||||
};
|
||||
|
||||
if let Ok(diff) = TryInto::<u128>::try_into(diff) {
|
||||
// If the number of blocks can be converted to a regular integer, then it's easy: just
|
||||
// do the math and turn it into a `f64`.
|
||||
let speed = diff.saturating_mul(10_000).checked_div(u128::from(elapsed_ms))
|
||||
.map_or(0.0, |s| s as f64) / 10.0;
|
||||
let speed = diff
|
||||
.saturating_mul(10_000)
|
||||
.checked_div(u128::from(elapsed_ms))
|
||||
.map_or(0.0, |s| s as f64) /
|
||||
10.0;
|
||||
info!("📦 Current best block: {} ({:4.1} bps)", self.best_number, speed);
|
||||
} else {
|
||||
// If the number of blocks can't be converted to a regular integer, then we need a more
|
||||
// algebraic approach and we stay within the realm of integers.
|
||||
let one_thousand = NumberFor::<B>::from(1_000u32);
|
||||
let elapsed = NumberFor::<B>::from(
|
||||
<u32 as TryFrom<_>>::try_from(elapsed_ms).unwrap_or(u32::MAX)
|
||||
);
|
||||
let elapsed =
|
||||
NumberFor::<B>::from(<u32 as TryFrom<_>>::try_from(elapsed_ms).unwrap_or(u32::MAX));
|
||||
|
||||
let speed = diff.saturating_mul(one_thousand).checked_div(&elapsed)
|
||||
let speed = diff
|
||||
.saturating_mul(one_thousand)
|
||||
.checked_div(&elapsed)
|
||||
.unwrap_or_else(Zero::zero);
|
||||
info!("📦 Current best block: {} ({} bps)", self.best_number, speed)
|
||||
}
|
||||
@@ -265,22 +265,23 @@ impl<B: BlockT> Speedometer<B> {
|
||||
}
|
||||
|
||||
/// Different State that the `import_blocks` future could be in.
|
||||
enum ImportState<R, B> where
|
||||
enum ImportState<R, B>
|
||||
where
|
||||
R: Read + Seek + 'static,
|
||||
B: BlockT + MaybeSerializeDeserialize,
|
||||
{
|
||||
/// We are reading from the BlockIter structure, adding those blocks to the queue if possible.
|
||||
Reading{block_iter: BlockIter<R, B>},
|
||||
Reading { block_iter: BlockIter<R, B> },
|
||||
/// The queue is full (contains at least MAX_PENDING_BLOCKS blocks) and we are waiting for it to
|
||||
/// catch up.
|
||||
WaitingForImportQueueToCatchUp{
|
||||
WaitingForImportQueueToCatchUp {
|
||||
block_iter: BlockIter<R, B>,
|
||||
delay: Delay,
|
||||
block: SignedBlock<B>
|
||||
block: SignedBlock<B>,
|
||||
},
|
||||
// We have added all the blocks to the queue but they are still being processed.
|
||||
WaitingForImportQueueToFinish{
|
||||
num_expected_blocks: Option<u64>,
|
||||
WaitingForImportQueueToFinish {
|
||||
num_expected_blocks: Option<u64>,
|
||||
read_block_count: u64,
|
||||
delay: Delay,
|
||||
},
|
||||
@@ -306,10 +307,7 @@ where
|
||||
|
||||
impl WaitLink {
|
||||
fn new() -> WaitLink {
|
||||
WaitLink {
|
||||
imported_blocks: 0,
|
||||
has_error: false,
|
||||
}
|
||||
WaitLink { imported_blocks: 0, has_error: false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +316,7 @@ where
|
||||
&mut self,
|
||||
imported: usize,
|
||||
_num_expected_blocks: usize,
|
||||
results: Vec<(Result<BlockImportResult<NumberFor<B>>, BlockImportError>, B::Hash)>
|
||||
results: Vec<(Result<BlockImportResult<NumberFor<B>>, BlockImportError>, B::Hash)>,
|
||||
) {
|
||||
self.imported_blocks += imported as u64;
|
||||
|
||||
@@ -326,7 +324,7 @@ where
|
||||
if let (Err(err), hash) = result {
|
||||
warn!("There was an error importing block with hash {:?}: {:?}", hash, err);
|
||||
self.has_error = true;
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,13 +336,13 @@ where
|
||||
let block_iter = match block_iter_res {
|
||||
Ok(block_iter) => block_iter,
|
||||
Err(e) => {
|
||||
// We've encountered an error while creating the block iterator
|
||||
// We've encountered an error while creating the block iterator
|
||||
// so we can just return a future that returns an error.
|
||||
return future::ready(Err(Error::Other(e))).boxed()
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut state = Some(ImportState::Reading{block_iter});
|
||||
let mut state = Some(ImportState::Reading { block_iter });
|
||||
let mut speedometer = Speedometer::<B>::new();
|
||||
|
||||
// Importing blocks is implemented as a future, because we want the operation to be
|
||||
@@ -358,7 +356,7 @@ where
|
||||
let client = &client;
|
||||
let queue = &mut import_queue;
|
||||
match state.take().expect("state should never be None; qed") {
|
||||
ImportState::Reading{mut block_iter} => {
|
||||
ImportState::Reading { mut block_iter } => {
|
||||
match block_iter.next() {
|
||||
None => {
|
||||
// The iterator is over: we now need to wait for the import queue to finish.
|
||||
@@ -366,7 +364,9 @@ where
|
||||
let read_block_count = block_iter.read_block_count();
|
||||
let delay = Delay::new(Duration::from_millis(DELAY_TIME));
|
||||
state = Some(ImportState::WaitingForImportQueueToFinish {
|
||||
num_expected_blocks, read_block_count, delay
|
||||
num_expected_blocks,
|
||||
read_block_count,
|
||||
delay,
|
||||
});
|
||||
},
|
||||
Some(block_result) => {
|
||||
@@ -378,32 +378,35 @@ where
|
||||
// until the queue has made some progress.
|
||||
let delay = Delay::new(Duration::from_millis(DELAY_TIME));
|
||||
state = Some(ImportState::WaitingForImportQueueToCatchUp {
|
||||
block_iter, delay, block
|
||||
block_iter,
|
||||
delay,
|
||||
block,
|
||||
});
|
||||
} else {
|
||||
// Queue is not full, we can keep on adding blocks to the queue.
|
||||
import_block_to_queue(block, queue, force);
|
||||
state = Some(ImportState::Reading{block_iter});
|
||||
state = Some(ImportState::Reading { block_iter });
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Poll::Ready(
|
||||
Err(Error::Other(
|
||||
format!("Error reading block #{}: {}", read_block_count, e)
|
||||
)))
|
||||
}
|
||||
},
|
||||
Err(e) =>
|
||||
return Poll::Ready(Err(Error::Other(format!(
|
||||
"Error reading block #{}: {}",
|
||||
read_block_count, e
|
||||
)))),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
ImportState::WaitingForImportQueueToCatchUp{block_iter, mut delay, block} => {
|
||||
ImportState::WaitingForImportQueueToCatchUp { block_iter, mut delay, block } => {
|
||||
let read_block_count = block_iter.read_block_count();
|
||||
if read_block_count - link.imported_blocks >= MAX_PENDING_BLOCKS {
|
||||
// Queue is still full, so wait until there is room to insert our block.
|
||||
match Pin::new(&mut delay).poll(cx) {
|
||||
Poll::Pending => {
|
||||
state = Some(ImportState::WaitingForImportQueueToCatchUp {
|
||||
block_iter, delay, block
|
||||
block_iter,
|
||||
delay,
|
||||
block,
|
||||
});
|
||||
return Poll::Pending
|
||||
},
|
||||
@@ -412,25 +415,30 @@ where
|
||||
},
|
||||
}
|
||||
state = Some(ImportState::WaitingForImportQueueToCatchUp {
|
||||
block_iter, delay, block
|
||||
block_iter,
|
||||
delay,
|
||||
block,
|
||||
});
|
||||
} else {
|
||||
// Queue is no longer full, so we can add our block to the queue.
|
||||
import_block_to_queue(block, queue, force);
|
||||
// Switch back to Reading state.
|
||||
state = Some(ImportState::Reading{block_iter});
|
||||
state = Some(ImportState::Reading { block_iter });
|
||||
}
|
||||
},
|
||||
ImportState::WaitingForImportQueueToFinish {
|
||||
num_expected_blocks, read_block_count, mut delay
|
||||
num_expected_blocks,
|
||||
read_block_count,
|
||||
mut delay,
|
||||
} => {
|
||||
// All the blocks have been added to the queue, which doesn't mean they
|
||||
// All the blocks have been added to the queue, which doesn't mean they
|
||||
// have all been properly imported.
|
||||
if importing_is_done(num_expected_blocks, read_block_count, link.imported_blocks) {
|
||||
// Importing is done, we can log the result and return.
|
||||
info!(
|
||||
"🎉 Imported {} blocks. Best: #{}",
|
||||
read_block_count, client.usage_info().chain.best_number
|
||||
read_block_count,
|
||||
client.usage_info().chain.best_number
|
||||
);
|
||||
return Poll::Ready(Ok(()))
|
||||
} else {
|
||||
@@ -439,7 +447,9 @@ where
|
||||
match Pin::new(&mut delay).poll(cx) {
|
||||
Poll::Pending => {
|
||||
state = Some(ImportState::WaitingForImportQueueToFinish {
|
||||
num_expected_blocks, read_block_count, delay
|
||||
num_expected_blocks,
|
||||
read_block_count,
|
||||
delay,
|
||||
});
|
||||
return Poll::Pending
|
||||
},
|
||||
@@ -449,10 +459,12 @@ where
|
||||
}
|
||||
|
||||
state = Some(ImportState::WaitingForImportQueueToFinish {
|
||||
num_expected_blocks, read_block_count, delay
|
||||
num_expected_blocks,
|
||||
read_block_count,
|
||||
delay,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
queue.poll_actions(cx, &mut link);
|
||||
@@ -461,11 +473,10 @@ where
|
||||
speedometer.notify_user(best_number);
|
||||
|
||||
if link.has_error {
|
||||
return Poll::Ready(Err(
|
||||
Error::Other(
|
||||
format!("Stopping after #{} blocks because of an error", link.imported_blocks)
|
||||
)
|
||||
))
|
||||
return Poll::Ready(Err(Error::Other(format!(
|
||||
"Stopping after #{} blocks because of an error",
|
||||
link.imported_blocks
|
||||
))))
|
||||
}
|
||||
|
||||
cx.waker().wake_by_ref();
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use log::info;
|
||||
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero};
|
||||
use sc_client_api::{Backend, UsageProvider};
|
||||
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Performs a revert of `blocks` blocks.
|
||||
pub fn revert_chain<B, BA, C>(
|
||||
client: Arc<C>,
|
||||
backend: Arc<BA>,
|
||||
blocks: NumberFor<B>
|
||||
blocks: NumberFor<B>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
B: BlockT,
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use sp_runtime::{
|
||||
traits::{Block as BlockT, NumberFor},
|
||||
};
|
||||
use sp_runtime::traits::{Block as BlockT, NumberFor};
|
||||
|
||||
use sc_client_api::{ForkBlocks, BadBlocks};
|
||||
use sc_client_api::{BadBlocks, ForkBlocks};
|
||||
|
||||
/// Chain specification rules lookup result.
|
||||
pub enum LookupResult<B: BlockT> {
|
||||
@@ -33,7 +31,7 @@ pub enum LookupResult<B: BlockT> {
|
||||
/// The block is known to be bad and should not be imported
|
||||
KnownBad,
|
||||
/// There is a specified canonical block hash for the given height
|
||||
Expected(B::Hash)
|
||||
Expected(B::Hash),
|
||||
}
|
||||
|
||||
/// Chain-specific block filtering rules.
|
||||
@@ -47,10 +45,7 @@ pub struct BlockRules<B: BlockT> {
|
||||
|
||||
impl<B: BlockT> BlockRules<B> {
|
||||
/// New block rules with provided black and white lists.
|
||||
pub fn new(
|
||||
fork_blocks: ForkBlocks<B>,
|
||||
bad_blocks: BadBlocks<B>,
|
||||
) -> Self {
|
||||
pub fn new(fork_blocks: ForkBlocks<B>, bad_blocks: BadBlocks<B>) -> Self {
|
||||
Self {
|
||||
bad: bad_blocks.unwrap_or_else(|| HashSet::new()),
|
||||
forks: fork_blocks.unwrap_or_else(|| vec![]).into_iter().collect(),
|
||||
@@ -66,7 +61,7 @@ impl<B: BlockT> BlockRules<B> {
|
||||
pub fn lookup(&self, number: NumberFor<B>, hash: &B::Hash) -> LookupResult<B> {
|
||||
if let Some(hash_for_height) = self.forks.get(&number) {
|
||||
if hash_for_height != hash {
|
||||
return LookupResult::Expected(hash_for_height.clone());
|
||||
return LookupResult::Expected(hash_for_height.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,23 +16,25 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{sync::Arc, panic::UnwindSafe, result, cell::RefCell};
|
||||
use codec::{Encode, Decode};
|
||||
use super::{client::ClientConfig, wasm_override::WasmOverride, wasm_substitutes::WasmSubstitutes};
|
||||
use codec::{Decode, Encode};
|
||||
use sc_client_api::{backend, call_executor::CallExecutor};
|
||||
use sc_executor::{NativeVersion, RuntimeInfo, RuntimeVersion};
|
||||
use sp_api::{ProofRecorder, StorageTransactionCache};
|
||||
use sp_core::{
|
||||
traits::{CodeExecutor, RuntimeCode, SpawnNamed},
|
||||
NativeOrEncoded, NeverNativeValue,
|
||||
};
|
||||
use sp_externalities::Extensions;
|
||||
use sp_runtime::{
|
||||
generic::BlockId, traits::{Block as BlockT, HashFor, NumberFor},
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, HashFor, NumberFor},
|
||||
};
|
||||
use sp_state_machine::{
|
||||
self, OverlayedChanges, Ext, ExecutionManager, StateMachine, ExecutionStrategy,
|
||||
backend::Backend as _, StorageProof,
|
||||
self, backend::Backend as _, ExecutionManager, ExecutionStrategy, Ext, OverlayedChanges,
|
||||
StateMachine, StorageProof,
|
||||
};
|
||||
use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
|
||||
use sp_externalities::Extensions;
|
||||
use sp_core::{
|
||||
NativeOrEncoded, NeverNativeValue, traits::{CodeExecutor, SpawnNamed, RuntimeCode},
|
||||
};
|
||||
use sp_api::{ProofRecorder, StorageTransactionCache};
|
||||
use sc_client_api::{backend, call_executor::CallExecutor};
|
||||
use super::{client::ClientConfig, wasm_override::WasmOverride, wasm_substitutes::WasmSubstitutes};
|
||||
use std::{cell::RefCell, panic::UnwindSafe, result, sync::Arc};
|
||||
|
||||
/// Call executor that executes methods locally, querying all required
|
||||
/// data from local backend.
|
||||
@@ -57,7 +59,8 @@ where
|
||||
spawn_handle: Box<dyn SpawnNamed>,
|
||||
client_config: ClientConfig<Block>,
|
||||
) -> sp_blockchain::Result<Self> {
|
||||
let wasm_override = client_config.wasm_runtime_overrides
|
||||
let wasm_override = client_config
|
||||
.wasm_runtime_overrides
|
||||
.as_ref()
|
||||
.map(|p| WasmOverride::new(p.clone(), executor.clone()))
|
||||
.transpose()?;
|
||||
@@ -91,10 +94,12 @@ where
|
||||
B: backend::Backend<Block>,
|
||||
{
|
||||
let spec = self.runtime_version(id)?.spec_version;
|
||||
let code = if let Some(d) = self.wasm_override
|
||||
let code = if let Some(d) = self
|
||||
.wasm_override
|
||||
.as_ref()
|
||||
.map(|o| o.get(&spec, onchain_code.heap_pages))
|
||||
.flatten() {
|
||||
.flatten()
|
||||
{
|
||||
log::debug!(target: "wasm_overrides", "using WASM override for block {}", id);
|
||||
d
|
||||
} else if let Some(s) = self.wasm_substitutes.get(spec, onchain_code.heap_pages, id) {
|
||||
@@ -113,7 +118,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT, B, E> Clone for LocalCallExecutor<Block, B, E> where E: Clone {
|
||||
impl<Block: BlockT, B, E> Clone for LocalCallExecutor<Block, B, E>
|
||||
where
|
||||
E: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
LocalCallExecutor {
|
||||
backend: self.backend.clone(),
|
||||
@@ -145,13 +153,12 @@ where
|
||||
extensions: Option<Extensions>,
|
||||
) -> sp_blockchain::Result<Vec<u8>> {
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let changes_trie = backend::changes_tries_state_at_block(
|
||||
id, self.backend.changes_trie_storage()
|
||||
)?;
|
||||
let changes_trie =
|
||||
backend::changes_tries_state_at_block(id, self.backend.changes_trie_storage())?;
|
||||
let state = self.backend.state_at(*id)?;
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
|
||||
let runtime_code = state_runtime_code.runtime_code()
|
||||
.map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code = self.check_override(runtime_code, id)?;
|
||||
|
||||
let return_data = StateMachine::new(
|
||||
@@ -164,7 +171,8 @@ where
|
||||
extensions.unwrap_or_default(),
|
||||
&runtime_code,
|
||||
self.spawn_handle.clone(),
|
||||
).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
|
||||
)
|
||||
.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
|
||||
strategy.get_manager(),
|
||||
None,
|
||||
)?;
|
||||
@@ -175,7 +183,7 @@ where
|
||||
fn contextual_call<
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
|
||||
@@ -185,15 +193,17 @@ where
|
||||
method: &str,
|
||||
call_data: &[u8],
|
||||
changes: &RefCell<OverlayedChanges>,
|
||||
storage_transaction_cache: Option<&RefCell<
|
||||
StorageTransactionCache<Block, B::State>
|
||||
>>,
|
||||
storage_transaction_cache: Option<&RefCell<StorageTransactionCache<Block, B::State>>>,
|
||||
execution_manager: ExecutionManager<EM>,
|
||||
native_call: Option<NC>,
|
||||
recorder: &Option<ProofRecorder<Block>>,
|
||||
extensions: Option<Extensions>,
|
||||
) -> Result<NativeOrEncoded<R>, sp_blockchain::Error> where ExecutionManager<EM>: Clone {
|
||||
let changes_trie_state = backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?;
|
||||
) -> Result<NativeOrEncoded<R>, sp_blockchain::Error>
|
||||
where
|
||||
ExecutionManager<EM>: Clone,
|
||||
{
|
||||
let changes_trie_state =
|
||||
backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?;
|
||||
let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut());
|
||||
|
||||
let mut state = self.backend.state_at(*at)?;
|
||||
@@ -202,16 +212,17 @@ where
|
||||
|
||||
match recorder {
|
||||
Some(recorder) => {
|
||||
let trie_state = state.as_trie_backend()
|
||||
.ok_or_else(||
|
||||
Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) as Box<dyn sp_state_machine::Error>
|
||||
)?;
|
||||
let trie_state = state.as_trie_backend().ok_or_else(|| {
|
||||
Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof)
|
||||
as Box<dyn sp_state_machine::Error>
|
||||
})?;
|
||||
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(trie_state);
|
||||
let state_runtime_code =
|
||||
sp_state_machine::backend::BackendRuntimeCode::new(trie_state);
|
||||
// It is important to extract the runtime code here before we create the proof
|
||||
// recorder.
|
||||
let runtime_code = state_runtime_code.runtime_code()
|
||||
.map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code = self.check_override(runtime_code, at)?;
|
||||
|
||||
let backend = sp_state_machine::ProvingBackend::new_with_recorder(
|
||||
@@ -239,8 +250,8 @@ where
|
||||
},
|
||||
None => {
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
|
||||
let runtime_code = state_runtime_code.runtime_code()
|
||||
.map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code = self.check_override(runtime_code, at)?;
|
||||
|
||||
let mut state_machine = StateMachine::new(
|
||||
@@ -253,34 +264,31 @@ where
|
||||
extensions.unwrap_or_default(),
|
||||
&runtime_code,
|
||||
self.spawn_handle.clone(),
|
||||
).with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c));
|
||||
)
|
||||
.with_storage_transaction_cache(
|
||||
storage_transaction_cache.as_mut().map(|c| &mut **c),
|
||||
);
|
||||
state_machine.execute_using_consensus_failure_handler(
|
||||
execution_manager,
|
||||
native_call.map(|n| || (n)().map_err(|e| Box::new(e) as Box<_>)),
|
||||
)
|
||||
}
|
||||
}.map_err(Into::into)
|
||||
},
|
||||
}
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn runtime_version(&self, id: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let changes_trie_state = backend::changes_tries_state_at_block(
|
||||
id,
|
||||
self.backend.changes_trie_storage(),
|
||||
)?;
|
||||
let changes_trie_state =
|
||||
backend::changes_tries_state_at_block(id, self.backend.changes_trie_storage())?;
|
||||
let state = self.backend.state_at(*id)?;
|
||||
let mut cache = StorageTransactionCache::<Block, B::State>::default();
|
||||
let mut ext = Ext::new(
|
||||
&mut overlay,
|
||||
&mut cache,
|
||||
&state,
|
||||
changes_trie_state,
|
||||
None,
|
||||
);
|
||||
let mut ext = Ext::new(&mut overlay, &mut cache, &state, changes_trie_state, None);
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
|
||||
let runtime_code = state_runtime_code.runtime_code()
|
||||
.map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
self.executor.runtime_version(&mut ext, &runtime_code)
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
self.executor
|
||||
.runtime_version(&mut ext, &runtime_code)
|
||||
.map_err(|e| sp_blockchain::Error::VersionInvalid(format!("{:?}", e)).into())
|
||||
}
|
||||
|
||||
@@ -289,11 +297,11 @@ where
|
||||
trie_state: &sp_state_machine::TrieBackend<S, HashFor<Block>>,
|
||||
overlay: &mut OverlayedChanges,
|
||||
method: &str,
|
||||
call_data: &[u8]
|
||||
call_data: &[u8],
|
||||
) -> Result<(Vec<u8>, StorageProof), sp_blockchain::Error> {
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(trie_state);
|
||||
let runtime_code = state_runtime_code.runtime_code()
|
||||
.map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
sp_state_machine::prove_execution_on_trie_backend::<_, _, NumberFor<Block>, _, _>(
|
||||
trie_state,
|
||||
overlay,
|
||||
@@ -312,19 +320,16 @@ where
|
||||
}
|
||||
|
||||
impl<Block, B, E> sp_version::GetRuntimeVersion<Block> for LocalCallExecutor<Block, B, E>
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
E: CodeExecutor + RuntimeInfo + Clone + 'static,
|
||||
Block: BlockT,
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
E: CodeExecutor + RuntimeInfo + Clone + 'static,
|
||||
Block: BlockT,
|
||||
{
|
||||
fn native_version(&self) -> &sp_version::NativeVersion {
|
||||
self.executor.native_version()
|
||||
}
|
||||
|
||||
fn runtime_version(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
) -> Result<sp_version::RuntimeVersion, String> {
|
||||
fn runtime_version(&self, at: &BlockId<Block>) -> Result<sp_version::RuntimeVersion, String> {
|
||||
CallExecutor::runtime_version(self, at).map_err(|e| format!("{:?}", e))
|
||||
}
|
||||
}
|
||||
@@ -332,10 +337,13 @@ impl<Block, B, E> sp_version::GetRuntimeVersion<Block> for LocalCallExecutor<Blo
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_test_runtime_client::{LocalExecutor, GenesisInit, runtime};
|
||||
use sc_executor::{NativeExecutor, WasmExecutionMethod};
|
||||
use sp_core::{traits::{WrappedRuntimeCode, FetchRuntimeCode}, testing::TaskExecutor};
|
||||
use sc_client_api::in_mem;
|
||||
use sc_executor::{NativeExecutor, WasmExecutionMethod};
|
||||
use sp_core::{
|
||||
testing::TaskExecutor,
|
||||
traits::{FetchRuntimeCode, WrappedRuntimeCode},
|
||||
};
|
||||
use substrate_test_runtime_client::{runtime, GenesisInit, LocalExecutor};
|
||||
|
||||
#[test]
|
||||
fn should_get_override_if_exists() {
|
||||
@@ -372,7 +380,8 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
).expect("Creates a client");
|
||||
)
|
||||
.expect("Creates a client");
|
||||
|
||||
let call_executor = LocalCallExecutor {
|
||||
backend: backend.clone(),
|
||||
@@ -384,10 +393,12 @@ mod tests {
|
||||
Default::default(),
|
||||
executor.clone(),
|
||||
backend.clone(),
|
||||
).unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
let check = call_executor.check_override(onchain_code, &BlockId::Number(Default::default()))
|
||||
let check = call_executor
|
||||
.check_override(onchain_code, &BlockId::Number(Default::default()))
|
||||
.expect("RuntimeCode override");
|
||||
|
||||
assert_eq!(Some(vec![2, 2, 2, 2, 2, 2, 2, 2]), check.fetch_runtime_code().map(Into::into));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,17 +18,12 @@
|
||||
|
||||
//! Tool for creating the genesis block.
|
||||
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero};
|
||||
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero};
|
||||
|
||||
/// Create a genesis block, given the initial storage.
|
||||
pub fn construct_genesis_block<
|
||||
Block: BlockT
|
||||
> (
|
||||
state_root: Block::Hash
|
||||
) -> Block {
|
||||
let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
Vec::new(),
|
||||
);
|
||||
pub fn construct_genesis_block<Block: BlockT>(state_root: Block::Hash) -> Block {
|
||||
let extrinsics_root =
|
||||
<<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(Vec::new());
|
||||
|
||||
Block::new(
|
||||
<<Block as BlockT>::Header as HeaderT>::new(
|
||||
@@ -36,8 +31,8 @@ pub fn construct_genesis_block<
|
||||
extrinsics_root,
|
||||
state_root,
|
||||
Default::default(),
|
||||
Default::default()
|
||||
Default::default(),
|
||||
),
|
||||
Default::default()
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,15 +20,20 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use sc_executor::RuntimeInfo;
|
||||
use sp_core::traits::{CodeExecutor, SpawnNamed};
|
||||
use sc_telemetry::TelemetryHandle;
|
||||
use sp_runtime::BuildStorage;
|
||||
use sp_runtime::traits::{Block as BlockT, HashFor};
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_executor::RuntimeInfo;
|
||||
use sc_telemetry::TelemetryHandle;
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
use sp_core::traits::{CodeExecutor, SpawnNamed};
|
||||
use sp_runtime::{
|
||||
traits::{Block as BlockT, HashFor},
|
||||
BuildStorage,
|
||||
};
|
||||
|
||||
use super::{call_executor::LocalCallExecutor, client::{Client, ClientConfig}};
|
||||
use super::{
|
||||
call_executor::LocalCallExecutor,
|
||||
client::{Client, ClientConfig},
|
||||
};
|
||||
use sc_client_api::light::Storage as BlockchainStorage;
|
||||
use sc_light::{Backend, GenesisCallExecutor};
|
||||
|
||||
@@ -41,26 +46,26 @@ pub fn new_light<B, S, RA, E>(
|
||||
prometheus_registry: Option<Registry>,
|
||||
telemetry: Option<TelemetryHandle>,
|
||||
) -> ClientResult<
|
||||
Client<
|
||||
Client<
|
||||
Backend<S, HashFor<B>>,
|
||||
GenesisCallExecutor<
|
||||
Backend<S, HashFor<B>>,
|
||||
GenesisCallExecutor<
|
||||
Backend<S, HashFor<B>>,
|
||||
LocalCallExecutor<B, Backend<S, HashFor<B>>, E>
|
||||
>,
|
||||
B,
|
||||
RA
|
||||
>
|
||||
>
|
||||
where
|
||||
B: BlockT,
|
||||
S: BlockchainStorage<B> + 'static,
|
||||
E: CodeExecutor + RuntimeInfo + Clone + 'static,
|
||||
LocalCallExecutor<B, Backend<S, HashFor<B>>, E>,
|
||||
>,
|
||||
B,
|
||||
RA,
|
||||
>,
|
||||
>
|
||||
where
|
||||
B: BlockT,
|
||||
S: BlockchainStorage<B> + 'static,
|
||||
E: CodeExecutor + RuntimeInfo + Clone + 'static,
|
||||
{
|
||||
let local_executor = LocalCallExecutor::new(
|
||||
backend.clone(),
|
||||
code_executor,
|
||||
spawn_handle.clone(),
|
||||
ClientConfig::default()
|
||||
ClientConfig::default(),
|
||||
)?;
|
||||
let executor = GenesisCallExecutor::new(backend.clone(), local_executor);
|
||||
Client::new(
|
||||
|
||||
@@ -45,11 +45,11 @@
|
||||
//! the ways in which the runtime can interface with the outside. Any code that builds a `Client`
|
||||
//! is responsible for putting the right marker.
|
||||
|
||||
pub mod genesis;
|
||||
pub mod light;
|
||||
mod block_rules;
|
||||
mod call_executor;
|
||||
mod client;
|
||||
mod block_rules;
|
||||
pub mod genesis;
|
||||
pub mod light;
|
||||
mod wasm_override;
|
||||
mod wasm_substitutes;
|
||||
|
||||
@@ -58,5 +58,5 @@ pub use self::{
|
||||
client::{Client, ClientConfig},
|
||||
};
|
||||
|
||||
#[cfg(feature="test-helpers")]
|
||||
pub use self::client::{new_with_backend, new_in_mem};
|
||||
#[cfg(feature = "test-helpers")]
|
||||
pub use self::client::{new_in_mem, new_with_backend};
|
||||
|
||||
@@ -35,18 +35,17 @@
|
||||
//! A custom WASM blob will override on-chain WASM if the spec version matches. If it is
|
||||
//! required to overrides multiple runtimes, multiple WASM blobs matching each of the spec versions
|
||||
//! needed must be provided in the given directory.
|
||||
//!
|
||||
use std::{
|
||||
fs, collections::{HashMap, hash_map::DefaultHasher},
|
||||
path::{Path, PathBuf},
|
||||
hash::Hasher as _,
|
||||
};
|
||||
use sp_core::traits::FetchRuntimeCode;
|
||||
use sp_state_machine::BasicExternalities;
|
||||
use sp_blockchain::Result;
|
||||
use sc_executor::RuntimeInfo;
|
||||
use sp_blockchain::Result;
|
||||
use sp_core::traits::{FetchRuntimeCode, RuntimeCode};
|
||||
use sp_state_machine::BasicExternalities;
|
||||
use sp_version::RuntimeVersion;
|
||||
use sp_core::traits::RuntimeCode;
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, HashMap},
|
||||
fs,
|
||||
hash::Hasher as _,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
/// Auxiliary structure that holds a wasm blob and its hash.
|
||||
@@ -62,11 +61,7 @@ impl WasmBlob {
|
||||
}
|
||||
|
||||
fn runtime_code(&self, heap_pages: Option<u64>) -> RuntimeCode {
|
||||
RuntimeCode {
|
||||
code_fetcher: self,
|
||||
hash: self.hash.clone(),
|
||||
heap_pages,
|
||||
}
|
||||
RuntimeCode { code_fetcher: self, hash: self.hash.clone(), heap_pages }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +112,7 @@ pub struct WasmOverride<E> {
|
||||
|
||||
impl<E> WasmOverride<E>
|
||||
where
|
||||
E: RuntimeInfo + Clone + 'static
|
||||
E: RuntimeInfo + Clone + 'static,
|
||||
{
|
||||
pub fn new<P>(path: P, executor: E) -> Result<Self>
|
||||
where
|
||||
@@ -130,26 +125,19 @@ where
|
||||
/// Gets an override by it's runtime spec version.
|
||||
///
|
||||
/// Returns `None` if an override for a spec version does not exist.
|
||||
pub fn get<'a, 'b: 'a>(
|
||||
&'b self,
|
||||
spec: &u32,
|
||||
pages: Option<u64>,
|
||||
) -> Option<RuntimeCode<'a>> {
|
||||
self.overrides
|
||||
.get(spec)
|
||||
.map(|w| w.runtime_code(pages))
|
||||
pub fn get<'a, 'b: 'a>(&'b self, spec: &u32, pages: Option<u64>) -> Option<RuntimeCode<'a>> {
|
||||
self.overrides.get(spec).map(|w| w.runtime_code(pages))
|
||||
}
|
||||
|
||||
/// Scrapes a folder for WASM runtimes.
|
||||
/// Returns a hashmap of the runtime version and wasm runtime code.
|
||||
fn scrape_overrides(dir: &Path, executor: &E) -> Result<HashMap<u32, WasmBlob>> {
|
||||
|
||||
let handle_err = |e: std::io::Error | -> sp_blockchain::Error {
|
||||
let handle_err = |e: std::io::Error| -> sp_blockchain::Error {
|
||||
WasmOverrideError::Io(dir.to_owned(), e).into()
|
||||
};
|
||||
|
||||
if !dir.is_dir() {
|
||||
return Err(WasmOverrideError::NotADirectory(dir.to_owned()).into());
|
||||
return Err(WasmOverrideError::NotADirectory(dir.to_owned()).into())
|
||||
}
|
||||
|
||||
let mut overrides = HashMap::new();
|
||||
@@ -176,13 +164,13 @@ where
|
||||
);
|
||||
duplicates.push(format!("{}", path.display()));
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
if !duplicates.is_empty() {
|
||||
return Err(WasmOverrideError::DuplicateRuntime(duplicates).into());
|
||||
return Err(WasmOverrideError::DuplicateRuntime(duplicates).into())
|
||||
}
|
||||
|
||||
Ok(overrides)
|
||||
@@ -194,7 +182,8 @@ where
|
||||
heap_pages: Option<u64>,
|
||||
) -> Result<RuntimeVersion> {
|
||||
let mut ext = BasicExternalities::default();
|
||||
executor.runtime_version(&mut ext, &code.runtime_code(heap_pages))
|
||||
executor
|
||||
.runtime_version(&mut ext, &code.runtime_code(heap_pages))
|
||||
.map_err(|e| WasmOverrideError::VersionInvalid(format!("{:?}", e)).into())
|
||||
}
|
||||
}
|
||||
@@ -203,28 +192,25 @@ where
|
||||
#[cfg(test)]
|
||||
pub fn dummy_overrides<E>(executor: &E) -> WasmOverride<E>
|
||||
where
|
||||
E: RuntimeInfo + Clone + 'static
|
||||
E: RuntimeInfo + Clone + 'static,
|
||||
{
|
||||
let mut overrides = HashMap::new();
|
||||
overrides.insert(0, WasmBlob::new(vec![0, 0, 0, 0, 0, 0, 0, 0]));
|
||||
overrides.insert(1, WasmBlob::new(vec![1, 1, 1, 1, 1, 1, 1, 1]));
|
||||
overrides.insert(2, WasmBlob::new(vec![2, 2, 2, 2, 2, 2, 2, 2]));
|
||||
WasmOverride {
|
||||
overrides,
|
||||
executor: executor.clone()
|
||||
}
|
||||
WasmOverride { overrides, executor: executor.clone() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sc_executor::{NativeExecutor, WasmExecutionMethod};
|
||||
use substrate_test_runtime_client::LocalExecutor;
|
||||
use std::fs::{self, File};
|
||||
use substrate_test_runtime_client::LocalExecutor;
|
||||
|
||||
fn wasm_test<F>(fun: F)
|
||||
where
|
||||
F: Fn(&Path, &[u8], &NativeExecutor::<LocalExecutor>)
|
||||
F: Fn(&Path, &[u8], &NativeExecutor<LocalExecutor>),
|
||||
{
|
||||
let exec = NativeExecutor::<substrate_test_runtime_client::LocalExecutor>::new(
|
||||
WasmExecutionMethod::Interpreted,
|
||||
@@ -252,8 +238,8 @@ mod tests {
|
||||
fn should_scrape_wasm() {
|
||||
wasm_test(|dir, wasm_bytes, exec| {
|
||||
fs::write(dir.join("test.wasm"), wasm_bytes).expect("Create test file");
|
||||
let overrides = WasmOverride::scrape_overrides(dir, exec)
|
||||
.expect("HashMap of u32 and WasmBlob");
|
||||
let overrides =
|
||||
WasmOverride::scrape_overrides(dir, exec).expect("HashMap of u32 and WasmBlob");
|
||||
let wasm = overrides.get(&2).expect("WASM binary");
|
||||
assert_eq!(wasm.code, substrate_test_runtime::wasm_binary_unwrap().to_vec())
|
||||
});
|
||||
@@ -272,10 +258,10 @@ mod tests {
|
||||
Some(WasmOverrideError::DuplicateRuntime(duplicates)) => {
|
||||
assert_eq!(duplicates.len(), 1);
|
||||
},
|
||||
_ => panic!("Test should end with Msg Error Variant")
|
||||
_ => panic!("Test should end with Msg Error Variant"),
|
||||
}
|
||||
},
|
||||
_ => panic!("Test should end in error")
|
||||
_ => panic!("Test should end in error"),
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -286,8 +272,8 @@ mod tests {
|
||||
File::create(dir.join("README.md")).expect("Create test file");
|
||||
File::create(dir.join("LICENSE")).expect("Create a test file");
|
||||
fs::write(dir.join("test0.wasm"), wasm_bytes).expect("Create test file");
|
||||
let scraped = WasmOverride::scrape_overrides(dir, exec)
|
||||
.expect("HashMap of u32 and WasmBlob");
|
||||
let scraped =
|
||||
WasmOverride::scrape_overrides(dir, exec).expect("HashMap of u32 and WasmBlob");
|
||||
assert_eq!(scraped.len(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,15 +18,22 @@
|
||||
|
||||
//! # WASM substitutes
|
||||
|
||||
use std::{collections::{HashMap, hash_map::DefaultHasher}, hash::Hasher as _, sync::Arc};
|
||||
use sp_core::traits::{FetchRuntimeCode, RuntimeCode};
|
||||
use sp_state_machine::BasicExternalities;
|
||||
use sp_blockchain::{Result, HeaderBackend};
|
||||
use sc_executor::RuntimeInfo;
|
||||
use sp_version::RuntimeVersion;
|
||||
use sc_client_api::backend;
|
||||
use sp_runtime::{traits::{NumberFor, Block as BlockT}, generic::BlockId};
|
||||
use parking_lot::RwLock;
|
||||
use sc_client_api::backend;
|
||||
use sc_executor::RuntimeInfo;
|
||||
use sp_blockchain::{HeaderBackend, Result};
|
||||
use sp_core::traits::{FetchRuntimeCode, RuntimeCode};
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, NumberFor},
|
||||
};
|
||||
use sp_state_machine::BasicExternalities;
|
||||
use sp_version::RuntimeVersion;
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, HashMap},
|
||||
hash::Hasher as _,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
/// A wasm substitute for the on chain wasm.
|
||||
#[derive(Debug)]
|
||||
@@ -51,11 +58,7 @@ impl<Block: BlockT> WasmSubstitute<Block> {
|
||||
}
|
||||
|
||||
fn runtime_code(&self, heap_pages: Option<u64>) -> RuntimeCode {
|
||||
RuntimeCode {
|
||||
code_fetcher: self,
|
||||
hash: self.hash.clone(),
|
||||
heap_pages,
|
||||
}
|
||||
RuntimeCode { code_fetcher: self, hash: self.hash.clone(), heap_pages }
|
||||
}
|
||||
|
||||
/// Returns `true` when the substitute matches for the given `block_id`.
|
||||
@@ -82,7 +85,8 @@ impl<Block: BlockT> WasmSubstitute<Block> {
|
||||
block_number
|
||||
};
|
||||
|
||||
let requested_block_number = backend.blockchain().block_number_from_id(&block_id).ok().flatten();
|
||||
let requested_block_number =
|
||||
backend.blockchain().block_number_from_id(&block_id).ok().flatten();
|
||||
|
||||
Some(block_number) <= requested_block_number
|
||||
}
|
||||
@@ -145,11 +149,14 @@ where
|
||||
executor: Executor,
|
||||
backend: Arc<Backend>,
|
||||
) -> Result<Self> {
|
||||
let substitutes = substitutes.into_iter().map(|(parent_block_hash, code)| {
|
||||
let substitute = WasmSubstitute::new(code, parent_block_hash, &*backend)?;
|
||||
let version = Self::runtime_version(&executor, &substitute)?;
|
||||
Ok((version.spec_version, substitute))
|
||||
}).collect::<Result<HashMap<_, _>>>()?;
|
||||
let substitutes = substitutes
|
||||
.into_iter()
|
||||
.map(|(parent_block_hash, code)| {
|
||||
let substitute = WasmSubstitute::new(code, parent_block_hash, &*backend)?;
|
||||
let version = Self::runtime_version(&executor, &substitute)?;
|
||||
Ok((version.spec_version, substitute))
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>>>()?;
|
||||
|
||||
Ok(Self { executor, substitutes: Arc::new(substitutes), backend })
|
||||
}
|
||||
@@ -172,8 +179,8 @@ where
|
||||
code: &WasmSubstitute<Block>,
|
||||
) -> Result<RuntimeVersion> {
|
||||
let mut ext = BasicExternalities::default();
|
||||
executor.runtime_version(&mut ext, &code.runtime_code(None))
|
||||
executor
|
||||
.runtime_version(&mut ext, &code.runtime_code(None))
|
||||
.map_err(|e| WasmSubstituteError::VersionInvalid(format!("{:?}", e)).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,25 +18,34 @@
|
||||
|
||||
//! Service configuration.
|
||||
|
||||
pub use sc_client_api::execution_extensions::{ExecutionStrategies, ExecutionStrategy};
|
||||
pub use sc_client_db::{
|
||||
Database, PruningMode, DatabaseSettingsSrc as DatabaseConfig,
|
||||
KeepBlocks, TransactionStorageMode
|
||||
};
|
||||
pub use sc_network::Multiaddr;
|
||||
pub use sc_network::config::{
|
||||
ExtTransport, MultiaddrWithPeerId, NetworkConfiguration, Role, NodeKeyConfig,
|
||||
SetConfig, NonDefaultSetConfig, TransportConfig,
|
||||
RequestResponseConfig, IncomingRequest, OutgoingResponse,
|
||||
Database, DatabaseSettingsSrc as DatabaseConfig, KeepBlocks, PruningMode,
|
||||
TransactionStorageMode,
|
||||
};
|
||||
pub use sc_executor::WasmExecutionMethod;
|
||||
pub use sc_client_api::execution_extensions::{ExecutionStrategies, ExecutionStrategy};
|
||||
pub use sc_network::{
|
||||
config::{
|
||||
ExtTransport, IncomingRequest, MultiaddrWithPeerId, NetworkConfiguration, NodeKeyConfig,
|
||||
NonDefaultSetConfig, OutgoingResponse, RequestResponseConfig, Role, SetConfig,
|
||||
TransportConfig,
|
||||
},
|
||||
Multiaddr,
|
||||
};
|
||||
|
||||
use std::{io, future::Future, path::{PathBuf, Path}, pin::Pin, net::SocketAddr, sync::Arc};
|
||||
pub use sc_transaction_pool::Options as TransactionPoolOptions;
|
||||
use sc_chain_spec::ChainSpec;
|
||||
use sp_core::crypto::SecretString;
|
||||
pub use sc_telemetry::TelemetryEndpoints;
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_chain_spec::ChainSpec;
|
||||
pub use sc_telemetry::TelemetryEndpoints;
|
||||
pub use sc_transaction_pool::Options as TransactionPoolOptions;
|
||||
use sp_core::crypto::SecretString;
|
||||
use std::{
|
||||
future::Future,
|
||||
io,
|
||||
net::SocketAddr,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
};
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -153,7 +162,7 @@ pub enum KeystoreConfig {
|
||||
/// The path of the keystore.
|
||||
path: PathBuf,
|
||||
/// Node keystore's password.
|
||||
password: Option<SecretString>
|
||||
password: Option<SecretString>,
|
||||
},
|
||||
/// In-memory keystore. Recommended for in-browser nodes.
|
||||
InMemory,
|
||||
@@ -194,7 +203,7 @@ impl PrometheusConfig {
|
||||
Self {
|
||||
port,
|
||||
registry: Registry::new_custom(Some("substrate".into()), None)
|
||||
.expect("this can only fail if the prefix is empty")
|
||||
.expect("this can only fail if the prefix is empty"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,11 +224,13 @@ impl Configuration {
|
||||
let protocol_id_full = match self.chain_spec.protocol_id() {
|
||||
Some(pid) => pid,
|
||||
None => {
|
||||
log::warn!("Using default protocol ID {:?} because none is configured in the \
|
||||
chain specs", crate::DEFAULT_PROTOCOL_ID
|
||||
log::warn!(
|
||||
"Using default protocol ID {:?} because none is configured in the \
|
||||
chain specs",
|
||||
crate::DEFAULT_PROTOCOL_ID
|
||||
);
|
||||
crate::DEFAULT_PROTOCOL_ID
|
||||
}
|
||||
},
|
||||
};
|
||||
sc_network::config::ProtocolId::from(protocol_id_full)
|
||||
}
|
||||
@@ -261,9 +272,7 @@ impl BasePath {
|
||||
/// instance is dropped.
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
pub fn new_temp_dir() -> io::Result<BasePath> {
|
||||
Ok(BasePath::Temporary(
|
||||
tempfile::Builder::new().prefix("substrate").tempdir()?,
|
||||
))
|
||||
Ok(BasePath::Temporary(tempfile::Builder::new().prefix("substrate").tempdir()?))
|
||||
}
|
||||
|
||||
/// Create a `BasePath` instance based on an existing path on disk.
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
//! Errors that can occur during the service operation.
|
||||
|
||||
use sc_network;
|
||||
use sc_keystore;
|
||||
use sp_consensus;
|
||||
use sc_network;
|
||||
use sp_blockchain;
|
||||
use sp_consensus;
|
||||
|
||||
/// Service Result typedef.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
+137
-122
@@ -22,65 +22,62 @@
|
||||
#![warn(missing_docs)]
|
||||
#![recursion_limit = "1024"]
|
||||
|
||||
pub mod config;
|
||||
pub mod chain_ops;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
|
||||
mod metrics;
|
||||
mod builder;
|
||||
#[cfg(feature = "test-helpers")]
|
||||
pub mod client;
|
||||
#[cfg(not(feature = "test-helpers"))]
|
||||
mod client;
|
||||
mod metrics;
|
||||
mod task_manager;
|
||||
|
||||
use std::{io, pin::Pin};
|
||||
use std::net::SocketAddr;
|
||||
use std::collections::HashMap;
|
||||
use std::task::Poll;
|
||||
use std::{collections::HashMap, io, net::SocketAddr, pin::Pin, task::Poll};
|
||||
|
||||
use futures::{Future, FutureExt, Stream, StreamExt, stream, compat::*};
|
||||
use sc_network::PeerId;
|
||||
use log::{warn, debug, error};
|
||||
use codec::{Encode, Decode};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
use codec::{Decode, Encode};
|
||||
use futures::{compat::*, stream, Future, FutureExt, Stream, StreamExt};
|
||||
use log::{debug, error, warn};
|
||||
use parity_util_mem::MallocSizeOf;
|
||||
use sc_network::PeerId;
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, Header as HeaderT},
|
||||
};
|
||||
use sp_utils::mpsc::TracingUnboundedReceiver;
|
||||
|
||||
pub use self::error::Error;
|
||||
pub use self::builder::{
|
||||
new_full_client, new_db_backend, new_client, new_full_parts, new_light_parts,
|
||||
spawn_tasks, build_network, build_offchain_workers,
|
||||
BuildNetworkParams, KeystoreContainer, NetworkStarter, SpawnTasksParams, TFullClient, TLightClient,
|
||||
TFullBackend, TLightBackend, TLightBackendWithHash, TLightClientWithBackend,
|
||||
TFullCallExecutor, TLightCallExecutor, RpcExtensionBuilder, NoopRpcExtensionBuilder,
|
||||
pub use self::{
|
||||
builder::{
|
||||
build_network, build_offchain_workers, new_client, new_db_backend, new_full_client,
|
||||
new_full_parts, new_light_parts, spawn_tasks, BuildNetworkParams, KeystoreContainer,
|
||||
NetworkStarter, NoopRpcExtensionBuilder, RpcExtensionBuilder, SpawnTasksParams,
|
||||
TFullBackend, TFullCallExecutor, TFullClient, TLightBackend, TLightBackendWithHash,
|
||||
TLightCallExecutor, TLightClient, TLightClientWithBackend,
|
||||
},
|
||||
client::{ClientConfig, LocalCallExecutor},
|
||||
error::Error,
|
||||
};
|
||||
pub use config::{
|
||||
BasePath, Configuration, DatabaseConfig, PruningMode, Role, RpcMethods, TaskExecutor, TaskType,
|
||||
KeepBlocks, TransactionStorageMode,
|
||||
BasePath, Configuration, DatabaseConfig, KeepBlocks, PruningMode, Role, RpcMethods,
|
||||
TaskExecutor, TaskType, TransactionStorageMode,
|
||||
};
|
||||
pub use sc_chain_spec::{
|
||||
ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension,
|
||||
NoExtension, ChainType,
|
||||
ChainSpec, ChainType, Extension as ChainSpecExtension, GenericChainSpec, NoExtension,
|
||||
Properties, RuntimeGenesis,
|
||||
};
|
||||
pub use sc_transaction_pool_api::{TransactionPool, InPoolTransaction, error::IntoPoolError};
|
||||
pub use sc_transaction_pool::Options as TransactionPoolOptions;
|
||||
pub use sc_rpc::Metadata as RpcMetadata;
|
||||
use sc_client_api::{blockchain::HeaderBackend, BlockchainEvents};
|
||||
pub use sc_executor::NativeExecutionDispatch;
|
||||
#[doc(hidden)]
|
||||
pub use std::{ops::Deref, result::Result, sync::Arc};
|
||||
#[doc(hidden)]
|
||||
pub use sc_network::config::{
|
||||
OnDemand, TransactionImport,
|
||||
TransactionImportFuture,
|
||||
};
|
||||
pub use sc_network::config::{OnDemand, TransactionImport, TransactionImportFuture};
|
||||
pub use sc_rpc::Metadata as RpcMetadata;
|
||||
pub use sc_tracing::TracingReceiver;
|
||||
pub use task_manager::SpawnTaskHandle;
|
||||
pub use task_manager::TaskManager;
|
||||
pub use sc_transaction_pool::Options as TransactionPoolOptions;
|
||||
pub use sc_transaction_pool_api::{error::IntoPoolError, InPoolTransaction, TransactionPool};
|
||||
pub use sp_consensus::import_queue::ImportQueue;
|
||||
pub use self::client::{LocalCallExecutor, ClientConfig};
|
||||
use sc_client_api::{blockchain::HeaderBackend, BlockchainEvents};
|
||||
#[doc(hidden)]
|
||||
pub use std::{ops::Deref, result::Result, sync::Arc};
|
||||
pub use task_manager::{SpawnTaskHandle, TaskManager};
|
||||
|
||||
const DEFAULT_PROTOCOL_ID: &str = "sup";
|
||||
|
||||
@@ -96,7 +93,9 @@ impl<T> MallocSizeOfWasm for T {}
|
||||
|
||||
/// RPC handlers that can perform RPC queries.
|
||||
#[derive(Clone)]
|
||||
pub struct RpcHandlers(Arc<jsonrpc_core::MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>>);
|
||||
pub struct RpcHandlers(
|
||||
Arc<jsonrpc_core::MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>>,
|
||||
);
|
||||
|
||||
impl RpcHandlers {
|
||||
/// Starts an RPC query.
|
||||
@@ -108,17 +107,22 @@ impl RpcHandlers {
|
||||
///
|
||||
/// If the request subscribes you to events, the `Sender` in the `RpcSession` object is used to
|
||||
/// send back spontaneous events.
|
||||
pub fn rpc_query(&self, mem: &RpcSession, request: &str)
|
||||
-> Pin<Box<dyn Future<Output = Option<String>> + Send>> {
|
||||
self.0.handle_request(request, mem.metadata.clone())
|
||||
pub fn rpc_query(
|
||||
&self,
|
||||
mem: &RpcSession,
|
||||
request: &str,
|
||||
) -> Pin<Box<dyn Future<Output = Option<String>> + Send>> {
|
||||
self.0
|
||||
.handle_request(request, mem.metadata.clone())
|
||||
.compat()
|
||||
.map(|res| res.expect("this should never fail"))
|
||||
.boxed()
|
||||
}
|
||||
|
||||
/// Provides access to the underlying `MetaIoHandler`
|
||||
pub fn io_handler(&self)
|
||||
-> Arc<jsonrpc_core::MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>> {
|
||||
pub fn io_handler(
|
||||
&self,
|
||||
) -> Arc<jsonrpc_core::MetaIoHandler<sc_rpc::Metadata, sc_rpc_server::RpcMiddleware>> {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
@@ -149,8 +153,8 @@ pub struct PartialComponents<Client, Backend, SelectChain, ImportQueue, Transact
|
||||
async fn build_network_future<
|
||||
B: BlockT,
|
||||
C: BlockchainEvents<B> + HeaderBackend<B>,
|
||||
H: sc_network::ExHashT
|
||||
> (
|
||||
H: sc_network::ExHashT,
|
||||
>(
|
||||
role: Role,
|
||||
mut network: sc_network::NetworkWorker<B, H>,
|
||||
client: Arc<C>,
|
||||
@@ -171,7 +175,9 @@ async fn build_network_future<
|
||||
// ready. This way, we only get the latest finalized block.
|
||||
stream::poll_fn(move |cx| {
|
||||
let mut last = None;
|
||||
while let Poll::Ready(Some(item)) = Pin::new(&mut finality_notification_stream).poll_next(cx) {
|
||||
while let Poll::Ready(Some(item)) =
|
||||
Pin::new(&mut finality_notification_stream).poll_next(cx)
|
||||
{
|
||||
last = Some(item);
|
||||
}
|
||||
if let Some(last) = last {
|
||||
@@ -179,11 +185,12 @@ async fn build_network_future<
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}).fuse()
|
||||
})
|
||||
.fuse()
|
||||
};
|
||||
|
||||
loop {
|
||||
futures::select!{
|
||||
futures::select! {
|
||||
// List of blocks that the client has imported.
|
||||
notification = imported_blocks_stream.next() => {
|
||||
let notification = match notification {
|
||||
@@ -338,79 +345,90 @@ mod waiting {
|
||||
/// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive.
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
fn start_rpc_servers<
|
||||
H: FnMut(sc_rpc::DenyUnsafe, sc_rpc_server::RpcMiddleware)
|
||||
-> sc_rpc_server::RpcHandler<sc_rpc::Metadata>
|
||||
H: FnMut(
|
||||
sc_rpc::DenyUnsafe,
|
||||
sc_rpc_server::RpcMiddleware,
|
||||
) -> sc_rpc_server::RpcHandler<sc_rpc::Metadata>,
|
||||
>(
|
||||
config: &Configuration,
|
||||
mut gen_handler: H,
|
||||
rpc_metrics: sc_rpc_server::RpcMetrics,
|
||||
) -> Result<Box<dyn std::any::Any + Send + Sync>, error::Error> {
|
||||
fn maybe_start_server<T, F>(address: Option<SocketAddr>, mut start: F) -> Result<Option<T>, io::Error>
|
||||
where F: FnMut(&SocketAddr) -> Result<T, io::Error>,
|
||||
{
|
||||
address.map(|mut address| start(&address)
|
||||
.or_else(|e| match e.kind() {
|
||||
io::ErrorKind::AddrInUse |
|
||||
io::ErrorKind::PermissionDenied => {
|
||||
fn maybe_start_server<T, F>(
|
||||
address: Option<SocketAddr>,
|
||||
mut start: F,
|
||||
) -> Result<Option<T>, io::Error>
|
||||
where
|
||||
F: FnMut(&SocketAddr) -> Result<T, io::Error>,
|
||||
{
|
||||
address
|
||||
.map(|mut address| {
|
||||
start(&address).or_else(|e| match e.kind() {
|
||||
io::ErrorKind::AddrInUse | io::ErrorKind::PermissionDenied => {
|
||||
warn!("Unable to bind RPC server to {}. Trying random port.", address);
|
||||
address.set_port(0);
|
||||
start(&address)
|
||||
},
|
||||
_ => Err(e),
|
||||
}
|
||||
) ).transpose()
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn deny_unsafe(addr: &SocketAddr, methods: &RpcMethods) -> sc_rpc::DenyUnsafe {
|
||||
let is_exposed_addr = !addr.ip().is_loopback();
|
||||
match (is_exposed_addr, methods) {
|
||||
| (_, RpcMethods::Unsafe)
|
||||
| (false, RpcMethods::Auto) => sc_rpc::DenyUnsafe::No,
|
||||
_ => sc_rpc::DenyUnsafe::Yes
|
||||
| (_, RpcMethods::Unsafe) | (false, RpcMethods::Auto) => sc_rpc::DenyUnsafe::No,
|
||||
_ => sc_rpc::DenyUnsafe::Yes,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Box::new((
|
||||
config.rpc_ipc.as_ref().map(|path| sc_rpc_server::start_ipc(
|
||||
&*path, gen_handler(
|
||||
sc_rpc::DenyUnsafe::No,
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics.clone(), "ipc")
|
||||
config.rpc_ipc.as_ref().map(|path| {
|
||||
sc_rpc_server::start_ipc(
|
||||
&*path,
|
||||
gen_handler(
|
||||
sc_rpc::DenyUnsafe::No,
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics.clone(), "ipc"),
|
||||
),
|
||||
)
|
||||
)),
|
||||
maybe_start_server(
|
||||
config.rpc_http,
|
||||
|address| sc_rpc_server::start_http(
|
||||
}),
|
||||
maybe_start_server(config.rpc_http, |address| {
|
||||
sc_rpc_server::start_http(
|
||||
address,
|
||||
config.rpc_http_threads,
|
||||
config.rpc_cors.as_ref(),
|
||||
gen_handler(
|
||||
deny_unsafe(&address, &config.rpc_methods),
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics.clone(), "http")
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics.clone(), "http"),
|
||||
),
|
||||
config.rpc_max_payload
|
||||
),
|
||||
)?.map(|s| waiting::HttpServer(Some(s))),
|
||||
maybe_start_server(
|
||||
config.rpc_ws,
|
||||
|address| sc_rpc_server::start_ws(
|
||||
config.rpc_max_payload,
|
||||
)
|
||||
})?
|
||||
.map(|s| waiting::HttpServer(Some(s))),
|
||||
maybe_start_server(config.rpc_ws, |address| {
|
||||
sc_rpc_server::start_ws(
|
||||
address,
|
||||
config.rpc_ws_max_connections,
|
||||
config.rpc_cors.as_ref(),
|
||||
gen_handler(
|
||||
deny_unsafe(&address, &config.rpc_methods),
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics.clone(), "ws")
|
||||
sc_rpc_server::RpcMiddleware::new(rpc_metrics.clone(), "ws"),
|
||||
),
|
||||
config.rpc_max_payload
|
||||
),
|
||||
)?.map(|s| waiting::WsServer(Some(s))),
|
||||
config.rpc_max_payload,
|
||||
)
|
||||
})?
|
||||
.map(|s| waiting::WsServer(Some(s))),
|
||||
)))
|
||||
}
|
||||
|
||||
/// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive.
|
||||
#[cfg(target_os = "unknown")]
|
||||
fn start_rpc_servers<
|
||||
H: FnMut(sc_rpc::DenyUnsafe, sc_rpc_server::RpcMiddleware)
|
||||
-> sc_rpc_server::RpcHandler<sc_rpc::Metadata>
|
||||
H: FnMut(
|
||||
sc_rpc::DenyUnsafe,
|
||||
sc_rpc_server::RpcMiddleware,
|
||||
) -> sc_rpc_server::RpcHandler<sc_rpc::Metadata>,
|
||||
>(
|
||||
_: &Configuration,
|
||||
_: H,
|
||||
@@ -434,9 +452,7 @@ impl RpcSession {
|
||||
///
|
||||
/// The `RpcSession` must be kept alive in order to receive messages on the sender.
|
||||
pub fn new(sender: futures01::sync::mpsc::Sender<String>) -> RpcSession {
|
||||
RpcSession {
|
||||
metadata: sender.into(),
|
||||
}
|
||||
RpcSession { metadata: sender.into() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,10 +466,9 @@ pub struct TransactionPoolAdapter<C, P> {
|
||||
/// Get transactions for propagation.
|
||||
///
|
||||
/// Function extracted to simplify the test and prevent creating `ServiceFactory`.
|
||||
fn transactions_to_propagate<Pool, B, H, E>(pool: &Pool)
|
||||
-> Vec<(H, B::Extrinsic)>
|
||||
fn transactions_to_propagate<Pool, B, H, E>(pool: &Pool) -> Vec<(H, B::Extrinsic)>
|
||||
where
|
||||
Pool: TransactionPool<Block=B, Hash=H, Error=E>,
|
||||
Pool: TransactionPool<Block = B, Hash = H, Error = E>,
|
||||
B: BlockT,
|
||||
H: std::hash::Hash + Eq + sp_runtime::traits::Member + sp_runtime::traits::MaybeSerialize,
|
||||
E: IntoPoolError + From<sc_transaction_pool_api::error::Error>,
|
||||
@@ -468,11 +483,10 @@ where
|
||||
.collect()
|
||||
}
|
||||
|
||||
impl<B, H, C, Pool, E> sc_network::config::TransactionPool<H, B> for
|
||||
TransactionPoolAdapter<C, Pool>
|
||||
impl<B, H, C, Pool, E> sc_network::config::TransactionPool<H, B> for TransactionPoolAdapter<C, Pool>
|
||||
where
|
||||
C: sc_network::config::Client<B> + Send + Sync,
|
||||
Pool: 'static + TransactionPool<Block=B, Hash=H, Error=E>,
|
||||
Pool: 'static + TransactionPool<Block = B, Hash = H, Error = E>,
|
||||
B: BlockT,
|
||||
H: std::hash::Hash + Eq + sp_runtime::traits::Member + sp_runtime::traits::MaybeSerialize,
|
||||
E: 'static + IntoPoolError + From<sc_transaction_pool_api::error::Error>,
|
||||
@@ -485,10 +499,7 @@ where
|
||||
self.pool.hash_of(transaction)
|
||||
}
|
||||
|
||||
fn import(
|
||||
&self,
|
||||
transaction: B::Extrinsic,
|
||||
) -> TransactionImportFuture {
|
||||
fn import(&self, transaction: B::Extrinsic) -> TransactionImportFuture {
|
||||
if !self.imports_external_transactions {
|
||||
debug!("Transaction rejected");
|
||||
Box::pin(futures::future::ready(TransactionImport::None));
|
||||
@@ -499,28 +510,33 @@ where
|
||||
Ok(uxt) => uxt,
|
||||
Err(e) => {
|
||||
debug!("Transaction invalid: {:?}", e);
|
||||
return Box::pin(futures::future::ready(TransactionImport::Bad));
|
||||
}
|
||||
return Box::pin(futures::future::ready(TransactionImport::Bad))
|
||||
},
|
||||
};
|
||||
|
||||
let best_block_id = BlockId::hash(self.client.info().best_hash);
|
||||
|
||||
let import_future = self.pool.submit_one(&best_block_id, sc_transaction_pool_api::TransactionSource::External, uxt);
|
||||
let import_future = self.pool.submit_one(
|
||||
&best_block_id,
|
||||
sc_transaction_pool_api::TransactionSource::External,
|
||||
uxt,
|
||||
);
|
||||
Box::pin(async move {
|
||||
match import_future.await {
|
||||
Ok(_) => TransactionImport::NewGood,
|
||||
Err(e) => match e.into_pool_error() {
|
||||
Ok(sc_transaction_pool_api::error::Error::AlreadyImported(_)) => TransactionImport::KnownGood,
|
||||
Ok(sc_transaction_pool_api::error::Error::AlreadyImported(_)) =>
|
||||
TransactionImport::KnownGood,
|
||||
Ok(e) => {
|
||||
debug!("Error adding transaction to the pool: {:?}", e);
|
||||
TransactionImport::Bad
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
debug!("Error converting pool error: {:?}", e);
|
||||
// it is not bad at least, just some internal node logic error, so peer is innocent.
|
||||
TransactionImport::KnownGood
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -530,11 +546,10 @@ where
|
||||
}
|
||||
|
||||
fn transaction(&self, hash: &H) -> Option<B::Extrinsic> {
|
||||
self.pool.ready_transaction(hash)
|
||||
.and_then(
|
||||
// Only propagable transactions should be resolved for network service.
|
||||
|tx| if tx.is_propagable() { Some(tx.data().clone()) } else { None }
|
||||
)
|
||||
self.pool.ready_transaction(hash).and_then(
|
||||
// Only propagable transactions should be resolved for network service.
|
||||
|tx| if tx.is_propagable() { Some(tx.data().clone()) } else { None },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,10 +557,13 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures::executor::block_on;
|
||||
use sc_transaction_pool::BasicPool;
|
||||
use sp_consensus::SelectChain;
|
||||
use sp_runtime::traits::BlindCheckable;
|
||||
use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}};
|
||||
use sc_transaction_pool::BasicPool;
|
||||
use substrate_test_runtime_client::{
|
||||
prelude::*,
|
||||
runtime::{Extrinsic, Transfer},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn should_not_propagate_transactions_that_are_marked_as_such() {
|
||||
@@ -553,13 +571,8 @@ mod tests {
|
||||
let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain();
|
||||
let client = Arc::new(client);
|
||||
let spawner = sp_core::testing::TaskExecutor::new();
|
||||
let pool = BasicPool::new_full(
|
||||
Default::default(),
|
||||
true.into(),
|
||||
None,
|
||||
spawner,
|
||||
client.clone(),
|
||||
);
|
||||
let pool =
|
||||
BasicPool::new_full(Default::default(), true.into(), None, spawner, client.clone());
|
||||
let source = sp_runtime::transaction_validity::TransactionSource::External;
|
||||
let best = block_on(longest_chain.best_chain()).unwrap();
|
||||
let transaction = Transfer {
|
||||
@@ -569,12 +582,14 @@ mod tests {
|
||||
to: Default::default(),
|
||||
}
|
||||
.into_signed_tx();
|
||||
block_on(pool.submit_one(&BlockId::hash(best.hash()), source, transaction.clone()))
|
||||
.unwrap();
|
||||
block_on(pool.submit_one(
|
||||
&BlockId::hash(best.hash()), source, transaction.clone()),
|
||||
).unwrap();
|
||||
block_on(pool.submit_one(
|
||||
&BlockId::hash(best.hash()), source, Extrinsic::IncludeData(vec![1])),
|
||||
).unwrap();
|
||||
&BlockId::hash(best.hash()),
|
||||
source,
|
||||
Extrinsic::IncludeData(vec![1]),
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(pool.status().ready, 2);
|
||||
|
||||
// when
|
||||
|
||||
@@ -20,16 +20,15 @@ use std::{convert::TryFrom, time::SystemTime};
|
||||
|
||||
use crate::config::Configuration;
|
||||
use futures_timer::Delay;
|
||||
use prometheus_endpoint::{register, Gauge, U64, Registry, PrometheusError, Opts, GaugeVec};
|
||||
use sc_telemetry::{telemetry, TelemetryHandle, SUBSTRATE_INFO};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_runtime::traits::{NumberFor, Block, SaturatedConversion, UniqueSaturatedInto};
|
||||
use sc_transaction_pool_api::{PoolStatus, MaintainedTransactionPool};
|
||||
use sp_utils::metrics::register_globals;
|
||||
use prometheus_endpoint::{register, Gauge, GaugeVec, Opts, PrometheusError, Registry, U64};
|
||||
use sc_client_api::{ClientInfo, UsageProvider};
|
||||
use sc_network::{config::Role, NetworkStatus, NetworkService};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use sc_network::{config::Role, NetworkService, NetworkStatus};
|
||||
use sc_telemetry::{telemetry, TelemetryHandle, SUBSTRATE_INFO};
|
||||
use sc_transaction_pool_api::{MaintainedTransactionPool, PoolStatus};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_runtime::traits::{Block, NumberFor, SaturatedConversion, UniqueSaturatedInto};
|
||||
use sp_utils::metrics::register_globals;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use wasm_timer::Instant;
|
||||
|
||||
struct PrometheusMetrics {
|
||||
@@ -51,54 +50,74 @@ impl PrometheusMetrics {
|
||||
version: &str,
|
||||
roles: u64,
|
||||
) -> Result<Self, PrometheusError> {
|
||||
register(Gauge::<U64>::with_opts(
|
||||
Opts::new(
|
||||
"build_info",
|
||||
"A metric with a constant '1' value labeled by name, version"
|
||||
)
|
||||
register(
|
||||
Gauge::<U64>::with_opts(
|
||||
Opts::new(
|
||||
"build_info",
|
||||
"A metric with a constant '1' value labeled by name, version",
|
||||
)
|
||||
.const_label("name", name)
|
||||
.const_label("version", version)
|
||||
)?, ®istry)?.set(1);
|
||||
.const_label("version", version),
|
||||
)?,
|
||||
®istry,
|
||||
)?
|
||||
.set(1);
|
||||
|
||||
register(Gauge::<U64>::new(
|
||||
"node_roles", "The roles the node is running as",
|
||||
)?, ®istry)?.set(roles);
|
||||
register(Gauge::<U64>::new("node_roles", "The roles the node is running as")?, ®istry)?
|
||||
.set(roles);
|
||||
|
||||
register_globals(registry)?;
|
||||
|
||||
let start_time_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap_or_default();
|
||||
register(Gauge::<U64>::new(
|
||||
"process_start_time_seconds",
|
||||
"Number of seconds between the UNIX epoch and the moment the process started",
|
||||
)?, registry)?.set(start_time_since_epoch.as_secs());
|
||||
let start_time_since_epoch =
|
||||
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap_or_default();
|
||||
register(
|
||||
Gauge::<U64>::new(
|
||||
"process_start_time_seconds",
|
||||
"Number of seconds between the UNIX epoch and the moment the process started",
|
||||
)?,
|
||||
registry,
|
||||
)?
|
||||
.set(start_time_since_epoch.as_secs());
|
||||
|
||||
Ok(Self {
|
||||
// generic internals
|
||||
block_height: register(GaugeVec::new(
|
||||
Opts::new("block_height", "Block height info of the chain"),
|
||||
&["status"]
|
||||
)?, registry)?,
|
||||
block_height: register(
|
||||
GaugeVec::new(
|
||||
Opts::new("block_height", "Block height info of the chain"),
|
||||
&["status"],
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
|
||||
number_leaves: register(Gauge::new(
|
||||
"number_leaves", "Number of known chain leaves (aka forks)",
|
||||
)?, registry)?,
|
||||
number_leaves: register(
|
||||
Gauge::new("number_leaves", "Number of known chain leaves (aka forks)")?,
|
||||
registry,
|
||||
)?,
|
||||
|
||||
ready_transactions_number: register(Gauge::new(
|
||||
"ready_transactions_number", "Number of transactions in the ready queue",
|
||||
)?, registry)?,
|
||||
ready_transactions_number: register(
|
||||
Gauge::new(
|
||||
"ready_transactions_number",
|
||||
"Number of transactions in the ready queue",
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
|
||||
// I/ O
|
||||
database_cache: register(Gauge::new(
|
||||
"database_cache_bytes", "RocksDB cache size in bytes",
|
||||
)?, registry)?,
|
||||
state_cache: register(Gauge::new(
|
||||
"state_cache_bytes", "State cache size in bytes",
|
||||
)?, registry)?,
|
||||
state_db: register(GaugeVec::new(
|
||||
Opts::new("state_db_cache_bytes", "State DB cache in bytes"),
|
||||
&["subtype"]
|
||||
)?, registry)?,
|
||||
database_cache: register(
|
||||
Gauge::new("database_cache_bytes", "RocksDB cache size in bytes")?,
|
||||
registry,
|
||||
)?,
|
||||
state_cache: register(
|
||||
Gauge::new("state_cache_bytes", "State cache size in bytes")?,
|
||||
registry,
|
||||
)?,
|
||||
state_db: register(
|
||||
GaugeVec::new(
|
||||
Opts::new("state_db_cache_bytes", "State DB cache in bytes"),
|
||||
&["subtype"],
|
||||
)?,
|
||||
registry,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -179,11 +198,7 @@ impl MetricsService {
|
||||
let net_status = network.status().await.ok();
|
||||
|
||||
// Update / Send the metrics.
|
||||
self.update(
|
||||
&client.usage_info(),
|
||||
&transactions.status(),
|
||||
net_status,
|
||||
);
|
||||
self.update(&client.usage_info(), &transactions.status(), net_status);
|
||||
|
||||
// Schedule next tick.
|
||||
timer.reset(timer_interval);
|
||||
@@ -220,14 +235,8 @@ impl MetricsService {
|
||||
);
|
||||
|
||||
if let Some(metrics) = self.metrics.as_ref() {
|
||||
metrics
|
||||
.block_height
|
||||
.with_label_values(&["finalized"])
|
||||
.set(finalized_number);
|
||||
metrics
|
||||
.block_height
|
||||
.with_label_values(&["best"])
|
||||
.set(best_number);
|
||||
metrics.block_height.with_label_values(&["finalized"]).set(finalized_number);
|
||||
metrics.block_height.with_label_values(&["best"]).set(best_number);
|
||||
|
||||
if let Ok(leaves) = u64::try_from(info.chain.number_leaves) {
|
||||
metrics.number_leaves.set(leaves);
|
||||
@@ -239,15 +248,17 @@ impl MetricsService {
|
||||
metrics.database_cache.set(info.memory.database_cache.as_bytes() as u64);
|
||||
metrics.state_cache.set(info.memory.state_cache.as_bytes() as u64);
|
||||
|
||||
metrics.state_db.with_label_values(&["non_canonical"]).set(
|
||||
info.memory.state_db.non_canonical.as_bytes() as u64,
|
||||
);
|
||||
metrics
|
||||
.state_db
|
||||
.with_label_values(&["non_canonical"])
|
||||
.set(info.memory.state_db.non_canonical.as_bytes() as u64);
|
||||
if let Some(pruning) = info.memory.state_db.pruning {
|
||||
metrics.state_db.with_label_values(&["pruning"]).set(pruning.as_bytes() as u64);
|
||||
}
|
||||
metrics.state_db.with_label_values(&["pinned"]).set(
|
||||
info.memory.state_db.pinned.as_bytes() as u64,
|
||||
);
|
||||
metrics
|
||||
.state_db
|
||||
.with_label_values(&["pinned"])
|
||||
.set(info.memory.state_db.pinned.as_bytes() as u64);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,14 +270,13 @@ impl MetricsService {
|
||||
|
||||
let diff_bytes_inbound = total_bytes_inbound - self.last_total_bytes_inbound;
|
||||
let diff_bytes_outbound = total_bytes_outbound - self.last_total_bytes_outbound;
|
||||
let (avg_bytes_per_sec_inbound, avg_bytes_per_sec_outbound) =
|
||||
if elapsed > 0 {
|
||||
self.last_total_bytes_inbound = total_bytes_inbound;
|
||||
self.last_total_bytes_outbound = total_bytes_outbound;
|
||||
(diff_bytes_inbound / elapsed, diff_bytes_outbound / elapsed)
|
||||
} else {
|
||||
(diff_bytes_inbound, diff_bytes_outbound)
|
||||
};
|
||||
let (avg_bytes_per_sec_inbound, avg_bytes_per_sec_outbound) = if elapsed > 0 {
|
||||
self.last_total_bytes_inbound = total_bytes_inbound;
|
||||
self.last_total_bytes_outbound = total_bytes_outbound;
|
||||
(diff_bytes_inbound / elapsed, diff_bytes_outbound / elapsed)
|
||||
} else {
|
||||
(diff_bytes_inbound, diff_bytes_outbound)
|
||||
};
|
||||
|
||||
telemetry!(
|
||||
self.telemetry;
|
||||
@@ -278,9 +288,10 @@ impl MetricsService {
|
||||
);
|
||||
|
||||
if let Some(metrics) = self.metrics.as_ref() {
|
||||
let best_seen_block: Option<u64> = net_status
|
||||
.best_seen_block
|
||||
.map(|num: NumberFor<T>| UniqueSaturatedInto::<u64>::unique_saturated_into(num));
|
||||
let best_seen_block: Option<u64> =
|
||||
net_status.best_seen_block.map(|num: NumberFor<T>| {
|
||||
UniqueSaturatedInto::<u64>::unique_saturated_into(num)
|
||||
});
|
||||
|
||||
if let Some(best_seen_block) = best_seen_block {
|
||||
metrics.block_height.with_label_values(&["sync_target"]).set(best_seen_block);
|
||||
|
||||
@@ -18,22 +18,24 @@
|
||||
|
||||
//! Substrate service tasks management module.
|
||||
|
||||
use std::{panic, result::Result, pin::Pin};
|
||||
use crate::{
|
||||
config::{JoinFuture, TaskExecutor, TaskType},
|
||||
Error,
|
||||
};
|
||||
use exit_future::Signal;
|
||||
use log::{debug, error};
|
||||
use futures::{
|
||||
Future, FutureExt, StreamExt,
|
||||
future::{select, Either, BoxFuture, join_all, try_join_all, pending},
|
||||
future::{join_all, pending, select, try_join_all, BoxFuture, Either},
|
||||
sink::SinkExt,
|
||||
Future, FutureExt, StreamExt,
|
||||
};
|
||||
use log::{debug, error};
|
||||
use prometheus_endpoint::{
|
||||
exponential_buckets, register,
|
||||
PrometheusError,
|
||||
CounterVec, HistogramOpts, HistogramVec, Opts, Registry, U64
|
||||
exponential_buckets, register, CounterVec, HistogramOpts, HistogramVec, Opts, PrometheusError,
|
||||
Registry, U64,
|
||||
};
|
||||
use sp_utils::mpsc::{TracingUnboundedSender, TracingUnboundedReceiver, tracing_unbounded};
|
||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
||||
use std::{panic, pin::Pin, result::Result};
|
||||
use tracing_futures::Instrument;
|
||||
use crate::{config::{TaskExecutor, TaskType, JoinFuture}, Error};
|
||||
|
||||
mod prometheus_future;
|
||||
#[cfg(test)]
|
||||
@@ -62,7 +64,11 @@ impl SpawnTaskHandle {
|
||||
}
|
||||
|
||||
/// Spawns the blocking task with the given name. See also `spawn`.
|
||||
pub fn spawn_blocking(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static) {
|
||||
pub fn spawn_blocking(
|
||||
&self,
|
||||
name: &'static str,
|
||||
task: impl Future<Output = ()> + Send + 'static,
|
||||
) {
|
||||
self.spawn_inner(name, task, TaskType::Blocking)
|
||||
}
|
||||
|
||||
@@ -75,7 +81,7 @@ impl SpawnTaskHandle {
|
||||
) {
|
||||
if self.task_notifier.is_closed() {
|
||||
debug!("Attempt to spawn a new task has been prevented: {}", name);
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
let on_exit = self.on_exit.clone();
|
||||
@@ -95,7 +101,8 @@ impl SpawnTaskHandle {
|
||||
let task = {
|
||||
let poll_duration = metrics.poll_duration.with_label_values(&[name]);
|
||||
let poll_start = metrics.poll_start.with_label_values(&[name]);
|
||||
let inner = prometheus_future::with_poll_durations(poll_duration, poll_start, task);
|
||||
let inner =
|
||||
prometheus_future::with_poll_durations(poll_duration, poll_start, task);
|
||||
// The logic of `AssertUnwindSafe` here is ok considering that we throw
|
||||
// away the `Future` after it has panicked.
|
||||
panic::AssertUnwindSafe(inner).catch_unwind()
|
||||
@@ -106,16 +113,15 @@ impl SpawnTaskHandle {
|
||||
Either::Right((Err(payload), _)) => {
|
||||
metrics.tasks_ended.with_label_values(&[name, "panic"]).inc();
|
||||
panic::resume_unwind(payload)
|
||||
}
|
||||
},
|
||||
Either::Right((Ok(()), _)) => {
|
||||
metrics.tasks_ended.with_label_values(&[name, "finished"]).inc();
|
||||
}
|
||||
},
|
||||
Either::Left(((), _)) => {
|
||||
// The `on_exit` has triggered.
|
||||
metrics.tasks_ended.with_label_values(&[name, "interrupted"]).inc();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
} else {
|
||||
futures::pin_mut!(task);
|
||||
let _ = select(on_exit, task).await;
|
||||
@@ -162,10 +168,7 @@ impl SpawnEssentialTaskHandle {
|
||||
essential_failed_tx: TracingUnboundedSender<()>,
|
||||
spawn_task_handle: SpawnTaskHandle,
|
||||
) -> SpawnEssentialTaskHandle {
|
||||
SpawnEssentialTaskHandle {
|
||||
essential_failed_tx,
|
||||
inner: spawn_task_handle,
|
||||
}
|
||||
SpawnEssentialTaskHandle { essential_failed_tx, inner: spawn_task_handle }
|
||||
}
|
||||
|
||||
/// Spawns the given task with the given name.
|
||||
@@ -193,12 +196,10 @@ impl SpawnEssentialTaskHandle {
|
||||
task_type: TaskType,
|
||||
) {
|
||||
let essential_failed = self.essential_failed_tx.clone();
|
||||
let essential_task = std::panic::AssertUnwindSafe(task)
|
||||
.catch_unwind()
|
||||
.map(move |_| {
|
||||
log::error!("Essential task `{}` failed. Shutting down service.", name);
|
||||
let _ = essential_failed.close_channel();
|
||||
});
|
||||
let essential_task = std::panic::AssertUnwindSafe(task).catch_unwind().map(move |_| {
|
||||
log::error!("Essential task `{}` failed. Shutting down service.", name);
|
||||
let _ = essential_failed.close_channel();
|
||||
});
|
||||
|
||||
let _ = self.inner.spawn_inner(name, essential_task, task_type);
|
||||
}
|
||||
@@ -260,10 +261,8 @@ impl TaskManager {
|
||||
// NOTE: for_each_concurrent will await on all the JoinHandle futures at the same time. It
|
||||
// is possible to limit this but it's actually better for the memory foot print to await
|
||||
// them all to not accumulate anything on that stream.
|
||||
let completion_future = executor.spawn(
|
||||
Box::pin(background_tasks.for_each_concurrent(None, |x| x)),
|
||||
TaskType::Async,
|
||||
);
|
||||
let completion_future = executor
|
||||
.spawn(Box::pin(background_tasks.for_each_concurrent(None, |x| x)), TaskType::Async);
|
||||
|
||||
Ok(Self {
|
||||
on_exit,
|
||||
@@ -323,16 +322,21 @@ impl TaskManager {
|
||||
///
|
||||
/// This function will not wait until the end of the remaining task. You must call and await
|
||||
/// `clean_shutdown()` after this.
|
||||
pub fn future<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>> {
|
||||
pub fn future<'a>(
|
||||
&'a mut self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let mut t1 = self.essential_failed_rx.next().fuse();
|
||||
let mut t2 = self.on_exit.clone().fuse();
|
||||
let mut t3 = try_join_all(
|
||||
self.children.iter_mut().map(|x| x.future())
|
||||
self.children
|
||||
.iter_mut()
|
||||
.map(|x| x.future())
|
||||
// Never end this future if there is no error because if there is no children,
|
||||
// it must not stop
|
||||
.chain(std::iter::once(pending().boxed()))
|
||||
).fuse();
|
||||
.chain(std::iter::once(pending().boxed())),
|
||||
)
|
||||
.fuse();
|
||||
|
||||
futures::select! {
|
||||
_ = t1 => Err(Error::Other("Essential task failed.".into())),
|
||||
|
||||
@@ -20,20 +20,20 @@
|
||||
|
||||
use futures::prelude::*;
|
||||
use prometheus_endpoint::{Counter, Histogram, U64};
|
||||
use std::{fmt, pin::Pin, task::{Context, Poll}};
|
||||
use std::{
|
||||
fmt,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// Wraps around a `Future`. Report the polling duration to the `Histogram` and when the polling
|
||||
/// starts to the `Counter`.
|
||||
pub fn with_poll_durations<T>(
|
||||
poll_duration: Histogram,
|
||||
poll_start: Counter<U64>,
|
||||
inner: T
|
||||
inner: T,
|
||||
) -> PrometheusFuture<T> {
|
||||
PrometheusFuture {
|
||||
inner,
|
||||
poll_duration,
|
||||
poll_start,
|
||||
}
|
||||
PrometheusFuture { inner, poll_duration, poll_start }
|
||||
}
|
||||
|
||||
/// Wraps around `Future` and adds diagnostics to it.
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::config::TaskExecutor;
|
||||
use crate::task_manager::TaskManager;
|
||||
use crate::{config::TaskExecutor, task_manager::TaskManager};
|
||||
use futures::{future::FutureExt, pin_mut, select};
|
||||
use parking_lot::Mutex;
|
||||
use std::{any::Any, sync::Arc, time::Duration};
|
||||
@@ -205,7 +204,9 @@ fn ensure_task_manager_future_ends_with_error_when_essential_task_fails() {
|
||||
runtime.block_on(async { tokio::time::delay_for(Duration::from_secs(1)).await });
|
||||
assert_eq!(drop_tester, 2);
|
||||
spawn_essential_handle.spawn("task3", async { panic!("task failed") });
|
||||
runtime.block_on(task_manager.future()).expect_err("future()'s Result must be Err");
|
||||
runtime
|
||||
.block_on(task_manager.future())
|
||||
.expect_err("future()'s Result must be Err");
|
||||
assert_eq!(drop_tester, 2);
|
||||
runtime.block_on(task_manager.clean_shutdown());
|
||||
assert_eq!(drop_tester, 0);
|
||||
@@ -265,7 +266,9 @@ fn ensure_task_manager_future_ends_with_error_when_childs_essential_task_fails()
|
||||
runtime.block_on(async { tokio::time::delay_for(Duration::from_secs(1)).await });
|
||||
assert_eq!(drop_tester, 4);
|
||||
spawn_essential_handle_child_1.spawn("task5", async { panic!("task failed") });
|
||||
runtime.block_on(task_manager.future()).expect_err("future()'s Result must be Err");
|
||||
runtime
|
||||
.block_on(task_manager.future())
|
||||
.expect_err("future()'s Result must be Err");
|
||||
assert_eq!(drop_tester, 4);
|
||||
runtime.block_on(task_manager.clean_shutdown());
|
||||
assert_eq!(drop_tester, 0);
|
||||
|
||||
Reference in New Issue
Block a user