Skip to content

Commit b2bcb74

Browse files
bkonturgithub-actions[bot]iulianbarbuEgorPopelyaevbkchr
authored
Bulletin as parachain missing features (#10662)
Relates to: paritytech/polkadot-bulletin-chain#74 This PR adds the required support and features for running Bulletin as a parachain. It is a top-level PR that merges three partial features/PRs, which can also be reviewed/merged separately: 1. Add `transaction_index::HostFunctions` with NO-OP impl to the cumulus ParachainSystem `validate_block` for polkadot-prepare/execute-worker - #10370 2. Add custom inherent provider for pallet-transaction-storage to omni node - #10494 3. Configurable StoragePeriod feeded to the inherent provider over runtime API - #10656 --------- Signed-off-by: Iulian Barbu <[email protected]> Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Iulian Barbu <[email protected]> Co-authored-by: Iulian Barbu <[email protected]> Co-authored-by: EgorPopelyaev <[email protected]> Co-authored-by: Bastian Köcher <[email protected]> Co-authored-by: Bastian Köcher <[email protected]>
1 parent 87844e6 commit b2bcb74

File tree

21 files changed

+239
-38
lines changed

21 files changed

+239
-38
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cumulus/pallets/parachain-system/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,13 @@ try-runtime = [
125125
"polkadot-runtime-parachains/try-runtime",
126126
"sp-runtime/try-runtime",
127127
]
128+
129+
# Enables `TransactionIndex` host functions for parachain validation
130+
# without requiring maintenance of a transaction index.
131+
# However, the host environment (polkadot-prepare/execute-worker) still expects these functions to exist,
132+
# so we provide a replacement no-op implementation gated by this feature.
133+
#
134+
# Used by: `validate_block::implementation::validate_block`.
135+
#
136+
# Note: The parachain collator software is expected to use/include `transaction_index::HostFunctions`.
137+
transaction-index = []

cumulus/pallets/parachain-system/src/validate_block/implementation.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ where
122122
sp_io::offchain_index::host_clear.replace_implementation(host_offchain_index_clear),
123123
cumulus_primitives_proof_size_hostfunction::storage_proof_size::host_storage_proof_size
124124
.replace_implementation(host_storage_proof_size),
125+
#[cfg(feature = "transaction-index")]
126+
sp_io::transaction_index::host_index.replace_implementation(host_transaction_index_index),
127+
#[cfg(feature = "transaction-index")]
128+
sp_io::transaction_index::host_renew.replace_implementation(host_transaction_index_renew),
125129
);
126130

127131
let block_data = codec::decode_from_bytes::<ParachainBlockData<B::LazyBlock>>(block_data)
@@ -230,7 +234,6 @@ where
230234
if overlay.storage(well_known_keys::CODE).is_some() && num_blocks > 1 {
231235
panic!("When applying a runtime upgrade, only one block per PoV is allowed. Received {num_blocks}.")
232236
}
233-
234237
run_with_externalities_and_recorder::<B, _, _>(
235238
&backend,
236239
&mut Default::default(),
@@ -548,3 +551,21 @@ fn host_default_child_storage_next_key(storage_key: &[u8], key: &[u8]) -> Option
548551
fn host_offchain_index_set(_key: &[u8], _value: &[u8]) {}
549552

550553
fn host_offchain_index_clear(_key: &[u8]) {}
554+
555+
/// Parachain validation does not require maintaining a transaction index,
556+
/// and indexing transactions does **not** contribute to the parachain state.
557+
/// However, the host environment still expects this function to exist,
558+
/// so we provide a no-op implementation.
559+
#[cfg(feature = "transaction-index")]
560+
fn host_transaction_index_index(_extrinsic: u32, _size: u32, _context_hash: [u8; 32]) {
561+
// No-op host function used during parachain validation.
562+
}
563+
564+
/// Parachain validation does not require maintaining a transaction index,
565+
/// and indexing transactions does **not** contribute to the parachain state.
566+
/// However, the host environment still expects this function to exist,
567+
/// so we provide a no-op implementation.
568+
#[cfg(feature = "transaction-index")]
569+
fn host_transaction_index_renew(_extrinsic: u32, _context_hash: [u8; 32]) {
570+
// No-op host function used during parachain validation.
571+
}

cumulus/polkadot-omni-node/lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ sp-statement-store = { workspace = true, default-features = true }
8080
sp-storage = { workspace = true, default-features = true }
8181
sp-timestamp = { workspace = true, default-features = true }
8282
sp-transaction-pool = { workspace = true, default-features = true }
83+
sp-transaction-storage-proof = { workspace = true, default-features = true }
8384
sp-version = { workspace = true, default-features = true }
8485
sp-weights = { workspace = true, default-features = true }
8586
substrate-frame-rpc-system = { workspace = true, default-features = true }

cumulus/polkadot-omni-node/lib/src/common/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use sp_runtime::{
4242
use sp_session::SessionKeys;
4343
use sp_statement_store::runtime_api::ValidateStatement;
4444
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
45+
use sp_transaction_storage_proof::runtime_api::TransactionStorageApi;
4546
use std::{fmt::Debug, path::PathBuf, str::FromStr};
4647

4748
pub trait NodeBlock:
@@ -74,6 +75,7 @@ pub trait NodeRuntimeApi<Block: BlockT>:
7475
+ CollectCollationInfo<Block>
7576
+ ValidateStatement<Block>
7677
+ GetParachainInfo<Block>
78+
+ TransactionStorageApi<Block>
7779
+ RelayParentOffsetApi<Block>
7880
+ Sized
7981
{
@@ -90,6 +92,7 @@ impl<T, Block: BlockT> NodeRuntimeApi<Block> for T where
9092
+ CollectCollationInfo<Block>
9193
+ ValidateStatement<Block>
9294
+ GetParachainInfo<Block>
95+
+ TransactionStorageApi<Block>
9396
{
9497
}
9598

cumulus/polkadot-omni-node/lib/src/common/spec.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use cumulus_client_service::{
3939
use cumulus_primitives_core::{BlockT, GetParachainInfo, ParaId};
4040
use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};
4141
use futures::FutureExt;
42-
use log::info;
42+
use log::{debug, info};
4343
use parachains_common_types::Hash;
4444
use polkadot_primitives::CollatorPair;
4545
use prometheus_endpoint::Registry;
@@ -61,6 +61,13 @@ use sp_keystore::KeystorePtr;
6161
use sp_runtime::traits::AccountIdConversion;
6262
use std::{future::Future, pin::Pin, sync::Arc, time::Duration};
6363

64+
// Override default idle connection timeout of 10 seconds to give IPFS clients more
65+
// time to query data over Bitswap. This is needed when manually adding our node
66+
// to a swarm of an IPFS node, because the IPFS node doesn't keep any active
67+
// substreams with us and our node closes a connection after
68+
// `idle_connection_timeout`.
69+
const IPFS_WORKAROUND_TIMEOUT: Duration = Duration::from_secs(3600);
70+
6471
pub(crate) trait BuildImportQueue<
6572
Block: BlockT,
6673
RuntimeApi,
@@ -326,7 +333,16 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
326333
Net: NetworkBackend<Self::Block, Hash>,
327334
{
328335
let fut = async move {
329-
let parachain_config = prepare_node_config(parachain_config);
336+
let mut parachain_config = prepare_node_config(parachain_config);
337+
338+
// Some additional customization in relation to starting the node as an ipfs server.
339+
if parachain_config.network.idle_connection_timeout < IPFS_WORKAROUND_TIMEOUT &&
340+
parachain_config.network.ipfs_server
341+
{
342+
debug!("Overriding `config.network.idle_connection_timeout` to allow long-lived connections with IPFS nodes. The old value: {:?} is replaced by: {:?}.", parachain_config.network.idle_connection_timeout, IPFS_WORKAROUND_TIMEOUT);
343+
parachain_config.network.idle_connection_timeout = IPFS_WORKAROUND_TIMEOUT;
344+
}
345+
330346
let parachain_public_addresses = parachain_config.network.public_addresses.clone();
331347
let parachain_fork_id = parachain_config.chain_spec.fork_id().map(ToString::to_string);
332348
let advertise_non_global_ips = parachain_config.network.allow_non_globals_in_dht;

cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ macro_rules! impl_node_runtime_apis {
248248
unimplemented!()
249249
}
250250
}
251+
252+
impl sp_transaction_storage_proof::runtime_api::TransactionStorageApi<$block> for $runtime {
253+
fn retention_period() -> sp_runtime::traits::NumberFor<$block> {
254+
unimplemented!()
255+
}
256+
}
251257
}
252258
};
253259
}

cumulus/polkadot-omni-node/lib/src/nodes/aura.rs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use sc_service::{Configuration, Error, PartialComponents, TaskManager};
6868
use sc_telemetry::TelemetryHandle;
6969
use sc_transaction_pool::TransactionPoolHandle;
7070
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
71-
use sp_api::ProvideRuntimeApi;
71+
use sp_api::{ApiExt, ProvideRuntimeApi};
7272
use sp_consensus::Environment;
7373
use sp_core::traits::SpawnEssentialNamed;
7474
use sp_inherents::CreateInherentDataProviders;
@@ -77,6 +77,7 @@ use sp_runtime::{
7777
app_crypto::AppCrypto,
7878
traits::{Block as BlockT, Header as HeaderT, UniqueSaturatedInto},
7979
};
80+
use sp_transaction_storage_proof::runtime_api::TransactionStorageApi;
8081
use std::{marker::PhantomData, sync::Arc, time::Duration};
8182

8283
struct Verifier<Block, Client, AuraId> {
@@ -596,8 +597,28 @@ where
596597
);
597598

598599
let client_for_aura = client.clone();
600+
let client_clone = client.clone();
599601
let params = SlotBasedParams {
600-
create_inherent_data_providers: move |_, ()| async move { Ok(()) },
602+
create_inherent_data_providers: move |parent, ()| {
603+
let client_clone = client_clone.clone();
604+
async move {
605+
let has_tx_storage_api = client_clone
606+
.runtime_api()
607+
.has_api::<dyn TransactionStorageApi<Block>>(parent)
608+
.unwrap_or(false);
609+
if has_tx_storage_api {
610+
let storage_proof =
611+
sp_transaction_storage_proof::registration::new_data_provider(
612+
&*client_clone,
613+
&parent,
614+
client_clone.runtime_api().retention_period(parent)?,
615+
)?;
616+
Ok(vec![storage_proof])
617+
} else {
618+
Ok(vec![])
619+
}
620+
}
621+
},
601622
block_import,
602623
para_client: client.clone(),
603624
para_backend: backend.clone(),
@@ -623,7 +644,6 @@ where
623644

624645
// We have a separate function only to be able to use `docify::export` on this piece of
625646
// code.
626-
627647
Self::launch_slot_based_collator(params);
628648

629649
Ok(())
@@ -721,10 +741,30 @@ where
721741
client.clone(),
722742
);
723743

744+
let client_clone = client.clone();
724745
let params = aura::ParamsWithExport {
725746
export_pov: node_extra_args.export_pov,
726747
params: AuraParams {
727-
create_inherent_data_providers: move |_, ()| async move { Ok(()) },
748+
create_inherent_data_providers: move |parent, ()| {
749+
let client_clone = client_clone.clone();
750+
async move {
751+
let has_tx_storage_api = client_clone
752+
.runtime_api()
753+
.has_api::<dyn TransactionStorageApi<Block>>(parent)
754+
.unwrap_or(false);
755+
if has_tx_storage_api {
756+
let storage_proof =
757+
sp_transaction_storage_proof::registration::new_data_provider(
758+
&*client_clone,
759+
&parent,
760+
client_clone.runtime_api().retention_period(parent)?,
761+
)?;
762+
Ok(vec![storage_proof])
763+
} else {
764+
Ok(vec![])
765+
}
766+
}
767+
},
728768
block_import,
729769
para_client: client.clone(),
730770
para_backend: backend,

prdoc/pr_10662.prdoc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
title: "Bulletin as parachain missing features"
2+
doc:
3+
- audience: Runtime Dev
4+
description: |-
5+
This PR adds the required support and features for running Bulletin as a parachain. It is a top-level PR that merges three partial features:
6+
7+
1. Add transaction_index::HostFunctions with NO-OP impl to the cumulus ParachainSystem validate_block for polkadot-prepare/execute-worker
8+
2. Add custom inherent provider for pallet-transaction-storage to omni node
9+
3. Configurable RetentionPeriod feeded to the inherent provider over runtime API
10+
11+
This PR also refactors `pallet-transaction-storage` and `sp-transaction-storage-proof` (the `new_data_provider` inherent provider), both of which rely on a hard-coded `DEFAULT_RETENTION_PERIOD`. This PR:
12+
- adds a new configurable argument `retention_period` to the `new_data_provider`
13+
- introduces the `TransactionStorageApi::retention_period` runtime API, which the runtime can specify arbitrary
14+
- provides an example of using `new_data_provider`, with the node client calling the runtime API when constructing inherent provider data
15+
- audience: [ Node Dev, Node Operator ]
16+
description: |
17+
* Node developers/operators could enable the transaction storage inherent data provider setup by using --enable-tx-storage-idp flag. This is especially useful in the context of bulletin chain.
18+
* Node developers will set up the network `idle_connection_timeout` to 1h when using `--ipfs-server` flag, again, useful in the context of bulletin chain.
19+
crates:
20+
- name: cumulus-pallet-parachain-system
21+
bump: patch
22+
- name: polkadot-omni-node-lib
23+
bump: major
24+
- name: sp-inherents
25+
bump: minor
26+
- name: sp-transaction-storage-proof
27+
bump: major
28+
- name: pallet-transaction-storage
29+
bump: major

substrate/bin/node/cli/src/service.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use sc_transaction_pool_api::OffchainTransactionPoolFactory;
4747
use sp_api::ProvideRuntimeApi;
4848
use sp_core::crypto::Pair;
4949
use sp_runtime::{generic, traits::Block as BlockT, SaturatedConversion};
50+
use sp_transaction_storage_proof::runtime_api::TransactionStorageApi;
5051
use std::{path::Path, sync::Arc};
5152

5253
/// Host functions required for kitchensink runtime and Substrate node.
@@ -631,6 +632,8 @@ pub fn new_full_base<N: NetworkBackend<Block, <Block as BlockT>::Hash>>(
631632
sp_transaction_storage_proof::registration::new_data_provider(
632633
&*client_clone,
633634
&parent,
635+
// Use `unwrap_or` in case the runtime api is not available.
636+
client_clone.runtime_api().retention_period(parent).unwrap_or(100800),
634637
)?;
635638

636639
Ok((slot, timestamp, storage_proof))

0 commit comments

Comments
 (0)