Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PoV-reclaim enablement guide to polkadot-sdk-docs #4244

Merged
merged 12 commits into from
May 2, 2024
5 changes: 5 additions & 0 deletions Cargo.lock

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

7 changes: 6 additions & 1 deletion docs/sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }

Expand All @@ -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" }
Expand Down
81 changes: 81 additions & 0 deletions docs/sdk/src/guides/enable_pov_reclaim.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! This guide will teach you how to enable storage weight reclaiming for a parachain. The
skunert marked this conversation as resolved.
Show resolved Hide resolved
//! 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).
//!
//! # 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`)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm when I build locally, this link and other cumulus links below are broken, but I am unable to figure out why 🤔. Anyone got an idea? They look correct to me.

//! hostfunction for this purpose. For convenience, cumulus provides
//! [ParachainHostFunctions](`cumulus_client_service::ParachainHostFunctions`), a set of
//! hostfunctions typically used by cumulus-based parachains. In the binary crate of your parachain,
skunert marked this conversation as resolved.
Show resolved Hide resolved
//! 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
//! hostfunctions.
skunert marked this conversation as resolved.
Show resolved Hide resolved
#![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. 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.
skunert marked this conversation as resolved.
Show resolved Hide resolved
#![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)]
3 changes: 3 additions & 0 deletions docs/sdk/src/guides/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
2 changes: 1 addition & 1 deletion docs/sdk/src/meta_contributing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
//! ```
//!
Expand Down
2 changes: 2 additions & 0 deletions templates/parachain/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sp_keystore::KeystorePtr;
use substrate_prometheus_endpoint::Registry;

#[docify::export(wasm_executor)]
type ParachainExecutor = WasmExecutor<ParachainHostFunctions>;

type ParachainClient = TFullClient<Block, RuntimeApi, ParachainExecutor>;
Expand All @@ -57,6 +58,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<Service, sc_service::Error> {
let telemetry = config
.telemetry_endpoints
Expand Down
1 change: 1 addition & 0 deletions templates/parachain/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub type SignedBlock = generic::SignedBlock<Block>;
pub type BlockId = generic::BlockId<Block>;

/// The SignedExtension to the basic transaction logic.
#[docify::export(template_signed_extra)]
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
frame_system::CheckSpecVersion<Runtime>,
Expand Down
Loading