diff --git a/Cargo.lock b/Cargo.lock index f5b2ee855f5d..d72d6229e1a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11786,6 +11786,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-relay-chain-interface", + "docify", "frame-benchmarking", "frame-benchmarking-cli", "futures", @@ -11842,6 +11843,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-utility", + "docify", "frame-benchmarking", "frame-executive", "frame-support", @@ -13897,8 +13899,11 @@ dependencies = [ name = "polkadot-sdk-docs" version = "0.0.1" dependencies = [ + "cumulus-client-service", "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", + "cumulus-primitives-proof-size-hostfunction", + "cumulus-primitives-storage-weight-reclaim", "docify", "frame-executive", "frame-support", @@ -13936,9 +13941,11 @@ dependencies = [ "sc-consensus-grandpa", "sc-consensus-manual-seal", "sc-consensus-pow", + "sc-executor", "sc-network", "sc-rpc", "sc-rpc-api", + "sc-service", "scale-info", "simple-mermaid", "sp-api", diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 426c5d9de4a0..fe53845d8490 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -51,6 +51,8 @@ sc-consensus-grandpa = { path = "../../substrate/client/consensus/grandpa" } sc-consensus-beefy = { path = "../../substrate/client/consensus/beefy" } sc-consensus-manual-seal = { path = "../../substrate/client/consensus/manual-seal" } sc-consensus-pow = { path = "../../substrate/client/consensus/pow" } +sc-executor = { path = "../../substrate/client/executor" } +sc-service = { path = "../../substrate/client/service" } substrate-wasm-builder = { path = "../../substrate/utils/wasm-builder" } @@ -60,9 +62,12 @@ cumulus-pallet-parachain-system = { path = "../../cumulus/pallets/parachain-syst "parameterized-consensus-hook", ] } parachain-info = { package = "staging-parachain-info", path = "../../cumulus/parachains/pallets/parachain-info" } -pallet-aura = { path = "../../substrate/frame/aura", default-features = false } +cumulus-primitives-proof-size-hostfunction = { path = "../../cumulus/primitives/proof-size-hostfunction" } +cumulus-client-service = { path = "../../cumulus/client/service" } +cumulus-primitives-storage-weight-reclaim = { path = "../../cumulus/primitives/storage-weight-reclaim" } # Pallets and FRAME internals +pallet-aura = { path = "../../substrate/frame/aura" } pallet-timestamp = { path = "../../substrate/frame/timestamp" } pallet-balances = { path = "../../substrate/frame/balances" } pallet-assets = { path = "../../substrate/frame/assets" } diff --git a/docs/sdk/src/guides/enable_pov_reclaim.rs b/docs/sdk/src/guides/enable_pov_reclaim.rs new file mode 100644 index 000000000000..3c0c5fba2158 --- /dev/null +++ b/docs/sdk/src/guides/enable_pov_reclaim.rs @@ -0,0 +1,84 @@ +//! This guide will teach you how to enable storage weight reclaiming for a parachain. The +//! explanations in this guide assume a project structure similar to the one detailed in +//! the [substrate documentation](crate::polkadot_sdk::substrate#anatomy-of-a-binary-crate). Full +//! technical details are available in the original [pull request](https://github.com/paritytech/polkadot-sdk/pull/3002). +//! +//! # What is PoV reclaim? +//! When a parachain submits a block to a relay chain like Polkadot or Kusama, it sends the block +//! itself and a storage proof. Together they form the Proof-of-Validity (PoV). The PoV allows the +//! relay chain to validate the parachain block by re-executing it. Relay chain +//! validators distribute this PoV among themselves over the network. This distribution is costly +//! and limits the size of the storage proof. The storage weight dimension of FRAME weights reflects +//! this cost and limits the size of the storage proof. However, the storage weight determined +//! during [benchmarking](crate::reference_docs::frame_benchmarking_weight) represents the worst +//! case. In reality, runtime operations often consume less space in the storage proof. PoV reclaim +//! offers a mechanism to reclaim the difference between the benchmarked worst-case and the real +//! proof-size consumption. +//! +//! +//! # How to enable PoV reclaim +//! ## 1. Add the host function to your node +//! +//! To reclaim excess storage weight, a parachain runtime needs the +//! ability to fetch the size of the storage proof from the node. The reclaim +//! mechanism uses the +//! [`storage_proof_size`](cumulus_primitives_proof_size_hostfunction::storage_proof_size) +//! host function for this purpose. For convenience, cumulus provides +//! [`ParachainHostFunctions`](cumulus_client_service::ParachainHostFunctions), a set of +//! host functions typically used by cumulus-based parachains. In the binary crate of your +//! parachain, find the instantiation of the [`WasmExecutor`](sc_executor::WasmExecutor) and set the +//! correct generic type. +//! +//! This example from the parachain-template shows a type definition that includes the correct +//! host functions. +#![doc = docify::embed!("../../templates/parachain/node/src/service.rs", wasm_executor)] +//! +//! > **Note:** +//! > +//! > If you see error `runtime requires function imports which are not present on the host: +//! > 'env:ext_storage_proof_size_storage_proof_size_version_1'`, it is likely +//! > that this step in the guide was not set up correctly. +//! +//! ## 2. Enable storage proof recording during import +//! +//! The reclaim mechanism reads the size of the currently recorded storage proof multiple times +//! during block authoring and block import. Proof recording during authoring is already enabled on +//! parachains. You must also ensure that storage proof recording is enabled during block import. +//! Find where your node builds the fundamental substrate components by calling +//! [`new_full_parts`](sc_service::new_full_parts). Replace this +//! with [`new_full_parts_record_import`](sc_service::new_full_parts_record_import) and +//! pass `true` as the last parameter to enable import recording. +#![doc = docify::embed!("../../templates/parachain/node/src/service.rs", component_instantiation)] +//! +//! > **Note:** +//! > +//! > If you see error `Storage root must match that calculated.` during block import, it is likely +//! > that this step in the guide was not +//! > set up correctly. +//! +//! ## 3. Add the SignedExtension to your runtime +//! +//! In your runtime, you will find a list of SignedExtensions. +//! To enable the reclaiming, +//! add [`StorageWeightReclaim`](cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim) +//! to that list. For maximum efficiency, make sure that `StorageWeightReclaim` is last in the list. +//! The extension will check the size of the storage proof before and after an extrinsic execution. +//! It reclaims the difference between the calculated size and the benchmarked size. +#![doc = docify::embed!("../../templates/parachain/runtime/src/lib.rs", template_signed_extra)] +//! +//! ## Optional: Verify that reclaim works +//! +//! Start your node with the log target `runtime::storage_reclaim` set to `trace` to enable full +//! logging for `StorageWeightReclaim`. The following log is an example from a local testnet. To +//! trigger the log, execute any extrinsic on the network. +//! +//! ```ignore +//! ... +//! 2024-04-22 17:31:48.014 TRACE runtime::storage_reclaim: [ferdie] Reclaiming storage weight. benchmarked: 3593, consumed: 265 unspent: 0 +//! ... +//! ``` +//! +//! In the above example we see a benchmarked size of 3593 bytes, while the extrinsic only consumed +//! 265 bytes of proof size. This results in 3328 bytes of reclaim. +#![deny(rustdoc::broken_intra_doc_links)] +#![deny(rustdoc::private_intra_doc_links)] diff --git a/docs/sdk/src/guides/mod.rs b/docs/sdk/src/guides/mod.rs index 3120f2533109..2dc807af8eae 100644 --- a/docs/sdk/src/guides/mod.rs +++ b/docs/sdk/src/guides/mod.rs @@ -23,3 +23,6 @@ pub mod cumulus_enabled_parachain; /// How to make a given runtime XCM-enabled, capable of sending messages (`Transact`) between itself /// and the relay chain to which it is connected. pub mod xcm_enabled_parachain; + +/// How to enable storage weight reclaiming in a parachain node and runtime. +pub mod enable_pov_reclaim; diff --git a/docs/sdk/src/meta_contributing.rs b/docs/sdk/src/meta_contributing.rs index fcdcea9934bb..a029595254c8 100644 --- a/docs/sdk/src/meta_contributing.rs +++ b/docs/sdk/src/meta_contributing.rs @@ -139,7 +139,7 @@ //! //! ```sh //! SKIP_WASM_BUILD=1 \ -//! RUSTDOCFLAGS="--html-in-header $(pwd)/docs/sdk/headers/header.html --extend-css $(pwd)/docs/sdk/headers/theme.css --default-theme=ayu" \ +//! RUSTDOCFLAGS="--html-in-header $(pwd)/docs/sdk/assets/header.html --extend-css $(pwd)/docs/sdk/assets/theme.css --default-theme=ayu" \ //! cargo doc -p polkadot-sdk-docs --no-deps --open //! ``` //! diff --git a/templates/parachain/node/Cargo.toml b/templates/parachain/node/Cargo.toml index 63267acdbca8..ed857b4e4b9f 100644 --- a/templates/parachain/node/Cargo.toml +++ b/templates/parachain/node/Cargo.toml @@ -24,6 +24,7 @@ serde = { features = ["derive"], workspace = true, default-features = true } jsonrpsee = { version = "0.22", features = ["server"] } futures = "0.3.28" serde_json = { workspace = true, default-features = true } +docify = "0.2.8" # Local parachain-template-runtime = { path = "../runtime" } diff --git a/templates/parachain/node/src/service.rs b/templates/parachain/node/src/service.rs index 20e5b37b41bd..ad4689c6e55d 100644 --- a/templates/parachain/node/src/service.rs +++ b/templates/parachain/node/src/service.rs @@ -39,6 +39,7 @@ use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_keystore::KeystorePtr; use substrate_prometheus_endpoint::Registry; +#[docify::export(wasm_executor)] type ParachainExecutor = WasmExecutor; type ParachainClient = TFullClient; @@ -61,6 +62,7 @@ pub type Service = PartialComponents< /// /// Use this macro if you don't actually need the full service, but just the builder in order to /// be able to perform chain operations. +#[docify::export(component_instantiation)] pub fn new_partial(config: &Configuration) -> Result { let telemetry = config .telemetry_endpoints diff --git a/templates/parachain/runtime/Cargo.toml b/templates/parachain/runtime/Cargo.toml index 9cd5b7ca5991..d15ff2807a66 100644 --- a/templates/parachain/runtime/Cargo.toml +++ b/templates/parachain/runtime/Cargo.toml @@ -28,6 +28,7 @@ scale-info = { version = "2.11.1", default-features = false, features = [ "derive", ] } smallvec = "1.11.0" +docify = "0.2.8" # Local pallet-parachain-template = { path = "../pallets/template", default-features = false } diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index 14af00f9b2ca..179a425ca041 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -75,6 +75,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. +#[docify::export(template_signed_extra)] pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion,