Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions cumulus/client/service/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[package]

name = "cumulus-client-service"
version = "0.7.0"
authors.workspace = true
Expand Down Expand Up @@ -26,6 +27,7 @@ sc-rpc = { workspace = true, default-features = true }
sc-service = { workspace = true, default-features = true }
sc-sysinfo = { workspace = true, default-features = true }
sc-telemetry = { workspace = true, default-features = true }
sc-tracing = { workspace = true, default-features = true }
sc-transaction-pool = { workspace = true, default-features = true }
sc-utils = { workspace = true, default-features = true }
sp-api = { workspace = true, default-features = true }
Expand All @@ -35,6 +37,7 @@ sp-core = { workspace = true, default-features = true }
sp-io = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
sp-transaction-pool = { workspace = true, default-features = true }
sp-trie = { workspace = true, default-features = true }

# Polkadot
polkadot-primitives = { workspace = true, default-features = true }
Expand Down
37 changes: 36 additions & 1 deletion cumulus/client/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,16 @@ use sc_network_sync::SyncingService;
use sc_network_transactions::TransactionsHandlerController;
use sc_service::{Configuration, SpawnTaskHandle, TaskManager, WarpSyncConfig};
use sc_telemetry::{log, TelemetryWorkerHandle};
use sc_tracing::block::TracingExecuteBlock;
use sc_utils::mpsc::TracingUnboundedSender;
use sp_api::ProvideRuntimeApi;
use sp_api::{ApiExt, Core, ProofRecorder, ProvideRuntimeApi};
use sp_blockchain::{HeaderBackend, HeaderMetadata};
use sp_core::Decode;
use sp_runtime::{
traits::{Block as BlockT, BlockIdTo, Header},
SaturatedConversion, Saturating,
};
use sp_trie::proof_size_extension::ProofSizeExt;
use std::{
sync::Arc,
time::{Duration, Instant},
Expand Down Expand Up @@ -597,3 +599,36 @@ impl ParachainInformantMetrics {
})
}
}

/// Implementation of [`TracingExecuteBlock`] for parachains.
///
/// Ensures that all the required extensions required by parachain runtimes are registered and
/// available.
pub struct ParachainTracingExecuteBlock<Client> {
client: Arc<Client>,
}

impl<Client> ParachainTracingExecuteBlock<Client> {
/// Creates a new instance of `self`.
pub fn new(client: Arc<Client>) -> Self {
Self { client }
}
}

impl<Block, Client> TracingExecuteBlock<Block> for ParachainTracingExecuteBlock<Client>
where
Block: BlockT,
Client: ProvideRuntimeApi<Block> + Send + Sync,
Client::Api: Core<Block>,
{
fn execute_block(&self, _: Block::Hash, block: Block) -> sp_blockchain::Result<()> {
let mut runtime_api = self.client.runtime_api();
let storage_proof_recorder = ProofRecorder::<Block>::default();
runtime_api.register_extension(ProofSizeExt::new(storage_proof_recorder.clone()));
runtime_api.record_proof_with_recorder(storage_proof_recorder);

runtime_api
.execute_block(*block.header().parent_hash(), block)
.map_err(Into::into)
}
}
6 changes: 5 additions & 1 deletion cumulus/polkadot-omni-node/lib/src/common/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ use cumulus_client_bootnodes::{start_bootnode_tasks, StartBootnodeTasksParams};
use cumulus_client_cli::CollatorOptions;
use cumulus_client_service::{
build_network, build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks,
BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams,
BuildNetworkParams, CollatorSybilResistance, DARecoveryProfile, ParachainTracingExecuteBlock,
StartRelayChainTasksParams,
};
use cumulus_primitives_core::{BlockT, GetParachainInfo, ParaId};
use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};
Expand Down Expand Up @@ -455,6 +456,9 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
system_rpc_tx,
tx_handler_controller,
telemetry: telemetry.as_mut(),
tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new(
client.clone(),
))),
})?;

if let Some(hwbench) = hwbench {
Expand Down
1 change: 1 addition & 0 deletions cumulus/polkadot-omni-node/lib/src/nodes/aura.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ where
sync_service,
config,
telemetry: telemetry.as_mut(),
tracing_execute_block: None,
})?;

Ok(task_manager)
Expand Down
4 changes: 3 additions & 1 deletion cumulus/test/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImpo
use cumulus_client_pov_recovery::{RecoveryDelayRange, RecoveryHandle};
use cumulus_client_service::{
build_network, prepare_node_config, start_relay_chain_tasks, BuildNetworkParams,
CollatorSybilResistance, DARecoveryProfile, StartRelayChainTasksParams,
CollatorSybilResistance, DARecoveryProfile, ParachainTracingExecuteBlock,
StartRelayChainTasksParams,
};
use cumulus_primitives_core::{relay_chain::ValidationCode, GetParachainInfo, ParaId};
use cumulus_relay_chain_inprocess_interface::RelayChainInProcessInterface;
Expand Down Expand Up @@ -389,6 +390,7 @@ where
system_rpc_tx,
tx_handler_controller,
telemetry: None,
tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new(client.clone()))),
})?;

let announce_block = {
Expand Down
1 change: 1 addition & 0 deletions polkadot/node/service/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ where
system_rpc_tx,
tx_handler_controller,
telemetry: telemetry.as_mut(),
tracing_execute_block: None,
})?;

if let Some(hwbench) = hwbench {
Expand Down
20 changes: 20 additions & 0 deletions prdoc/pr_9871.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
title: '`trace_block`: Support overwriting `execute_block`'
doc:
- audience: Node Dev
description: |-
This is required for example for parachains that require special extensions to be registered (e.g. `ProofSizeExt`) to succeed the block execution.

This pull request changes the signature of `spawn_tasks` which now requires a `tracing_execute_block` parameter. If your chain is a solochain, just set the parameter to `None` or overwrite it if you need any special handling. For parachain builders, this value can be set to `cumulus_service::ParachainTracingExecuteBlock`.
crates:
- name: cumulus-client-service
bump: major
- name: polkadot-omni-node-lib
bump: major
- name: polkadot-service
bump: major
- name: sc-rpc
bump: major
- name: sc-service
bump: major
- name: sc-tracing
bump: major
1 change: 1 addition & 0 deletions substrate/bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ pub fn new_full_base<N: NetworkBackend<Block, <Block as BlockT>::Hash>>(
tx_handler_controller,
sync_service: sync_service.clone(),
telemetry: telemetry.as_mut(),
tracing_execute_block: None,
})?;

if let Some(hwbench) = hwbench {
Expand Down
12 changes: 9 additions & 3 deletions substrate/client/rpc/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use sc_client_api::{
Backend, BlockBackend, BlockchainEvents, ExecutorProvider, ProofProvider, StorageProvider,
};
use sc_rpc_api::{check_if_safe, DenyUnsafe};
use sc_tracing::block::TracingExecuteBlock;
use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi};
use sp_blockchain::{HeaderBackend, HeaderMetadata};
use sp_core::{
Expand Down Expand Up @@ -164,6 +165,7 @@ where
pub fn new_full<BE, Block: BlockT, Client>(
client: Arc<Client>,
executor: SubscriptionTaskExecutor,
execute_block: Option<Arc<dyn TracingExecuteBlock<Block>>>,
) -> (State<Block, Client>, ChildState<Block, Client>)
where
Block: BlockT + 'static,
Expand All @@ -183,9 +185,13 @@ where
+ 'static,
Client::Api: Metadata<Block>,
{
let child_backend =
Box::new(self::state_full::FullState::new(client.clone(), executor.clone()));
let backend = Box::new(self::state_full::FullState::new(client, executor));
let child_backend = Box::new(self::state_full::FullState::new(
client.clone(),
executor.clone(),
execute_block.clone(),
));
let backend =
Box::new(self::state_full::FullState::new(client, executor, execute_block.clone()));
(State { backend }, ChildState { backend: child_backend })
}

Expand Down
15 changes: 11 additions & 4 deletions substrate/client/rpc/src/state/state_full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use sc_client_api::{
StorageProvider,
};
use sc_rpc_api::state::ReadProof;
use sc_tracing::block::TracingExecuteBlock;
use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi};
use sp_blockchain::{
CachedHeaderMetadata, Error as ClientError, HeaderBackend, HeaderMetadata,
Expand All @@ -55,7 +56,7 @@ use sp_version::RuntimeVersion;
/// The maximum time allowed for an RPC call when running without unsafe RPC enabled.
const MAXIMUM_SAFE_RPC_CALL_TIMEOUT: Duration = Duration::from_secs(30);

/// Ranges to query in state_queryStorage.
/// Ranges to query in `state_queryStorage`.
struct QueryStorageRange<Block: BlockT> {
/// Hashes of all the blocks in the range.
pub hashes: Vec<Block::Hash>,
Expand All @@ -65,7 +66,8 @@ struct QueryStorageRange<Block: BlockT> {
pub struct FullState<BE, Block: BlockT, Client> {
client: Arc<Client>,
executor: SubscriptionTaskExecutor,
_phantom: PhantomData<(BE, Block)>,
execute_block: Option<Arc<dyn TracingExecuteBlock<Block>>>,
_phantom: PhantomData<BE>,
}

impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
Expand All @@ -78,8 +80,12 @@ where
Block: BlockT + 'static,
{
/// Create new state API backend for full nodes.
pub fn new(client: Arc<Client>, executor: SubscriptionTaskExecutor) -> Self {
Self { client, executor, _phantom: PhantomData }
pub fn new(
client: Arc<Client>,
executor: SubscriptionTaskExecutor,
execute_block: Option<Arc<dyn TracingExecuteBlock<Block>>>,
) -> Self {
Self { client, executor, execute_block, _phantom: PhantomData }
}

/// Returns given block hash or best block hash if None is passed.
Expand Down Expand Up @@ -479,6 +485,7 @@ where
targets,
storage_keys,
methods,
self.execute_block.clone(),
)
.trace_block()
.map_err(|e| invalid_block::<Block>(block, None, e.to_string()))
Expand Down
24 changes: 12 additions & 12 deletions substrate/client/rpc/src/state/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async fn should_return_storage() {
.add_extra_storage(b":map:acc2".to_vec(), vec![1, 2, 3])
.build();
let genesis_hash = client.genesis_hash();
let (client, child) = new_full(Arc::new(client), test_executor());
let (client, child) = new_full(Arc::new(client), test_executor(), None);
let key = StorageKey(KEY.to_vec());
let ext = allow_unsafe();

Expand Down Expand Up @@ -106,7 +106,7 @@ async fn should_return_storage_entries() {
.add_extra_child_storage(&child_info, KEY2.to_vec(), CHILD_VALUE2.to_vec())
.build();
let genesis_hash = client.genesis_hash();
let (_client, child) = new_full(Arc::new(client), test_executor());
let (_client, child) = new_full(Arc::new(client), test_executor(), None);

let keys = &[StorageKey(KEY1.to_vec()), StorageKey(KEY2.to_vec())];
assert_eq!(
Expand Down Expand Up @@ -137,7 +137,7 @@ async fn should_return_child_storage() {
.build(),
);
let genesis_hash = client.genesis_hash();
let (_client, child) = new_full(client, test_executor());
let (_client, child) = new_full(client, test_executor(), None);
let child_key = prefixed_storage_key();
let key = StorageKey(b"key".to_vec());

Expand Down Expand Up @@ -168,7 +168,7 @@ async fn should_return_child_storage_entries() {
.build(),
);
let genesis_hash = client.genesis_hash();
let (_client, child) = new_full(client, test_executor());
let (_client, child) = new_full(client, test_executor(), None);
let child_key = prefixed_storage_key();
let keys = vec![StorageKey(b"key1".to_vec()), StorageKey(b"key2".to_vec())];

Expand Down Expand Up @@ -199,7 +199,7 @@ async fn should_return_child_storage_entries() {
async fn should_call_contract() {
let client = Arc::new(substrate_test_runtime_client::new());
let genesis_hash = client.genesis_hash();
let (client, _child) = new_full(client, test_executor());
let (client, _child) = new_full(client, test_executor(), None);

assert_matches!(
client.call("balanceOf".into(), Bytes(vec![1, 2, 3]), Some(genesis_hash).into()),
Expand All @@ -211,7 +211,7 @@ async fn should_call_contract() {
async fn should_notify_about_storage_changes() {
let mut sub = {
let client = Arc::new(substrate_test_runtime_client::new());
let (api, _child) = new_full(client.clone(), test_executor());
let (api, _child) = new_full(client.clone(), test_executor(), None);
let mut api_rpc = api.into_rpc();
api_rpc.extensions_mut().insert(DenyUnsafe::No);

Expand Down Expand Up @@ -250,7 +250,7 @@ async fn should_notify_about_storage_changes() {
async fn should_send_initial_storage_changes_and_notifications() {
let mut sub = {
let client = Arc::new(substrate_test_runtime_client::new());
let (api, _child) = new_full(client.clone(), test_executor());
let (api, _child) = new_full(client.clone(), test_executor(), None);

let alice_balance_key = [
sp_crypto_hashing::twox_128(b"System"),
Expand Down Expand Up @@ -300,7 +300,7 @@ async fn should_send_initial_storage_changes_and_notifications() {
#[tokio::test]
async fn should_query_storage() {
async fn run_tests(client: Arc<TestClient>) {
let (api, _child) = new_full(client.clone(), test_executor());
let (api, _child) = new_full(client.clone(), test_executor(), None);

let add_block = |index| {
let mut builder = BlockBuilderBuilder::new(&*client)
Expand Down Expand Up @@ -468,7 +468,7 @@ async fn should_query_storage() {
#[tokio::test]
async fn should_return_runtime_version() {
let client = Arc::new(substrate_test_runtime_client::new());
let (api, _child) = new_full(client.clone(), test_executor());
let (api, _child) = new_full(client.clone(), test_executor(), None);

// it is basically json-encoded substrate_test_runtime_client::runtime::VERSION
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
Expand All @@ -491,7 +491,7 @@ async fn should_return_runtime_version() {
async fn should_notify_on_runtime_version_initially() {
let mut sub = {
let client = Arc::new(substrate_test_runtime_client::new());
let (api, _child) = new_full(client, test_executor());
let (api, _child) = new_full(client, test_executor(), None);
let mut api_rpc = api.into_rpc();
api_rpc.extensions_mut().insert(DenyUnsafe::No);

Expand All @@ -518,7 +518,7 @@ fn should_deserialize_storage_key() {
#[tokio::test]
async fn wildcard_storage_subscriptions_are_rpc_unsafe() {
let client = Arc::new(substrate_test_runtime_client::new());
let (api, _child) = new_full(client, test_executor());
let (api, _child) = new_full(client, test_executor(), None);
let mut api_rpc = api.into_rpc();
api_rpc.extensions_mut().insert(DenyUnsafe::Yes);

Expand All @@ -529,7 +529,7 @@ async fn wildcard_storage_subscriptions_are_rpc_unsafe() {
#[tokio::test]
async fn concrete_storage_subscriptions_are_rpc_safe() {
let client = Arc::new(substrate_test_runtime_client::new());
let (api, _child) = new_full(client, test_executor());
let (api, _child) = new_full(client, test_executor(), None);
let mut api_rpc = api.into_rpc();
api_rpc.extensions_mut().insert(DenyUnsafe::Yes);

Expand Down
Loading
Loading