referrerpolicy=no-referrer-when-downgrade

polkadot_sdk_docs/guides/
enable_pov_reclaim.rs

1//! # Enable storage weight reclaiming
2//!
3//! This guide will teach you how to enable storage weight reclaiming for a parachain. The
4//! explanations in this guide assume a project structure similar to the one detailed in
5//! the [substrate documentation](crate::polkadot_sdk::substrate#anatomy-of-a-binary-crate). Full
6//! technical details are available in the original [pull request](https://github.com/paritytech/polkadot-sdk/pull/3002).
7//!
8//! # What is PoV reclaim?
9//! When a parachain submits a block to a relay chain like Polkadot or Kusama, it sends the block
10//! itself and a storage proof. Together they form the Proof-of-Validity (PoV). The PoV allows the
11//! relay chain to validate the parachain block by re-executing it. Relay chain
12//! validators distribute this PoV among themselves over the network. This distribution is costly
13//! and limits the size of the storage proof. The storage weight dimension of FRAME weights reflects
14//! this cost and limits the size of the storage proof. However, the storage weight determined
15//! during [benchmarking](crate::reference_docs::frame_benchmarking_weight) represents the worst
16//! case. In reality, runtime operations often consume less space in the storage proof. PoV reclaim
17//! offers a mechanism to reclaim the difference between the benchmarked worst-case and the real
18//! proof-size consumption.
19//!
20//!
21//! # How to enable PoV reclaim
22//! ## 1. Add the host function to your node
23//!
24//! To reclaim excess storage weight, a parachain runtime needs the
25//! ability to fetch the size of the storage proof from the node. The reclaim
26//! mechanism uses the
27//! [`storage_proof_size`](cumulus_primitives_proof_size_hostfunction::storage_proof_size)
28//! host function for this purpose. For convenience, cumulus provides
29//! [`ParachainHostFunctions`](cumulus_client_service::ParachainHostFunctions), a set of
30//! host functions typically used by cumulus-based parachains. In the binary crate of your
31//! parachain, find the instantiation of the [`WasmExecutor`](sc_executor::WasmExecutor) and set the
32//! correct generic type.
33//!
34//! This example from the parachain-template shows a type definition that includes the correct
35//! host functions.
36#![doc = docify::embed!("../../templates/parachain/node/src/service.rs", wasm_executor)]
37//!
38//! > **Note:**
39//! >
40//! > If you see error `runtime requires function imports which are not present on the host:
41//! > 'env:ext_storage_proof_size_storage_proof_size_version_1'`, it is likely
42//! > that this step in the guide was not set up correctly.
43//!
44//! ## 2. Enable storage proof recording during import
45//!
46//! The reclaim mechanism reads the size of the currently recorded storage proof multiple times
47//! during block authoring and block import. Proof recording during authoring is already enabled on
48//! parachains. You must also ensure that storage proof recording is enabled during block import.
49//! Find where your node builds the fundamental substrate components by calling
50//! [`new_full_parts`](sc_service::new_full_parts). Replace this
51//! with [`new_full_parts_record_import`](sc_service::new_full_parts_record_import) and
52//! pass `true` as the last parameter to enable import recording.
53#![doc = docify::embed!("../../templates/parachain/node/src/service.rs", component_instantiation)]
54//!
55//! > **Note:**
56//! >
57//! > If you see error `Storage root must match that calculated.` during block import, it is likely
58//! > that this step in the guide was not
59//! > set up correctly.
60//!
61//! ## 3. Add the TransactionExtension to your runtime
62//!
63//! In your runtime, you will find a list of TransactionExtensions.
64//! To enable the reclaiming,
65//! set [`StorageWeightReclaim`](cumulus_pallet_weight_reclaim::StorageWeightReclaim)
66//! as a warpper of that list.
67//! It is necessary that this extension wraps all the other transaction extensions in order to catch
68//! the whole PoV size of the transactions.
69//! The extension will check the size of the storage proof before and after an extrinsic execution.
70//! It reclaims the difference between the calculated size and the benchmarked size.
71#![doc = docify::embed!("../../templates/parachain/runtime/src/lib.rs", template_signed_extra)]
72//!
73//! ## Optional: Verify that reclaim works
74//!
75//! Start your node with the log target `runtime::storage_reclaim` set to `trace` to enable full
76//! logging for `StorageWeightReclaim`. The following log is an example from a local testnet. To
77//! trigger the log, execute any extrinsic on the network.
78//!
79//! ```ignore
80//! ...
81//! 2024-04-22 17:31:48.014 TRACE runtime::storage_reclaim: [ferdie] Reclaiming storage weight. benchmarked: 3593, consumed: 265 unspent: 0
82//! ...
83//! ```
84//!
85//! In the above example we see a benchmarked size of 3593 bytes, while the extrinsic only consumed
86//! 265 bytes of proof size. This results in 3328 bytes of reclaim.
87#![deny(rustdoc::broken_intra_doc_links)]
88#![deny(rustdoc::private_intra_doc_links)]