Skip to content

Commit

Permalink
Implement cumulus StorageWeightReclaim as wrapping transaction extens…
Browse files Browse the repository at this point in the history
…ion + frame system ReclaimWeight (paritytech#6140)

(rebasing of paritytech#5234)

## Issues:

* Transaction extensions have weights and refund weight. So the
reclaiming of unused weight must happen last in the transaction
extension pipeline. Currently it is inside `CheckWeight`.
* cumulus storage weight reclaim transaction extension misses the proof
size of logic happening prior to itself.

## Done:

* a new storage `ExtrinsicWeightReclaimed` in frame-system. Any logic
which attempts to do some reclaim must use this storage to avoid double
reclaim.
* a new function `reclaim_weight` in frame-system pallet: info and post
info in arguments, read the already reclaimed weight, calculate the new
unused weight from info and post info. do the more accurate reclaim if
higher.
* `CheckWeight` is unchanged and still reclaim the weight in post
dispatch
* `ReclaimWeight` is a new transaction extension in frame system. For
solo chains it must be used last in the transactino extension pipeline.
It does the final most accurate reclaim
* `StorageWeightReclaim` is moved from cumulus primitives into its own
pallet (in order to define benchmark) and is changed into a wrapping
transaction extension.
It does the recording of proof size and does the reclaim using this
recording and the info and post info. So parachains don't need to use
`ReclaimWeight`. But also if they use it, there is no bug.

    ```rust
  /// The TransactionExtension to the basic transaction logic.
pub type TxExtension =
cumulus_pallet_weight_reclaim::StorageWeightReclaim<
         Runtime,
         (
                 frame_system::CheckNonZeroSender<Runtime>,
                 frame_system::CheckSpecVersion<Runtime>,
                 frame_system::CheckTxVersion<Runtime>,
                 frame_system::CheckGenesis<Runtime>,
                 frame_system::CheckEra<Runtime>,
                 frame_system::CheckNonce<Runtime>,
                 frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
                 BridgeRejectObsoleteHeadersAndMessages,

(bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages,),
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
         ),
  >;
  ```

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
Co-authored-by: command-bot <>
  • Loading branch information
5 people authored Jan 5, 2025
1 parent b5a5ac4 commit 63c73bf
Show file tree
Hide file tree
Showing 113 changed files with 4,007 additions and 666 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/runtimes-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
{
"name": "glutton-westend",
"package": "glutton-westend-runtime",
"path": "cumulus/parachains/runtimes/gluttons/glutton-westend",
"path": "cumulus/parachains/runtimes/glutton/glutton-westend",
"header": "cumulus/file_header.txt",
"template": "cumulus/templates/xcm-bench-template.hbs",
"bench_features": "runtime-benchmarks",
Expand Down
50 changes: 35 additions & 15 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ members = [
"cumulus/pallets/parachain-system/proc-macro",
"cumulus/pallets/session-benchmarking",
"cumulus/pallets/solo-to-para",
"cumulus/pallets/weight-reclaim",
"cumulus/pallets/xcm",
"cumulus/pallets/xcmp-queue",
"cumulus/parachains/common",
Expand Down Expand Up @@ -717,6 +718,7 @@ cumulus-pallet-parachain-system = { path = "cumulus/pallets/parachain-system", d
cumulus-pallet-parachain-system-proc-macro = { path = "cumulus/pallets/parachain-system/proc-macro", default-features = false }
cumulus-pallet-session-benchmarking = { path = "cumulus/pallets/session-benchmarking", default-features = false }
cumulus-pallet-solo-to-para = { path = "cumulus/pallets/solo-to-para", default-features = false }
cumulus-pallet-weight-reclaim = { path = "cumulus/pallets/weight-reclaim", default-features = false }
cumulus-pallet-xcm = { path = "cumulus/pallets/xcm", default-features = false }
cumulus-pallet-xcmp-queue = { path = "cumulus/pallets/xcmp-queue", default-features = false }
cumulus-ping = { path = "cumulus/parachains/pallets/ping", default-features = false }
Expand Down
63 changes: 63 additions & 0 deletions cumulus/pallets/weight-reclaim/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[package]
name = "cumulus-pallet-weight-reclaim"
version = "1.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "pallet and transaction extensions for accurate proof size reclaim"

[lints]
workspace = true

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
# Substrate dependencies
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-trie = { workspace = true }

cumulus-primitives-storage-weight-reclaim = { workspace = true }
frame-benchmarking = { optional = true, workspace = true }
frame-support = { workspace = true }
frame-system = { workspace = true }

# Other dependencies
codec = { features = ["derive"], workspace = true }
derivative = { features = ["use_core"], workspace = true }
docify = { workspace = true }
log = { workspace = true, default-features = true }
scale-info = { features = ["derive"], workspace = true }

[dev-dependencies]
cumulus-primitives-proof-size-hostfunction = { workspace = true }

[features]
default = ["std"]
std = [
"codec/std",
"cumulus-primitives-proof-size-hostfunction/std",
"cumulus-primitives-storage-weight-reclaim/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"log/std",
"scale-info/std",
"sp-io/std",
"sp-runtime/std",
"sp-trie/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"sp-runtime/try-runtime",
]
71 changes: 71 additions & 0 deletions cumulus/pallets/weight-reclaim/src/benchmarks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Cumulus.

// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.

#![cfg(feature = "runtime-benchmarks")]

use super::*;
use frame_support::pallet_prelude::{DispatchClass, Pays};
use frame_system::RawOrigin;
use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction};

#[frame_benchmarking::v2::benchmarks(
where T: Send + Sync,
<T as frame_system::Config>::RuntimeCall:
Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
<T as frame_system::Config>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
)]
mod bench {
use super::*;
use frame_benchmarking::impl_test_function;

#[benchmark]
fn storage_weight_reclaim() {
let ext = StorageWeightReclaim::<T, ()>::new(());

let origin = RawOrigin::Root.into();
let call = T::RuntimeCall::from(frame_system::Call::remark { remark: alloc::vec![] });

let overestimate = 10_000;
let info = DispatchInfo {
call_weight: Weight::zero().add_proof_size(overestimate),
extension_weight: Weight::zero(),
class: DispatchClass::Normal,
pays_fee: Pays::No,
};

let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Pays::No };

let mut block_weight = frame_system::ConsumedWeight::default();
block_weight.accrue(Weight::from_parts(0, overestimate), info.class);

frame_system::BlockWeight::<T>::put(block_weight);

#[block]
{
assert!(ext.test_run(origin, &call, &info, 0, 0, |_| Ok(post_info)).unwrap().is_ok());
}

let final_block_proof_size =
frame_system::BlockWeight::<T>::get().get(info.class).proof_size();

assert!(
final_block_proof_size < overestimate,
"The proof size measured should be less than {overestimate}"
);
}

impl_benchmark_test_suite!(Pallet, crate::tests::setup_test_ext_default(), crate::tests::Test);
}
Loading

0 comments on commit 63c73bf

Please sign in to comment.