From 2324bd7b2d6dafb21c20ffaeb73e0a393db19e22 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 24 Oct 2024 12:47:44 +0300 Subject: [PATCH 01/15] Fix `zombienet-bridges-0001-asset-transfer-works` (#6175) Closes https://github.com/paritytech/polkadot-sdk/issues/6161 Westend BridgeHub freezes for a while at block 3 and if we try to init the bridge and fund the accounts during that time, it fails. So we wait untill all the parachains produced at least 10 blocks, in order to make sure that they work reliably. --- .gitlab/pipeline/zombienet/bridges.yml | 4 +--- .../rococo-westend/{rococo.zndsl => rococo-bridge.zndsl} | 0 .../environments/rococo-westend/rococo-start.zndsl | 8 ++++++++ bridges/testing/environments/rococo-westend/spawn.sh | 5 +++-- .../testing/environments/rococo-westend/start_relayer.sh | 4 ++-- .../{westend.zndsl => westend-bridge.zndsl} | 0 .../environments/rococo-westend/westend-start.zndsl | 8 ++++++++ 7 files changed, 22 insertions(+), 7 deletions(-) rename bridges/testing/environments/rococo-westend/{rococo.zndsl => rococo-bridge.zndsl} (100%) create mode 100644 bridges/testing/environments/rococo-westend/rococo-start.zndsl rename bridges/testing/environments/rococo-westend/{westend.zndsl => westend-bridge.zndsl} (100%) create mode 100644 bridges/testing/environments/rococo-westend/westend-start.zndsl diff --git a/.gitlab/pipeline/zombienet/bridges.yml b/.gitlab/pipeline/zombienet/bridges.yml index 0472601a6a2b..07711e32a9a3 100644 --- a/.gitlab/pipeline/zombienet/bridges.yml +++ b/.gitlab/pipeline/zombienet/bridges.yml @@ -11,7 +11,7 @@ - if: $CI_COMMIT_REF_NAME =~ /^gh-readonly-queue.*$/ variables: DOCKER_IMAGES_VERSION: ${CI_COMMIT_SHORT_SHA} - - !reference [.build-refs, rules] + - !reference [ .build-refs, rules ] before_script: - echo "Zombienet Tests Config" - echo "${ZOMBIENET_IMAGE}" @@ -47,8 +47,6 @@ - cp -r /tmp/bridges-tests-run-*/bridge_hub_rococo_local_network/*.log ./zombienet-logs/ # copy logs of westend nodes - cp -r /tmp/bridges-tests-run-*/bridge_hub_westend_local_network/*.log ./zombienet-logs/ - tags: - - zombienet-polkadot-integration-test zombienet-bridges-0001-asset-transfer-works: extends: diff --git a/bridges/testing/environments/rococo-westend/rococo.zndsl b/bridges/testing/environments/rococo-westend/rococo-bridge.zndsl similarity index 100% rename from bridges/testing/environments/rococo-westend/rococo.zndsl rename to bridges/testing/environments/rococo-westend/rococo-bridge.zndsl diff --git a/bridges/testing/environments/rococo-westend/rococo-start.zndsl b/bridges/testing/environments/rococo-westend/rococo-start.zndsl new file mode 100644 index 000000000000..8c719b010df6 --- /dev/null +++ b/bridges/testing/environments/rococo-westend/rococo-start.zndsl @@ -0,0 +1,8 @@ +Description: Check if the Rococo parachains started producing blocks reliably +Network: ./bridge_hub_westend_local_network.toml +Creds: config + +# ensure that initialization has completed +asset-hub-rococo-collator1: reports block height is at least 10 within 180 seconds +bridge-hub-rococo-collator1: reports block height is at least 10 within 180 seconds + diff --git a/bridges/testing/environments/rococo-westend/spawn.sh b/bridges/testing/environments/rococo-westend/spawn.sh index a0ab00be1444..83b3b0720bb8 100755 --- a/bridges/testing/environments/rococo-westend/spawn.sh +++ b/bridges/testing/environments/rococo-westend/spawn.sh @@ -35,9 +35,11 @@ start_zombienet $TEST_DIR $westend_def westend_dir westend_pid echo if [[ $init -eq 1 ]]; then + run_zndsl ${BASH_SOURCE%/*}/rococo-start.zndsl $rococo_dir + run_zndsl ${BASH_SOURCE%/*}/westend-start.zndsl $westend_dir + rococo_init_log=$logs_dir/rococo-init.log echo -e "Setting up the rococo side of the bridge. Logs available at: $rococo_init_log\n" - westend_init_log=$logs_dir/westend-init.log echo -e "Setting up the westend side of the bridge. Logs available at: $westend_init_log\n" @@ -47,7 +49,6 @@ if [[ $init -eq 1 ]]; then westend_init_pid=$! wait -n $rococo_init_pid $westend_init_pid - $helper_script init-bridge-hub-rococo-local >> $rococo_init_log 2>&1 & rococo_init_pid=$! $helper_script init-bridge-hub-westend-local >> $westend_init_log 2>&1 & diff --git a/bridges/testing/environments/rococo-westend/start_relayer.sh b/bridges/testing/environments/rococo-westend/start_relayer.sh index 9c57e4a6ab6e..150fce035071 100755 --- a/bridges/testing/environments/rococo-westend/start_relayer.sh +++ b/bridges/testing/environments/rococo-westend/start_relayer.sh @@ -29,8 +29,8 @@ messages_relayer_log=$logs_dir/relayer_messages.log echo -e "Starting rococo-westend messages relayer. Logs available at: $messages_relayer_log\n" start_background_process "$helper_script run-messages-relay" $messages_relayer_log messages_relayer_pid -run_zndsl ${BASH_SOURCE%/*}/rococo.zndsl $rococo_dir -run_zndsl ${BASH_SOURCE%/*}/westend.zndsl $westend_dir +run_zndsl ${BASH_SOURCE%/*}/rococo-bridge.zndsl $rococo_dir +run_zndsl ${BASH_SOURCE%/*}/westend-bridge.zndsl $westend_dir eval $__finality_relayer_pid="'$finality_relayer_pid'" eval $__parachains_relayer_pid="'$parachains_relayer_pid'" diff --git a/bridges/testing/environments/rococo-westend/westend.zndsl b/bridges/testing/environments/rococo-westend/westend-bridge.zndsl similarity index 100% rename from bridges/testing/environments/rococo-westend/westend.zndsl rename to bridges/testing/environments/rococo-westend/westend-bridge.zndsl diff --git a/bridges/testing/environments/rococo-westend/westend-start.zndsl b/bridges/testing/environments/rococo-westend/westend-start.zndsl new file mode 100644 index 000000000000..fe587322edb6 --- /dev/null +++ b/bridges/testing/environments/rococo-westend/westend-start.zndsl @@ -0,0 +1,8 @@ +Description: Check if the Westend parachains started producing blocks reliably +Network: ./bridge_hub_westend_local_network.toml +Creds: config + +# ensure that initialization has completed +asset-hub-westend-collator1: reports block height is at least 10 within 180 seconds +bridge-hub-westend-collator1: reports block height is at least 10 within 180 seconds + From d4b01add06139b39b9ce69216f06b827f7f388a7 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Thu, 24 Oct 2024 12:14:02 +0200 Subject: [PATCH 02/15] [pallet-revive] fix hardcoded gas in tests (#6192) Fix hardcoded gas limits in tests --------- Co-authored-by: GitHub Action --- prdoc/pr_6192.prdoc | 7 ++++++ substrate/frame/revive/src/evm/runtime.rs | 30 +++++++++++++++++------ substrate/frame/revive/src/lib.rs | 3 ++- 3 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 prdoc/pr_6192.prdoc diff --git a/prdoc/pr_6192.prdoc b/prdoc/pr_6192.prdoc new file mode 100644 index 000000000000..cd9255486706 --- /dev/null +++ b/prdoc/pr_6192.prdoc @@ -0,0 +1,7 @@ +title: '[pallet-revive] fix hardcoded gas in tests' +doc: +- audience: Runtime Dev + description: Fix hardcoded gas limits in tests +crates: +- name: pallet-revive + bump: patch diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs index e4340b27a187..4c3fdeca720c 100644 --- a/substrate/frame/revive/src/evm/runtime.rs +++ b/substrate/frame/revive/src/evm/runtime.rs @@ -356,12 +356,7 @@ pub trait EthExtra { Default::default(), ) .into(); - - log::debug!(target: LOG_TARGET, "Checking Ethereum transaction fees: - dispatch_info: {info:?} - encoded_len: {encoded_len:?} - fees: {actual_fee:?} - "); + log::debug!(target: LOG_TARGET, "try_into_checked_extrinsic: encoded_len: {encoded_len:?} actual_fee: {actual_fee:?} eth_fee: {eth_fee:?}"); if eth_fee < actual_fee { log::debug!(target: LOG_TARGET, "fees {eth_fee:?} too low for the extrinsic {actual_fee:?}"); @@ -490,11 +485,30 @@ mod test { } } + fn estimate_gas(&mut self) { + let dry_run = crate::Pallet::::bare_eth_transact( + Account::default().account_id(), + self.tx.to, + self.tx.value.try_into().unwrap(), + self.tx.input.clone().0, + Weight::MAX, + u64::MAX, + |call| { + let call = RuntimeCall::Contracts(call); + let uxt: Ex = sp_runtime::generic::UncheckedExtrinsic::new_bare(call).into(); + uxt.encoded_size() as u32 + }, + crate::DebugInfo::Skip, + crate::CollectEvents::Skip, + ); + self.tx.gas = ((dry_run.fee + GAS_PRICE as u64) / (GAS_PRICE as u64)).into(); + } + /// Create a new builder with a call to the given address. fn call_with(dest: H160) -> Self { let mut builder = Self::new(); builder.tx.to = Some(dest); - builder.tx.gas = U256::from(516_708u128); + builder.estimate_gas(); builder } @@ -502,7 +516,7 @@ mod test { fn instantiate_with(code: Vec, data: Vec) -> Self { let mut builder = Self::new(); builder.tx.input = Bytes(code.into_iter().chain(data.into_iter()).collect()); - builder.tx.gas = U256::from(1_035_070u128); + builder.estimate_gas(); builder } diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 9b0bbb2d6bcb..11752e47cf2a 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -1212,6 +1212,7 @@ where to: Some(dest), ..Default::default() }; + let eth_dispatch_call = crate::Call::::eth_transact { payload: tx.dummy_signed_payload(), gas_limit: result.gas_required, @@ -1238,7 +1239,7 @@ where ) .into(); - log::debug!(target: LOG_TARGET, "Call dry run Result: dispatch_info: {dispatch_info:?} len: {encoded_len:?} fee: {fee:?}"); + log::debug!(target: LOG_TARGET, "bare_eth_call: len: {encoded_len:?} fee: {fee:?}"); EthContractResult { gas_required: result.gas_required, storage_deposit: result.storage_deposit.charge_or_zero(), From b9c3172313a9c381210bbc237888648b22269722 Mon Sep 17 00:00:00 2001 From: Andrii Date: Thu, 24 Oct 2024 15:21:52 +0300 Subject: [PATCH 03/15] Added Trusted Query API implementation for Westend and Rococo relay chains (#6212) Added missing API methods to Rococo and Westend parachains. Preparatory work for making chopstick tests run smoothly. Follow-up of [PR#6039](https://github.com/paritytech/polkadot-sdk/pull/6039) --- polkadot/runtime/rococo/src/lib.rs | 14 ++++++++++++- polkadot/runtime/westend/src/lib.rs | 14 ++++++++++++- prdoc/pr_6212.prdoc | 32 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 prdoc/pr_6212.prdoc diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index e94b6666ed07..44dd820f8c3c 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -112,7 +112,10 @@ use sp_staking::SessionIndex; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use xcm::{latest::prelude::*, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; +use xcm::{ + latest::prelude::*, VersionedAsset, VersionedAssetId, VersionedAssets, VersionedLocation, + VersionedXcm, +}; use xcm_builder::PayOverXcm; pub use frame_system::Call as SystemCall; @@ -2622,6 +2625,15 @@ sp_api::impl_runtime_apis! { genesis_config_presets::preset_names() } } + + impl xcm_runtime_apis::trusted_query::TrustedQueryApi for Runtime { + fn is_trusted_reserve(asset: VersionedAsset, location: VersionedLocation) -> Result { + XcmPallet::is_trusted_reserve(asset, location) + } + fn is_trusted_teleporter(asset: VersionedAsset, location: VersionedLocation) -> Result { + XcmPallet::is_trusted_teleporter(asset, location) + } + } } #[cfg(all(test, feature = "try-runtime"))] diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 461be186ee51..a91ca399db41 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -107,7 +107,10 @@ use sp_staking::SessionIndex; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use xcm::{latest::prelude::*, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; +use xcm::{ + latest::prelude::*, VersionedAsset, VersionedAssetId, VersionedAssets, VersionedLocation, + VersionedXcm, +}; use xcm_builder::PayOverXcm; use xcm_runtime_apis::{ @@ -2791,4 +2794,13 @@ sp_api::impl_runtime_apis! { genesis_config_presets::preset_names() } } + + impl xcm_runtime_apis::trusted_query::TrustedQueryApi for Runtime { + fn is_trusted_reserve(asset: VersionedAsset, location: VersionedLocation) -> Result { + XcmPallet::is_trusted_reserve(asset, location) + } + fn is_trusted_teleporter(asset: VersionedAsset, location: VersionedLocation) -> Result { + XcmPallet::is_trusted_teleporter(asset, location) + } + } } diff --git a/prdoc/pr_6212.prdoc b/prdoc/pr_6212.prdoc new file mode 100644 index 000000000000..97f522025d1e --- /dev/null +++ b/prdoc/pr_6212.prdoc @@ -0,0 +1,32 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Added Trusted Query API calls for Westend and Rococo chains" + +doc: + - audience: Runtime Dev + description: | + Added is_trusted_reserve and is_trusted_teleporter API calls to relay chains. + Given an asset and a location, they return if the chain trusts that location as a reserve or teleporter for that asset respectively. + You can implement them on your runtime by simply calling a helper function on `pallet-xcm`. + ```rust + impl xcm_runtime_apis::trusted_query::TrustedQueryApi for Runtime { + fn is_trusted_reserve(asset: VersionedAsset, location: VersionedLocation) -> Result { + PolkadotXcm::is_trusted_reserve(asset, location) + } + fn is_trusted_teleporter(asset: VersionedAsset, location: VersionedLocation) -> Result { + PolkadotXcm::is_trusted_teleporter(asset, location) + } + } + ``` + + - audience: Runtime User + description: | + There's a new runtime API to check if a chain trust a Location as a reserve or teleporter for a given Asset. + It's implemented in all the relays and system parachains in Westend and Rococo. + +crates: + - name: westend-runtime + bump: minor + - name: rococo-runtime + bump: minor From 5682f9a273309c7160722a7937a75152a2793b23 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Thu, 24 Oct 2024 14:27:01 +0200 Subject: [PATCH 04/15] Snowbridge: PNA Audit Better Documentation and minor Refactorings (#6216) # Description Snowbridge PNA has been audited. A number of issues where raised due to not understanding the fee model for Polkadot Native Assets(PNA) implementation. This PR addresses this by adding more comments and better naming of private functions. ## Integration None, documentation and private method name changes. --- .../primitives/router/src/inbound/mod.rs | 2 ++ .../primitives/router/src/outbound/mod.rs | 26 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/bridges/snowbridge/primitives/router/src/inbound/mod.rs b/bridges/snowbridge/primitives/router/src/inbound/mod.rs index fbfc52d01c83..a9324ac42470 100644 --- a/bridges/snowbridge/primitives/router/src/inbound/mod.rs +++ b/bridges/snowbridge/primitives/router/src/inbound/mod.rs @@ -416,6 +416,8 @@ where // Final destination is a 32-byte account on AssetHub Destination::AccountId32 { id } => Ok(Location::new(0, [AccountId32 { network: None, id }])), + // Forwarding to a destination parachain is not allowed for PNA and is validated on the + // Ethereum side. https://github.com/Snowfork/snowbridge/blob/e87ddb2215b513455c844463a25323bb9c01ff36/contracts/src/Assets.sol#L216-L224 _ => Err(ConvertMessageError::InvalidDestination), }?; diff --git a/bridges/snowbridge/primitives/router/src/outbound/mod.rs b/bridges/snowbridge/primitives/router/src/outbound/mod.rs index efc1ef56f304..3b5dbdb77c89 100644 --- a/bridges/snowbridge/primitives/router/src/outbound/mod.rs +++ b/bridges/snowbridge/primitives/router/src/outbound/mod.rs @@ -207,9 +207,9 @@ where fn convert(&mut self) -> Result<(Command, [u8; 32]), XcmConverterError> { let result = match self.peek() { - Ok(ReserveAssetDeposited { .. }) => self.send_native_tokens_message(), + Ok(ReserveAssetDeposited { .. }) => self.make_mint_foreign_token_command(), // Get withdraw/deposit and make native tokens create message. - Ok(WithdrawAsset { .. }) => self.send_tokens_message(), + Ok(WithdrawAsset { .. }) => self.make_unlock_native_token_command(), Err(e) => Err(e), _ => return Err(XcmConverterError::UnexpectedInstruction), }?; @@ -222,7 +222,9 @@ where Ok(result) } - fn send_tokens_message(&mut self) -> Result<(Command, [u8; 32]), XcmConverterError> { + fn make_unlock_native_token_command( + &mut self, + ) -> Result<(Command, [u8; 32]), XcmConverterError> { use XcmConverterError::*; // Get the reserve assets from WithdrawAsset. @@ -271,7 +273,12 @@ where ensure!(reserve_assets.len() == 1, TooManyAssets); let reserve_asset = reserve_assets.get(0).ok_or(AssetResolutionFailed)?; - // If there was a fee specified verify it. + // Fees are collected on AH, up front and directly from the user, to cover the + // complete cost of the transfer. Any additional fees provided in the XCM program are + // refunded to the beneficiary. We only validate the fee here if its provided to make sure + // the XCM program is well formed. Another way to think about this from an XCM perspective + // would be that the user offered to pay X amount in fees, but we charge 0 of that X amount + // (no fee) and refund X to the user. if let Some(fee_asset) = fee_asset { // The fee asset must be the same as the reserve asset. if fee_asset.id != reserve_asset.id || fee_asset.fun > reserve_asset.fun { @@ -328,7 +335,9 @@ where /// # BuyExecution /// # DepositAsset /// # SetTopic - fn send_native_tokens_message(&mut self) -> Result<(Command, [u8; 32]), XcmConverterError> { + fn make_mint_foreign_token_command( + &mut self, + ) -> Result<(Command, [u8; 32]), XcmConverterError> { use XcmConverterError::*; // Get the reserve assets. @@ -377,7 +386,12 @@ where ensure!(reserve_assets.len() == 1, TooManyAssets); let reserve_asset = reserve_assets.get(0).ok_or(AssetResolutionFailed)?; - // If there was a fee specified verify it. + // Fees are collected on AH, up front and directly from the user, to cover the + // complete cost of the transfer. Any additional fees provided in the XCM program are + // refunded to the beneficiary. We only validate the fee here if its provided to make sure + // the XCM program is well formed. Another way to think about this from an XCM perspective + // would be that the user offered to pay X amount in fees, but we charge 0 of that X amount + // (no fee) and refund X to the user. if let Some(fee_asset) = fee_asset { // The fee asset must be the same as the reserve asset. if fee_asset.id != reserve_asset.id || fee_asset.fun > reserve_asset.fun { From c0df223e13862851ab5a4dadc1e592acea37f88d Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:01:12 +0300 Subject: [PATCH 05/15] Enable approval-voting-parallel by default on kusama (#6218) The approval-voting-parallel introduced with https://github.com/paritytech/polkadot-sdk/pull/4849 has been tested on `versi` and approximately 3 weeks on parity's existing kusama nodes https://github.com/paritytech/devops/issues/3583, things worked as expected, so enable it by default on all kusama nodes in the next release. The next step will be enabling by default on polkadot if no issue arrises while running on kusama. --------- Signed-off-by: Alexandru Gheorghe --- polkadot/node/service/src/lib.rs | 9 ++++----- prdoc/pr_6218.prdoc | 9 +++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 prdoc/pr_6218.prdoc diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index da3ab760ed22..d6f24159e1da 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -759,13 +759,12 @@ pub fn new_full< Some(backoff) }; - // Running approval voting in parallel is enabled by default on all networks except Polkadot and - // Kusama, unless explicitly enabled by the commandline option. + // Running approval voting in parallel is enabled by default on all networks except Polkadot + // unless explicitly enabled by the commandline option. // This is meant to be temporary until we have enough confidence in the new system to enable it // by default on all networks. - let enable_approval_voting_parallel = (!config.chain_spec.is_kusama() && - !config.chain_spec.is_polkadot()) || - enable_approval_voting_parallel; + let enable_approval_voting_parallel = + !config.chain_spec.is_polkadot() || enable_approval_voting_parallel; let disable_grandpa = config.disable_grandpa; let name = config.network.node_name.clone(); diff --git a/prdoc/pr_6218.prdoc b/prdoc/pr_6218.prdoc new file mode 100644 index 000000000000..5c97c926f238 --- /dev/null +++ b/prdoc/pr_6218.prdoc @@ -0,0 +1,9 @@ +title: Enable approval-voting-parallel by default on kusama + +doc: + - audience: Node Dev + description: | + Enable approval-voting-parallel by default on kusama +crates: + - name: polkadot-service + bump: patch From 68af85e739b4e7589466879fb99ecd8624e0c29f Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Thu, 24 Oct 2024 16:33:59 +0200 Subject: [PATCH 06/15] pallet macro: Support instantiable pallets in tasks (#5194) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix https://github.com/paritytech/polkadot-sdk/issues/5185 also implement handling of attr in expansion in construct-runtime --------- Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Bastian Köcher --- prdoc/pr_5194.prdoc | 11 ++ .../src/construct_runtime/expand/task.rs | 57 +++++-- .../procedural/src/pallet/expand/tasks.rs | 155 +++++++----------- .../src/pallet/expand/tt_default_parts.rs | 4 +- .../procedural/src/pallet/parse/mod.rs | 7 +- .../procedural/src/pallet/parse/tasks.rs | 34 ++-- .../test/tests/pallet_ui/pass/task_valid.rs | 26 +++ .../test/tests/pallet_ui/task_invalid_gen.rs | 39 +++++ .../tests/pallet_ui/task_invalid_gen.stderr | 5 + .../test/tests/pallet_ui/task_invalid_gen2.rs | 39 +++++ .../tests/pallet_ui/task_invalid_gen2.stderr | 13 ++ substrate/frame/support/test/tests/tasks.rs | 135 +++++++++++++++ 12 files changed, 392 insertions(+), 133 deletions(-) create mode 100644 prdoc/pr_5194.prdoc create mode 100644 substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.stderr create mode 100644 substrate/frame/support/test/tests/tasks.rs diff --git a/prdoc/pr_5194.prdoc b/prdoc/pr_5194.prdoc new file mode 100644 index 000000000000..afb9d57e79e3 --- /dev/null +++ b/prdoc/pr_5194.prdoc @@ -0,0 +1,11 @@ +title: "FRAME: Support instantiable pallets in tasks." + +doc: + - audience: Runtime Dev + description: | + In FRAME, tasks can now be used in instantiable pallet. Also some fix for expansion with + conditional compilation in construct runtine. + +crates: + - name: frame-support-procedural + bump: patch diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs index 6531c0e9e070..1302f86455f2 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs @@ -16,6 +16,7 @@ // limitations under the License use crate::construct_runtime::Pallet; +use core::str::FromStr; use proc_macro2::{Ident, TokenStream as TokenStream2}; use quote::quote; @@ -28,7 +29,8 @@ pub fn expand_outer_task( let mut from_impls = Vec::new(); let mut task_variants = Vec::new(); let mut variant_names = Vec::new(); - let mut task_paths = Vec::new(); + let mut task_types = Vec::new(); + let mut cfg_attrs = Vec::new(); for decl in pallet_decls { if decl.find_part("Task").is_none() { continue @@ -37,18 +39,31 @@ pub fn expand_outer_task( let variant_name = &decl.name; let path = &decl.path; let index = decl.index; + let instance = decl.instance.as_ref().map(|instance| quote!(, #path::#instance)); + let task_type = quote!(#path::Task<#runtime_name #instance>); + + let attr = decl.cfg_pattern.iter().fold(TokenStream2::new(), |acc, pattern| { + let attr = TokenStream2::from_str(&format!("#[cfg({})]", pattern.original())) + .expect("was successfully parsed before; qed"); + quote! { + #acc + #attr + } + }); from_impls.push(quote! { - impl From<#path::Task<#runtime_name>> for RuntimeTask { - fn from(hr: #path::Task<#runtime_name>) -> Self { + #attr + impl From<#task_type> for RuntimeTask { + fn from(hr: #task_type) -> Self { RuntimeTask::#variant_name(hr) } } - impl TryInto<#path::Task<#runtime_name>> for RuntimeTask { + #attr + impl TryInto<#task_type> for RuntimeTask { type Error = (); - fn try_into(self) -> Result<#path::Task<#runtime_name>, Self::Error> { + fn try_into(self) -> Result<#task_type, Self::Error> { match self { RuntimeTask::#variant_name(hr) => Ok(hr), _ => Err(()), @@ -58,13 +73,16 @@ pub fn expand_outer_task( }); task_variants.push(quote! { + #attr #[codec(index = #index)] - #variant_name(#path::Task<#runtime_name>), + #variant_name(#task_type), }); variant_names.push(quote!(#variant_name)); - task_paths.push(quote!(#path::Task)); + task_types.push(task_type); + + cfg_attrs.push(attr); } let prelude = quote!(#scrate::traits::tasks::__private); @@ -91,35 +109,50 @@ pub fn expand_outer_task( fn is_valid(&self) -> bool { match self { - #(RuntimeTask::#variant_names(val) => val.is_valid(),)* + #( + #cfg_attrs + RuntimeTask::#variant_names(val) => val.is_valid(), + )* _ => unreachable!(#INCOMPLETE_MATCH_QED), } } fn run(&self) -> Result<(), #scrate::traits::tasks::__private::DispatchError> { match self { - #(RuntimeTask::#variant_names(val) => val.run(),)* + #( + #cfg_attrs + RuntimeTask::#variant_names(val) => val.run(), + )* _ => unreachable!(#INCOMPLETE_MATCH_QED), } } fn weight(&self) -> #scrate::pallet_prelude::Weight { match self { - #(RuntimeTask::#variant_names(val) => val.weight(),)* + #( + #cfg_attrs + RuntimeTask::#variant_names(val) => val.weight(), + )* _ => unreachable!(#INCOMPLETE_MATCH_QED), } } fn task_index(&self) -> u32 { match self { - #(RuntimeTask::#variant_names(val) => val.task_index(),)* + #( + #cfg_attrs + RuntimeTask::#variant_names(val) => val.task_index(), + )* _ => unreachable!(#INCOMPLETE_MATCH_QED), } } fn iter() -> Self::Enumeration { let mut all_tasks = Vec::new(); - #(all_tasks.extend(#task_paths::iter().map(RuntimeTask::from).collect::>());)* + #( + #cfg_attrs + all_tasks.extend(<#task_types>::iter().map(RuntimeTask::from).collect::>()); + )* all_tasks.into_iter() } } diff --git a/substrate/frame/support/procedural/src/pallet/expand/tasks.rs b/substrate/frame/support/procedural/src/pallet/expand/tasks.rs index 7201c352d92c..b6346ca8ff34 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/tasks.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/tasks.rs @@ -20,21 +20,25 @@ //! Home of the expansion code for the Tasks API use crate::pallet::{parse::tasks::*, Def}; -use derive_syn_parse::Parse; use inflector::Inflector; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote, ToTokens}; -use syn::{parse_quote, spanned::Spanned, ItemEnum, ItemImpl}; +use syn::{parse_quote_spanned, spanned::Spanned}; impl TaskEnumDef { /// Since we optionally allow users to manually specify a `#[pallet::task_enum]`, in the /// event they _don't_ specify one (which is actually the most common behavior) we have to /// generate one based on the existing [`TasksDef`]. This method performs that generation. - pub fn generate( - tasks: &TasksDef, - type_decl_bounded_generics: TokenStream2, - type_use_generics: TokenStream2, - ) -> Self { + pub fn generate(tasks: &TasksDef, def: &Def) -> Self { + // We use the span of the attribute to indicate that the error comes from code generated + // for the specific section, otherwise the item impl. + let span = tasks + .tasks_attr + .as_ref() + .map_or_else(|| tasks.item_impl.span(), |attr| attr.span()); + + let type_decl_bounded_generics = def.type_decl_bounded_generics(span); + let variants = if tasks.tasks_attr.is_some() { tasks .tasks @@ -58,7 +62,8 @@ impl TaskEnumDef { } else { Vec::new() }; - let mut task_enum_def: TaskEnumDef = parse_quote! { + + parse_quote_spanned! { span => /// Auto-generated enum that encapsulates all tasks defined by this pallet. /// /// Conceptually similar to the [`Call`] enum, but for tasks. This is only @@ -69,33 +74,32 @@ impl TaskEnumDef { #variants, )* } - }; - task_enum_def.type_use_generics = type_use_generics; - task_enum_def + } } } -impl ToTokens for TaskEnumDef { - fn to_tokens(&self, tokens: &mut TokenStream2) { - let item_enum = &self.item_enum; - let ident = &item_enum.ident; - let vis = &item_enum.vis; - let attrs = &item_enum.attrs; - let generics = &item_enum.generics; - let variants = &item_enum.variants; - let scrate = &self.scrate; - let type_use_generics = &self.type_use_generics; - if self.attr.is_some() { +impl TaskEnumDef { + fn expand_to_tokens(&self, def: &Def) -> TokenStream2 { + if let Some(attr) = &self.attr { + let ident = &self.item_enum.ident; + let vis = &self.item_enum.vis; + let attrs = &self.item_enum.attrs; + let generics = &self.item_enum.generics; + let variants = &self.item_enum.variants; + let frame_support = &def.frame_support; + let type_use_generics = &def.type_use_generics(attr.span()); + let type_impl_generics = &def.type_impl_generics(attr.span()); + // `item_enum` is short-hand / generated enum - tokens.extend(quote! { + quote! { #(#attrs)* #[derive( - #scrate::CloneNoBound, - #scrate::EqNoBound, - #scrate::PartialEqNoBound, - #scrate::pallet_prelude::Encode, - #scrate::pallet_prelude::Decode, - #scrate::pallet_prelude::TypeInfo, + #frame_support::CloneNoBound, + #frame_support::EqNoBound, + #frame_support::PartialEqNoBound, + #frame_support::pallet_prelude::Encode, + #frame_support::pallet_prelude::Decode, + #frame_support::pallet_prelude::TypeInfo, )] #[codec(encode_bound())] #[codec(decode_bound())] @@ -104,32 +108,25 @@ impl ToTokens for TaskEnumDef { #variants #[doc(hidden)] #[codec(skip)] - __Ignore(core::marker::PhantomData, #scrate::Never), + __Ignore(core::marker::PhantomData<(#type_use_generics)>, #frame_support::Never), } - impl core::fmt::Debug for #ident<#type_use_generics> { + impl<#type_impl_generics> core::fmt::Debug for #ident<#type_use_generics> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct(stringify!(#ident)).field("value", self).finish() } } - }); + } } else { // `item_enum` is a manually specified enum (no attribute) - tokens.extend(item_enum.to_token_stream()); + self.item_enum.to_token_stream() } } } -/// Represents an already-expanded [`TasksDef`]. -#[derive(Parse)] -pub struct ExpandedTasksDef { - pub task_item_impl: ItemImpl, - pub task_trait_impl: ItemImpl, -} - -impl ToTokens for TasksDef { - fn to_tokens(&self, tokens: &mut TokenStream2) { - let scrate = &self.scrate; +impl TasksDef { + fn expand_to_tokens(&self, def: &Def) -> TokenStream2 { + let frame_support = &def.frame_support; let enum_ident = syn::Ident::new("Task", self.enum_ident.span()); let enum_arguments = &self.enum_arguments; let enum_use = quote!(#enum_ident #enum_arguments); @@ -160,21 +157,21 @@ impl ToTokens for TasksDef { let task_arg_names = self.tasks.iter().map(|task| &task.arg_names).collect::>(); let impl_generics = &self.item_impl.generics; - tokens.extend(quote! { + quote! { impl #impl_generics #enum_use { #(#task_fn_impls)* } - impl #impl_generics #scrate::traits::Task for #enum_use + impl #impl_generics #frame_support::traits::Task for #enum_use { - type Enumeration = #scrate::__private::IntoIter<#enum_use>; + type Enumeration = #frame_support::__private::IntoIter<#enum_use>; fn iter() -> Self::Enumeration { - let mut all_tasks = #scrate::__private::vec![]; + let mut all_tasks = #frame_support::__private::vec![]; #(all_tasks .extend(#task_iters.map(|(#(#task_arg_names),*)| #enum_ident::#task_fn_idents { #(#task_arg_names: #task_arg_names.clone()),* }) - .collect::<#scrate::__private::Vec<_>>()); + .collect::<#frame_support::__private::Vec<_>>()); )* all_tasks.into_iter() } @@ -193,7 +190,7 @@ impl ToTokens for TasksDef { } } - fn run(&self) -> Result<(), #scrate::pallet_prelude::DispatchError> { + fn run(&self) -> Result<(), #frame_support::pallet_prelude::DispatchError> { match self.clone() { #(#enum_ident::#task_fn_idents { #(#task_arg_names),* } => { <#enum_use>::#task_fn_names(#( #task_arg_names, )* ) @@ -203,64 +200,32 @@ impl ToTokens for TasksDef { } #[allow(unused_variables)] - fn weight(&self) -> #scrate::pallet_prelude::Weight { + fn weight(&self) -> #frame_support::pallet_prelude::Weight { match self.clone() { #(#enum_ident::#task_fn_idents { #(#task_arg_names),* } => #task_weights,)* Task::__Ignore(_, _) => unreachable!(), } } } - }); + } } } -/// Expands the [`TasksDef`] in the enclosing [`Def`], if present, and returns its tokens. -/// -/// This modifies the underlying [`Def`] in addition to returning any tokens that were added. -pub fn expand_tasks_impl(def: &mut Def) -> TokenStream2 { - let Some(tasks) = &mut def.tasks else { return quote!() }; - let ExpandedTasksDef { task_item_impl, task_trait_impl } = parse_quote!(#tasks); - quote! { - #task_item_impl - #task_trait_impl - } -} +/// Generate code related to tasks. +pub fn expand_tasks(def: &Def) -> TokenStream2 { + let Some(tasks_def) = &def.tasks else { + return quote!(); + }; -/// Represents a fully-expanded [`TaskEnumDef`]. -#[derive(Parse)] -pub struct ExpandedTaskEnum { - pub item_enum: ItemEnum, - pub debug_impl: ItemImpl, -} + let default_task_enum = TaskEnumDef::generate(&tasks_def, def); -/// Modifies a [`Def`] to expand the underlying [`TaskEnumDef`] if present, and also returns -/// its tokens. A blank [`TokenStream2`] is returned if no [`TaskEnumDef`] has been generated -/// or defined. -pub fn expand_task_enum(def: &mut Def) -> TokenStream2 { - let Some(task_enum) = &mut def.task_enum else { return quote!() }; - let ExpandedTaskEnum { item_enum, debug_impl } = parse_quote!(#task_enum); - quote! { - #item_enum - #debug_impl - } -} + let task_enum = def.task_enum.as_ref().unwrap_or_else(|| &default_task_enum); + + let tasks_expansion = tasks_def.expand_to_tokens(def); + let task_enum_expansion = task_enum.expand_to_tokens(def); -/// Modifies a [`Def`] to expand the underlying [`TasksDef`] and also generate a -/// [`TaskEnumDef`] if applicable. The tokens for these items are returned if they are created. -pub fn expand_tasks(def: &mut Def) -> TokenStream2 { - if let Some(tasks_def) = &def.tasks { - if def.task_enum.is_none() { - def.task_enum = Some(TaskEnumDef::generate( - &tasks_def, - def.type_decl_bounded_generics(tasks_def.item_impl.span()), - def.type_use_generics(tasks_def.item_impl.span()), - )); - } - } - let tasks_extra_output = expand_tasks_impl(def); - let task_enum_extra_output = expand_task_enum(def); quote! { - #tasks_extra_output - #task_enum_extra_output + #tasks_expansion + #task_enum_expansion } } diff --git a/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs b/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs index 1975f059152c..6d53de3133e8 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs @@ -33,7 +33,7 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { let call_part = def.call.as_ref().map(|_| quote::quote!(Call,)); - let task_part = def.task_enum.as_ref().map(|_| quote::quote!(Task,)); + let task_part = def.tasks.as_ref().map(|_| quote::quote!(Task,)); let storage_part = (!def.storages.is_empty()).then(|| quote::quote!(Storage,)); @@ -85,7 +85,7 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { let call_part_v2 = def.call.as_ref().map(|_| quote::quote!(+ Call)); - let task_part_v2 = def.task_enum.as_ref().map(|_| quote::quote!(+ Task)); + let task_part_v2 = def.tasks.as_ref().map(|_| quote::quote!(+ Task)); let storage_part_v2 = (!def.storages.is_empty()).then(|| quote::quote!(+ Storage)); diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index 5036f691690f..c9a150effccb 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -126,11 +126,11 @@ impl Def { }, Some(PalletAttr::RuntimeCall(cw, span)) if call.is_none() => call = Some(call::CallDef::try_from(span, index, item, dev_mode, cw)?), - Some(PalletAttr::Tasks(_)) if tasks.is_none() => { + Some(PalletAttr::Tasks(span)) if tasks.is_none() => { let item_tokens = item.to_token_stream(); // `TasksDef::parse` needs to know if attr was provided so we artificially // re-insert it here - tasks = Some(syn::parse2::(quote::quote! { + tasks = Some(syn::parse2::(quote::quote_spanned! { span => #[pallet::tasks_experimental] #item_tokens })?); @@ -404,6 +404,9 @@ impl Def { if let Some(extra_constants) = &self.extra_constants { instances.extend_from_slice(&extra_constants.instances[..]); } + if let Some(task_enum) = &self.task_enum { + instances.push(task_enum.instance_usage.clone()); + } let mut errors = instances.into_iter().filter_map(|instances| { if instances.has_instance == self.config.has_instance { diff --git a/substrate/frame/support/procedural/src/pallet/parse/tasks.rs b/substrate/frame/support/procedural/src/pallet/parse/tasks.rs index ed860849a4db..5bff64643df1 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/tasks.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/tasks.rs @@ -25,8 +25,8 @@ use crate::assert_parse_error_matches; #[cfg(test)] use crate::pallet::parse::tests::simulate_manifest_dir; +use super::helper; use derive_syn_parse::Parse; -use frame_support_procedural_tools::generate_access_from_frame_or_crate; use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens}; use syn::{ @@ -34,8 +34,8 @@ use syn::{ parse2, spanned::Spanned, token::{Bracket, Paren, PathSep, Pound}, - Error, Expr, Ident, ImplItem, ImplItemFn, ItemEnum, ItemImpl, LitInt, Path, PathArguments, - Result, TypePath, + Error, Expr, Ident, ImplItem, ImplItemFn, ItemEnum, ItemImpl, LitInt, PathArguments, Result, + TypePath, }; pub mod keywords { @@ -57,8 +57,6 @@ pub struct TasksDef { pub tasks_attr: Option, pub tasks: Vec, pub item_impl: ItemImpl, - /// Path to `frame_support` - pub scrate: Path, pub enum_ident: Ident, pub enum_arguments: PathArguments, } @@ -114,11 +112,7 @@ impl syn::parse::Parse for TasksDef { let enum_ident = last_seg.ident.clone(); let enum_arguments = last_seg.arguments.clone(); - // We do this here because it would be improper to do something fallible like this at - // the expansion phase. Fallible stuff should happen during parsing. - let scrate = generate_access_from_frame_or_crate("frame-support")?; - - Ok(TasksDef { tasks_attr, item_impl, tasks, scrate, enum_ident, enum_arguments }) + Ok(TasksDef { tasks_attr, item_impl, tasks, enum_ident, enum_arguments }) } } @@ -146,12 +140,11 @@ pub type PalletTaskEnumAttr = PalletTaskAttr; /// Parsing for a manually-specified (or auto-generated) task enum, optionally including the /// attached `#[pallet::task_enum]` attribute. -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct TaskEnumDef { pub attr: Option, pub item_enum: ItemEnum, - pub scrate: Path, - pub type_use_generics: TokenStream2, + pub instance_usage: helper::InstanceUsage, } impl syn::parse::Parse for TaskEnumDef { @@ -163,13 +156,10 @@ impl syn::parse::Parse for TaskEnumDef { None => None, }; - // We do this here because it would be improper to do something fallible like this at - // the expansion phase. Fallible stuff should happen during parsing. - let scrate = generate_access_from_frame_or_crate("frame-support")?; - - let type_use_generics = quote!(T); + let instance_usage = + helper::check_type_def_gen(&item_enum.generics, item_enum.ident.span())?; - Ok(TaskEnumDef { attr, item_enum, scrate, type_use_generics }) + Ok(TaskEnumDef { attr, item_enum, instance_usage }) } } @@ -896,7 +886,7 @@ fn test_parse_task_enum_def_non_task_name() { simulate_manifest_dir("../../examples/basic", || { parse2::(quote! { #[pallet::task_enum] - pub enum Something { + pub enum Something { Foo } }) @@ -921,7 +911,7 @@ fn test_parse_task_enum_def_missing_attr_allowed() { fn test_parse_task_enum_def_missing_attr_alternate_name_allowed() { simulate_manifest_dir("../../examples/basic", || { parse2::(quote! { - pub enum Foo { + pub enum Foo { Red, } }) @@ -951,7 +941,7 @@ fn test_parse_task_enum_def_wrong_item() { assert_parse_error_matches!( parse2::(quote! { #[pallet::task_enum] - pub struct Something; + pub struct Something; }), "expected `enum`" ); diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs b/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs index 234e220f49d8..bc66c09de7e8 100644 --- a/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs +++ b/substrate/frame/support/test/tests/pallet_ui/pass/task_valid.rs @@ -39,5 +39,31 @@ mod pallet { } } +#[frame_support::pallet(dev_mode)] +mod pallet_with_instance { + use frame_support::pallet_prelude::{ValueQuery, StorageValue}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + pub type SomeStorage = StorageValue<_, u32, ValueQuery>; + + #[pallet::tasks_experimental] + impl, I> Pallet { + #[pallet::task_index(0)] + #[pallet::task_condition(|i, j| i == 0u32 && j == 2u64)] + #[pallet::task_list(vec![(0u32, 2u64), (2u32, 4u64)].iter())] + #[pallet::task_weight(0.into())] + fn foo(_i: u32, _j: u64) -> frame_support::pallet_prelude::DispatchResult { + >::get(); + Ok(()) + } + } +} + fn main() { } diff --git a/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.rs b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.rs new file mode 100644 index 000000000000..52ae19dcb02d --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet(dev_mode)] +mod pallet_with_instance { + use frame_support::pallet_prelude::{ValueQuery, StorageValue}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + pub type SomeStorage = StorageValue<_, u32, ValueQuery>; + + #[pallet::task_enum] + pub enum Task {} + + #[pallet::tasks_experimental] + impl frame_support::traits::Task for Task {} +} + +fn main() { +} diff --git a/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.stderr b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.stderr new file mode 100644 index 000000000000..1dc9e3d4aa11 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen.stderr @@ -0,0 +1,5 @@ +error: Invalid generic declaration, trait is defined with instance but generic use none + --> tests/pallet_ui/task_invalid_gen.rs:32:11 + | +32 | pub enum Task {} + | ^^^^ diff --git a/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.rs b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.rs new file mode 100644 index 000000000000..56392cbad2dc --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet(dev_mode)] +mod pallet_with_instance { + use frame_support::pallet_prelude::{ValueQuery, StorageValue}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + pub type SomeStorage = StorageValue<_, u32, ValueQuery>; + + #[pallet::task_enum] + pub enum Task {} + + #[pallet::tasks_experimental] + impl frame_support::traits::Task for Task {} +} + +fn main() { +} diff --git a/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.stderr b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.stderr new file mode 100644 index 000000000000..448825e60155 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/task_invalid_gen2.stderr @@ -0,0 +1,13 @@ +error: Invalid type def generics: expected `T` or `T: Config` or `T, I = ()` or `T: Config, I: 'static = ()` + --> tests/pallet_ui/task_invalid_gen2.rs:32:11 + | +32 | pub enum Task {} + | ^^^^ + +error: unexpected end of input, expected `T` + --> tests/pallet_ui/task_invalid_gen2.rs:18:1 + | +18 | #[frame_support::pallet(dev_mode)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/tasks.rs b/substrate/frame/support/test/tests/tasks.rs new file mode 100644 index 000000000000..97e58388362b --- /dev/null +++ b/substrate/frame/support/test/tests/tasks.rs @@ -0,0 +1,135 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(feature = "experimental")] + +#[frame_support::pallet(dev_mode)] +mod my_pallet { + use frame_support::pallet_prelude::{StorageValue, ValueQuery}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + pub type SomeStorage = StorageValue<_, (u32, u64), ValueQuery>; + + #[pallet::tasks_experimental] + impl, I> Pallet { + #[pallet::task_index(0)] + #[pallet::task_condition(|i, j| i == 0u32 && j == 2u64)] + #[pallet::task_list(vec![(0u32, 2u64), (2u32, 4u64)].iter())] + #[pallet::task_weight(0.into())] + fn foo(i: u32, j: u64) -> frame_support::pallet_prelude::DispatchResult { + >::put((i, j)); + Ok(()) + } + } +} + +// Another pallet for which we won't implement the default instance. +#[frame_support::pallet(dev_mode)] +mod my_pallet_2 { + use frame_support::pallet_prelude::{StorageValue, ValueQuery}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + pub type SomeStorage = StorageValue<_, (u32, u64), ValueQuery>; + + #[pallet::tasks_experimental] + impl, I> Pallet { + #[pallet::task_index(0)] + #[pallet::task_condition(|i, j| i == 0u32 && j == 2u64)] + #[pallet::task_list(vec![(0u32, 2u64), (2u32, 4u64)].iter())] + #[pallet::task_weight(0.into())] + fn foo(i: u32, j: u64) -> frame_support::pallet_prelude::DispatchResult { + >::put((i, j)); + Ok(()) + } + } +} + +type BlockNumber = u32; +type AccountId = u64; +type Header = sp_runtime::generic::Header; +type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; +type Block = sp_runtime::generic::Block; + +frame_support::construct_runtime!( + pub enum Runtime + { + System: frame_system, + MyPallet: my_pallet, + MyPallet2: my_pallet::, + #[cfg(feature = "frame-feature-testing")] + MyPallet3: my_pallet::, + MyPallet4: my_pallet_2::, + } +); + +// NOTE: Needed for derive_impl expansion +use frame_support::derive_impl; +#[frame_support::derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type Block = Block; + type AccountId = AccountId; +} + +impl my_pallet::Config for Runtime {} + +impl my_pallet::Config for Runtime {} + +#[cfg(feature = "frame-feature-testing")] +impl my_pallet::Config for Runtime {} + +impl my_pallet_2::Config for Runtime {} + +fn new_test_ext() -> sp_io::TestExternalities { + use sp_runtime::BuildStorage; + + RuntimeGenesisConfig::default().build_storage().unwrap().into() +} + +#[test] +fn tasks_work() { + new_test_ext().execute_with(|| { + use frame_support::instances::{Instance1, Instance2}; + + let task = RuntimeTask::MyPallet(my_pallet::Task::::Foo { i: 0u32, j: 2u64 }); + + frame_support::assert_ok!(System::do_task(RuntimeOrigin::signed(1), task.clone(),)); + assert_eq!(my_pallet::SomeStorage::::get(), (0, 2)); + + let task = RuntimeTask::MyPallet2(my_pallet::Task::::Foo { i: 0u32, j: 2u64 }); + + frame_support::assert_ok!(System::do_task(RuntimeOrigin::signed(1), task.clone(),)); + assert_eq!(my_pallet::SomeStorage::::get(), (0, 2)); + + let task = + RuntimeTask::MyPallet4(my_pallet_2::Task::::Foo { i: 0u32, j: 2u64 }); + + frame_support::assert_ok!(System::do_task(RuntimeOrigin::signed(1), task.clone(),)); + assert_eq!(my_pallet_2::SomeStorage::::get(), (0, 2)); + }); +} From 860d93bdc90aad99a23ba403ac824db046d273f1 Mon Sep 17 00:00:00 2001 From: Javier Viola <363911+pepoviola@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:58:17 -0300 Subject: [PATCH 07/15] Disable tests reported in #6062 (#6064) Flaky tests reported in #6062 #6063 (already fixed) Thx! --- .gitlab/pipeline/zombienet/polkadot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/pipeline/zombienet/polkadot.yml b/.gitlab/pipeline/zombienet/polkadot.yml index 60870caf26c8..9a907d8d9946 100644 --- a/.gitlab/pipeline/zombienet/polkadot.yml +++ b/.gitlab/pipeline/zombienet/polkadot.yml @@ -158,7 +158,7 @@ zombienet-polkadot-functional-0010-validator-disabling: --local-dir="${LOCAL_DIR}/functional" --test="0010-validator-disabling.zndsl" -zombienet-polkadot-functional-0011-async-backing-6-seconds-rate: +.zombienet-polkadot-functional-0011-async-backing-6-seconds-rate: extends: - .zombienet-polkadot-common script: From 0596928e649dbd7b8ea8f94cf301926555943534 Mon Sep 17 00:00:00 2001 From: Jun Jiang Date: Fri, 25 Oct 2024 04:27:55 +0800 Subject: [PATCH 08/15] Fix a tiny typo (#6229) Just fix a tiny typo --- templates/solochain/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index 42361a2ff360..f2eb49592be9 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -146,7 +146,7 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The `TransactionExtension`` to the basic transaction logic. +/// The `TransactionExtension` to the basic transaction logic. pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, From 5d7181cda209053fda007679e34afccfa3e95130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 25 Oct 2024 00:53:03 +0200 Subject: [PATCH 09/15] pallet-message-queue: Fix max message size calculation (#6205) The max size of a message should not depend on the weight left in a given execution context. Instead the max message size depends on the service weights configured for the pallet. A message that may does not fit into `on_idle` is not automatically overweight, because it may can be executed successfully in `on_initialize` or in another block in `on_idle` when there is more weight left. --------- Co-authored-by: GitHub Action --- prdoc/pr_6205.prdoc | 8 ++ substrate/frame/message-queue/src/lib.rs | 49 ++++++++++- substrate/frame/message-queue/src/mock.rs | 2 +- substrate/frame/message-queue/src/tests.rs | 99 ++++++++++++---------- 4 files changed, 106 insertions(+), 52 deletions(-) create mode 100644 prdoc/pr_6205.prdoc diff --git a/prdoc/pr_6205.prdoc b/prdoc/pr_6205.prdoc new file mode 100644 index 000000000000..0874eb468db4 --- /dev/null +++ b/prdoc/pr_6205.prdoc @@ -0,0 +1,8 @@ +title: 'pallet-message-queue: Fix max message size calculation' +doc: +- audience: Runtime Dev + description: |- + The max size of a message should not depend on the weight left in a given execution context. Instead the max message size depends on the service weights configured for the pallet. A message that may does not fit into `on_idle` is not automatically overweight, because it may can be executed successfully in `on_initialize` or in another block in `on_idle` when there is more weight left. +crates: +- name: pallet-message-queue + bump: patch diff --git a/substrate/frame/message-queue/src/lib.rs b/substrate/frame/message-queue/src/lib.rs index 31402f2a9d81..04620fa88d85 100644 --- a/substrate/frame/message-queue/src/lib.rs +++ b/substrate/frame/message-queue/src/lib.rs @@ -868,13 +868,26 @@ impl Pallet { } } - /// The maximal weight that a single message can consume. + /// The maximal weight that a single message ever can consume. /// /// Any message using more than this will be marked as permanently overweight and not /// automatically re-attempted. Returns `None` if the servicing of a message cannot begin. /// `Some(0)` means that only messages with no weight may be served. fn max_message_weight(limit: Weight) -> Option { - limit.checked_sub(&Self::single_msg_overhead()) + let service_weight = T::ServiceWeight::get().unwrap_or_default(); + let on_idle_weight = T::IdleMaxServiceWeight::get().unwrap_or_default(); + + // Whatever weight is set, the one with the biggest one is used as the maximum weight. If a + // message is tried in one context and fails, it will be retried in the other context later. + let max_message_weight = + if service_weight.any_gt(on_idle_weight) { service_weight } else { on_idle_weight }; + + if max_message_weight.is_zero() { + // If no service weight is set, we need to use the given limit as max message weight. + limit.checked_sub(&Self::single_msg_overhead()) + } else { + max_message_weight.checked_sub(&Self::single_msg_overhead()) + } } /// The overhead of servicing a single message. @@ -896,6 +909,8 @@ impl Pallet { fn do_integrity_test() -> Result<(), String> { ensure!(!MaxMessageLenOf::::get().is_zero(), "HeapSize too low"); + let max_block = T::BlockWeights::get().max_block; + if let Some(service) = T::ServiceWeight::get() { if Self::max_message_weight(service).is_none() { return Err(format!( @@ -904,6 +919,31 @@ impl Pallet { Self::single_msg_overhead(), )) } + + if service.any_gt(max_block) { + return Err(format!( + "ServiceWeight {service} is bigger than max block weight {max_block}" + )) + } + } + + if let Some(on_idle) = T::IdleMaxServiceWeight::get() { + if on_idle.any_gt(max_block) { + return Err(format!( + "IdleMaxServiceWeight {on_idle} is bigger than max block weight {max_block}" + )) + } + } + + if let (Some(service_weight), Some(on_idle)) = + (T::ServiceWeight::get(), T::IdleMaxServiceWeight::get()) + { + if !(service_weight.all_gt(on_idle) || + on_idle.all_gt(service_weight) || + service_weight == on_idle) + { + return Err("One of `ServiceWeight` or `IdleMaxServiceWeight` needs to be `all_gt` or both need to be equal.".into()) + } } Ok(()) @@ -1531,7 +1571,7 @@ impl Pallet { let mut weight = WeightMeter::with_limit(weight_limit); // Get the maximum weight that processing a single message may take: - let max_weight = Self::max_message_weight(weight_limit).unwrap_or_else(|| { + let overweight_limit = Self::max_message_weight(weight_limit).unwrap_or_else(|| { if matches!(context, ServiceQueuesContext::OnInitialize) { defensive!("Not enough weight to service a single message."); } @@ -1549,7 +1589,8 @@ impl Pallet { let mut last_no_progress = None; loop { - let (progressed, n) = Self::service_queue(next.clone(), &mut weight, max_weight); + let (progressed, n) = + Self::service_queue(next.clone(), &mut weight, overweight_limit); next = match n { Some(n) => if !progressed { diff --git a/substrate/frame/message-queue/src/mock.rs b/substrate/frame/message-queue/src/mock.rs index d3f719c62356..f1d341d1a5db 100644 --- a/substrate/frame/message-queue/src/mock.rs +++ b/substrate/frame/message-queue/src/mock.rs @@ -42,7 +42,7 @@ impl frame_system::Config for Test { type Block = Block; } parameter_types! { - pub const HeapSize: u32 = 24; + pub const HeapSize: u32 = 40; pub const MaxStale: u32 = 2; pub const ServiceWeight: Option = Some(Weight::from_parts(100, 100)); } diff --git a/substrate/frame/message-queue/src/tests.rs b/substrate/frame/message-queue/src/tests.rs index b75764b67bea..c81e486a40df 100644 --- a/substrate/frame/message-queue/src/tests.rs +++ b/substrate/frame/message-queue/src/tests.rs @@ -177,7 +177,7 @@ fn service_queues_failing_messages_works() { MessageQueue::enqueue_message(msg("stacklimitreached"), Here); MessageQueue::enqueue_message(msg("yield"), Here); // Starts with four pages. - assert_pages(&[0, 1, 2, 3, 4]); + assert_pages(&[0, 1, 2]); assert_eq!(MessageQueue::service_queues(1.into_weight()), 1.into_weight()); assert_last_event::( @@ -209,7 +209,7 @@ fn service_queues_failing_messages_works() { assert_eq!(MessageQueue::service_queues(1.into_weight()), 1.into_weight()); assert_eq!(System::events().len(), 4); // Last page with the `yield` stays in. - assert_pages(&[4]); + assert_pages(&[2]); }); } @@ -313,7 +313,7 @@ fn reap_page_permanent_overweight_works() { // Create 10 pages more than the stale limit. let n = (MaxStale::get() + 10) as usize; for _ in 0..n { - MessageQueue::enqueue_message(msg("weight=2"), Here); + MessageQueue::enqueue_message(msg("weight=200 datadatadata"), Here); } assert_eq!(Pages::::iter().count(), n); assert_eq!(MessageQueue::footprint(Here).pages, n as u32); @@ -334,7 +334,7 @@ fn reap_page_permanent_overweight_works() { break } assert_ok!(MessageQueue::do_reap_page(&Here, i)); - assert_eq!(QueueChanges::take(), vec![(Here, b.message_count - 1, b.size - 8)]); + assert_eq!(QueueChanges::take(), vec![(Here, b.message_count - 1, b.size - 23)]); } // Cannot reap any more pages. @@ -353,20 +353,20 @@ fn reaping_overweight_fails_properly() { build_and_execute::(|| { // page 0 - MessageQueue::enqueue_message(msg("weight=4"), Here); + MessageQueue::enqueue_message(msg("weight=200 datadata"), Here); MessageQueue::enqueue_message(msg("a"), Here); // page 1 - MessageQueue::enqueue_message(msg("weight=4"), Here); + MessageQueue::enqueue_message(msg("weight=200 datadata"), Here); MessageQueue::enqueue_message(msg("b"), Here); // page 2 - MessageQueue::enqueue_message(msg("weight=4"), Here); + MessageQueue::enqueue_message(msg("weight=200 datadata"), Here); MessageQueue::enqueue_message(msg("c"), Here); // page 3 - MessageQueue::enqueue_message(msg("bigbig 1"), Here); + MessageQueue::enqueue_message(msg("bigbig 1 datadata"), Here); // page 4 - MessageQueue::enqueue_message(msg("bigbig 2"), Here); + MessageQueue::enqueue_message(msg("bigbig 2 datadata"), Here); // page 5 - MessageQueue::enqueue_message(msg("bigbig 3"), Here); + MessageQueue::enqueue_message(msg("bigbig 3 datadata"), Here); // Double-check that exactly these pages exist. assert_pages(&[0, 1, 2, 3, 4, 5]); @@ -385,7 +385,7 @@ fn reaping_overweight_fails_properly() { // 3 stale now: can take something 4 pages in history. assert_eq!(MessageQueue::service_queues(1.into_weight()), 1.into_weight()); - assert_eq!(MessagesProcessed::take(), vec![(vmsg("bigbig 1"), Here)]); + assert_eq!(MessagesProcessed::take(), vec![(vmsg("bigbig 1 datadata"), Here)]); // Nothing reapable yet, because we haven't hit the stale limit. for (o, i, _) in Pages::::iter() { @@ -394,7 +394,7 @@ fn reaping_overweight_fails_properly() { assert_pages(&[0, 1, 2, 4, 5]); assert_eq!(MessageQueue::service_queues(1.into_weight()), 1.into_weight()); - assert_eq!(MessagesProcessed::take(), vec![(vmsg("bigbig 2"), Here)]); + assert_eq!(MessagesProcessed::take(), vec![(vmsg("bigbig 2 datadata"), Here)]); assert_pages(&[0, 1, 2, 5]); // First is now reapable as it is too far behind the first ready page (5). @@ -406,7 +406,7 @@ fn reaping_overweight_fails_properly() { assert_pages(&[1, 2, 5]); assert_eq!(MessageQueue::service_queues(1.into_weight()), 1.into_weight()); - assert_eq!(MessagesProcessed::take(), vec![(vmsg("bigbig 3"), Here)]); + assert_eq!(MessagesProcessed::take(), vec![(vmsg("bigbig 3 datadata"), Here)]); assert_noop!(MessageQueue::do_reap_page(&Here, 0), Error::::NoPage); assert_noop!(MessageQueue::do_reap_page(&Here, 3), Error::::NoPage); @@ -1062,29 +1062,29 @@ fn footprint_on_swept_works() { fn footprint_num_pages_works() { use MessageOrigin::*; build_and_execute::(|| { - MessageQueue::enqueue_message(msg("weight=2"), Here); - MessageQueue::enqueue_message(msg("weight=3"), Here); + MessageQueue::enqueue_message(msg("weight=200"), Here); + MessageQueue::enqueue_message(msg("weight=300"), Here); - assert_eq!(MessageQueue::footprint(Here), fp(2, 2, 2, 16)); + assert_eq!(MessageQueue::footprint(Here), fp(1, 1, 2, 20)); // Mark the messages as overweight. assert_eq!(MessageQueue::service_queues(1.into_weight()), 0.into_weight()); assert_eq!(System::events().len(), 2); // `ready_pages` decreases but `page` count does not. - assert_eq!(MessageQueue::footprint(Here), fp(2, 0, 2, 16)); + assert_eq!(MessageQueue::footprint(Here), fp(1, 0, 2, 20)); // Now execute the second message. assert_eq!( - ::execute_overweight(3.into_weight(), (Here, 1, 0)) + ::execute_overweight(300.into_weight(), (Here, 0, 1)) .unwrap(), - 3.into_weight() + 300.into_weight() ); - assert_eq!(MessageQueue::footprint(Here), fp(1, 0, 1, 8)); + assert_eq!(MessageQueue::footprint(Here), fp(1, 0, 1, 10)); // And the first one: assert_eq!( - ::execute_overweight(2.into_weight(), (Here, 0, 0)) + ::execute_overweight(200.into_weight(), (Here, 0, 0)) .unwrap(), - 2.into_weight() + 200.into_weight() ); assert_eq!(MessageQueue::footprint(Here), Default::default()); assert_eq!(MessageQueue::footprint(Here), fp(0, 0, 0, 0)); @@ -1104,7 +1104,7 @@ fn execute_overweight_works() { // Enqueue a message let origin = MessageOrigin::Here; - MessageQueue::enqueue_message(msg("weight=6"), origin); + MessageQueue::enqueue_message(msg("weight=200"), origin); // Load the current book let book = BookStateFor::::get(origin); assert_eq!(book.message_count, 1); @@ -1112,10 +1112,10 @@ fn execute_overweight_works() { // Mark the message as permanently overweight. assert_eq!(MessageQueue::service_queues(4.into_weight()), 4.into_weight()); - assert_eq!(QueueChanges::take(), vec![(origin, 1, 8)]); + assert_eq!(QueueChanges::take(), vec![(origin, 1, 10)]); assert_last_event::( Event::OverweightEnqueued { - id: blake2_256(b"weight=6"), + id: blake2_256(b"weight=200"), origin: MessageOrigin::Here, message_index: 0, page_index: 0, @@ -1132,9 +1132,9 @@ fn execute_overweight_works() { assert_eq!(Pages::::iter().count(), 1); assert!(QueueChanges::take().is_empty()); let consumed = - ::execute_overweight(7.into_weight(), (origin, 0, 0)) + ::execute_overweight(200.into_weight(), (origin, 0, 0)) .unwrap(); - assert_eq!(consumed, 6.into_weight()); + assert_eq!(consumed, 200.into_weight()); assert_eq!(QueueChanges::take(), vec![(origin, 0, 0)]); // There is no message left in the book. let book = BookStateFor::::get(origin); @@ -1162,7 +1162,7 @@ fn permanently_overweight_book_unknits() { set_weight("service_queue_base", 1.into_weight()); set_weight("service_page_base_completion", 1.into_weight()); - MessageQueue::enqueue_messages([msg("weight=9")].into_iter(), Here); + MessageQueue::enqueue_messages([msg("weight=200")].into_iter(), Here); // It is the only ready book. assert_ring(&[Here]); @@ -1170,7 +1170,7 @@ fn permanently_overweight_book_unknits() { assert_eq!(MessageQueue::service_queues(8.into_weight()), 4.into_weight()); assert_last_event::( Event::OverweightEnqueued { - id: blake2_256(b"weight=9"), + id: blake2_256(b"weight=200"), origin: Here, message_index: 0, page_index: 0, @@ -1201,19 +1201,19 @@ fn permanently_overweight_book_unknits_multiple() { set_weight("service_page_base_completion", 1.into_weight()); MessageQueue::enqueue_messages( - [msg("weight=1"), msg("weight=9"), msg("weight=9")].into_iter(), + [msg("weight=1"), msg("weight=200"), msg("weight=200")].into_iter(), Here, ); assert_ring(&[Here]); // Process the first message. assert_eq!(MessageQueue::service_queues(4.into_weight()), 4.into_weight()); - assert_eq!(num_overweight_enqueued_events(), 0); + assert_eq!(num_overweight_enqueued_events(), 1); assert_eq!(MessagesProcessed::take().len(), 1); // Book is still ready since it was not marked as overweight yet. assert_ring(&[Here]); - assert_eq!(MessageQueue::service_queues(8.into_weight()), 5.into_weight()); + assert_eq!(MessageQueue::service_queues(8.into_weight()), 4.into_weight()); assert_eq!(num_overweight_enqueued_events(), 2); assert_eq!(MessagesProcessed::take().len(), 0); // Now it is overweight. @@ -1566,12 +1566,12 @@ fn service_queues_suspend_works() { fn execute_overweight_respects_suspension() { build_and_execute::(|| { let origin = MessageOrigin::Here; - MessageQueue::enqueue_message(msg("weight=5"), origin); + MessageQueue::enqueue_message(msg("weight=200"), origin); // Mark the message as permanently overweight. MessageQueue::service_queues(4.into_weight()); assert_last_event::( Event::OverweightEnqueued { - id: blake2_256(b"weight=5"), + id: blake2_256(b"weight=200"), origin, message_index: 0, page_index: 0, @@ -1598,9 +1598,9 @@ fn execute_overweight_respects_suspension() { assert_last_event::( Event::Processed { - id: blake2_256(b"weight=5").into(), + id: blake2_256(b"weight=200").into(), origin, - weight_used: 5.into_weight(), + weight_used: 200.into_weight(), success: true, } .into(), @@ -1768,7 +1768,7 @@ fn recursive_overweight_while_service_is_forbidden() { // Check that the message was permanently overweight. assert_last_event::( Event::OverweightEnqueued { - id: blake2_256(b"weight=10"), + id: blake2_256(b"weight=200"), origin: There, message_index: 0, page_index: 0, @@ -1786,13 +1786,13 @@ fn recursive_overweight_while_service_is_forbidden() { Ok(()) })); - MessageQueue::enqueue_message(msg("weight=10"), There); + MessageQueue::enqueue_message(msg("weight=200"), There); MessageQueue::enqueue_message(msg("callback=0"), Here); // Mark it as permanently overweight. MessageQueue::service_queues(5.into_weight()); assert_ok!(::execute_overweight( - 10.into_weight(), + 200.into_weight(), (There, 0, 0) )); }); @@ -1812,7 +1812,7 @@ fn recursive_reap_page_is_forbidden() { // Create 10 pages more than the stale limit. let n = (MaxStale::get() + 10) as usize; for _ in 0..n { - MessageQueue::enqueue_message(msg("weight=2"), Here); + MessageQueue::enqueue_message(msg("weight=200"), Here); } // Mark all pages as stale since their message is permanently overweight. @@ -1886,6 +1886,11 @@ fn process_enqueued_on_idle_requires_enough_weight() { // Not enough weight to process on idle. Pallet::::on_idle(1, Weight::from_parts(0, 0)); assert_eq!(MessagesProcessed::take(), vec![]); + + assert!(!System::events().into_iter().any(|e| matches!( + e.event, + RuntimeEvent::MessageQueue(Event::::OverweightEnqueued { .. }) + ))); }) } @@ -1923,12 +1928,12 @@ fn execute_overweight_keeps_stack_ov_message() { // We need to create a mocked message that first reports insufficient weight, and then // `StackLimitReached`: IgnoreStackOvError::set(true); - MessageQueue::enqueue_message(msg("stacklimitreached"), Here); + MessageQueue::enqueue_message(msg("weight=200 stacklimitreached"), Here); MessageQueue::service_queues(0.into_weight()); assert_last_event::( Event::OverweightEnqueued { - id: blake2_256(b"stacklimitreached"), + id: blake2_256(b"weight=200 stacklimitreached"), origin: MessageOrigin::Here, message_index: 0, page_index: 0, @@ -1952,7 +1957,7 @@ fn execute_overweight_keeps_stack_ov_message() { ); assert_last_event::( Event::ProcessingFailed { - id: blake2_256(b"stacklimitreached").into(), + id: blake2_256(b"weight=200 stacklimitreached").into(), origin: MessageOrigin::Here, error: ProcessMessageError::StackLimitReached, } @@ -1964,16 +1969,16 @@ fn execute_overweight_keeps_stack_ov_message() { // Now let's process it normally: IgnoreStackOvError::set(true); assert_eq!( - ::execute_overweight(1.into_weight(), (Here, 0, 0)) + ::execute_overweight(200.into_weight(), (Here, 0, 0)) .unwrap(), - 1.into_weight() + 200.into_weight() ); assert_last_event::( Event::Processed { - id: blake2_256(b"stacklimitreached").into(), + id: blake2_256(b"weight=200 stacklimitreached").into(), origin: MessageOrigin::Here, - weight_used: 1.into_weight(), + weight_used: 200.into_weight(), success: true, } .into(), From 7e99621108b2a98644c73a22eaceb732b1c0f743 Mon Sep 17 00:00:00 2001 From: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:42:07 +0200 Subject: [PATCH 10/15] `RuntimeGenesiConfig`: json macro added (#5813) This PR adds `build_struct_json_patch` which helps to generate a JSON used for preset. Here is doc and example: https://github.com/paritytech/polkadot-sdk/blob/d868b858758d3886d16c8ba8feb3c93c188044f3/substrate/frame/support/src/generate_genesis_config.rs#L168-L266 And real-world usage: https://github.com/paritytech/polkadot-sdk/blob/d868b858758d3886d16c8ba8feb3c93c188044f3/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/genesis_config_presets.rs#L37-L61 Closes #5700 --------- Co-authored-by: Sebastian Kunert --- Cargo.lock | 2 + .../src/genesis_config_presets.rs | 17 +- .../src/reference_docs/chain_spec_genesis.rs | 22 +- .../chain_spec_runtime/Cargo.toml | 2 + .../chain_spec_runtime/src/pallets.rs | 2 +- .../chain_spec_runtime/src/presets.rs | 42 +- .../tests/chain_spec_builder_tests.rs | 19 +- .../westend/src/genesis_config_presets.rs | 17 +- prdoc/pr_5813.prdoc | 18 + substrate/frame/support/Cargo.toml | 1 + .../support/src/generate_genesis_config.rs | 951 ++++++++++++++++++ substrate/frame/support/src/lib.rs | 6 +- 12 files changed, 1044 insertions(+), 55 deletions(-) create mode 100644 prdoc/pr_5813.prdoc create mode 100644 substrate/frame/support/src/generate_genesis_config.rs diff --git a/Cargo.lock b/Cargo.lock index 602891892a2b..335c465e0aa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2824,6 +2824,7 @@ name = "chain-spec-guide-runtime" version = "0.0.0" dependencies = [ "docify", + "frame-support", "pallet-balances", "pallet-sudo", "pallet-timestamp", @@ -6442,6 +6443,7 @@ dependencies = [ name = "frame-support" version = "28.0.0" dependencies = [ + "Inflector", "aquamarine", "array-bytes", "assert_matches", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/genesis_config_presets.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/genesis_config_presets.rs index dc98d00f8f63..d15dd971a819 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/genesis_config_presets.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/genesis_config_presets.rs @@ -18,6 +18,7 @@ use crate::*; use alloc::{vec, vec::Vec}; use cumulus_primitives_core::ParaId; +use frame_support::build_struct_json_patch; use hex_literal::hex; use parachains_common::{AccountId, AuraId}; use sp_core::crypto::UncheckedInto; @@ -33,15 +34,14 @@ fn asset_hub_rococo_genesis( endowment: Balance, id: ParaId, ) -> serde_json::Value { - let config = RuntimeGenesisConfig { + build_struct_json_patch!(RuntimeGenesisConfig { balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, endowment)).collect(), }, - parachain_info: ParachainInfoConfig { parachain_id: id, ..Default::default() }, + parachain_info: ParachainInfoConfig { parachain_id: id }, collator_selection: CollatorSelectionConfig { invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), candidacy_bond: ASSET_HUB_ROCOCO_ED * 16, - ..Default::default() }, session: SessionConfig { keys: invulnerables @@ -54,16 +54,9 @@ fn asset_hub_rococo_genesis( ) }) .collect(), - ..Default::default() }, - polkadot_xcm: PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - ..Default::default() - }, - ..Default::default() - }; - - serde_json::to_value(config).expect("Could not build genesis config.") + polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) }, + }) } /// Encapsulates names of predefined presets. diff --git a/docs/sdk/src/reference_docs/chain_spec_genesis.rs b/docs/sdk/src/reference_docs/chain_spec_genesis.rs index 3326f433f288..b7a0a648d0cf 100644 --- a/docs/sdk/src/reference_docs/chain_spec_genesis.rs +++ b/docs/sdk/src/reference_docs/chain_spec_genesis.rs @@ -100,17 +100,22 @@ //! others useful for testing. //! //! Internally, presets can be provided in a number of ways: -//! - JSON in string form: -#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_1)] -//! - JSON using runtime types to serialize values: +//! - using [`build_struct_json_patch`] macro (**recommended**): #![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_2)] +//! - JSON using runtime types to serialize values: #![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_3)] +//! - JSON in string form: +#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_1)] +//! //! It is worth noting that a preset does not have to be the full `RuntimeGenesisConfig`, in that //! sense that it does not have to contain all the keys of the struct. The preset is actually a JSON //! patch that will be merged with the default value of `RuntimeGenesisConfig`. This approach should //! simplify maintenance of built-in presets. The following example illustrates a runtime genesis -//! config patch: +//! config patch with a single key built using [`build_struct_json_patch`] macro: #![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_4)] +//! This results in the following JSON blob: +#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs", preset_4_json)] +//! //! //! ## Note on the importance of testing presets //! @@ -122,8 +127,8 @@ //! //! ## Note on the importance of using the `deny_unknown_fields` attribute //! -//! It is worth noting that it is easy to make a hard-to-spot mistake, as in the following example -//! ([`FooStruct`] does not contain `fieldC`): +//! It is worth noting that when manually building preset JSON blobs it is easy to make a +//! hard-to-spot mistake, as in the following example ([`FooStruct`] does not contain `fieldC`): #![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_invalid)] //! Even though `preset_invalid` contains a key that does not exist, the deserialization of the JSON //! blob does not fail. The misspelling is silently ignored due to the lack of the @@ -131,6 +136,10 @@ //! `GenesisConfig`. #![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", invalid_preset_works)] //! +//! To avoid this problem [`build_struct_json_patch`] macro shall be used whenever possible (it +//! internally instantiates the struct before serializang it JSON blob, so all unknown fields shall +//! be caught at compilation time). +//! //! ## Runtime `GenesisConfig` raw format //! //! A raw format of genesis config contains just the state's keys and values as they are stored in @@ -182,6 +191,7 @@ //! [`get_preset`]: frame_support::genesis_builder_helper::get_preset //! [`pallet::genesis_build`]: frame_support::pallet_macros::genesis_build //! [`pallet::genesis_config`]: frame_support::pallet_macros::genesis_config +//! [`build_struct_json_patch`]: frame_support::build_struct_json_patch //! [`BuildGenesisConfig`]: frame_support::traits::BuildGenesisConfig //! [`serde`]: https://serde.rs/field-attrs.html //! [`get_storage_for_patch`]: sc_chain_spec::GenesisConfigBuilderRuntimeCaller::get_storage_for_patch diff --git a/docs/sdk/src/reference_docs/chain_spec_runtime/Cargo.toml b/docs/sdk/src/reference_docs/chain_spec_runtime/Cargo.toml index 028495712032..07c0342f5fbe 100644 --- a/docs/sdk/src/reference_docs/chain_spec_runtime/Cargo.toml +++ b/docs/sdk/src/reference_docs/chain_spec_runtime/Cargo.toml @@ -12,6 +12,7 @@ publish = false [dependencies] docify = { workspace = true } codec = { workspace = true } +frame-support = { workspace = true } scale-info = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -49,6 +50,7 @@ std = [ "codec/std", "scale-info/std", + "frame-support/std", "frame/std", "pallet-balances/std", diff --git a/docs/sdk/src/reference_docs/chain_spec_runtime/src/pallets.rs b/docs/sdk/src/reference_docs/chain_spec_runtime/src/pallets.rs index 2ff2d9539e2d..571632ecd272 100644 --- a/docs/sdk/src/reference_docs/chain_spec_runtime/src/pallets.rs +++ b/docs/sdk/src/reference_docs/chain_spec_runtime/src/pallets.rs @@ -118,7 +118,7 @@ pub mod pallet_foo { pub some_enum: FooEnum, pub some_struct: FooStruct, #[serde(skip)] - _phantom: PhantomData, + pub _phantom: PhantomData, } #[pallet::genesis_build] diff --git a/docs/sdk/src/reference_docs/chain_spec_runtime/src/presets.rs b/docs/sdk/src/reference_docs/chain_spec_runtime/src/presets.rs index 02c2d90f7c82..c1316b2f8734 100644 --- a/docs/sdk/src/reference_docs/chain_spec_runtime/src/presets.rs +++ b/docs/sdk/src/reference_docs/chain_spec_runtime/src/presets.rs @@ -17,8 +17,12 @@ //! Presets for the chain-spec demo runtime. -use crate::pallets::{FooEnum, SomeFooData1, SomeFooData2}; +use crate::{ + pallets::{FooEnum, SomeFooData1, SomeFooData2}, + runtime::{BarConfig, FooConfig, RuntimeGenesisConfig}, +}; use alloc::vec; +use frame_support::build_struct_json_patch; use serde_json::{json, to_string, Value}; use sp_application_crypto::Ss58Codec; use sp_keyring::AccountKeyring; @@ -27,7 +31,7 @@ use sp_keyring::AccountKeyring; pub const PRESET_1: &str = "preset_1"; /// A demo preset with real types. pub const PRESET_2: &str = "preset_2"; -/// Another demo preset with real types. +/// Another demo preset with real types and manually created json object. pub const PRESET_3: &str = "preset_3"; /// A single value patch preset. pub const PRESET_4: &str = "preset_4"; @@ -58,21 +62,21 @@ fn preset_1() -> Value { } #[docify::export] -/// Function provides a preset demonstrating how use the actual types to create a preset. +/// Function provides a preset demonstrating how to create a preset using +/// [`build_struct_json_patch`] macro. fn preset_2() -> Value { - json!({ - "bar": { - "initialAccount": AccountKeyring::Ferdie.public().to_ss58check(), - }, - "foo": { - "someEnum": FooEnum::Data2(SomeFooData2 { values: vec![12,16] }), - "someInteger": 200 + build_struct_json_patch!(RuntimeGenesisConfig { + foo: FooConfig { + some_integer: 200, + some_enum: FooEnum::Data2(SomeFooData2 { values: vec![0x0c, 0x10] }) }, + bar: BarConfig { initial_account: Some(AccountKeyring::Ferdie.public().into()) }, }) } #[docify::export] -/// Function provides a preset demonstrating how use the actual types to create a preset. +/// Function provides a preset demonstrating how use the actual types to manually create a JSON +/// representing the preset. fn preset_3() -> Value { json!({ "bar": { @@ -92,22 +96,16 @@ fn preset_3() -> Value { #[docify::export] /// Function provides a minimal preset demonstrating how to patch single key in -/// `RuntimeGenesisConfig`. -fn preset_4() -> Value { - json!({ - "foo": { - "someEnum": { - "Data2": { - "values": "0x0c0f" - } - }, - }, +/// `RuntimeGenesisConfig` using [`build_struct_json_patch`] macro. +pub fn preset_4() -> Value { + build_struct_json_patch!(RuntimeGenesisConfig { + foo: FooConfig { some_enum: FooEnum::Data2(SomeFooData2 { values: vec![0x0c, 0x10] }) }, }) } #[docify::export] /// Function provides an invalid preset demonstrating how important is use of -/// [`deny_unknown_fields`] in data structures used in `GenesisConfig`. +/// `deny_unknown_fields` in data structures used in `GenesisConfig`. fn preset_invalid() -> Value { json!({ "foo": { diff --git a/docs/sdk/src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs b/docs/sdk/src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs index cc273685fcb4..c2fe5a6727e6 100644 --- a/docs/sdk/src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs +++ b/docs/sdk/src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs @@ -58,7 +58,7 @@ fn get_preset() { let output: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap(); - //note: copy of chain_spec_guide_runtime::preset_1 + //note: copy of chain_spec_guide_runtime::preset_2 let expected_output = json!({ "bar": { "initialAccount": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", @@ -186,3 +186,20 @@ fn generate_para_chain_spec() { }); assert_eq!(output, expected_output, "Output did not match expected"); } + +#[test] +#[docify::export] +fn preset_4_json() { + assert_eq!( + chain_spec_guide_runtime::presets::preset_4(), + json!({ + "foo": { + "someEnum": { + "Data2": { + "values": "0x0c10" + } + }, + }, + }) + ); +} diff --git a/polkadot/runtime/westend/src/genesis_config_presets.rs b/polkadot/runtime/westend/src/genesis_config_presets.rs index 621ef38f0b75..a9e22898ddb4 100644 --- a/polkadot/runtime/westend/src/genesis_config_presets.rs +++ b/polkadot/runtime/westend/src/genesis_config_presets.rs @@ -23,6 +23,7 @@ use crate::{ #[cfg(not(feature = "std"))] use alloc::format; use alloc::{vec, vec::Vec}; +use frame_support::build_struct_json_patch; use pallet_staking::{Forcing, StakerStatus}; use polkadot_primitives::{AccountId, AssignmentId, SchedulerParams, ValidatorId}; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -170,7 +171,7 @@ fn westend_testnet_genesis( const ENDOWMENT: u128 = 1_000_000 * WND; const STASH: u128 = 100 * WND; - let config = RuntimeGenesisConfig { + build_struct_json_patch!(RuntimeGenesisConfig { balances: BalancesConfig { balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect::>(), }, @@ -192,7 +193,6 @@ fn westend_testnet_genesis( ) }) .collect::>(), - ..Default::default() }, staking: StakingConfig { minimum_validator_count: 1, @@ -204,19 +204,12 @@ fn westend_testnet_genesis( invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect::>(), force_era: Forcing::NotForcing, slash_reward_fraction: Perbill::from_percent(10), - ..Default::default() }, - babe: BabeConfig { epoch_config: BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, + babe: BabeConfig { epoch_config: BABE_GENESIS_EPOCH_CONFIG }, sudo: SudoConfig { key: Some(root_key) }, configuration: ConfigurationConfig { config: default_parachains_host_configuration() }, - registrar: RegistrarConfig { - next_free_para_id: polkadot_primitives::LOWEST_PUBLIC_ID, - ..Default::default() - }, - ..Default::default() - }; - - serde_json::to_value(config).expect("Could not build genesis config.") + registrar: RegistrarConfig { next_free_para_id: polkadot_primitives::LOWEST_PUBLIC_ID }, + }) } // staging_testnet diff --git a/prdoc/pr_5813.prdoc b/prdoc/pr_5813.prdoc new file mode 100644 index 000000000000..e48f29bbfb63 --- /dev/null +++ b/prdoc/pr_5813.prdoc @@ -0,0 +1,18 @@ +title: "build_struct_json_patch macro added" + +doc: + - audience: Runtime Dev + description: | + This PR adds a macro that allows to construct a RuntimeGenesisConfig preset + containing only provided fields, while performing the validation of the + entire struct. + + Related issue: https://github.com/paritytech/polkadot-sdk/issues/5700 + +crates: + - name: frame-support + bump: minor + - name: asset-hub-rococo-runtime + bump: patch + - name: westend-runtime + bump: patch diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index 18ca4a3acdab..d7da034b3492 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -71,6 +71,7 @@ pretty_assertions = { workspace = true } sp-timestamp = { workspace = true } frame-system = { workspace = true, default-features = true } sp-crypto-hashing = { workspace = true, default-features = true } +Inflector = { workspace = true } [features] default = ["std"] diff --git a/substrate/frame/support/src/generate_genesis_config.rs b/substrate/frame/support/src/generate_genesis_config.rs new file mode 100644 index 000000000000..fc21e76c7427 --- /dev/null +++ b/substrate/frame/support/src/generate_genesis_config.rs @@ -0,0 +1,951 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Helper macro allowing to construct JSON representation of partially initialized structs. + +use serde_json::Value; +extern crate alloc; +use alloc::{borrow::Cow, format, string::String}; + +/// Represents the initialization method of a field within a struct. +/// +/// This enum provides information about how it was initialized and the field name (as a `String`). +/// +/// Intended to be used in `build_struct_json_patch` macro. +#[derive(Debug)] +pub enum InitializedField<'a> { + /// The field was partially initialized (e.g., specific fields within the struct were set + /// manually). + Partial(Cow<'a, str>), + /// The field was fully initialized (e.g., using `new()` or `default()` like methods). + Full(Cow<'a, str>), +} + +impl<'a> InitializedField<'a> { + /// Returns a name of the field. + pub fn get_name(&'a self) -> &'a str { + match self { + Self::Partial(s) | Self::Full(s) => s, + } + } + + /// Injects a prefix to the field name. + pub fn add_prefix(&mut self, prefix: &str) { + match self { + Self::Partial(s) | Self::Full(s) => *s = format!("{prefix}.{s}").into(), + }; + } + + /// Creates new partial field instiance. + pub fn partial(s: &'a str) -> Self { + Self::Partial(s.into()) + } + + /// Creates new full field instiance. + pub fn full(s: &'a str) -> Self { + Self::Full(s.into()) + } +} + +impl PartialEq for InitializedField<'_> { + fn eq(&self, other: &String) -> bool { + #[inline] + /// We need to respect the `camelCase` naming for field names. This means that + /// `"camelCaseKey"` should be considered equal to `"camel_case_key"`. This + /// function implements this comparison. + fn compare_keys(ident_chars: core::str::Chars, camel_chars: core::str::Chars) -> bool { + ident_chars + .filter(|c| *c != '_') + .map(|c| c.to_ascii_uppercase()) + .eq(camel_chars.map(|c| c.to_ascii_uppercase())) + } + match self { + InitializedField::Partial(field_name) | InitializedField::Full(field_name) => + field_name == other || compare_keys(field_name.chars(), other.chars()), + } + } +} + +/// Recursively removes keys from provided `json_value` object, retaining only specified keys. +/// +/// This function modifies the provided `json_value` in-place, keeping only the keys listed in +/// `keys_to_retain`. The keys are matched recursively by combining the current key with +/// the `current_root`, allowing for nested field retention. +/// +/// Keys marked as `Full`, are retained as-is. For keys marked as `Partial`, the +/// function recurses into nested objects to retain matching subfields. +/// +/// Function respects the `camelCase` serde_json attribute for structures. This means that +/// `"camelCaseKey"` key will be retained in JSON blob if `"camel_case_key"` exists in +/// `keys_to_retain`. +/// +/// Intended to be used from `build_struct_json_patch` macro. +pub fn retain_initialized_fields( + json_value: &mut Value, + keys_to_retain: &[InitializedField], + current_root: String, +) { + if let serde_json::Value::Object(ref mut map) = json_value { + map.retain(|key, value| { + let current_key = + if current_root.is_empty() { key.clone() } else { format!("{current_root}.{key}") }; + match keys_to_retain.iter().find(|key| **key == current_key) { + Some(InitializedField::Full(_)) => true, + Some(InitializedField::Partial(_)) => { + retain_initialized_fields(value, keys_to_retain, current_key.clone()); + true + }, + None => false, + } + }) + } +} + +/// Creates a JSON patch for given `struct_type`, supporting recursive field initialization. +/// +/// This macro creates a default `struct_type`, initializing specified fields (which can be nested) +/// with the provided values. Any fields not explicitly given are initialized with their default +/// values. The macro then serializes the fully initialized structure into a JSON blob, retaining +/// only the fields that were explicitly provided, either partially or fully initialized. +/// +/// Using this macro prevents errors from manually creating JSON objects, such as typos or +/// inconsistencies with the `struct_type` structure, by relying on the actual +/// struct definition. This ensures the generated JSON is valid and reflects any future changes +/// to the structure. +/// +/// # Example +/// +/// ```rust +/// use frame_support::build_struct_json_patch; +/// #[derive(Default, serde::Serialize, serde::Deserialize)] +/// #[serde(rename_all = "camelCase")] +/// struct RuntimeGenesisConfig { +/// a_field: u32, +/// b_field: B, +/// c_field: u32, +/// } +/// +/// #[derive(Default, serde::Serialize, serde::Deserialize)] +/// #[serde(rename_all = "camelCase")] +/// struct B { +/// i_field: u32, +/// j_field: u32, +/// } +/// impl B { +/// fn new() -> Self { +/// Self { i_field: 0, j_field: 2 } +/// } +/// } +/// +/// assert_eq!( +/// build_struct_json_patch! ( RuntimeGenesisConfig { +/// a_field: 66, +/// }), +/// serde_json::json!({ +/// "aField": 66, +/// }) +/// ); +/// +/// assert_eq!( +/// build_struct_json_patch! ( RuntimeGenesisConfig { +/// //"partial" initialization of `b_field` +/// b_field: B { +/// i_field: 2, +/// } +/// }), +/// serde_json::json!({ +/// "bField": {"iField": 2} +/// }) +/// ); +/// +/// assert_eq!( +/// build_struct_json_patch! ( RuntimeGenesisConfig { +/// a_field: 66, +/// //"full" initialization of `b_field` +/// b_field: B::new() +/// }), +/// serde_json::json!({ +/// "aField": 66, +/// "bField": {"iField": 0, "jField": 2} +/// }) +/// ); +/// ``` +/// +/// In this example: +/// ```ignore +/// build_struct_json_patch! ( RuntimeGenesisConfig { +/// b_field: B { +/// i_field: 2, +/// } +/// }), +/// ``` +/// `b_field` is partially initialized, it will be expanded to: +/// ```ignore +/// RuntimeGenesisConfig { +/// b_field { +/// i_field: 2, +/// ..Default::default() +/// }, +/// ..Default::default() +/// } +/// ``` +/// While all other fields are initialized with default values. The macro serializes this, retaining +/// only the provided fields. +#[macro_export] +macro_rules! build_struct_json_patch { + ( + $($struct_type:ident)::+ { $($tail:tt)* } + ) => { + { + let mut keys = $crate::__private::Vec::<$crate::generate_genesis_config::InitializedField>::default(); + #[allow(clippy::needless_update)] + let struct_instance = $crate::build_struct_json_patch!($($struct_type)::+, keys @ { $($tail)* }); + let mut json_value = + $crate::__private::serde_json::to_value(struct_instance).expect("serialization to json should work. qed"); + $crate::generate_genesis_config::retain_initialized_fields(&mut json_value, &keys, Default::default()); + json_value + } + }; + ($($struct_type:ident)::+, $all_keys:ident @ { $($tail:tt)* }) => { + $($struct_type)::+ { + ..$crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($tail)*) + } + }; + ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $($type:ident)::+ { $keyi:ident : $value:tt } ) => { + $($struct_type)::+ { + $key: { + $all_keys.push($crate::generate_genesis_config::InitializedField::partial(stringify!($key))); + $all_keys.push( + $crate::generate_genesis_config::InitializedField::full(concat!(stringify!($key), ".", stringify!($keyi))) + ); + $($type)::+ { + $keyi:$value, + ..Default::default() + } + }, + ..Default::default() + } + }; + ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $($type:ident)::+ { $($body:tt)* } ) => { + $($struct_type)::+ { + $key: { + $all_keys.push($crate::generate_genesis_config::InitializedField::partial(stringify!($key))); + let mut inner_keys = $crate::__private::Vec::<$crate::generate_genesis_config::InitializedField>::default(); + let value = $crate::build_struct_json_patch!($($type)::+, inner_keys @ { $($body)* }); + for i in inner_keys.iter_mut() { + i.add_prefix(stringify!($key)); + }; + $all_keys.extend(inner_keys); + value + }, + ..Default::default() + } + }; + ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $($type:ident)::+ { $($body:tt)* }, $($tail:tt)* ) => { + $($struct_type)::+ { + $key : { + $all_keys.push($crate::generate_genesis_config::InitializedField::partial(stringify!($key))); + let mut inner_keys = $crate::__private::Vec::<$crate::generate_genesis_config::InitializedField>::default(); + let value = $crate::build_struct_json_patch!($($type)::+, inner_keys @ { $($body)* }); + for i in inner_keys.iter_mut() { + i.add_prefix(stringify!($key)); + }; + $all_keys.extend(inner_keys); + value + }, + .. $crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($tail)*) + } + }; + ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $value:expr, $($tail:tt)* ) => { + $($struct_type)::+ { + $key: { + $all_keys.push($crate::generate_genesis_config::InitializedField::full(stringify!($key))); + $value + }, + ..$crate::build_struct_json_patch!($($struct_type)::+, $all_keys @ $($tail)*) + } + }; + ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $value:expr ) => { + $($struct_type)::+ { + $key: { + $all_keys.push($crate::generate_genesis_config::InitializedField::full(stringify!($key))); + $value + }, + ..Default::default() + } + }; + + ($($struct_type:ident)::+, $all_keys:ident @ $(,)?) => { + $($struct_type)::+ { ..Default::default() } + }; +} + +#[cfg(test)] +mod test { + mod nested_mod { + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + pub struct InsideMod { + pub a: u32, + pub b: u32, + } + + pub mod nested_mod2 { + pub mod nested_mod3 { + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + pub struct InsideMod3 { + pub a: u32, + pub b: u32, + pub s: super::super::InsideMod, + } + } + } + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct TestStruct { + a: u32, + b: u32, + s: S, + s3: S3, + t3: S3, + i: Nested1, + e: E, + t: nested_mod::InsideMod, + u: nested_mod::nested_mod2::nested_mod3::InsideMod3, + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct S { + x: u32, + } + + impl S { + fn new(c: u32) -> Self { + Self { x: c } + } + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct E(u8); + + #[derive(Default, Debug, serde::Serialize, serde::Deserialize)] + enum SomeEnum { + #[default] + A, + B(T), + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct S3 { + x: u32, + y: u32, + z: u32, + } + + impl S3 { + fn new(c: u32) -> Self { + Self { x: c, y: c, z: c } + } + + fn new_from_s(s: S) -> Self { + Self { x: s.x, ..Default::default() } + } + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct Nested3 { + a: u32, + b: u32, + s: S, + v: Vec<(u32, u32, u32, SomeEnum)>, + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct Nested2 { + a: u32, + iii: Nested3, + v: Vec, + s3: S3, + } + + impl Nested2 { + fn new(a: u32) -> Self { + Nested2 { + a, + v: vec![a, a, a], + iii: Nested3 { a, b: a, ..Default::default() }, + s3: S3 { x: a, ..Default::default() }, + } + } + } + + #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] + struct Nested1 { + a: u32, + ii: Nested2, + } + + macro_rules! test { + ($($struct:ident)::+ { $($v:tt)* }, { $($j:tt)* } ) => {{ + println!("--"); + let expected = serde_json::json!({ $($j)* }); + println!("json: {}", serde_json::to_string_pretty(&expected).unwrap()); + let value = build_struct_json_patch!($($struct)::+ { $($v)* }); + println!("gc: {}", serde_json::to_string_pretty(&value).unwrap()); + assert_eq!(value, expected); + }}; + } + + #[test] + fn test_generate_config_macro() { + let t = 5; + const C: u32 = 5; + test!(TestStruct { b: 5 }, { "b": 5 }); + #[allow(unused_braces)] + { + test!(TestStruct { b: { 4 + 34 } } , { "b": 38 }); + } + test!(TestStruct { s: S { x: 5 } }, { "s": { "x": 5 } }); + test!( + TestStruct { s: S::new(C) }, + { + "s": { "x": 5 } + } + ); + test!( + TestStruct { s: S { x: t } }, + { + "s": { "x": t } + } + ); + test!( + TestStruct { + b: 5, + s: S { x: t } + }, + { + "b": 5, + "s": { "x": 5 } + } + ); + test!( + TestStruct { s: S::new(C), b: 5 }, + { + "s": { "x": 5 }, "b": 5 + } + ); + test!( + TestStruct { s3: S3 { x: t } }, + { + "s3": { "x": 5 } + } + ); + test!( + TestStruct { + s3: S3 { x: t, y: 2 } + }, + { + "s3": { "x": 5, "y": 2 } + } + ); + // // + test!( + TestStruct { + s3: S3 { x: t, y: 2 }, + t3: S3 { x: 2 } + }, + { + "s3": { "x": t, "y": 2 }, + "t3": { "x": 2 } + } + + ); + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { iii: Nested3 { a: 2 } } + } + } + , + { + "i": { + "ii": { "iii": { "a": 2 } } + } + } + + ); + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { + iii: Nested3 { a: 2, s: S::new(C) } + } + } + }, + { + "i": { + "ii": { + "iii": { "a": 2, "s": { "x": 5} } + } + } + } + ); + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { + iii: Nested3 { s: S::new(C), a: 2 } + }, + a: 44 + }, + a: 3, + s3: S3 { x: 5 }, + b: 4 + }, + { + "i": { + "ii": { + "iii": { "a": 2, "s": { "x": 5} } + }, + "a": 44 + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + test!( + TestStruct { + i: Nested1 { + ii: Nested2::new(66), + a: 44, + }, + a: 3, + s3: S3 { x: 5 }, + b: 4 + }, + { + "i": { + "ii": { + "a": 66, + "s3": { "x":66, "y": 0, "z": 0 }, + "iii": { "a": 66,"b":66, "s": { "x": 0 }, "v": Vec::::default() }, + "v": vec![66,66,66] + }, + "a": 44 + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { + a: 66, + s3: S3 { x: 66 }, + iii: Nested3 { + a: 66,b:66 + }, + v: vec![66,66,66] + }, + a: 44, + }, + a: 3, + s3: S3 { x: 5 }, + b: 4 + }, + { + "i": { + "ii": { + "a": 66, + "s3": { "x":66, }, + "iii": { "a": 66,"b":66, }, + "v": vec![66,66,66] + }, + "a": 44 + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { + iii: Nested3 { a: 2, s: S::new(C) }, + }, + a: 44, + }, + a: 3, + s3: S3 { x: 5 }, + b: 4, + }, + { + "i": { + "ii": { + "iii": { "a": 2, "s": { "x": 5 } }, + }, + "a" : 44, + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { + s3: S3::new(5), + iii: Nested3 { a: 2, s: S::new(C) }, + }, + a: 44, + }, + a: 3, + s3: S3 { x: 5 }, + b: 4, + }, + { + "i": { + "ii": { + "iii": { "a": 2, "s": { "x": 5 } }, + "s3": {"x": 5, "y": 5, "z": 5 } + }, + "a" : 44, + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + test!( + TestStruct { + a: 3, + s3: S3 { x: 5 }, + b: 4, + i: Nested1 { + ii: Nested2 { + iii: Nested3 { a: 2, s: S::new(C) }, + s3: S3::new_from_s(S { x: 4 }) + }, + a: 44, + } + }, + { + "i": { + "ii": { + "iii": { "a": 2, "s": { "x": 5 } }, + "s3": {"x": 4, "y": 0, "z": 0 } + }, + "a" : 44, + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + let i = [0u32, 1u32, 2u32]; + test!( + TestStruct { + i: Nested1 { + ii: Nested2 { + iii: Nested3 { + a: 2, + s: S::new(C), + v: i.iter() + .map(|x| (*x, 2 * x, 100 + x, SomeEnum::::A)) + .collect::>(), + }, + s3: S3::new_from_s(S { x: 4 }) + }, + a: 44, + }, + a: 3, + s3: S3 { x: 5 }, + b: 4, + }, + + { + "i": { + "ii": { + "iii": { + "a": 2, + "s": { "x": 5 }, + "v": i.iter() + .map(|x| (*x, 2 * x, 100 + x, SomeEnum::::A)) + .collect::>(), + }, + "s3": {"x": 4, "y": 0, "z": 0 } + }, + "a" : 44, + }, + "a": 3, + "s3": { "x": 5 }, + "b": 4 + } + ); + } + + #[test] + fn test_generate_config_macro_with_nested_mods() { + test!( + TestStruct { t: nested_mod::InsideMod { a: 32 } }, + { + "t" : { "a": 32 } + } + ); + test!( + TestStruct { + t: nested_mod::InsideMod { a: 32 }, + u: nested_mod::nested_mod2::nested_mod3::InsideMod3 { a: 32 } + }, + { + "t" : { "a": 32 }, + "u" : { "a": 32 } + } + ); + test!( + TestStruct { + t: nested_mod::InsideMod { a: 32 }, + u: nested_mod::nested_mod2::nested_mod3::InsideMod3 { + a: 32, + s: nested_mod::InsideMod { a: 34 }, + } + }, + { + "t" : { "a": 32 }, + "u" : { "a": 32, "s": { "a": 34 } } + } + ); + test!( + TestStruct { + t: nested_mod::InsideMod { a: 32 }, + u: nested_mod::nested_mod2::nested_mod3::InsideMod3::default() + }, + { + "t" : { "a": 32 }, + "u" : { "a": 0, "b": 0, "s": { "a": 0, "b": 0} } + } + ); + + let i = [0u32, 1u32, 2u32]; + const C: u32 = 5; + test!( + TestStruct { + t: nested_mod::InsideMod { a: 32 }, + u: nested_mod::nested_mod2::nested_mod3::InsideMod3::default(), + i: Nested1 { + ii: Nested2 { + iii: Nested3 { + a: 2, + s: S::new(C), + v: i.iter() + .map(|x| (*x, 2 * x, 100 + x, SomeEnum::::A)) + .collect::>(), + }, + s3: S3::new_from_s(S { x: 4 }) + }, + a: 44, + }, + }, + { + "t" : { "a": 32 }, + "u" : { "a": 0, "b": 0, "s": { "a": 0, "b": 0} } , + "i": { + "ii": { + "iii": { + "a": 2, + "s": { "x": 5 }, + "v": i.iter() + .map(|x| (*x, 2 * x, 100 + x, SomeEnum::::A)) + .collect::>(), + }, + "s3": {"x": 4, "y": 0, "z": 0 } + }, + "a" : 44, + }, + } + ); + } +} + +#[cfg(test)] +mod retain_keys_test { + use super::*; + use serde_json::json; + + macro_rules! check_initialized_field_eq_cc( + ( $s:literal ) => { + let field = InitializedField::full($s); + let cc = inflector::cases::camelcase::to_camel_case($s); + println!("field: {:?}, cc: {}", field, cc); + assert_eq!(field,cc); + } ; + ( &[ $f:literal $(, $r:literal)* ]) => { + let field = InitializedField::full( + concat!( $f $(,".",$r)+ ) + ); + let cc = [ $f $(,$r)+ ].into_iter() + .map(|s| inflector::cases::camelcase::to_camel_case(s)) + .collect::>() + .join("."); + println!("field: {:?}, cc: {}", field, cc); + assert_eq!(field,cc); + } ; + ); + + #[test] + fn test_initialized_field_eq_cc_string() { + check_initialized_field_eq_cc!("a_"); + check_initialized_field_eq_cc!("abc"); + check_initialized_field_eq_cc!("aBc"); + check_initialized_field_eq_cc!("aBC"); + check_initialized_field_eq_cc!("ABC"); + check_initialized_field_eq_cc!("2abs"); + check_initialized_field_eq_cc!("2Abs"); + check_initialized_field_eq_cc!("2ABs"); + check_initialized_field_eq_cc!("2aBs"); + check_initialized_field_eq_cc!("AlreadyCamelCase"); + check_initialized_field_eq_cc!("alreadyCamelCase"); + check_initialized_field_eq_cc!("C"); + check_initialized_field_eq_cc!("1a"); + check_initialized_field_eq_cc!("_1a"); + check_initialized_field_eq_cc!("a_b"); + check_initialized_field_eq_cc!("_a_b"); + check_initialized_field_eq_cc!("a___b"); + check_initialized_field_eq_cc!("__a_b"); + check_initialized_field_eq_cc!("_a___b_C"); + check_initialized_field_eq_cc!("__A___B_C"); + check_initialized_field_eq_cc!(&["a_b", "b_c"]); + check_initialized_field_eq_cc!(&["al_pha", "_a___b_C"]); + check_initialized_field_eq_cc!(&["al_pha_", "_a___b_C"]); + check_initialized_field_eq_cc!(&["first_field", "al_pha_", "_a___b_C"]); + check_initialized_field_eq_cc!(&["al_pha_", "__2nd_field", "_a___b_C"]); + check_initialized_field_eq_cc!(&["al_pha_", "__2nd3and_field", "_a___b_C"]); + check_initialized_field_eq_cc!(&["_a1", "_a2", "_a3_"]); + } + + #[test] + fn test01() { + let mut v = json!({ + "a":1 + }); + let e = v.clone(); + retain_initialized_fields(&mut v, &[InitializedField::full("a")], String::default()); + assert_eq!(e, v); + } + + #[test] + fn test02() { + let mut v = json!({ + "a":1 + }); + retain_initialized_fields(&mut v, &[InitializedField::full("b")], String::default()); + assert_eq!(Value::Object(Default::default()), v); + } + + #[test] + fn test03() { + let mut v = json!({}); + retain_initialized_fields(&mut v, &[], String::default()); + assert_eq!(Value::Object(Default::default()), v); + } + + #[test] + fn test04() { + let mut v = json!({}); + retain_initialized_fields(&mut v, &[InitializedField::full("b")], String::default()); + assert_eq!(Value::Object(Default::default()), v); + } + + #[test] + fn test05() { + let mut v = json!({ + "a":1 + }); + retain_initialized_fields(&mut v, &[], String::default()); + assert_eq!(Value::Object(Default::default()), v); + } + + #[test] + fn test06() { + let mut v = json!({ + "a": { + "b":1, + "c":2 + } + }); + retain_initialized_fields(&mut v, &[], String::default()); + assert_eq!(Value::Object(Default::default()), v); + } + + #[test] + fn test07() { + let mut v = json!({ + "a": { + "b":1, + "c":2 + } + }); + retain_initialized_fields(&mut v, &[InitializedField::full("a.b")], String::default()); + assert_eq!(Value::Object(Default::default()), v); + } + + #[test] + fn test08() { + let mut v = json!({ + "a": { + "b":1, + "c":2 + } + }); + let e = json!({ + "a": { + "b":1, + } + }); + retain_initialized_fields( + &mut v, + &[InitializedField::partial("a"), InitializedField::full("a.b")], + String::default(), + ); + assert_eq!(e, v); + } + + #[test] + fn test09() { + let mut v = json!({ + "a": { + "b":1, + "c":2 + } + }); + let e = json!({ + "a": { + "b":1, + "c":2, + } + }); + retain_initialized_fields(&mut v, &[InitializedField::full("a")], String::default()); + assert_eq!(e, v); + } +} diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index cc805d724857..2e7ea0a07d7d 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -53,6 +53,7 @@ pub mod __private { pub use paste; pub use scale_info; pub use serde; + pub use serde_json; pub use sp_core::{Get, OpaqueMetadata, Void}; pub use sp_crypto_hashing_proc_macro; pub use sp_inherents; @@ -2588,9 +2589,12 @@ sp_core::generate_feature_enabled_macro!(try_runtime_enabled, feature = "try-run sp_core::generate_feature_enabled_macro!(try_runtime_or_std_enabled, any(feature = "try-runtime", feature = "std"), $); sp_core::generate_feature_enabled_macro!(try_runtime_and_std_not_enabled, all(not(feature = "try-runtime"), not(feature = "std")), $); -// Helper for implementing GenesisBuilder runtime API +/// Helper for implementing GenesisBuilder runtime API pub mod genesis_builder_helper; +/// Helper for generating the `RuntimeGenesisConfig` instance for presets. +pub mod generate_genesis_config; + #[cfg(test)] mod test { // use super::*; From 5a142856520fd450b6be8361a50e1f4d385e8a6c Mon Sep 17 00:00:00 2001 From: "Shoyu Vanilla (Flint)" Date: Fri, 25 Oct 2024 18:00:15 +0900 Subject: [PATCH 11/15] substrate-offchain: upgrade hyper to v1 (#5919) Closes #4896 --- Cargo.lock | 67 +++++--- Cargo.toml | 9 +- polkadot/node/service/src/lib.rs | 6 +- prdoc/pr_5919.prdoc | 19 +++ substrate/bin/node/cli/src/service.rs | 14 +- substrate/client/offchain/Cargo.toml | 10 +- substrate/client/offchain/src/api.rs | 2 +- substrate/client/offchain/src/api/http.rs | 183 +++++++++++++--------- substrate/client/offchain/src/lib.rs | 11 +- templates/minimal/node/src/service.rs | 12 +- templates/parachain/node/src/service.rs | 12 +- templates/solochain/node/src/service.rs | 12 +- 12 files changed, 211 insertions(+), 146 deletions(-) create mode 100644 prdoc/pr_5919.prdoc diff --git a/Cargo.lock b/Cargo.lock index 335c465e0aa3..3d5193fe0ee8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7501,16 +7501,17 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", "hyper 1.3.1", "hyper-util", "log", - "rustls 0.23.10", + "rustls 0.23.14", + "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -8148,7 +8149,7 @@ dependencies = [ "http 1.1.0", "jsonrpsee-core 0.23.2", "pin-project", - "rustls 0.23.10", + "rustls 0.23.14", "rustls-pki-types", "rustls-platform-verifier", "soketto 0.8.0", @@ -8173,7 +8174,7 @@ dependencies = [ "http 1.1.0", "jsonrpsee-core 0.24.3", "pin-project", - "rustls 0.23.10", + "rustls 0.23.14", "rustls-pki-types", "rustls-platform-verifier", "soketto 0.8.0", @@ -8287,11 +8288,11 @@ dependencies = [ "base64 0.22.1", "http-body 1.0.0", "hyper 1.3.1", - "hyper-rustls 0.27.2", + "hyper-rustls 0.27.3", "hyper-util", "jsonrpsee-core 0.24.3", "jsonrpsee-types 0.24.3", - "rustls 0.23.10", + "rustls 0.23.14", "rustls-platform-verifier", "serde", "serde_json", @@ -17083,7 +17084,7 @@ dependencies = [ "quinn-proto 0.11.8", "quinn-udp 0.5.4", "rustc-hash 2.0.0", - "rustls 0.23.10", + "rustls 0.23.14", "socket2 0.5.7", "thiserror", "tokio", @@ -17117,7 +17118,7 @@ dependencies = [ "rand", "ring 0.17.7", "rustc-hash 2.0.0", - "rustls 0.23.10", + "rustls 0.23.14", "slab", "thiserror", "tinyvec", @@ -17610,7 +17611,7 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-rustls 0.27.2", + "hyper-rustls 0.27.3", "hyper-util", "ipnet", "js-sys", @@ -17620,7 +17621,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn 0.11.5", - "rustls 0.23.10", + "rustls 0.23.14", "rustls-pemfile 2.0.0", "rustls-pki-types", "serde", @@ -18199,22 +18200,22 @@ dependencies = [ "log", "ring 0.17.7", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.8", "subtle 2.5.0", "zeroize", ] [[package]] name = "rustls" -version = "0.23.10" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ "log", "once_cell", "ring 0.17.7", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.8", "subtle 2.5.0", "zeroize", ] @@ -18244,6 +18245,19 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.0.0", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.3" @@ -18265,9 +18279,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" [[package]] name = "rustls-platform-verifier" @@ -18280,10 +18294,10 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.10", + "rustls 0.23.14", "rustls-native-certs 0.7.0", "rustls-platform-verifier-android", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.8", "security-framework", "security-framework-sys", "webpki-roots 0.26.3", @@ -18308,9 +18322,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring 0.17.7", "rustls-pki-types", @@ -19485,14 +19499,17 @@ dependencies = [ "fnv", "futures", "futures-timer", - "hyper 0.14.29", - "hyper-rustls 0.24.2", + "http-body-util", + "hyper 1.3.1", + "hyper-rustls 0.27.3", + "hyper-util", "log", "num_cpus", "once_cell", "parity-scale-codec", "parking_lot 0.12.3", "rand", + "rustls 0.23.14", "sc-block-builder", "sc-client-api", "sc-client-db", @@ -24976,7 +24993,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.10", + "rustls 0.23.14", "rustls-pki-types", "tokio", ] @@ -25700,7 +25717,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.10", + "rustls 0.23.14", "rustls-pki-types", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 6ba91de3c09b..dd1fa40e146a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -757,6 +757,8 @@ femme = { version = "2.2.1" } filetime = { version = "0.2.16" } finality-grandpa = { version = "0.16.2", default-features = false } finality-relay = { path = "bridges/relays/finality" } +first-pallet = { package = "polkadot-sdk-docs-first-pallet", path = "docs/sdk/packages/guides/first-pallet", default-features = false } +first-runtime = { package = "polkadot-sdk-docs-first-runtime", path = "docs/sdk/packages/guides/first-runtime", default-features = false } flate2 = { version = "1.0" } fnv = { version = "1.0.6" } fork-tree = { path = "substrate/utils/fork-tree", default-features = false } @@ -805,12 +807,8 @@ http = { version = "1.1" } http-body = { version = "1", default-features = false } http-body-util = { version = "0.1.2", default-features = false } hyper = { version = "1.3.1", default-features = false } -hyper-rustls = { version = "0.24.2" } +hyper-rustls = { version = "0.27.3", default-features = false, features = ["http1", "http2", "logging", "ring", "rustls-native-certs", "tls12"] } hyper-util = { version = "0.1.5", default-features = false } -# TODO: remove hyper v0.14 https://github.com/paritytech/polkadot-sdk/issues/4896 -first-pallet = { package = "polkadot-sdk-docs-first-pallet", path = "docs/sdk/packages/guides/first-pallet", default-features = false } -first-runtime = { package = "polkadot-sdk-docs-first-runtime", path = "docs/sdk/packages/guides/first-runtime", default-features = false } -hyperv14 = { package = "hyper", version = "0.14.29", default-features = false } impl-serde = { version = "0.5.0", default-features = false } impl-trait-for-tuples = { version = "0.2.2" } indexmap = { version = "2.0.0" } @@ -1127,6 +1125,7 @@ rstest = { version = "0.18.2" } rustc-hash = { version = "1.1.0" } rustc-hex = { version = "2.1.0", default-features = false } rustix = { version = "0.36.7", default-features = false } +rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] } rustversion = { version = "1.0.17" } rusty-fork = { version = "0.3.0", default-features = false } safe-mix = { version = "1.0", default-features = false } diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index d6f24159e1da..abba91a38a97 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -1044,7 +1044,7 @@ pub fn new_full< is_validator: role.is_authority(), enable_http_requests: false, custom_extensions: move |_| vec![], - }) + })? .run(client.clone(), task_manager.spawn_handle()) .boxed(), ); @@ -1436,7 +1436,7 @@ pub fn new_chain_ops( } else if config.chain_spec.is_kusama() { chain_ops!(config, None) } else if config.chain_spec.is_westend() { - return chain_ops!(config, None) + return chain_ops!(config, None); } else { chain_ops!(config, None) } @@ -1488,7 +1488,7 @@ pub fn revert_backend( let revertible = blocks.min(best_number - finalized); if revertible == 0 { - return Ok(()) + return Ok(()); } let number = best_number - revertible; diff --git a/prdoc/pr_5919.prdoc b/prdoc/pr_5919.prdoc new file mode 100644 index 000000000000..1b48a24a9e28 --- /dev/null +++ b/prdoc/pr_5919.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "substrate-offchain: upgrade hyper to v1" + +doc: + - audience: Node Dev + description: | + Bump depencency `hyper` of `substrait-offchain` for http from `0.14` to `1`. + This changed APIs a bit; + - `sc_offchain::Offchainworker::new()` now returns `std::io::Result` (Previously was `Self`) + +crates: + - name: sc-offchain + bump: major + - name: polkadot-service + bump: patch + - name: staging-node-cli + bump: patch diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 7b166f94bcc8..057e0bbdcefc 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -790,9 +790,7 @@ pub fn new_full_base::Hash>>( ); if enable_offchain_worker { - task_manager.spawn_handle().spawn( - "offchain-workers-runner", - "offchain-work", + let offchain_workers = sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { runtime_api_provider: client.clone(), keystore: Some(keystore_container.keystore()), @@ -806,9 +804,11 @@ pub fn new_full_base::Hash>>( custom_extensions: move |_| { vec![Box::new(statement_store.clone().as_statement_store_ext()) as Box<_>] }, - }) - .run(client.clone(), task_manager.spawn_handle()) - .boxed(), + })?; + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-work", + offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), ); } @@ -992,7 +992,7 @@ mod tests { sc_consensus_babe::authorship::claim_slot(slot.into(), &epoch, &keystore) .map(|(digest, _)| digest) { - break (babe_pre_digest, epoch_descriptor) + break (babe_pre_digest, epoch_descriptor); } slot += 1; diff --git a/substrate/client/offchain/Cargo.toml b/substrate/client/offchain/Cargo.toml index bbbe7018d106..71b40211e126 100644 --- a/substrate/client/offchain/Cargo.toml +++ b/substrate/client/offchain/Cargo.toml @@ -22,15 +22,15 @@ codec = { features = ["derive"], workspace = true, default-features = true } fnv = { workspace = true } futures = { workspace = true } futures-timer = { workspace = true } -hyperv14 = { features = [ - "http2", - "stream", -], workspace = true, default-features = true } -hyper-rustls = { features = ["http2"], workspace = true } +http-body-util = { workspace = true } +hyper = { features = ["http1", "http2"], workspace = true, default-features = true } +hyper-rustls = { workspace = true } +hyper-util = { features = ["client-legacy", "http1", "http2"], workspace = true } num_cpus = { workspace = true } once_cell = { workspace = true } parking_lot = { workspace = true, default-features = true } rand = { workspace = true, default-features = true } +rustls = { workspace = true } threadpool = { workspace = true } tracing = { workspace = true, default-features = true } sc-client-api = { workspace = true, default-features = true } diff --git a/substrate/client/offchain/src/api.rs b/substrate/client/offchain/src/api.rs index 19ccdbcf498f..a5981f14c093 100644 --- a/substrate/client/offchain/src/api.rs +++ b/substrate/client/offchain/src/api.rs @@ -326,7 +326,7 @@ mod tests { fn offchain_api() -> (Api, AsyncApi) { sp_tracing::try_init_simple(); let mock = Arc::new(TestNetwork()); - let shared_client = SharedClient::new(); + let shared_client = SharedClient::new().unwrap(); AsyncApi::new(mock, false, shared_client) } diff --git a/substrate/client/offchain/src/api/http.rs b/substrate/client/offchain/src/api/http.rs index 73407b1359d7..56f5c0230094 100644 --- a/substrate/client/offchain/src/api/http.rs +++ b/substrate/client/offchain/src/api/http.rs @@ -27,14 +27,14 @@ //! (i.e.: the socket should continue being processed) in the background even if the runtime isn't //! actively calling any function. -use hyperv14 as hyper; - use crate::api::timestamp; use bytes::buf::{Buf, Reader}; use fnv::FnvHashMap; use futures::{channel::mpsc, future, prelude::*}; -use hyper::{client, Body, Client as HyperClient}; +use http_body_util::{combinators::BoxBody, StreamBody}; +use hyper::body::Body as _; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; +use hyper_util::{client::legacy as client, rt::TokioExecutor}; use once_cell::sync::Lazy; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Timestamp}; @@ -48,21 +48,26 @@ use std::{ const LOG_TARGET: &str = "offchain-worker::http"; +pub type Body = BoxBody; + +type Sender = mpsc::Sender, hyper::Error>>; +type Receiver = mpsc::Receiver, hyper::Error>>; + +type HyperClient = client::Client, Body>; +type LazyClient = Lazy HyperClient + Send>>; + /// Wrapper struct used for keeping the hyper_rustls client running. #[derive(Clone)] -pub struct SharedClient(Arc, Body>>>); +pub struct SharedClient(Arc); impl SharedClient { - pub fn new() -> Self { - Self(Arc::new(Lazy::new(|| { - let connector = HttpsConnectorBuilder::new() - .with_native_roots() - .https_or_http() - .enable_http1() - .enable_http2() - .build(); - HyperClient::builder().build(connector) - }))) + pub fn new() -> std::io::Result { + let builder = HttpsConnectorBuilder::new() + .with_provider_and_native_roots(rustls::crypto::ring::default_provider())?; + Ok(Self(Arc::new(Lazy::new(Box::new(|| { + let connector = builder.https_or_http().enable_http1().enable_http2().build(); + client::Client::builder(TokioExecutor::new()).build(connector) + }))))) } } @@ -105,23 +110,23 @@ pub struct HttpApi { /// One active request within `HttpApi`. enum HttpApiRequest { /// The request object is being constructed locally and not started yet. - NotDispatched(hyper::Request, hyper::body::Sender), + NotDispatched(hyper::Request, Sender), /// The request has been dispatched and we're in the process of sending out the body (if the /// field is `Some`) or waiting for a response (if the field is `None`). - Dispatched(Option), + Dispatched(Option), /// Received a response. Response(HttpApiRequestRp), /// A request has been dispatched but the worker notified us of an error. We report this /// failure to the user as an `IoError` and remove the request from the list as soon as /// possible. - Fail(hyper::Error), + Fail(client::Error), } /// A request within `HttpApi` that has received a response. struct HttpApiRequestRp { /// We might still be writing the request's body when the response comes. /// This field allows to continue writing that body. - sending_body: Option, + sending_body: Option, /// Status code of the response. status_code: hyper::StatusCode, /// Headers of the response. @@ -132,7 +137,7 @@ struct HttpApiRequestRp { /// Elements extracted from the channel are first put into `current_read_chunk`. /// If the channel produces an error, then that is translated into an `IoError` and the request /// is removed from the list. - body: stream::Fuse>>, + body: stream::Fuse, /// Chunk that has been extracted from the channel and that is currently being read. /// Reading data from the response should read from this field in priority. current_read_chunk: Option>, @@ -144,7 +149,9 @@ impl HttpApi { // Start by building the prototype of the request. // We do this first so that we don't touch anything in `self` if building the prototype // fails. - let (body_sender, body) = hyper::Body::channel(); + let (body_sender, receiver) = mpsc::channel(0); + let body = StreamBody::new(receiver); + let body = BoxBody::new(body); let mut request = hyper::Request::new(body); *request.method_mut() = hyper::Method::from_bytes(method.as_bytes()).map_err(|_| ())?; *request.uri_mut() = hyper::Uri::from_maybe_shared(uri.to_owned()).map_err(|_| ())?; @@ -158,7 +165,7 @@ impl HttpApi { target: LOG_TARGET, "Overflow in offchain worker HTTP request ID assignment" ); - return Err(()) + return Err(()); }, }; self.requests @@ -213,7 +220,7 @@ impl HttpApi { // Closure that writes data to a sender, taking the deadline into account. Can return `Ok` // (if the body has been written), or `DeadlineReached`, or `IoError`. // If `IoError` is returned, don't forget to remove the request from the list. - let mut poll_sender = move |sender: &mut hyper::body::Sender| -> Result<(), HttpError> { + let mut poll_sender = move |sender: &mut Sender| -> Result<(), HttpError> { let mut when_ready = future::maybe_done(future::poll_fn(|cx| sender.poll_ready(cx))); futures::executor::block_on(future::select(&mut when_ready, &mut deadline)); match when_ready { @@ -221,12 +228,15 @@ impl HttpApi { future::MaybeDone::Done(Err(_)) => return Err(HttpError::IoError), future::MaybeDone::Future(_) | future::MaybeDone::Gone => { debug_assert!(matches!(deadline, future::MaybeDone::Done(..))); - return Err(HttpError::DeadlineReached) + return Err(HttpError::DeadlineReached); }, }; futures::executor::block_on( - sender.send_data(hyper::body::Bytes::from(chunk.to_owned())), + async { + future::poll_fn(|cx| sender.poll_ready(cx)).await?; + sender.start_send(Ok(hyper::body::Frame::data(hyper::body::Bytes::from(chunk.to_owned())))) + } ) .map_err(|_| { tracing::error!(target: "offchain-worker::http", "HTTP sender refused data despite being ready"); @@ -250,13 +260,13 @@ impl HttpApi { match poll_sender(&mut sender) { Err(HttpError::IoError) => { tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Encountered io error while trying to add new chunk to body"); - return Err(HttpError::IoError) + return Err(HttpError::IoError); }, other => { tracing::debug!(target: LOG_TARGET, id = %request_id.0, res = ?other, "Added chunk to body"); self.requests .insert(request_id, HttpApiRequest::Dispatched(Some(sender))); - return other + return other; }, } } else { @@ -265,7 +275,7 @@ impl HttpApi { // Writing an empty body is a hint that we should stop writing. Dropping // the sender. self.requests.insert(request_id, HttpApiRequest::Dispatched(None)); - return Ok(()) + return Ok(()); } }, @@ -281,13 +291,13 @@ impl HttpApi { ) { Err(HttpError::IoError) => { tracing::debug!(target: LOG_TARGET, id = %request_id.0, "Encountered io error while trying to add new chunk to body"); - return Err(HttpError::IoError) + return Err(HttpError::IoError); }, other => { tracing::debug!(target: LOG_TARGET, id = %request_id.0, res = ?other, "Added chunk to body"); self.requests .insert(request_id, HttpApiRequest::Response(response)); - return other + return other; }, } } else { @@ -302,7 +312,7 @@ impl HttpApi { ..response }), ); - return Ok(()) + return Ok(()); } }, @@ -311,7 +321,7 @@ impl HttpApi { // If the request has already failed, return without putting back the request // in the list. - return Err(HttpError::IoError) + return Err(HttpError::IoError); }, v @ HttpApiRequest::Dispatched(None) | @@ -320,7 +330,7 @@ impl HttpApi { // We have already finished sending this body. self.requests.insert(request_id, v); - return Err(HttpError::Invalid) + return Err(HttpError::Invalid); }, } } @@ -340,7 +350,7 @@ impl HttpApi { Some(HttpApiRequest::Dispatched(sending_body)) | Some(HttpApiRequest::Response(HttpApiRequestRp { sending_body, .. })) => { let _ = sending_body.take(); - continue + continue; }, _ => continue, }; @@ -405,7 +415,7 @@ impl HttpApi { }, } } - return output + return output; } } @@ -418,7 +428,7 @@ impl HttpApi { msg } else { debug_assert!(matches!(deadline, future::MaybeDone::Done(..))); - continue + continue; } }; @@ -458,7 +468,7 @@ impl HttpApi { None => { tracing::error!(target: "offchain-worker::http", "Worker has crashed"); - return ids.iter().map(|_| HttpRequestStatus::IoError).collect() + return ids.iter().map(|_| HttpRequestStatus::IoError).collect(); }, } } @@ -498,14 +508,14 @@ impl HttpApi { // and we still haven't received a response. Some(rq @ HttpApiRequest::Dispatched(_)) => { self.requests.insert(request_id, rq); - return Err(HttpError::DeadlineReached) + return Err(HttpError::DeadlineReached); }, // The request has failed. Some(HttpApiRequest::Fail { .. }) => return Err(HttpError::IoError), // Request hasn't been dispatched yet; reading the body is invalid. Some(rq @ HttpApiRequest::NotDispatched(_, _)) => { self.requests.insert(request_id, rq); - return Err(HttpError::Invalid) + return Err(HttpError::Invalid); }, None => return Err(HttpError::Invalid), }; @@ -526,12 +536,12 @@ impl HttpApi { ..response }), ); - return Ok(n) + return Ok(n); }, Err(err) => { // This code should never be reached unless there's a logic error somewhere. tracing::error!(target: "offchain-worker::http", "Failed to read from current read chunk: {:?}", err); - return Err(HttpError::IoError) + return Err(HttpError::IoError); }, } } @@ -544,7 +554,10 @@ impl HttpApi { if let future::MaybeDone::Done(next_body) = next_body { match next_body { - Some(Ok(chunk)) => response.current_read_chunk = Some(chunk.reader()), + Some(Ok(chunk)) => + if let Ok(chunk) = chunk.into_data() { + response.current_read_chunk = Some(chunk.reader()); + }, Some(Err(_)) => return Err(HttpError::IoError), None => return Ok(0), // eof } @@ -552,7 +565,7 @@ impl HttpApi { if let future::MaybeDone::Done(_) = deadline { self.requests.insert(request_id, HttpApiRequest::Response(response)); - return Err(HttpError::DeadlineReached) + return Err(HttpError::DeadlineReached); } } } @@ -587,7 +600,7 @@ enum ApiToWorker { /// ID to send back when the response comes back. id: HttpRequestId, /// Request to start executing. - request: hyper::Request, + request: hyper::Request, }, } @@ -608,14 +621,14 @@ enum WorkerToApi { /// the next item. /// Can also be used to send an error, in case an error happened on the HTTP socket. After /// an error is sent, the channel will close. - body: mpsc::Receiver>, + body: Receiver, }, /// A request has failed because of an error. The request is then no longer valid. Fail { /// The ID that was passed to the worker. id: HttpRequestId, /// Error that happened. - error: hyper::Error, + error: client::Error, }, } @@ -626,7 +639,7 @@ pub struct HttpWorker { /// Used to receive messages from the `HttpApi`. from_api: TracingUnboundedReceiver, /// The engine that runs HTTP requests. - http_client: Arc, Body>>>, + http_client: Arc, /// HTTP requests that are being worked on by the engine. requests: Vec<(HttpRequestId, HttpWorkerRequest)>, } @@ -634,13 +647,13 @@ pub struct HttpWorker { /// HTTP request being processed by the worker. enum HttpWorkerRequest { /// Request has been dispatched and is waiting for a response from the Internet. - Dispatched(hyper::client::ResponseFuture), + Dispatched(client::ResponseFuture), /// Progressively reading the body of the response and sending it to the channel. ReadBody { /// Body to read `Chunk`s from. Only used if the channel is ready to accept data. - body: hyper::Body, + body: Body, /// Channel to the [`HttpApi`] where we send the chunks to. - tx: mpsc::Sender>, + tx: Sender, }, } @@ -663,12 +676,12 @@ impl Future for HttpWorker { let response = match Future::poll(Pin::new(&mut future), cx) { Poll::Pending => { me.requests.push((id, HttpWorkerRequest::Dispatched(future))); - continue + continue; }, Poll::Ready(Ok(response)) => response, Poll::Ready(Err(error)) => { let _ = me.to_api.unbounded_send(WorkerToApi::Fail { id, error }); - continue // don't insert the request back + continue; // don't insert the request back }, }; @@ -684,9 +697,12 @@ impl Future for HttpWorker { body: body_rx, }); - me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx: body_tx })); + me.requests.push(( + id, + HttpWorkerRequest::ReadBody { body: Body::new(body), tx: body_tx }, + )); cx.waker().wake_by_ref(); // reschedule in order to poll the new future - continue + continue; }, HttpWorkerRequest::ReadBody { mut body, mut tx } => { @@ -697,12 +713,11 @@ impl Future for HttpWorker { Poll::Ready(Err(_)) => continue, // don't insert the request back Poll::Pending => { me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); - continue + continue; }, } - // `tx` is ready. Read a chunk from the socket and send it to the channel. - match Stream::poll_next(Pin::new(&mut body), cx) { + match Pin::new(&mut body).poll_frame(cx) { Poll::Ready(Some(Ok(chunk))) => { let _ = tx.start_send(Ok(chunk)); me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); @@ -762,19 +777,22 @@ mod tests { }; use crate::api::timestamp; use core::convert::Infallible; - use futures::{future, StreamExt}; + use futures::future; + use http_body_util::BodyExt; use sp_core::offchain::{Duration, Externalities, HttpError, HttpRequestId, HttpRequestStatus}; use std::sync::LazyLock; // Using LazyLock to avoid spawning lots of different SharedClients, // as spawning a SharedClient is CPU-intensive and opens lots of fds. - static SHARED_CLIENT: LazyLock = LazyLock::new(|| SharedClient::new()); + static SHARED_CLIENT: LazyLock = LazyLock::new(|| SharedClient::new().unwrap()); // Returns an `HttpApi` whose worker is ran in the background, and a `SocketAddr` to an HTTP // server that runs in the background as well. macro_rules! build_api_server { () => { - build_api_server!(hyper::Response::new(hyper::Body::from("Hello World!"))) + build_api_server!(hyper::Response::new(http_body_util::Full::new( + hyper::body::Bytes::from("Hello World!") + ))) }; ( $response:expr ) => {{ let hyper_client = SHARED_CLIENT.clone(); @@ -785,21 +803,32 @@ mod tests { let rt = tokio::runtime::Runtime::new().unwrap(); let worker = rt.spawn(worker); let server = rt.spawn(async move { - let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()).serve( - hyper::service::make_service_fn(|_| async move { - Ok::<_, Infallible>(hyper::service::service_fn( - move |req: hyper::Request| async move { - // Wait until the complete request was received and processed, - // otherwise the tests are flaky. - let _ = req.into_body().collect::>().await; - - Ok::<_, Infallible>($response) - }, - )) - }), - ); - let _ = addr_tx.send(server.local_addr()); - server.await.map_err(drop) + let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 0)); + let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); + let _ = addr_tx.send(listener.local_addr().unwrap()); + loop { + let (stream, _) = listener.accept().await.unwrap(); + let io = hyper_util::rt::TokioIo::new(stream); + tokio::task::spawn(async move { + if let Err(err) = hyper::server::conn::http1::Builder::new() + .serve_connection( + io, + hyper::service::service_fn( + move |req: hyper::Request| async move { + // Wait until the complete request was received and + // processed, otherwise the tests are flaky. + let _ = req.into_body().collect().await; + + Ok::<_, Infallible>($response) + }, + ), + ) + .await + { + eprintln!("Error serving connection: {:?}", err); + } + }); + } }); let _ = rt.block_on(future::join(worker, server)); }); @@ -839,7 +868,7 @@ mod tests { let (mut api, addr) = build_api_server!(hyper::Response::builder() .version(hyper::Version::HTTP_2) - .body(hyper::Body::from("Hello World!")) + .body(http_body_util::Full::new(hyper::body::Bytes::from("Hello World!"))) .unwrap()); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); @@ -1097,7 +1126,7 @@ mod tests { #[test] fn shared_http_client_is_only_initialized_on_access() { - let shared_client = SharedClient::new(); + let shared_client = SharedClient::new().unwrap(); { let mock = Arc::new(TestNetwork()); @@ -1112,7 +1141,7 @@ mod tests { // Check that the http client wasn't initialized, because it wasn't used. assert!(Lazy::into_value(Arc::try_unwrap(shared_client.0).unwrap()).is_err()); - let shared_client = SharedClient::new(); + let shared_client = SharedClient::new().unwrap(); { let mock = Arc::new(TestNetwork()); diff --git a/substrate/client/offchain/src/lib.rs b/substrate/client/offchain/src/lib.rs index 3d5728aad17d..b0a7a66520b7 100644 --- a/substrate/client/offchain/src/lib.rs +++ b/substrate/client/offchain/src/lib.rs @@ -153,14 +153,14 @@ impl OffchainWorkers { enable_http_requests, custom_extensions, }: OffchainWorkerOptions, - ) -> Self { - Self { + ) -> std::io::Result { + Ok(Self { runtime_api_provider, thread_pool: Mutex::new(ThreadPool::with_name( "offchain-worker".into(), num_cpus::get(), )), - shared_http_client: api::SharedClient::new(), + shared_http_client: api::SharedClient::new()?, enable_http_requests, keystore, offchain_db: offchain_db.map(OffchainDb::new), @@ -168,7 +168,7 @@ impl OffchainWorkers { is_validator, network_provider, custom_extensions: Box::new(custom_extensions), - } + }) } } @@ -466,7 +466,8 @@ mod tests { is_validator: false, enable_http_requests: false, custom_extensions: |_| Vec::new(), - }); + }) + .unwrap(); futures::executor::block_on(offchain.on_block_imported(&header)); // then diff --git a/templates/minimal/node/src/service.rs b/templates/minimal/node/src/service.rs index 6ba6959202c4..169993e2e93a 100644 --- a/templates/minimal/node/src/service.rs +++ b/templates/minimal/node/src/service.rs @@ -161,9 +161,7 @@ pub fn new_full::Ha })?; if config.offchain_worker.enabled { - task_manager.spawn_handle().spawn( - "offchain-workers-runner", - "offchain-worker", + let offchain_workers = sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { runtime_api_provider: client.clone(), is_validator: config.role.is_authority(), @@ -175,9 +173,11 @@ pub fn new_full::Ha network_provider: Arc::new(network.clone()), enable_http_requests: true, custom_extensions: |_| vec![], - }) - .run(client.clone(), task_manager.spawn_handle()) - .boxed(), + })?; + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-worker", + offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), ); } diff --git a/templates/parachain/node/src/service.rs b/templates/parachain/node/src/service.rs index dd7dff2ebf16..57ffcb9049d8 100644 --- a/templates/parachain/node/src/service.rs +++ b/templates/parachain/node/src/service.rs @@ -287,9 +287,7 @@ pub async fn start_parachain_node( if parachain_config.offchain_worker.enabled { use futures::FutureExt; - task_manager.spawn_handle().spawn( - "offchain-workers-runner", - "offchain-work", + let offchain_workers = sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { runtime_api_provider: client.clone(), keystore: Some(params.keystore_container.keystore()), @@ -301,9 +299,11 @@ pub async fn start_parachain_node( is_validator: parachain_config.role.is_authority(), enable_http_requests: false, custom_extensions: move |_| vec![], - }) - .run(client.clone(), task_manager.spawn_handle()) - .boxed(), + })?; + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-work", + offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), ); } diff --git a/templates/solochain/node/src/service.rs b/templates/solochain/node/src/service.rs index 4192128b6724..2524906fd508 100644 --- a/templates/solochain/node/src/service.rs +++ b/templates/solochain/node/src/service.rs @@ -197,9 +197,7 @@ pub fn new_full< })?; if config.offchain_worker.enabled { - task_manager.spawn_handle().spawn( - "offchain-workers-runner", - "offchain-worker", + let offchain_workers = sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { runtime_api_provider: client.clone(), is_validator: config.role.is_authority(), @@ -211,9 +209,11 @@ pub fn new_full< network_provider: Arc::new(network.clone()), enable_http_requests: true, custom_extensions: |_| vec![], - }) - .run(client.clone(), task_manager.spawn_handle()) - .boxed(), + })?; + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-worker", + offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), ); } From 0796326267bb9e84e6aeed13ef334115dc1a5ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 11:27:46 +0200 Subject: [PATCH 12/15] pallet-revive: Add stateful address mapping (#6096) Fixes #5576 This allows contracts to be used with an AccountId32 through normal extrinsics and not only through the eth compat layer. It works by adding a new extrinsic `map_account` that lets people register their AccountId32. --------- Co-authored-by: command-bot <> Co-authored-by: GitHub Action Co-authored-by: Cyrill Leutwiler --- .../assets/asset-hub-westend/src/lib.rs | 2 +- prdoc/pr_6096.prdoc | 15 + substrate/bin/node/runtime/src/lib.rs | 2 +- .../contracts/locking_delegate_dependency.rs | 4 +- .../fixtures/contracts/self_destruct.rs | 4 +- .../contracts/terminate_and_send_to_eve.rs | 33 + .../src/parachain/contracts_config.rs | 2 +- substrate/frame/revive/src/address.rs | 288 ++++- .../frame/revive/src/benchmarking/mod.rs | 112 +- substrate/frame/revive/src/evm/runtime.rs | 4 +- substrate/frame/revive/src/exec.rs | 121 +- substrate/frame/revive/src/lib.rs | 79 +- substrate/frame/revive/src/test_utils.rs | 39 +- substrate/frame/revive/src/tests.rs | 115 +- substrate/frame/revive/src/weights.rs | 1089 +++++++++-------- 15 files changed, 1235 insertions(+), 674 deletions(-) create mode 100644 prdoc/pr_6096.prdoc create mode 100644 substrate/frame/revive/fixtures/contracts/terminate_and_send_to_eve.rs diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 9a60de77a584..adfa2b74df65 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -957,7 +957,7 @@ impl pallet_revive::Config for Runtime { type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_revive::weights::SubstrateWeight; type ChainExtension = (); - type AddressMapper = pallet_revive::DefaultAddressMapper; + type AddressMapper = pallet_revive::AccountId32Mapper; type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>; type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>; type UnsafeUnstableInterface = ConstBool; diff --git a/prdoc/pr_6096.prdoc b/prdoc/pr_6096.prdoc new file mode 100644 index 000000000000..c77c323a2e08 --- /dev/null +++ b/prdoc/pr_6096.prdoc @@ -0,0 +1,15 @@ +title: 'pallet-revive: Add stateful address mapping' +doc: +- audience: + - Runtime Dev + description: |- + Fixes #5576 + + This allows contracts to be used with an AccountId32 through normal extrinsics and not only through the eth compat layer. It works by adding a new extrinsic `map_account` that lets people register their AccountId32. +crates: +- name: pallet-revive-fixtures + bump: minor +- name: pallet-revive-mock-network + bump: patch +- name: pallet-revive + bump: major diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index d6a17856e470..89b5bf26ce75 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1415,7 +1415,7 @@ impl pallet_revive::Config for Runtime { type WeightPrice = pallet_transaction_payment::Pallet; type WeightInfo = pallet_revive::weights::SubstrateWeight; type ChainExtension = (); - type AddressMapper = pallet_revive::DefaultAddressMapper; + type AddressMapper = pallet_revive::AccountId32Mapper; type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>; type PVFMemory = ConstU32<{ 512 * 1024 * 1024 }>; type UnsafeUnstableInterface = ConstBool; diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs index 2efacb4e683f..54c7c7f3d5e2 100644 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs @@ -23,7 +23,7 @@ use common::input; use uapi::{HostFn, HostFnImpl as api}; -const ETH_ALICE: [u8; 20] = [1u8; 20]; +const ALICE_FALLBACK: [u8; 20] = [1u8; 20]; /// Load input data and perform the action specified by the input. /// If `delegate_call` is true, then delegate call into the contract. @@ -44,7 +44,7 @@ fn load_input(delegate_call: bool) { }, // 3 = Terminate 3 => { - api::terminate(Ð_ALICE); + api::terminate(&ALICE_FALLBACK); }, // Everything else is a noop _ => {}, diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index 524979991ec7..2f37706634bd 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -21,7 +21,7 @@ use common::input; use uapi::{HostFn, HostFnImpl as api}; -const ETH_DJANGO: [u8; 20] = [4u8; 20]; +const DJANGO_FALLBACK: [u8; 20] = [4u8; 20]; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -52,6 +52,6 @@ pub extern "C" fn call() { .unwrap(); } else { // Try to terminate and give balance to django. - api::terminate(Ð_DJANGO); + api::terminate(&DJANGO_FALLBACK); } } diff --git a/substrate/frame/revive/fixtures/contracts/terminate_and_send_to_eve.rs b/substrate/frame/revive/fixtures/contracts/terminate_and_send_to_eve.rs new file mode 100644 index 000000000000..c078f9d46c1d --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/terminate_and_send_to_eve.rs @@ -0,0 +1,33 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![no_std] +#![no_main] + +extern crate common; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + let eve = [5u8; 20]; + api::terminate(&eve); +} diff --git a/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs b/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs index c13c337d1667..a2fa7cbf7068 100644 --- a/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs +++ b/substrate/frame/revive/mock-network/src/parachain/contracts_config.rs @@ -20,7 +20,7 @@ use frame_support::derive_impl; #[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)] impl pallet_revive::Config for Runtime { - type AddressMapper = pallet_revive::DefaultAddressMapper; + type AddressMapper = pallet_revive::AccountId32Mapper; type Currency = Balances; type Time = super::Timestamp; type Xcm = pallet_xcm::Pallet; diff --git a/substrate/frame/revive/src/address.rs b/substrate/frame/revive/src/address.rs index 4633fce1f327..45b5bf822dc9 100644 --- a/substrate/frame/revive/src/address.rs +++ b/substrate/frame/revive/src/address.rs @@ -17,61 +17,173 @@ //! Functions that deal contract addresses. +use crate::{ensure, AddressSuffix, Config, Error, HoldReason}; use alloc::vec::Vec; -use sp_core::H160; +use core::marker::PhantomData; +use frame_support::traits::{fungible::MutateHold, tokens::Precision}; +use sp_core::{Get, H160}; use sp_io::hashing::keccak_256; -use sp_runtime::AccountId32; +use sp_runtime::{AccountId32, DispatchResult, SaturatedConversion, Saturating}; /// Map between the native chain account id `T` and an Ethereum [`H160`]. /// /// This trait exists only to emulate specialization for different concrete /// native account ids. **Not** to make the mapping user configurable. Hence -/// the trait is `Sealed` and only one mandatory implementor [`DefaultAddressMapper`] -/// exists. +/// the trait is `Sealed` and depending on your runtime configuration you need +/// to pick either [`AccountId32Mapper`] or [`H160Mapper`]. Picking the wrong +/// one will result in a compilation error. No footguns here. /// /// Please note that we assume that the native account is at least 20 bytes and /// only implement this type for a `T` where this is the case. Luckily, this is the -/// case for all existing runtimes as of right now. Reasing is that this will allow +/// case for all existing runtimes as of right now. Reasoning is that this will allow /// us to reverse an address -> account_id mapping by just stripping the prefix. -pub trait AddressMapper: private::Sealed { - /// Convert an account id to an ethereum address. - /// - /// This mapping is **not** required to be reversible. - fn to_address(account_id: &T) -> H160; +/// +/// We require the mapping to be reversible. Since we are potentially dealing with types of +/// different sizes one direction of the mapping is necessarily lossy. This requires the mapping to +/// make use of the [`AddressSuffix`] storage item to reverse the mapping. +pub trait AddressMapper: private::Sealed { + /// Convert an account id to an ethereum adress. + fn to_address(account_id: &T::AccountId) -> H160; /// Convert an ethereum address to a native account id. + fn to_account_id(address: &H160) -> T::AccountId; + + /// Same as [`Self::to_account_id`] but always returns the fallback account. + /// + /// This skips the query into [`AddressSuffix`] and always returns the stateless + /// fallback account. This is useful when we know for a fact that the `address` + /// in question is originally a `H160`. This is usually only the case when we + /// generated a new contract address. + fn to_fallback_account_id(address: &H160) -> T::AccountId; + + /// Create a stateful mapping for `account_id` + /// + /// This will enable `to_account_id` to map back to the original + /// `account_id` instead of the fallback account id. + fn map(account_id: &T::AccountId) -> DispatchResult; + + /// Remove the mapping in order to reclaim the deposit. /// - /// This mapping is **required** to be reversible. - fn to_account_id(address: &H160) -> T; + /// There is no reason why one would unmap their `account_id` except + /// for reclaiming the deposit. + fn unmap(account_id: &T::AccountId) -> DispatchResult; - /// Same as [`Self::to_account_id`] but when we know the address is a contract. + /// Returns true if the `account_id` is useable as an origin. /// - /// This is only the case when we just generated the new address. - fn to_account_id_contract(address: &H160) -> T; + /// This means either the `account_id` doesn't require a stateful mapping + /// or a stateful mapping exists. + fn is_mapped(account_id: &T::AccountId) -> bool; } mod private { pub trait Sealed {} - impl Sealed for super::DefaultAddressMapper {} + impl Sealed for super::AccountId32Mapper {} + impl Sealed for super::H160Mapper {} } -/// The only implementor for `AddressMapper`. -pub enum DefaultAddressMapper {} +/// The mapper to be used if the account id is `AccountId32`. +/// +/// It converts between addresses by either truncating the last 12 bytes or +/// suffixing them. The suffix is queried from [`AddressSuffix`] and will fall +/// back to all `0xEE` if no suffix was registered. This means contracts and +/// plain wallets controlled by an `secp256k1` always have a `0xEE` suffixed +/// account. +pub struct AccountId32Mapper(PhantomData); + +/// The mapper to be used if the account id is `H160`. +/// +/// It just trivially returns its inputs and doesn't make use of any state. +pub struct H160Mapper(PhantomData); -impl AddressMapper for DefaultAddressMapper { +impl AddressMapper for AccountId32Mapper +where + T: Config, +{ fn to_address(account_id: &AccountId32) -> H160 { H160::from_slice(&>::as_ref(&account_id)[..20]) } fn to_account_id(address: &H160) -> AccountId32 { + if let Some(suffix) = >::get(address) { + let mut account_id = Self::to_fallback_account_id(address); + let account_bytes: &mut [u8; 32] = account_id.as_mut(); + account_bytes[20..].copy_from_slice(suffix.as_slice()); + account_id + } else { + Self::to_fallback_account_id(address) + } + } + + fn to_fallback_account_id(address: &H160) -> AccountId32 { let mut account_id = AccountId32::new([0xEE; 32]); - >::as_mut(&mut account_id)[..20] - .copy_from_slice(address.as_bytes()); + let account_bytes: &mut [u8; 32] = account_id.as_mut(); + account_bytes[..20].copy_from_slice(address.as_bytes()); account_id } - fn to_account_id_contract(address: &H160) -> AccountId32 { - Self::to_account_id(address) + fn map(account_id: &T::AccountId) -> DispatchResult { + ensure!(!Self::is_mapped(account_id), >::AccountAlreadyMapped); + + let account_bytes: &[u8; 32] = account_id.as_ref(); + + // each mapping entry stores one AccountId32 distributed between key and value + let deposit = T::DepositPerByte::get() + .saturating_mul(account_bytes.len().saturated_into()) + .saturating_add(T::DepositPerItem::get()); + + let suffix: [u8; 12] = account_bytes[20..] + .try_into() + .expect("Skipping 20 byte of a an 32 byte array will fit into 12 bytes; qed"); + T::Currency::hold(&HoldReason::AddressMapping.into(), account_id, deposit)?; + >::insert(Self::to_address(account_id), suffix); + Ok(()) + } + + fn unmap(account_id: &T::AccountId) -> DispatchResult { + // will do nothing if address is not mapped so no check required + >::remove(Self::to_address(account_id)); + T::Currency::release_all( + &HoldReason::AddressMapping.into(), + account_id, + Precision::BestEffort, + )?; + Ok(()) + } + + fn is_mapped(account_id: &T::AccountId) -> bool { + let account_bytes: &[u8; 32] = account_id.as_ref(); + &account_bytes[20..] == &[0xEE; 12] || + >::contains_key(Self::to_address(account_id)) + } +} + +impl AddressMapper for H160Mapper +where + T: Config, + crate::AccountIdOf: AsRef<[u8; 20]> + From, +{ + fn to_address(account_id: &T::AccountId) -> H160 { + H160::from_slice(account_id.as_ref()) + } + + fn to_account_id(address: &H160) -> T::AccountId { + Self::to_fallback_account_id(address) + } + + fn to_fallback_account_id(address: &H160) -> T::AccountId { + (*address).into() + } + + fn map(_account_id: &T::AccountId) -> DispatchResult { + Ok(()) + } + + fn unmap(_account_id: &T::AccountId) -> DispatchResult { + Ok(()) + } + + fn is_mapped(_account_id: &T::AccountId) -> bool { + true } } @@ -102,7 +214,16 @@ pub fn create2(deployer: &H160, code: &[u8], input_data: &[u8], salt: &[u8; 32]) #[cfg(test)] mod test { use super::*; - use crate::test_utils::ALICE_ADDR; + use crate::{ + test_utils::*, + tests::{ExtBuilder, Test}, + AddressMapper, Error, + }; + use frame_support::{ + assert_err, + traits::fungible::{InspectHold, Mutate}, + }; + use pretty_assertions::assert_eq; use sp_core::{hex2array, H160}; #[test] @@ -125,4 +246,123 @@ mod test { H160(hex2array!("7f31e795e5836a19a8f919ab5a9de9a197ecd2b6")), ) } + + #[test] + fn fallback_map_works() { + assert!(::AddressMapper::is_mapped(&ALICE)); + assert_eq!( + ALICE_FALLBACK, + ::AddressMapper::to_fallback_account_id(&ALICE_ADDR) + ); + assert_eq!(ALICE_ADDR, ::AddressMapper::to_address(&ALICE_FALLBACK)); + } + + #[test] + fn map_works() { + ExtBuilder::default().build().execute_with(|| { + ::Currency::set_balance(&EVE, 1_000_000); + // before mapping the fallback account is returned + assert!(!::AddressMapper::is_mapped(&EVE)); + assert_eq!(EVE_FALLBACK, ::AddressMapper::to_account_id(&EVE_ADDR)); + assert_eq!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE + ), + 0 + ); + + // when mapped the full account id is returned + ::AddressMapper::map(&EVE).unwrap(); + assert!(::AddressMapper::is_mapped(&EVE)); + assert_eq!(EVE, ::AddressMapper::to_account_id(&EVE_ADDR)); + assert!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE + ) > 0 + ); + }); + } + + #[test] + fn map_fallback_account_fails() { + ExtBuilder::default().build().execute_with(|| { + assert!(::AddressMapper::is_mapped(&ALICE)); + // alice is an e suffixed account and hence cannot be mapped + assert_err!( + ::AddressMapper::map(&ALICE), + >::AccountAlreadyMapped, + ); + assert_eq!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &ALICE + ), + 0 + ); + }); + } + + #[test] + fn double_map_fails() { + ExtBuilder::default().build().execute_with(|| { + assert!(!::AddressMapper::is_mapped(&EVE)); + ::Currency::set_balance(&EVE, 1_000_000); + ::AddressMapper::map(&EVE).unwrap(); + assert!(::AddressMapper::is_mapped(&EVE)); + let deposit = ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE, + ); + assert_err!( + ::AddressMapper::map(&EVE), + >::AccountAlreadyMapped, + ); + assert!(::AddressMapper::is_mapped(&EVE)); + assert_eq!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE + ), + deposit + ); + }); + } + + #[test] + fn unmap_works() { + ExtBuilder::default().build().execute_with(|| { + ::Currency::set_balance(&EVE, 1_000_000); + ::AddressMapper::map(&EVE).unwrap(); + assert!(::AddressMapper::is_mapped(&EVE)); + assert!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE + ) > 0 + ); + + ::AddressMapper::unmap(&EVE).unwrap(); + assert!(!::AddressMapper::is_mapped(&EVE)); + assert_eq!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE + ), + 0 + ); + + // another unmap is a noop + ::AddressMapper::unmap(&EVE).unwrap(); + assert!(!::AddressMapper::is_mapped(&EVE)); + assert_eq!( + ::Currency::balance_on_hold( + &HoldReason::AddressMapping.into(), + &EVE + ), + 0 + ); + }); + } } diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index ebafb6c7054a..8c9bf2cf70f0 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -63,6 +63,7 @@ const UNBALANCED_TRIE_LAYERS: u32 = 20; struct Contract { caller: T::AccountId, account_id: T::AccountId, + address: H160, } impl Contract @@ -71,11 +72,6 @@ where BalanceOf: Into + TryFrom, MomentOf: Into, { - /// Returns the address of the contract. - fn address(&self) -> H160 { - T::AddressMapper::to_address(&self.account_id) - } - /// Create new contract and use a default account id as instantiator. fn new(module: WasmModule, data: Vec) -> Result, &'static str> { Self::with_index(0, module, data) @@ -98,9 +94,12 @@ where ) -> Result, &'static str> { T::Currency::set_balance(&caller, caller_funding::()); let salt = Some([0xffu8; 32]); + let origin: T::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into(); + + Contracts::::map_account(origin.clone()).unwrap(); let outcome = Contracts::::bare_instantiate( - RawOrigin::Signed(caller.clone()).into(), + origin, 0u32.into(), Weight::MAX, default_deposit_limit::(), @@ -112,8 +111,8 @@ where ); let address = outcome.result?.addr; - let account_id = T::AddressMapper::to_account_id_contract(&address); - let result = Contract { caller, account_id: account_id.clone() }; + let account_id = T::AddressMapper::to_fallback_account_id(&address); + let result = Contract { caller, address, account_id }; ContractInfoOf::::insert(&address, result.info()?); @@ -143,7 +142,7 @@ where info.write(&Key::Fix(item.0), Some(item.1.clone()), None, false) .map_err(|_| "Failed to write storage to restoration dest")?; } - >::insert(T::AddressMapper::to_address(&self.account_id), info); + >::insert(&self.address, info); Ok(()) } @@ -223,6 +222,7 @@ fn default_deposit_limit() -> BalanceOf { T: Config + pallet_balances::Config, MomentOf: Into, ::RuntimeEvent: From>, + ::RuntimeCall: From>, as Currency>::Balance: From>, )] mod benchmarks { @@ -263,13 +263,12 @@ mod benchmarks { let instance = Contract::::with_caller(whitelisted_caller(), WasmModule::sized(c), vec![])?; let value = Pallet::::min_balance(); - let callee = T::AddressMapper::to_address(&instance.account_id); let storage_deposit = default_deposit_limit::(); #[extrinsic_call] call( RawOrigin::Signed(instance.caller.clone()), - callee, + instance.address, value, Weight::MAX, storage_deposit, @@ -293,9 +292,10 @@ mod benchmarks { T::Currency::set_balance(&caller, caller_funding::()); let WasmModule { code, .. } = WasmModule::sized(c); let origin = RawOrigin::Signed(caller.clone()); + Contracts::::map_account(origin.clone().into()).unwrap(); let deployer = T::AddressMapper::to_address(&caller); let addr = crate::address::create2(&deployer, &code, &input, &salt); - let account_id = T::AddressMapper::to_account_id_contract(&addr); + let account_id = T::AddressMapper::to_fallback_account_id(&addr); let storage_deposit = default_deposit_limit::(); #[extrinsic_call] _(origin, value, Weight::MAX, storage_deposit, code, input, Some(salt)); @@ -305,9 +305,14 @@ mod benchmarks { // uploading the code reserves some balance in the callers account let code_deposit = T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &caller); + let mapping_deposit = + T::Currency::balance_on_hold(&HoldReason::AddressMapping.into(), &caller); assert_eq!( T::Currency::balance(&caller), - caller_funding::() - value - deposit - code_deposit - Pallet::::min_balance(), + caller_funding::() - + value - deposit - + code_deposit - mapping_deposit - + Pallet::::min_balance(), ); // contract has the full value assert_eq!(T::Currency::balance(&account_id), value + Pallet::::min_balance()); @@ -323,33 +328,31 @@ mod benchmarks { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); let origin = RawOrigin::Signed(caller.clone()); + Contracts::::map_account(origin.clone().into()).unwrap(); let WasmModule { code, .. } = WasmModule::dummy(); let storage_deposit = default_deposit_limit::(); let deployer = T::AddressMapper::to_address(&caller); let addr = crate::address::create2(&deployer, &code, &input, &salt); - let hash = - Contracts::::bare_upload_code(origin.into(), code, storage_deposit)?.code_hash; - let account_id = T::AddressMapper::to_account_id_contract(&addr); + let hash = Contracts::::bare_upload_code(origin.clone().into(), code, storage_deposit)? + .code_hash; + let account_id = T::AddressMapper::to_fallback_account_id(&addr); #[extrinsic_call] - _( - RawOrigin::Signed(caller.clone()), - value, - Weight::MAX, - storage_deposit, - hash, - input, - Some(salt), - ); + _(origin, value, Weight::MAX, storage_deposit, hash, input, Some(salt)); let deposit = T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account_id); let code_deposit = T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &account_id); + let mapping_deposit = + T::Currency::balance_on_hold(&HoldReason::AddressMapping.into(), &account_id); // value was removed from the caller assert_eq!( T::Currency::total_balance(&caller), - caller_funding::() - value - deposit - code_deposit - Pallet::::min_balance(), + caller_funding::() - + value - deposit - + code_deposit - mapping_deposit - + Pallet::::min_balance(), ); // contract has the full value assert_eq!(T::Currency::balance(&account_id), value + Pallet::::min_balance()); @@ -371,11 +374,10 @@ mod benchmarks { Contract::::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; let value = Pallet::::min_balance(); let origin = RawOrigin::Signed(instance.caller.clone()); - let callee = T::AddressMapper::to_address(&instance.account_id); let before = T::Currency::balance(&instance.account_id); let storage_deposit = default_deposit_limit::(); #[extrinsic_call] - _(origin, callee, value, Weight::MAX, storage_deposit, data); + _(origin, instance.address, value, Weight::MAX, storage_deposit, data); let deposit = T::Currency::balance_on_hold( &HoldReason::StorageDepositReserve.into(), &instance.account_id, @@ -384,10 +386,15 @@ mod benchmarks { &HoldReason::CodeUploadDepositReserve.into(), &instance.caller, ); + let mapping_deposit = + T::Currency::balance_on_hold(&HoldReason::AddressMapping.into(), &instance.caller); // value and value transferred via call should be removed from the caller assert_eq!( T::Currency::balance(&instance.caller), - caller_funding::() - value - deposit - code_deposit - Pallet::::min_balance(), + caller_funding::() - + value - deposit - + code_deposit - mapping_deposit - + Pallet::::min_balance() ); // contract should have received the value assert_eq!(T::Currency::balance(&instance.account_id), before + value); @@ -447,14 +454,46 @@ mod benchmarks { let storage_deposit = default_deposit_limit::(); let hash = >::bare_upload_code(origin.into(), code, storage_deposit)?.code_hash; - let callee = T::AddressMapper::to_address(&instance.account_id); assert_ne!(instance.info()?.code_hash, hash); #[extrinsic_call] - _(RawOrigin::Root, callee, hash); + _(RawOrigin::Root, instance.address, hash); assert_eq!(instance.info()?.code_hash, hash); Ok(()) } + #[benchmark(pov_mode = Measured)] + fn map_account() { + let caller = whitelisted_caller(); + T::Currency::set_balance(&caller, caller_funding::()); + let origin = RawOrigin::Signed(caller.clone()); + assert!(!T::AddressMapper::is_mapped(&caller)); + #[extrinsic_call] + _(origin); + assert!(T::AddressMapper::is_mapped(&caller)); + } + + #[benchmark(pov_mode = Measured)] + fn unmap_account() { + let caller = whitelisted_caller(); + T::Currency::set_balance(&caller, caller_funding::()); + let origin = RawOrigin::Signed(caller.clone()); + >::map_account(origin.clone().into()).unwrap(); + assert!(T::AddressMapper::is_mapped(&caller)); + #[extrinsic_call] + _(origin); + assert!(!T::AddressMapper::is_mapped(&caller)); + } + + #[benchmark(pov_mode = Measured)] + fn dispatch_as_fallback_account() { + let caller = whitelisted_caller(); + T::Currency::set_balance(&caller, caller_funding::()); + let origin = RawOrigin::Signed(caller.clone()); + let dispatchable = frame_system::Call::remark { remark: vec![] }.into(); + #[extrinsic_call] + _(origin, Box::new(dispatchable)); + } + #[benchmark(pov_mode = Measured)] fn noop_host_fn(r: Linear<0, API_BENCHMARK_RUNS>) { let mut setup = CallSetup::::new(WasmModule::noop()); @@ -636,7 +675,7 @@ mod benchmarks { build_runtime!(runtime, contract, memory: [(len as u32).encode(), vec![0u8; len],]); >::insert::<_, BoundedVec<_, _>>( - contract.address(), + contract.address, immutable_data.clone().try_into().unwrap(), ); @@ -669,10 +708,7 @@ mod benchmarks { } assert_ok!(result); - assert_eq!( - &memory[..], - &>::get(setup.contract().address()).unwrap()[..] - ); + assert_eq!(&memory[..], &>::get(setup.contract().address).unwrap()[..]); } #[benchmark(pov_mode = Measured)] @@ -835,7 +871,7 @@ mod benchmarks { assert_eq!( record.event, - crate::Event::ContractEmitted { contract: instance.address(), data, topics }.into(), + crate::Event::ContractEmitted { contract: instance.address, data, topics }.into(), ); } @@ -1542,7 +1578,7 @@ mod benchmarks { let salt = [42u8; 32]; let deployer = T::AddressMapper::to_address(&account_id); let addr = crate::address::create2(&deployer, &code.code, &input, &salt); - let account_id = T::AddressMapper::to_account_id_contract(&addr); + let account_id = T::AddressMapper::to_fallback_account_id(&addr); let mut memory = memory!(hash_bytes, deposit_bytes, value_bytes, input, salt,); let mut offset = { diff --git a/substrate/frame/revive/src/evm/runtime.rs b/substrate/frame/revive/src/evm/runtime.rs index 4c3fdeca720c..80406a49bca2 100644 --- a/substrate/frame/revive/src/evm/runtime.rs +++ b/substrate/frame/revive/src/evm/runtime.rs @@ -290,7 +290,7 @@ pub trait EthExtra { })?; let signer = - ::AddressMapper::to_account_id_contract(&signer); + ::AddressMapper::to_fallback_account_id(&signer); let TransactionLegacyUnsigned { nonce, chain_id, to, value, input, gas, gas_price, .. } = tx.transaction_legacy_unsigned; @@ -419,7 +419,7 @@ mod test { /// Get the [`AccountId`] of the account. pub fn account_id(&self) -> AccountIdOf { let address = self.address(); - ::AddressMapper::to_account_id_contract(&address) + ::AddressMapper::to_fallback_account_id(&address) } /// Get the [`H160`] address of the account. diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 759fba9f1c6a..9f3a75c0090d 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -167,6 +167,18 @@ impl Origin { Origin::Root => Err(DispatchError::RootNotAllowed), } } + + /// Make sure that this origin is mapped. + /// + /// We require an origin to be mapped in order to be used in a `Stack`. Otherwise + /// [`Stack::caller`] returns an address that can't be reverted to the original address. + fn ensure_mapped(&self) -> DispatchResult { + match self { + Self::Root => Ok(()), + Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()), + Self::Signed(_) => Err(>::AccountUnmapped.into()), + } + } } /// An interface that provides access to the external environment in which the @@ -752,7 +764,7 @@ where )? { stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output) } else { - Self::transfer_no_contract(&origin, &dest, value) + Self::transfer_from_origin(&origin, &dest, value) } } @@ -833,6 +845,7 @@ where value: BalanceOf, debug_message: Option<&'a mut DebugBuffer>, ) -> Result, ExecError> { + origin.ensure_mapped()?; let Some((first_frame, executable)) = Self::new_frame( args, value, @@ -925,7 +938,7 @@ where *executable.code_hash(), )?; ( - T::AddressMapper::to_account_id_contract(&address), + T::AddressMapper::to_fallback_account_id(&address), contract, executable, None, @@ -1241,13 +1254,13 @@ where } /// Transfer some funds from `from` to `to`. - fn transfer(from: &T::AccountId, to: &T::AccountId, value: BalanceOf) -> DispatchResult { + fn transfer(from: &T::AccountId, to: &T::AccountId, value: BalanceOf) -> ExecResult { // this avoids events to be emitted for zero balance transfers if !value.is_zero() { T::Currency::transfer(from, to, value, Preservation::Preserve) .map_err(|_| Error::::TransferFailed)?; } - Ok(()) + Ok(Default::default()) } /// Same as `transfer` but `from` is an `Origin`. @@ -1255,28 +1268,17 @@ where from: &Origin, to: &T::AccountId, value: BalanceOf, - ) -> DispatchResult { + ) -> ExecResult { // If the from address is root there is no account to transfer from, and therefore we can't // take any `value` other than 0. let from = match from { Origin::Signed(caller) => caller, - Origin::Root if value.is_zero() => return Ok(()), - Origin::Root => return DispatchError::RootNotAllowed.into(), + Origin::Root if value.is_zero() => return Ok(Default::default()), + Origin::Root => return Err(DispatchError::RootNotAllowed.into()), }; Self::transfer(from, to, value) } - /// Same as `transfer_from_origin` but creates an `ExecReturnValue` on success. - fn transfer_no_contract( - from: &Origin, - to: &T::AccountId, - value: BalanceOf, - ) -> ExecResult { - Self::transfer_from_origin(from, to, value) - .map(|_| ExecReturnValue::default()) - .map_err(Into::into) - } - /// Reference to the current (top) frame. fn top_frame(&self) -> &Frame { top_frame!(self) @@ -1379,12 +1381,7 @@ where )? { self.run(executable, input_data) } else { - Self::transfer_no_contract( - &Origin::from_account_id(self.account_id().clone()), - &dest, - value, - )?; - Ok(()) + Self::transfer(&self.account_id(), &dest, value).map(|_| ()) } }; @@ -1488,6 +1485,8 @@ where &T::AddressMapper::to_account_id(to), value.try_into().map_err(|_| Error::::BalanceConversionFailed)?, ) + .map(|_| ()) + .map_err(|error| error.error) } fn get_storage(&mut self, key: &Key) -> Option> { @@ -2031,7 +2030,7 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, success_ch); set_balance(&ALICE, 100); - let balance = get_balance(&BOB_CONTRACT_ID); + let balance = get_balance(&BOB_FALLBACK); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 0, value).unwrap(); @@ -2047,7 +2046,7 @@ mod tests { .unwrap(); assert_eq!(get_balance(&ALICE), 100 - value); - assert_eq!(get_balance(&BOB_CONTRACT_ID), balance + value); + assert_eq!(get_balance(&BOB_FALLBACK), balance + value); }); } @@ -2069,7 +2068,7 @@ mod tests { ExtBuilder::default().build().execute_with(|| { place_contract(&BOB, delegate_ch); set_balance(&ALICE, 100); - let balance = get_balance(&BOB_CONTRACT_ID); + let balance = get_balance(&BOB_FALLBACK); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 0, 55).unwrap(); @@ -2085,7 +2084,7 @@ mod tests { .unwrap(); assert_eq!(get_balance(&ALICE), 100 - value); - assert_eq!(get_balance(&BOB_CONTRACT_ID), balance + value); + assert_eq!(get_balance(&BOB_FALLBACK), balance + value); }); } @@ -2326,9 +2325,10 @@ mod tests { // Record the caller for bob. WitnessedCallerBob::mutate(|caller| { let origin = ctx.ext.caller(); - *caller = Some(::AddressMapper::to_address( - &origin.account_id().unwrap(), - )); + *caller = + Some(<::AddressMapper as AddressMapper>::to_address( + &origin.account_id().unwrap(), + )); }); // Call into CHARLIE contract. @@ -2350,9 +2350,10 @@ mod tests { // Record the caller for charlie. WitnessedCallerCharlie::mutate(|caller| { let origin = ctx.ext.caller(); - *caller = Some(::AddressMapper::to_address( - &origin.account_id().unwrap(), - )); + *caller = + Some(<::AddressMapper as AddressMapper>::to_address( + &origin.account_id().unwrap(), + )); }); exec_success() }); @@ -2716,10 +2717,11 @@ mod tests { ), Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address ); - let instantiated_contract_id = - ::AddressMapper::to_account_id_contract( - &instantiated_contract_address, - ); + let instantiated_contract_id = <::AddressMapper as AddressMapper< + Test, + >>::to_fallback_account_id( + &instantiated_contract_address + ); // Check that the newly created account has the expected code hash and // there are instantiation event. @@ -2771,10 +2773,11 @@ mod tests { Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address ); - let instantiated_contract_id = - ::AddressMapper::to_account_id_contract( - &instantiated_contract_address, - ); + let instantiated_contract_id = <::AddressMapper as AddressMapper< + Test, + >>::to_fallback_account_id( + &instantiated_contract_address + ); // Check that the account has not been created. assert!(ContractInfo::::load_code_hash(&instantiated_contract_id).is_none()); @@ -2837,10 +2840,11 @@ mod tests { let instantiated_contract_address = *instantiated_contract_address.borrow().as_ref().unwrap(); - let instantiated_contract_id = - ::AddressMapper::to_account_id_contract( - &instantiated_contract_address, - ); + let instantiated_contract_id = <::AddressMapper as AddressMapper< + Test, + >>::to_fallback_account_id( + &instantiated_contract_address + ); // Check that the newly created account has the expected code hash and // there are instantiation event. @@ -2895,7 +2899,7 @@ mod tests { .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB_CONTRACT_ID, 100); + set_balance(&BOB_FALLBACK, 100); place_contract(&BOB, instantiator_ch); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); @@ -3025,7 +3029,8 @@ mod tests { fn recursive_call_during_constructor_is_balance_transfer() { let code = MockLoader::insert(Constructor, |ctx, _| { let account_id = ctx.ext.account_id().clone(); - let addr = ::AddressMapper::to_address(&account_id); + let addr = + <::AddressMapper as AddressMapper>::to_address(&account_id); let balance = ctx.ext.balance(); // Calling ourselves during the constructor will trigger a balance @@ -3086,7 +3091,8 @@ mod tests { fn cannot_send_more_balance_than_available_to_self() { let code_hash = MockLoader::insert(Call, |ctx, _| { let account_id = ctx.ext.account_id().clone(); - let addr = ::AddressMapper::to_address(&account_id); + let addr = + <::AddressMapper as AddressMapper>::to_address(&account_id); let balance = ctx.ext.balance(); assert_err!( @@ -3358,7 +3364,7 @@ mod tests { EventRecord { phase: Phase::Initialization, event: MetaEvent::System(frame_system::Event::Remarked { - sender: BOB_CONTRACT_ID, + sender: BOB_FALLBACK, hash: remark_hash }), topics: vec![], @@ -3442,7 +3448,7 @@ mod tests { EventRecord { phase: Phase::Initialization, event: MetaEvent::System(frame_system::Event::Remarked { - sender: BOB_CONTRACT_ID, + sender: BOB_FALLBACK, hash: remark_hash }), topics: vec![], @@ -3506,7 +3512,10 @@ mod tests { ) .unwrap(); - let account_id = ::AddressMapper::to_account_id_contract(&addr); + let account_id = + <::AddressMapper as AddressMapper>::to_fallback_account_id( + &addr, + ); assert_eq!(System::account_nonce(&ALICE), alice_nonce); assert_eq!(System::account_nonce(ctx.ext.account_id()), 1); @@ -4299,7 +4308,7 @@ mod tests { .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB_CONTRACT_ID, 100); + set_balance(&BOB, 100); place_contract(&BOB, instantiator_ch); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); @@ -4484,7 +4493,7 @@ mod tests { .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB_CONTRACT_ID, 100); + set_balance(&BOB, 100); place_contract(&BOB, instantiator_ch); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); @@ -4601,7 +4610,7 @@ mod tests { .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB_CONTRACT_ID, 100); + set_balance(&BOB, 100); place_contract(&BOB, instantiator_ch); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); @@ -4645,7 +4654,7 @@ mod tests { .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB_CONTRACT_ID, 100); + set_balance(&BOB, 100); place_contract(&BOB, instantiator_ch); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 11752e47cf2a..1967f9868d2b 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -48,6 +48,7 @@ use crate::{ storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager}, wasm::{CodeInfo, RuntimeCosts, WasmBlob}, }; +use alloc::boxed::Box; use codec::{Codec, Decode, Encode}; use environmental::*; use frame_support::{ @@ -78,7 +79,7 @@ use sp_runtime::{ }; pub use crate::{ - address::{create1, create2, AddressMapper, DefaultAddressMapper}, + address::{create1, create2, AccountId32Mapper, AddressMapper}, debug::Tracing, exec::MomentOf, pallet::*, @@ -160,11 +161,9 @@ pub mod pallet { /// The overarching call type. #[pallet::no_default_bounds] - type RuntimeCall: Dispatchable - + GetDispatchInfo - + codec::Decode - + core::fmt::Debug - + IsType<::RuntimeCall>; + type RuntimeCall: Parameter + + Dispatchable + + GetDispatchInfo; /// Overarching hold reason. #[pallet::no_default_bounds] @@ -233,9 +232,9 @@ pub mod pallet { #[pallet::constant] type CodeHashLockupDepositPercent: Get; - /// Only valid type is [`DefaultAddressMapper`]. - #[pallet::no_default_bounds] - type AddressMapper: AddressMapper>; + /// Use either valid type is [`address::AccountId32Mapper`] or [`address::H160Mapper`]. + #[pallet::no_default] + type AddressMapper: AddressMapper; /// Make contract callable functions marked as `#[unstable]` available. /// @@ -361,7 +360,6 @@ pub mod pallet { #[inject_runtime_type] type RuntimeCall = (); - type AddressMapper = DefaultAddressMapper; type CallFilter = (); type ChainExtension = (); type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; @@ -562,6 +560,12 @@ pub mod pallet { /// Immutable data can only be set during deploys and only be read during calls. /// Additionally, it is only valid to set the data once and it must not be empty. InvalidImmutableAccess, + /// An `AccountID32` account tried to interact with the pallet without having a mapping. + /// + /// Call [`Pallet::map_account`] in order to create a mapping for the account. + AccountUnmapped, + /// Tried to map an account that is already mapped. + AccountAlreadyMapped, } /// A reason for the pallet contracts placing a hold on funds. @@ -571,6 +575,8 @@ pub mod pallet { CodeUploadDepositReserve, /// The Pallet has reserved it for storage deposit. StorageDepositReserve, + /// Deposit for creating an address mapping in [`AddressSuffix`]. + AddressMapping, } /// A mapping from a contract's code hash to its code. @@ -602,6 +608,14 @@ pub mod pallet { pub(crate) type DeletionQueueCounter = StorageValue<_, DeletionQueueManager, ValueQuery>; + /// Map a Ethereum address to its original `AccountId32`. + /// + /// Stores the last 12 byte for addresses that were originally an `AccountId32` instead + /// of an `H160`. Register your `AccountId32` using [`Pallet::map_account`] in order to + /// use it with this pallet. + #[pallet::storage] + pub(crate) type AddressSuffix = StorageMap<_, Identity, H160, [u8; 12]>; + #[pallet::extra_constants] impl Pallet { #[pallet::constant_name(ApiVersion)] @@ -995,6 +1009,51 @@ pub mod pallet { Ok(()) }) } + + /// Register the callers account id so that it can be used in contract interactions. + /// + /// This will error if the origin is already mapped or is a eth native `Address20`. It will + /// take a deposit that can be released by calling [`Self::unmap_account`]. + #[pallet::call_index(7)] + #[pallet::weight(T::WeightInfo::map_account())] + pub fn map_account(origin: OriginFor) -> DispatchResult { + let origin = ensure_signed(origin)?; + T::AddressMapper::map(&origin) + } + + /// Unregister the callers account id in order to free the deposit. + /// + /// There is no reason to ever call this function other than freeing up the deposit. + /// This is only useful when the account should no longer be used. + #[pallet::call_index(8)] + #[pallet::weight(T::WeightInfo::unmap_account())] + pub fn unmap_account(origin: OriginFor) -> DispatchResult { + let origin = ensure_signed(origin)?; + T::AddressMapper::unmap(&origin) + } + + /// Dispatch an `call` with the origin set to the callers fallback address. + /// + /// Every `AccountId32` can control its corresponding fallback account. The fallback account + /// is the `AccountId20` with the last 12 bytes set to `0xEE`. This is essentially a + /// recovery function in case an `AccountId20` was used without creating a mapping first. + #[pallet::call_index(9)] + #[pallet::weight({ + let dispatch_info = call.get_dispatch_info(); + ( + T::WeightInfo::dispatch_as_fallback_account().saturating_add(dispatch_info.call_weight), + dispatch_info.class + ) + })] + pub fn dispatch_as_fallback_account( + origin: OriginFor, + call: Box<::RuntimeCall>, + ) -> DispatchResultWithPostInfo { + let origin = ensure_signed(origin)?; + let unmapped_account = + T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin)); + call.dispatch(RawOrigin::Signed(unmapped_account).into()) + } } } diff --git a/substrate/frame/revive/src/test_utils.rs b/substrate/frame/revive/src/test_utils.rs index 92c21297a3ec..acd9a4cda38a 100644 --- a/substrate/frame/revive/src/test_utils.rs +++ b/substrate/frame/revive/src/test_utils.rs @@ -27,38 +27,35 @@ use frame_support::weights::Weight; use sp_core::H160; pub use sp_runtime::AccountId32; -const fn ee_suffix(addr: H160) -> AccountId32 { - let mut id = [0u8; 32]; - let mut i = 0; - while i < 20 { - id[i] = addr.0[i]; +const fn ee_suffix(mut account: [u8; 32]) -> AccountId32 { + let mut i = 20; + while i < 32 { + account[i] = 0xee; i += 1; } - - let mut j = 20; - while j < 32 { - id[j] = 0xee; - j += 1; - } - - AccountId32::new(id) + AccountId32::new(account) } -pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); +pub const ALICE: AccountId32 = ee_suffix([1u8; 32]); pub const ALICE_ADDR: H160 = H160([1u8; 20]); -pub const ETH_ALICE: AccountId32 = ee_suffix(ALICE_ADDR); +pub const ALICE_FALLBACK: AccountId32 = ee_suffix([1u8; 32]); -pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); +pub const BOB: AccountId32 = ee_suffix([2u8; 32]); pub const BOB_ADDR: H160 = H160([2u8; 20]); -pub const BOB_CONTRACT_ID: AccountId32 = ee_suffix(BOB_ADDR); +pub const BOB_FALLBACK: AccountId32 = ee_suffix([2u8; 32]); -pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]); +pub const CHARLIE: AccountId32 = ee_suffix([3u8; 32]); pub const CHARLIE_ADDR: H160 = H160([3u8; 20]); -pub const CHARLIE_CONTRACT_ID: AccountId32 = ee_suffix(CHARLIE_ADDR); +pub const CHARLIE_FALLBACK: AccountId32 = ee_suffix([3u8; 32]); -pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]); +pub const DJANGO: AccountId32 = ee_suffix([4u8; 32]); pub const DJANGO_ADDR: H160 = H160([4u8; 20]); -pub const ETH_DJANGO: AccountId32 = ee_suffix(DJANGO_ADDR); +pub const DJANGO_FALLBACK: AccountId32 = ee_suffix([4u8; 32]); + +/// Eve is a non ee account and hence needs a stateful mapping. +pub const EVE: AccountId32 = AccountId32::new([5u8; 32]); +pub const EVE_ADDR: H160 = H160([5u8; 20]); +pub const EVE_FALLBACK: AccountId32 = ee_suffix([5u8; 32]); pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 94af7dbd04d8..1b5e64739d88 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -39,9 +39,9 @@ use crate::{ tests::test_utils::{get_contract, get_contract_checked}, wasm::Memory, weights::WeightInfo, - BalanceOf, Code, CodeInfoOf, CollectEvents, Config, ContractInfo, ContractInfoOf, DebugInfo, - DefaultAddressMapper, DeletionQueueCounter, Error, HoldReason, Origin, Pallet, PristineCode, - H160, + AccountId32Mapper, BalanceOf, Code, CodeInfoOf, CollectEvents, Config, ContractInfo, + ContractInfoOf, DebugInfo, DeletionQueueCounter, Error, HoldReason, Origin, Pallet, + PristineCode, H160, }; use crate::test_utils::builder::Contract; @@ -114,7 +114,8 @@ pub mod test_utils { pub fn place_contract(address: &AccountIdOf, code_hash: sp_core::H256) { set_balance(address, Contracts::min_balance() * 10); >::insert(code_hash, CodeInfo::new(address.clone())); - let address = ::AddressMapper::to_address(&address); + let address = + <::AddressMapper as AddressMapper>::to_address(&address); let contract = >::new(&address, 0, code_hash).unwrap(); >::insert(address, contract); } @@ -508,13 +509,13 @@ parameter_types! { #[derive_impl(crate::config_preludes::TestDefaultConfig)] impl Config for Test { type Time = Timestamp; + type AddressMapper = AccountId32Mapper; type Currency = Balances; type CallFilter = TestFilter; type ChainExtension = (TestExtension, DisabledExtension, RevertingExtension, TempStorageExtension); type DepositPerByte = DepositPerByte; type DepositPerItem = DepositPerItem; - type AddressMapper = DefaultAddressMapper; type UnsafeUnstableInterface = UnstableInterface; type UploadOrigin = EnsureAccount; type InstantiateOrigin = EnsureAccount; @@ -635,9 +636,9 @@ mod run_tests { ExtBuilder::default().build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 100_000_000); assert!(!>::contains_key(BOB_ADDR)); - assert_eq!(test_utils::get_balance(&BOB_CONTRACT_ID), 0); + assert_eq!(test_utils::get_balance(&BOB_FALLBACK), 0); let result = builder::bare_call(BOB_ADDR).value(42).build_and_unwrap_result(); - assert_eq!(test_utils::get_balance(&BOB_CONTRACT_ID), 42); + assert_eq!(test_utils::get_balance(&BOB_FALLBACK), 42); assert_eq!(result, Default::default()); }); } @@ -1302,7 +1303,7 @@ mod run_tests { let (wasm, code_hash) = compile_module("self_destruct").unwrap(); ExtBuilder::default().existential_deposit(1_000).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); - let _ = ::Currency::set_balance(Ð_DJANGO, 1_000_000); + let _ = ::Currency::set_balance(&DJANGO_FALLBACK, 1_000_000); let min_balance = Contracts::min_balance(); // Instantiate the BOB contract. @@ -1330,7 +1331,7 @@ mod run_tests { // Check that the beneficiary (django) got remaining balance. assert_eq!( - ::Currency::free_balance(ETH_DJANGO), + ::Currency::free_balance(DJANGO_FALLBACK), 1_000_000 + 100_000 + min_balance ); @@ -1382,7 +1383,7 @@ mod run_tests { phase: Phase::Initialization, event: RuntimeEvent::Balances(pallet_balances::Event::Transfer { from: contract.account_id.clone(), - to: ETH_DJANGO, + to: DJANGO_FALLBACK, amount: 100_000 + min_balance, }), topics: vec![], @@ -1545,7 +1546,7 @@ mod run_tests { // Sending at least the minimum balance should result in success but // no code called. - assert_eq!(test_utils::get_balance(Ð_DJANGO), 0); + assert_eq!(test_utils::get_balance(&DJANGO_FALLBACK), 0); let result = builder::bare_call(bob.addr) .data( AsRef::<[u8]>::as_ref(&DJANGO_ADDR) @@ -1556,7 +1557,7 @@ mod run_tests { ) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::Success); - assert_eq!(test_utils::get_balance(Ð_DJANGO), 55); + assert_eq!(test_utils::get_balance(&DJANGO_FALLBACK), 55); let django = builder::bare_instantiate(Code::Upload(callee_code)) .origin(RuntimeOrigin::signed(CHARLIE)) @@ -3732,7 +3733,7 @@ mod run_tests { // Instantiate the caller contract with the given input. let instantiate = |input: &(u32, H256)| { builder::bare_instantiate(Code::Upload(wasm_caller.clone())) - .origin(RuntimeOrigin::signed(ETH_ALICE)) + .origin(RuntimeOrigin::signed(ALICE_FALLBACK)) .data(input.encode()) .build() }; @@ -3740,13 +3741,13 @@ mod run_tests { // Call contract with the given input. let call = |addr_caller: &H160, input: &(u32, H256)| { builder::bare_call(*addr_caller) - .origin(RuntimeOrigin::signed(ETH_ALICE)) + .origin(RuntimeOrigin::signed(ALICE_FALLBACK)) .data(input.encode()) .build() }; const ED: u64 = 2000; ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let _ = Balances::set_balance(Ð_ALICE, 1_000_000); + let _ = Balances::set_balance(&ALICE_FALLBACK, 1_000_000); // Instantiate with lock_delegate_dependency should fail since the code is not yet on // chain. @@ -3760,7 +3761,7 @@ mod run_tests { for code in callee_codes.iter() { let CodeUploadReturnValue { deposit: deposit_per_code, .. } = Contracts::bare_upload_code( - RuntimeOrigin::signed(ETH_ALICE), + RuntimeOrigin::signed(ALICE_FALLBACK), code.clone(), deposit_limit::(), ) @@ -3790,7 +3791,7 @@ mod run_tests { // Removing the code should fail, since we have added a dependency. assert_err!( - Contracts::remove_code(RuntimeOrigin::signed(ETH_ALICE), callee_hashes[0]), + Contracts::remove_code(RuntimeOrigin::signed(ALICE_FALLBACK), callee_hashes[0]), >::CodeInUse ); @@ -3848,14 +3849,17 @@ mod run_tests { ); // Since we unlocked the dependency we should now be able to remove the code. - assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ETH_ALICE), callee_hashes[0])); + assert_ok!(Contracts::remove_code( + RuntimeOrigin::signed(ALICE_FALLBACK), + callee_hashes[0] + )); // Calling should fail since the delegated contract is not on chain anymore. assert_err!(call(&addr_caller, &noop_input).result, Error::::ContractTrapped); // Add the dependency back. Contracts::upload_code( - RuntimeOrigin::signed(ETH_ALICE), + RuntimeOrigin::signed(ALICE_FALLBACK), callee_codes[0].clone(), deposit_limit::(), ) @@ -3863,15 +3867,18 @@ mod run_tests { call(&addr_caller, &lock_delegate_dependency_input).result.unwrap(); // Call terminate should work, and return the deposit. - let balance_before = test_utils::get_balance(Ð_ALICE); + let balance_before = test_utils::get_balance(&ALICE_FALLBACK); assert_ok!(call(&addr_caller, &terminate_input).result); assert_eq!( - test_utils::get_balance(Ð_ALICE), + test_utils::get_balance(&ALICE_FALLBACK), ED + balance_before + contract.storage_base_deposit() + dependency_deposit ); // Terminate should also remove the dependency, so we can remove the code. - assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ETH_ALICE), callee_hashes[0])); + assert_ok!(Contracts::remove_code( + RuntimeOrigin::signed(ALICE_FALLBACK), + callee_hashes[0] + )); }); } @@ -4109,13 +4116,13 @@ mod run_tests { let (wasm, _code_hash) = compile_module("balance_of").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = Balances::set_balance(&ALICE, 1_000_000); - let _ = Balances::set_balance(Ð_ALICE, 1_000_000); + let _ = Balances::set_balance(&ALICE_FALLBACK, 1_000_000); let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(wasm.to_vec())).build_and_unwrap_contract(); // The fixture asserts a non-zero returned free balance of the account; - // The ETH_ALICE account is endowed; + // The ALICE_FALLBACK account is endowed; // Hence we should not revert assert_ok!(builder::call(addr).data(ALICE_ADDR.0.to_vec()).build()); @@ -4510,4 +4517,64 @@ mod run_tests { .build()); }); } + + #[test] + fn origin_must_be_mapped() { + let (code, hash) = compile_module("dummy").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + ::Currency::set_balance(&ALICE, 1_000_000); + ::Currency::set_balance(&EVE, 1_000_000); + + let eve = RuntimeOrigin::signed(EVE); + + // alice can instantiate as she doesn't need a mapping + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + // without a mapping eve can neither call nor instantiate + assert_err!( + builder::bare_call(addr).origin(eve.clone()).build().result, + >::AccountUnmapped + ); + assert_err!( + builder::bare_instantiate(Code::Existing(hash)) + .origin(eve.clone()) + .build() + .result, + >::AccountUnmapped + ); + + // after mapping eve is usable as an origin + >::map_account(eve.clone()).unwrap(); + assert_ok!(builder::bare_call(addr).origin(eve.clone()).build().result); + assert_ok!(builder::bare_instantiate(Code::Existing(hash)).origin(eve).build().result); + }); + } + + #[test] + fn mapped_address_works() { + let (code, _) = compile_module("terminate_and_send_to_eve").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + ::Currency::set_balance(&ALICE, 1_000_000); + + // without a mapping everything will be send to the fallback account + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code.clone())).build_and_unwrap_contract(); + assert_eq!(::Currency::total_balance(&EVE_FALLBACK), 0); + builder::bare_call(addr).build_and_unwrap_result(); + assert_eq!(::Currency::total_balance(&EVE_FALLBACK), 100); + + // after mapping it will be sent to the real eve account + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + // need some balance to pay for the map deposit + ::Currency::set_balance(&EVE, 1_000); + >::map_account(RuntimeOrigin::signed(EVE)).unwrap(); + builder::bare_call(addr).build_and_unwrap_result(); + assert_eq!(::Currency::total_balance(&EVE_FALLBACK), 100); + assert_eq!(::Currency::total_balance(&EVE), 1_100); + }); + } } diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 9a1b2310b4eb..3203a0cba9fb 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -18,9 +18,9 @@ //! Autogenerated weights for `pallet_revive` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-10-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-10-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-jniz7bxx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-dr4vwrkf-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: @@ -58,6 +58,9 @@ pub trait WeightInfo { fn upload_code(c: u32, ) -> Weight; fn remove_code() -> Weight; fn set_code() -> Weight; + fn map_account() -> Weight; + fn unmap_account() -> Weight; + fn dispatch_as_fallback_account() -> Weight; fn noop_host_fn(r: u32, ) -> Weight; fn seal_caller() -> Weight; fn seal_is_contract() -> Weight; @@ -126,8 +129,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 2_712_000 picoseconds. - Weight::from_parts(2_882_000, 1594) + // Minimum execution time: 3_053_000 picoseconds. + Weight::from_parts(3_150_000, 1594) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -135,18 +138,20 @@ impl WeightInfo for SubstrateWeight { /// The range of component `k` is `[0, 1024]`. fn on_initialize_per_trie_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `392 + k * (69 ±0)` - // Estimated: `382 + k * (70 ±0)` - // Minimum execution time: 13_394_000 picoseconds. - Weight::from_parts(13_668_000, 382) - // Standard Error: 2_208 - .saturating_add(Weight::from_parts(1_340_842, 0).saturating_mul(k.into())) + // Measured: `425 + k * (69 ±0)` + // Estimated: `415 + k * (70 ±0)` + // Minimum execution time: 15_219_000 picoseconds. + Weight::from_parts(12_576_960, 415) + // Standard Error: 1_429 + .saturating_add(Weight::from_parts(1_341_896, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) .saturating_add(Weight::from_parts(0, 70).saturating_mul(k.into())) } + /// Storage: `Revive::AddressSuffix` (r:2 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) @@ -158,21 +163,21 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. - fn call_with_code_per_byte(c: u32, ) -> Weight { + fn call_with_code_per_byte(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1466` - // Estimated: `4931` - // Minimum execution time: 80_390_000 picoseconds. - Weight::from_parts(83_627_295, 4931) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `1519` + // Estimated: `7459` + // Minimum execution time: 88_906_000 picoseconds. + Weight::from_parts(93_353_224, 7459) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) @@ -185,19 +190,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 262144]`. fn instantiate_with_code(_c: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `303` - // Estimated: `6232` - // Minimum execution time: 184_708_000 picoseconds. - Weight::from_parts(177_995_416, 6232) - // Standard Error: 11 - .saturating_add(Weight::from_parts(4_609, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Measured: `416` + // Estimated: `6360` + // Minimum execution time: 202_688_000 picoseconds. + Weight::from_parts(197_366_807, 6360) + // Standard Error: 13 + .saturating_add(Weight::from_parts(4_261, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) @@ -205,19 +212,21 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) /// The range of component `i` is `[0, 262144]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1261` - // Estimated: `4706` - // Minimum execution time: 150_137_000 picoseconds. - Weight::from_parts(136_548_469, 4706) + // Measured: `1313` + // Estimated: `4779` + // Minimum execution time: 169_246_000 picoseconds. + Weight::from_parts(149_480_457, 4779) // Standard Error: 16 - .saturating_add(Weight::from_parts(4_531, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(Weight::from_parts(4_041, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } + /// Storage: `Revive::AddressSuffix` (r:2 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) @@ -230,17 +239,17 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1466` - // Estimated: `4931` - // Minimum execution time: 83_178_000 picoseconds. - Weight::from_parts(84_633_000, 4931) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `1519` + // Estimated: `7459` + // Minimum execution time: 91_129_000 picoseconds. + Weight::from_parts(94_220_000, 7459) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. @@ -248,23 +257,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3574` - // Minimum execution time: 51_526_000 picoseconds. - Weight::from_parts(54_565_973, 3574) + // Minimum execution time: 54_849_000 picoseconds. + Weight::from_parts(57_508_591, 3574) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: // Measured: `285` // Estimated: `3750` - // Minimum execution time: 41_885_000 picoseconds. - Weight::from_parts(42_467_000, 3750) + // Minimum execution time: 45_017_000 picoseconds. + Weight::from_parts(46_312_000, 3750) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -274,113 +283,153 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `492` - // Estimated: `6432` - // Minimum execution time: 24_905_000 picoseconds. - Weight::from_parts(25_483_000, 6432) + // Measured: `529` + // Estimated: `6469` + // Minimum execution time: 26_992_000 picoseconds. + Weight::from_parts(28_781_000, 6469) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } + /// Storage: `Revive::AddressSuffix` (r:1 w:1) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + fn map_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `3574` + // Minimum execution time: 44_031_000 picoseconds. + Weight::from_parts(45_133_000, 3574) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Storage: `Revive::AddressSuffix` (r:0 w:1) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) + fn unmap_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `56` + // Estimated: `3521` + // Minimum execution time: 35_681_000 picoseconds. + Weight::from_parts(36_331_000, 3521) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `Measured`) + fn dispatch_as_fallback_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 11_550_000 picoseconds. + Weight::from_parts(12_114_000, 3610) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } /// The range of component `r` is `[0, 1600]`. fn noop_host_fn(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_979_000 picoseconds. - Weight::from_parts(8_272_348, 0) - // Standard Error: 137 - .saturating_add(Weight::from_parts(172_489, 0).saturating_mul(r.into())) + // Minimum execution time: 7_063_000 picoseconds. + Weight::from_parts(7_671_454, 0) + // Standard Error: 105 + .saturating_add(Weight::from_parts(175_349, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 251_000 picoseconds. - Weight::from_parts(318_000, 0) + // Minimum execution time: 266_000 picoseconds. + Weight::from_parts(313_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) fn seal_is_contract() -> Weight { // Proof Size summary in bytes: - // Measured: `272` - // Estimated: `3737` - // Minimum execution time: 6_966_000 picoseconds. - Weight::from_parts(7_240_000, 3737) + // Measured: `306` + // Estimated: `3771` + // Minimum execution time: 7_397_000 picoseconds. + Weight::from_parts(7_967_000, 3771) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `369` - // Estimated: `3834` - // Minimum execution time: 7_589_000 picoseconds. - Weight::from_parts(7_958_000, 3834) + // Measured: `403` + // Estimated: `3868` + // Minimum execution time: 8_395_000 picoseconds. + Weight::from_parts(8_863_000, 3868) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 235_000 picoseconds. - Weight::from_parts(285_000, 0) + // Minimum execution time: 265_000 picoseconds. + Weight::from_parts(292_000, 0) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 283_000 picoseconds. - Weight::from_parts(326_000, 0) + // Minimum execution time: 298_000 picoseconds. + Weight::from_parts(334_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 266_000 picoseconds. - Weight::from_parts(298_000, 0) + // Minimum execution time: 262_000 picoseconds. + Weight::from_parts(274_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 240_000 picoseconds. - Weight::from_parts(290_000, 0) + // Minimum execution time: 277_000 picoseconds. + Weight::from_parts(297_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 651_000 picoseconds. - Weight::from_parts(714_000, 0) + // Minimum execution time: 620_000 picoseconds. + Weight::from_parts(706_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `103` + // Measured: `140` // Estimated: `0` - // Minimum execution time: 4_476_000 picoseconds. - Weight::from_parts(4_671_000, 0) + // Minimum execution time: 5_475_000 picoseconds. + Weight::from_parts(5_706_000, 0) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn seal_balance_of() -> Weight { // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3517` - // Minimum execution time: 3_800_000 picoseconds. - Weight::from_parts(3_968_000, 3517) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Measured: `264` + // Estimated: `3729` + // Minimum execution time: 9_141_000 picoseconds. + Weight::from_parts(9_674_000, 3729) + .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) /// The range of component `n` is `[1, 4096]`. fn seal_get_immutable_data(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `205 + n * (1 ±0)` - // Estimated: `3670 + n * (1 ±0)` - // Minimum execution time: 5_845_000 picoseconds. - Weight::from_parts(6_473_478, 3670) - // Standard Error: 4 - .saturating_add(Weight::from_parts(651, 0).saturating_mul(n.into())) + // Measured: `238 + n * (1 ±0)` + // Estimated: `3703 + n * (1 ±0)` + // Minimum execution time: 6_443_000 picoseconds. + Weight::from_parts(7_252_595, 3703) + // Standard Error: 12 + .saturating_add(Weight::from_parts(915, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -391,39 +440,39 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_980_000 picoseconds. - Weight::from_parts(2_324_567, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(512, 0).saturating_mul(n.into())) + // Minimum execution time: 2_745_000 picoseconds. + Weight::from_parts(3_121_250, 0) + // Standard Error: 4 + .saturating_add(Weight::from_parts(627, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 259_000 picoseconds. - Weight::from_parts(285_000, 0) + // Minimum execution time: 255_000 picoseconds. + Weight::from_parts(274_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 244_000 picoseconds. - Weight::from_parts(291_000, 0) + // Minimum execution time: 235_000 picoseconds. + Weight::from_parts(261_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 252_000 picoseconds. - Weight::from_parts(291_000, 0) + // Minimum execution time: 249_000 picoseconds. + Weight::from_parts(263_000, 0) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 245_000 picoseconds. - Weight::from_parts(277_000, 0) + // Minimum execution time: 287_000 picoseconds. + Weight::from_parts(300_000, 0) } /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) @@ -431,8 +480,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `67` // Estimated: `1552` - // Minimum execution time: 5_650_000 picoseconds. - Weight::from_parts(5_783_000, 1552) + // Minimum execution time: 6_147_000 picoseconds. + Weight::from_parts(6_562_000, 1552) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// The range of component `n` is `[0, 262140]`. @@ -440,21 +489,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 427_000 picoseconds. - Weight::from_parts(351_577, 0) + // Minimum execution time: 453_000 picoseconds. + Weight::from_parts(548_774, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(114, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(147, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262140]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 265_000 picoseconds. - Weight::from_parts(746_316, 0) + // Minimum execution time: 264_000 picoseconds. + Weight::from_parts(490_374, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(236, 0).saturating_mul(n.into())) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:33 w:33) @@ -466,13 +517,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 32]`. fn seal_terminate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `272 + n * (88 ±0)` - // Estimated: `3737 + n * (2563 ±0)` - // Minimum execution time: 15_988_000 picoseconds. - Weight::from_parts(18_796_705, 3737) - // Standard Error: 10_437 - .saturating_add(Weight::from_parts(4_338_085, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `323 + n * (88 ±0)` + // Estimated: `3788 + n * (2563 ±0)` + // Minimum execution time: 22_833_000 picoseconds. + Weight::from_parts(24_805_620, 3788) + // Standard Error: 9_498 + .saturating_add(Weight::from_parts(4_486_714, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -484,22 +535,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_237_000 picoseconds. - Weight::from_parts(4_128_112, 0) - // Standard Error: 2_947 - .saturating_add(Weight::from_parts(198_825, 0).saturating_mul(t.into())) - // Standard Error: 26 - .saturating_add(Weight::from_parts(1_007, 0).saturating_mul(n.into())) + // Minimum execution time: 4_969_000 picoseconds. + Weight::from_parts(4_994_916, 0) + // Standard Error: 3_727 + .saturating_add(Weight::from_parts(188_374, 0).saturating_mul(t.into())) + // Standard Error: 33 + .saturating_add(Weight::from_parts(925, 0).saturating_mul(n.into())) } /// The range of component `i` is `[0, 262144]`. fn seal_debug_message(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 292_000 picoseconds. - Weight::from_parts(1_297_376, 0) + // Minimum execution time: 328_000 picoseconds. + Weight::from_parts(928_905, 0) // Standard Error: 1 - .saturating_add(Weight::from_parts(724, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(753, 0).saturating_mul(i.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -507,8 +558,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 7_812_000 picoseconds. - Weight::from_parts(8_171_000, 744) + // Minimum execution time: 8_612_000 picoseconds. + Weight::from_parts(9_326_000, 744) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -517,8 +568,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 44_179_000 picoseconds. - Weight::from_parts(45_068_000, 10754) + // Minimum execution time: 44_542_000 picoseconds. + Weight::from_parts(45_397_000, 10754) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -527,8 +578,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 8_964_000 picoseconds. - Weight::from_parts(9_336_000, 744) + // Minimum execution time: 10_343_000 picoseconds. + Weight::from_parts(10_883_000, 744) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -538,8 +589,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 45_606_000 picoseconds. - Weight::from_parts(47_190_000, 10754) + // Minimum execution time: 46_835_000 picoseconds. + Weight::from_parts(47_446_000, 10754) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -551,12 +602,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_077_000 picoseconds. - Weight::from_parts(9_823_489, 247) - // Standard Error: 54 - .saturating_add(Weight::from_parts(392, 0).saturating_mul(n.into())) - // Standard Error: 54 - .saturating_add(Weight::from_parts(408, 0).saturating_mul(o.into())) + // Minimum execution time: 10_604_000 picoseconds. + Weight::from_parts(11_282_849, 247) + // Standard Error: 48 + .saturating_add(Weight::from_parts(496, 0).saturating_mul(n.into())) + // Standard Error: 48 + .saturating_add(Weight::from_parts(764, 0).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -568,10 +619,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_812_000 picoseconds. - Weight::from_parts(9_626_925, 247) - // Standard Error: 77 - .saturating_add(Weight::from_parts(269, 0).saturating_mul(n.into())) + // Minimum execution time: 10_081_000 picoseconds. + Weight::from_parts(11_186_557, 247) + // Standard Error: 68 + .saturating_add(Weight::from_parts(782, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -583,10 +634,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_143_000 picoseconds. - Weight::from_parts(9_229_363, 247) - // Standard Error: 77 - .saturating_add(Weight::from_parts(1_198, 0).saturating_mul(n.into())) + // Minimum execution time: 8_758_000 picoseconds. + Weight::from_parts(9_939_492, 247) + // Standard Error: 69 + .saturating_add(Weight::from_parts(1_703, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -597,10 +648,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_899_000 picoseconds. - Weight::from_parts(8_591_860, 247) - // Standard Error: 56 - .saturating_add(Weight::from_parts(461, 0).saturating_mul(n.into())) + // Minimum execution time: 8_525_000 picoseconds. + Weight::from_parts(9_522_265, 247) + // Standard Error: 66 + .saturating_add(Weight::from_parts(426, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -611,10 +662,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_215_000 picoseconds. - Weight::from_parts(10_198_528, 247) - // Standard Error: 75 - .saturating_add(Weight::from_parts(1_521, 0).saturating_mul(n.into())) + // Minimum execution time: 10_603_000 picoseconds. + Weight::from_parts(11_817_752, 247) + // Standard Error: 82 + .saturating_add(Weight::from_parts(1_279, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -623,36 +674,36 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_406_000 picoseconds. - Weight::from_parts(1_515_000, 0) + // Minimum execution time: 1_553_000 picoseconds. + Weight::from_parts(1_615_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_782_000 picoseconds. - Weight::from_parts(1_890_000, 0) + // Minimum execution time: 1_932_000 picoseconds. + Weight::from_parts(2_064_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_380_000 picoseconds. - Weight::from_parts(1_422_000, 0) + // Minimum execution time: 1_510_000 picoseconds. + Weight::from_parts(1_545_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_504_000 picoseconds. - Weight::from_parts(1_583_000, 0) + // Minimum execution time: 1_663_000 picoseconds. + Weight::from_parts(1_801_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_045_000 picoseconds. - Weight::from_parts(1_138_000, 0) + // Minimum execution time: 1_026_000 picoseconds. + Weight::from_parts(1_137_000, 0) } /// The range of component `n` is `[0, 512]`. /// The range of component `o` is `[0, 512]`. @@ -660,60 +711,63 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_039_000 picoseconds. - Weight::from_parts(2_317_406, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(283, 0).saturating_mul(n.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(347, 0).saturating_mul(o.into())) + // Minimum execution time: 2_446_000 picoseconds. + Weight::from_parts(2_644_525, 0) + // Standard Error: 17 + .saturating_add(Weight::from_parts(113, 0).saturating_mul(n.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(179, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 512]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_880_000 picoseconds. - Weight::from_parts(2_251_392, 0) - // Standard Error: 17 - .saturating_add(Weight::from_parts(313, 0).saturating_mul(n.into())) + // Minimum execution time: 2_085_000 picoseconds. + Weight::from_parts(2_379_853, 0) + // Standard Error: 19 + .saturating_add(Weight::from_parts(366, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_763_000 picoseconds. - Weight::from_parts(1_951_912, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(268, 0).saturating_mul(n.into())) + // Minimum execution time: 1_876_000 picoseconds. + Weight::from_parts(2_073_689, 0) + // Standard Error: 16 + .saturating_add(Weight::from_parts(376, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_536_000 picoseconds. - Weight::from_parts(1_779_085, 0) - // Standard Error: 14 - .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) + // Minimum execution time: 1_688_000 picoseconds. + Weight::from_parts(1_914_470, 0) + // Standard Error: 15 + .saturating_add(Weight::from_parts(125, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. - fn seal_take_transient_storage(n: u32, ) -> Weight { + fn seal_take_transient_storage(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_343_000 picoseconds. - Weight::from_parts(2_587_750, 0) - // Standard Error: 22 - .saturating_add(Weight::from_parts(30, 0).saturating_mul(n.into())) + // Minimum execution time: 2_479_000 picoseconds. + Weight::from_parts(2_758_250, 0) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) fn seal_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `103` - // Estimated: `0` - // Minimum execution time: 9_250_000 picoseconds. - Weight::from_parts(9_637_000, 0) + // Measured: `352` + // Estimated: `3817` + // Minimum execution time: 15_745_000 picoseconds. + Weight::from_parts(16_300_000, 3817) + .saturating_add(T::DbWeight::get().reads(1_u64)) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) @@ -724,17 +778,17 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 262144]`. fn seal_call(t: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1221 + t * (103 ±0)` - // Estimated: `4686 + t * (103 ±0)` - // Minimum execution time: 33_333_000 picoseconds. - Weight::from_parts(34_378_774, 4686) - // Standard Error: 41_131 - .saturating_add(Weight::from_parts(1_756_626, 0).saturating_mul(t.into())) + // Measured: `1309 + t * (140 ±0)` + // Estimated: `4774 + t * (140 ±0)` + // Minimum execution time: 39_639_000 picoseconds. + Weight::from_parts(40_909_376, 4774) + // Standard Error: 54_479 + .saturating_add(Weight::from_parts(1_526_185, 0).saturating_mul(t.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(3, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(Weight::from_parts(4, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 103).saturating_mul(t.into())) + .saturating_add(Weight::from_parts(0, 140).saturating_mul(t.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) @@ -742,10 +796,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `1048` - // Estimated: `4513` - // Minimum execution time: 27_096_000 picoseconds. - Weight::from_parts(27_934_000, 4513) + // Measured: `1081` + // Estimated: `4546` + // Minimum execution time: 29_651_000 picoseconds. + Weight::from_parts(31_228_000, 4546) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) @@ -759,12 +813,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 262144]`. fn seal_instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1257` - // Estimated: `4715` - // Minimum execution time: 118_412_000 picoseconds. - Weight::from_parts(106_130_041, 4715) - // Standard Error: 12 - .saturating_add(Weight::from_parts(4_235, 0).saturating_mul(i.into())) + // Measured: `1327` + // Estimated: `4792` + // Minimum execution time: 126_995_000 picoseconds. + Weight::from_parts(114_028_446, 4792) + // Standard Error: 11 + .saturating_add(Weight::from_parts(3_781, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -773,73 +827,73 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 614_000 picoseconds. - Weight::from_parts(4_320_897, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_371, 0).saturating_mul(n.into())) + // Minimum execution time: 653_000 picoseconds. + Weight::from_parts(973_524, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_048, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_062_000 picoseconds. - Weight::from_parts(4_571_371, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(3_572, 0).saturating_mul(n.into())) + // Minimum execution time: 1_118_000 picoseconds. + Weight::from_parts(795_498, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(3_260, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 609_000 picoseconds. - Weight::from_parts(4_008_056, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_497, 0).saturating_mul(n.into())) + // Minimum execution time: 647_000 picoseconds. + Weight::from_parts(667_024, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_183, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 608_000 picoseconds. - Weight::from_parts(3_839_383, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_504, 0).saturating_mul(n.into())) + // Minimum execution time: 605_000 picoseconds. + Weight::from_parts(675_568, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_181, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 261889]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 43_110_000 picoseconds. - Weight::from_parts(31_941_593, 0) - // Standard Error: 12 - .saturating_add(Weight::from_parts(5_233, 0).saturating_mul(n.into())) + // Minimum execution time: 42_743_000 picoseconds. + Weight::from_parts(26_131_984, 0) + // Standard Error: 15 + .saturating_add(Weight::from_parts(4_867, 0).saturating_mul(n.into())) } fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 47_798_000 picoseconds. - Weight::from_parts(49_225_000, 0) + // Minimum execution time: 50_838_000 picoseconds. + Weight::from_parts(52_248_000, 0) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_576_000 picoseconds. - Weight::from_parts(12_731_000, 0) + // Minimum execution time: 12_605_000 picoseconds. + Weight::from_parts(12_796_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_set_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `266` - // Estimated: `3731` - // Minimum execution time: 14_306_000 picoseconds. - Weight::from_parts(15_011_000, 3731) + // Measured: `300` + // Estimated: `3765` + // Minimum execution time: 16_377_000 picoseconds. + Weight::from_parts(16_932_000, 3765) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -847,10 +901,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn lock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `303` - // Estimated: `3768` - // Minimum execution time: 10_208_000 picoseconds. - Weight::from_parts(10_514_000, 3768) + // Measured: `338` + // Estimated: `3803` + // Minimum execution time: 11_499_000 picoseconds. + Weight::from_parts(12_104_000, 3803) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -858,10 +912,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) fn unlock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `303` + // Measured: `338` // Estimated: `3561` - // Minimum execution time: 9_062_000 picoseconds. - Weight::from_parts(9_414_000, 3561) + // Minimum execution time: 10_308_000 picoseconds. + Weight::from_parts(11_000_000, 3561) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -870,10 +924,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_074_000 picoseconds. - Weight::from_parts(9_646_158, 0) - // Standard Error: 58 - .saturating_add(Weight::from_parts(84_694, 0).saturating_mul(r.into())) + // Minimum execution time: 8_162_000 picoseconds. + Weight::from_parts(9_180_011, 0) + // Standard Error: 63 + .saturating_add(Weight::from_parts(84_822, 0).saturating_mul(r.into())) } } @@ -885,8 +939,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 2_712_000 picoseconds. - Weight::from_parts(2_882_000, 1594) + // Minimum execution time: 3_053_000 picoseconds. + Weight::from_parts(3_150_000, 1594) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -894,18 +948,20 @@ impl WeightInfo for () { /// The range of component `k` is `[0, 1024]`. fn on_initialize_per_trie_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `392 + k * (69 ±0)` - // Estimated: `382 + k * (70 ±0)` - // Minimum execution time: 13_394_000 picoseconds. - Weight::from_parts(13_668_000, 382) - // Standard Error: 2_208 - .saturating_add(Weight::from_parts(1_340_842, 0).saturating_mul(k.into())) + // Measured: `425 + k * (69 ±0)` + // Estimated: `415 + k * (70 ±0)` + // Minimum execution time: 15_219_000 picoseconds. + Weight::from_parts(12_576_960, 415) + // Standard Error: 1_429 + .saturating_add(Weight::from_parts(1_341_896, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) .saturating_add(Weight::from_parts(0, 70).saturating_mul(k.into())) } + /// Storage: `Revive::AddressSuffix` (r:2 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) @@ -917,21 +973,21 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. - fn call_with_code_per_byte(c: u32, ) -> Weight { + fn call_with_code_per_byte(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1466` - // Estimated: `4931` - // Minimum execution time: 80_390_000 picoseconds. - Weight::from_parts(83_627_295, 4931) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Measured: `1519` + // Estimated: `7459` + // Minimum execution time: 88_906_000 picoseconds. + Weight::from_parts(93_353_224, 7459) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) @@ -944,19 +1000,21 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn instantiate_with_code(_c: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `303` - // Estimated: `6232` - // Minimum execution time: 184_708_000 picoseconds. - Weight::from_parts(177_995_416, 6232) - // Standard Error: 11 - .saturating_add(Weight::from_parts(4_609, 0).saturating_mul(i.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Measured: `416` + // Estimated: `6360` + // Minimum execution time: 202_688_000 picoseconds. + Weight::from_parts(197_366_807, 6360) + // Standard Error: 13 + .saturating_add(Weight::from_parts(4_261, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) @@ -964,19 +1022,21 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) /// The range of component `i` is `[0, 262144]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1261` - // Estimated: `4706` - // Minimum execution time: 150_137_000 picoseconds. - Weight::from_parts(136_548_469, 4706) + // Measured: `1313` + // Estimated: `4779` + // Minimum execution time: 169_246_000 picoseconds. + Weight::from_parts(149_480_457, 4779) // Standard Error: 16 - .saturating_add(Weight::from_parts(4_531, 0).saturating_mul(i.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(Weight::from_parts(4_041, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } + /// Storage: `Revive::AddressSuffix` (r:2 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) @@ -989,17 +1049,17 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1466` - // Estimated: `4931` - // Minimum execution time: 83_178_000 picoseconds. - Weight::from_parts(84_633_000, 4931) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Measured: `1519` + // Estimated: `7459` + // Minimum execution time: 91_129_000 picoseconds. + Weight::from_parts(94_220_000, 7459) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. @@ -1007,23 +1067,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3574` - // Minimum execution time: 51_526_000 picoseconds. - Weight::from_parts(54_565_973, 3574) + // Minimum execution time: 54_849_000 picoseconds. + Weight::from_parts(57_508_591, 3574) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: // Measured: `285` // Estimated: `3750` - // Minimum execution time: 41_885_000 picoseconds. - Weight::from_parts(42_467_000, 3750) + // Minimum execution time: 45_017_000 picoseconds. + Weight::from_parts(46_312_000, 3750) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1033,113 +1093,153 @@ impl WeightInfo for () { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `492` - // Estimated: `6432` - // Minimum execution time: 24_905_000 picoseconds. - Weight::from_parts(25_483_000, 6432) + // Measured: `529` + // Estimated: `6469` + // Minimum execution time: 26_992_000 picoseconds. + Weight::from_parts(28_781_000, 6469) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } + /// Storage: `Revive::AddressSuffix` (r:1 w:1) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + fn map_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `3574` + // Minimum execution time: 44_031_000 picoseconds. + Weight::from_parts(45_133_000, 3574) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Storage: `Revive::AddressSuffix` (r:0 w:1) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) + fn unmap_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `56` + // Estimated: `3521` + // Minimum execution time: 35_681_000 picoseconds. + Weight::from_parts(36_331_000, 3521) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Measured`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `Measured`) + fn dispatch_as_fallback_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 11_550_000 picoseconds. + Weight::from_parts(12_114_000, 3610) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } /// The range of component `r` is `[0, 1600]`. fn noop_host_fn(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_979_000 picoseconds. - Weight::from_parts(8_272_348, 0) - // Standard Error: 137 - .saturating_add(Weight::from_parts(172_489, 0).saturating_mul(r.into())) + // Minimum execution time: 7_063_000 picoseconds. + Weight::from_parts(7_671_454, 0) + // Standard Error: 105 + .saturating_add(Weight::from_parts(175_349, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 251_000 picoseconds. - Weight::from_parts(318_000, 0) + // Minimum execution time: 266_000 picoseconds. + Weight::from_parts(313_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) fn seal_is_contract() -> Weight { // Proof Size summary in bytes: - // Measured: `272` - // Estimated: `3737` - // Minimum execution time: 6_966_000 picoseconds. - Weight::from_parts(7_240_000, 3737) + // Measured: `306` + // Estimated: `3771` + // Minimum execution time: 7_397_000 picoseconds. + Weight::from_parts(7_967_000, 3771) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `369` - // Estimated: `3834` - // Minimum execution time: 7_589_000 picoseconds. - Weight::from_parts(7_958_000, 3834) + // Measured: `403` + // Estimated: `3868` + // Minimum execution time: 8_395_000 picoseconds. + Weight::from_parts(8_863_000, 3868) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 235_000 picoseconds. - Weight::from_parts(285_000, 0) + // Minimum execution time: 265_000 picoseconds. + Weight::from_parts(292_000, 0) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 283_000 picoseconds. - Weight::from_parts(326_000, 0) + // Minimum execution time: 298_000 picoseconds. + Weight::from_parts(334_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 266_000 picoseconds. - Weight::from_parts(298_000, 0) + // Minimum execution time: 262_000 picoseconds. + Weight::from_parts(274_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 240_000 picoseconds. - Weight::from_parts(290_000, 0) + // Minimum execution time: 277_000 picoseconds. + Weight::from_parts(297_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 651_000 picoseconds. - Weight::from_parts(714_000, 0) + // Minimum execution time: 620_000 picoseconds. + Weight::from_parts(706_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: - // Measured: `103` + // Measured: `140` // Estimated: `0` - // Minimum execution time: 4_476_000 picoseconds. - Weight::from_parts(4_671_000, 0) + // Minimum execution time: 5_475_000 picoseconds. + Weight::from_parts(5_706_000, 0) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn seal_balance_of() -> Weight { // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3517` - // Minimum execution time: 3_800_000 picoseconds. - Weight::from_parts(3_968_000, 3517) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Measured: `264` + // Estimated: `3729` + // Minimum execution time: 9_141_000 picoseconds. + Weight::from_parts(9_674_000, 3729) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) /// The range of component `n` is `[1, 4096]`. fn seal_get_immutable_data(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `205 + n * (1 ±0)` - // Estimated: `3670 + n * (1 ±0)` - // Minimum execution time: 5_845_000 picoseconds. - Weight::from_parts(6_473_478, 3670) - // Standard Error: 4 - .saturating_add(Weight::from_parts(651, 0).saturating_mul(n.into())) + // Measured: `238 + n * (1 ±0)` + // Estimated: `3703 + n * (1 ±0)` + // Minimum execution time: 6_443_000 picoseconds. + Weight::from_parts(7_252_595, 3703) + // Standard Error: 12 + .saturating_add(Weight::from_parts(915, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1150,39 +1250,39 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_980_000 picoseconds. - Weight::from_parts(2_324_567, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(512, 0).saturating_mul(n.into())) + // Minimum execution time: 2_745_000 picoseconds. + Weight::from_parts(3_121_250, 0) + // Standard Error: 4 + .saturating_add(Weight::from_parts(627, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 259_000 picoseconds. - Weight::from_parts(285_000, 0) + // Minimum execution time: 255_000 picoseconds. + Weight::from_parts(274_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 244_000 picoseconds. - Weight::from_parts(291_000, 0) + // Minimum execution time: 235_000 picoseconds. + Weight::from_parts(261_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 252_000 picoseconds. - Weight::from_parts(291_000, 0) + // Minimum execution time: 249_000 picoseconds. + Weight::from_parts(263_000, 0) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 245_000 picoseconds. - Weight::from_parts(277_000, 0) + // Minimum execution time: 287_000 picoseconds. + Weight::from_parts(300_000, 0) } /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `Measured`) @@ -1190,8 +1290,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `67` // Estimated: `1552` - // Minimum execution time: 5_650_000 picoseconds. - Weight::from_parts(5_783_000, 1552) + // Minimum execution time: 6_147_000 picoseconds. + Weight::from_parts(6_562_000, 1552) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// The range of component `n` is `[0, 262140]`. @@ -1199,21 +1299,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 427_000 picoseconds. - Weight::from_parts(351_577, 0) + // Minimum execution time: 453_000 picoseconds. + Weight::from_parts(548_774, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(114, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(147, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262140]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 265_000 picoseconds. - Weight::from_parts(746_316, 0) + // Minimum execution time: 264_000 picoseconds. + Weight::from_parts(490_374, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(236, 0).saturating_mul(n.into())) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:33 w:33) @@ -1225,13 +1327,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 32]`. fn seal_terminate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `272 + n * (88 ±0)` - // Estimated: `3737 + n * (2563 ±0)` - // Minimum execution time: 15_988_000 picoseconds. - Weight::from_parts(18_796_705, 3737) - // Standard Error: 10_437 - .saturating_add(Weight::from_parts(4_338_085, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `323 + n * (88 ±0)` + // Estimated: `3788 + n * (2563 ±0)` + // Minimum execution time: 22_833_000 picoseconds. + Weight::from_parts(24_805_620, 3788) + // Standard Error: 9_498 + .saturating_add(Weight::from_parts(4_486_714, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -1243,22 +1345,22 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_237_000 picoseconds. - Weight::from_parts(4_128_112, 0) - // Standard Error: 2_947 - .saturating_add(Weight::from_parts(198_825, 0).saturating_mul(t.into())) - // Standard Error: 26 - .saturating_add(Weight::from_parts(1_007, 0).saturating_mul(n.into())) + // Minimum execution time: 4_969_000 picoseconds. + Weight::from_parts(4_994_916, 0) + // Standard Error: 3_727 + .saturating_add(Weight::from_parts(188_374, 0).saturating_mul(t.into())) + // Standard Error: 33 + .saturating_add(Weight::from_parts(925, 0).saturating_mul(n.into())) } /// The range of component `i` is `[0, 262144]`. fn seal_debug_message(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 292_000 picoseconds. - Weight::from_parts(1_297_376, 0) + // Minimum execution time: 328_000 picoseconds. + Weight::from_parts(928_905, 0) // Standard Error: 1 - .saturating_add(Weight::from_parts(724, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(753, 0).saturating_mul(i.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1266,8 +1368,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 7_812_000 picoseconds. - Weight::from_parts(8_171_000, 744) + // Minimum execution time: 8_612_000 picoseconds. + Weight::from_parts(9_326_000, 744) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1276,8 +1378,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 44_179_000 picoseconds. - Weight::from_parts(45_068_000, 10754) + // Minimum execution time: 44_542_000 picoseconds. + Weight::from_parts(45_397_000, 10754) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1286,8 +1388,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `744` // Estimated: `744` - // Minimum execution time: 8_964_000 picoseconds. - Weight::from_parts(9_336_000, 744) + // Minimum execution time: 10_343_000 picoseconds. + Weight::from_parts(10_883_000, 744) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1297,8 +1399,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10754` // Estimated: `10754` - // Minimum execution time: 45_606_000 picoseconds. - Weight::from_parts(47_190_000, 10754) + // Minimum execution time: 46_835_000 picoseconds. + Weight::from_parts(47_446_000, 10754) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1310,12 +1412,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_077_000 picoseconds. - Weight::from_parts(9_823_489, 247) - // Standard Error: 54 - .saturating_add(Weight::from_parts(392, 0).saturating_mul(n.into())) - // Standard Error: 54 - .saturating_add(Weight::from_parts(408, 0).saturating_mul(o.into())) + // Minimum execution time: 10_604_000 picoseconds. + Weight::from_parts(11_282_849, 247) + // Standard Error: 48 + .saturating_add(Weight::from_parts(496, 0).saturating_mul(n.into())) + // Standard Error: 48 + .saturating_add(Weight::from_parts(764, 0).saturating_mul(o.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -1327,10 +1429,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_812_000 picoseconds. - Weight::from_parts(9_626_925, 247) - // Standard Error: 77 - .saturating_add(Weight::from_parts(269, 0).saturating_mul(n.into())) + // Minimum execution time: 10_081_000 picoseconds. + Weight::from_parts(11_186_557, 247) + // Standard Error: 68 + .saturating_add(Weight::from_parts(782, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1342,10 +1444,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_143_000 picoseconds. - Weight::from_parts(9_229_363, 247) - // Standard Error: 77 - .saturating_add(Weight::from_parts(1_198, 0).saturating_mul(n.into())) + // Minimum execution time: 8_758_000 picoseconds. + Weight::from_parts(9_939_492, 247) + // Standard Error: 69 + .saturating_add(Weight::from_parts(1_703, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1356,10 +1458,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_899_000 picoseconds. - Weight::from_parts(8_591_860, 247) - // Standard Error: 56 - .saturating_add(Weight::from_parts(461, 0).saturating_mul(n.into())) + // Minimum execution time: 8_525_000 picoseconds. + Weight::from_parts(9_522_265, 247) + // Standard Error: 66 + .saturating_add(Weight::from_parts(426, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1370,10 +1472,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_215_000 picoseconds. - Weight::from_parts(10_198_528, 247) - // Standard Error: 75 - .saturating_add(Weight::from_parts(1_521, 0).saturating_mul(n.into())) + // Minimum execution time: 10_603_000 picoseconds. + Weight::from_parts(11_817_752, 247) + // Standard Error: 82 + .saturating_add(Weight::from_parts(1_279, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1382,36 +1484,36 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_406_000 picoseconds. - Weight::from_parts(1_515_000, 0) + // Minimum execution time: 1_553_000 picoseconds. + Weight::from_parts(1_615_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_782_000 picoseconds. - Weight::from_parts(1_890_000, 0) + // Minimum execution time: 1_932_000 picoseconds. + Weight::from_parts(2_064_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_380_000 picoseconds. - Weight::from_parts(1_422_000, 0) + // Minimum execution time: 1_510_000 picoseconds. + Weight::from_parts(1_545_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_504_000 picoseconds. - Weight::from_parts(1_583_000, 0) + // Minimum execution time: 1_663_000 picoseconds. + Weight::from_parts(1_801_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_045_000 picoseconds. - Weight::from_parts(1_138_000, 0) + // Minimum execution time: 1_026_000 picoseconds. + Weight::from_parts(1_137_000, 0) } /// The range of component `n` is `[0, 512]`. /// The range of component `o` is `[0, 512]`. @@ -1419,60 +1521,63 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_039_000 picoseconds. - Weight::from_parts(2_317_406, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(283, 0).saturating_mul(n.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(347, 0).saturating_mul(o.into())) + // Minimum execution time: 2_446_000 picoseconds. + Weight::from_parts(2_644_525, 0) + // Standard Error: 17 + .saturating_add(Weight::from_parts(113, 0).saturating_mul(n.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(179, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 512]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_880_000 picoseconds. - Weight::from_parts(2_251_392, 0) - // Standard Error: 17 - .saturating_add(Weight::from_parts(313, 0).saturating_mul(n.into())) + // Minimum execution time: 2_085_000 picoseconds. + Weight::from_parts(2_379_853, 0) + // Standard Error: 19 + .saturating_add(Weight::from_parts(366, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_763_000 picoseconds. - Weight::from_parts(1_951_912, 0) - // Standard Error: 13 - .saturating_add(Weight::from_parts(268, 0).saturating_mul(n.into())) + // Minimum execution time: 1_876_000 picoseconds. + Weight::from_parts(2_073_689, 0) + // Standard Error: 16 + .saturating_add(Weight::from_parts(376, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_536_000 picoseconds. - Weight::from_parts(1_779_085, 0) - // Standard Error: 14 - .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) + // Minimum execution time: 1_688_000 picoseconds. + Weight::from_parts(1_914_470, 0) + // Standard Error: 15 + .saturating_add(Weight::from_parts(125, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 512]`. - fn seal_take_transient_storage(n: u32, ) -> Weight { + fn seal_take_transient_storage(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_343_000 picoseconds. - Weight::from_parts(2_587_750, 0) - // Standard Error: 22 - .saturating_add(Weight::from_parts(30, 0).saturating_mul(n.into())) + // Minimum execution time: 2_479_000 picoseconds. + Weight::from_parts(2_758_250, 0) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) fn seal_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `103` - // Estimated: `0` - // Minimum execution time: 9_250_000 picoseconds. - Weight::from_parts(9_637_000, 0) + // Measured: `352` + // Estimated: `3817` + // Minimum execution time: 15_745_000 picoseconds. + Weight::from_parts(16_300_000, 3817) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } + /// Storage: `Revive::AddressSuffix` (r:1 w:0) + /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:0) /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) @@ -1483,17 +1588,17 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn seal_call(t: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1221 + t * (103 ±0)` - // Estimated: `4686 + t * (103 ±0)` - // Minimum execution time: 33_333_000 picoseconds. - Weight::from_parts(34_378_774, 4686) - // Standard Error: 41_131 - .saturating_add(Weight::from_parts(1_756_626, 0).saturating_mul(t.into())) + // Measured: `1309 + t * (140 ±0)` + // Estimated: `4774 + t * (140 ±0)` + // Minimum execution time: 39_639_000 picoseconds. + Weight::from_parts(40_909_376, 4774) + // Standard Error: 54_479 + .saturating_add(Weight::from_parts(1_526_185, 0).saturating_mul(t.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(3, 0).saturating_mul(i.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(Weight::from_parts(4, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 103).saturating_mul(t.into())) + .saturating_add(Weight::from_parts(0, 140).saturating_mul(t.into())) } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) @@ -1501,10 +1606,10 @@ impl WeightInfo for () { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `1048` - // Estimated: `4513` - // Minimum execution time: 27_096_000 picoseconds. - Weight::from_parts(27_934_000, 4513) + // Measured: `1081` + // Estimated: `4546` + // Minimum execution time: 29_651_000 picoseconds. + Weight::from_parts(31_228_000, 4546) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) @@ -1518,12 +1623,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn seal_instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1257` - // Estimated: `4715` - // Minimum execution time: 118_412_000 picoseconds. - Weight::from_parts(106_130_041, 4715) - // Standard Error: 12 - .saturating_add(Weight::from_parts(4_235, 0).saturating_mul(i.into())) + // Measured: `1327` + // Estimated: `4792` + // Minimum execution time: 126_995_000 picoseconds. + Weight::from_parts(114_028_446, 4792) + // Standard Error: 11 + .saturating_add(Weight::from_parts(3_781, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1532,73 +1637,73 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 614_000 picoseconds. - Weight::from_parts(4_320_897, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_371, 0).saturating_mul(n.into())) + // Minimum execution time: 653_000 picoseconds. + Weight::from_parts(973_524, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_048, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_062_000 picoseconds. - Weight::from_parts(4_571_371, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(3_572, 0).saturating_mul(n.into())) + // Minimum execution time: 1_118_000 picoseconds. + Weight::from_parts(795_498, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(3_260, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 609_000 picoseconds. - Weight::from_parts(4_008_056, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_497, 0).saturating_mul(n.into())) + // Minimum execution time: 647_000 picoseconds. + Weight::from_parts(667_024, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_183, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 608_000 picoseconds. - Weight::from_parts(3_839_383, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_504, 0).saturating_mul(n.into())) + // Minimum execution time: 605_000 picoseconds. + Weight::from_parts(675_568, 0) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_181, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 261889]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 43_110_000 picoseconds. - Weight::from_parts(31_941_593, 0) - // Standard Error: 12 - .saturating_add(Weight::from_parts(5_233, 0).saturating_mul(n.into())) + // Minimum execution time: 42_743_000 picoseconds. + Weight::from_parts(26_131_984, 0) + // Standard Error: 15 + .saturating_add(Weight::from_parts(4_867, 0).saturating_mul(n.into())) } fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 47_798_000 picoseconds. - Weight::from_parts(49_225_000, 0) + // Minimum execution time: 50_838_000 picoseconds. + Weight::from_parts(52_248_000, 0) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_576_000 picoseconds. - Weight::from_parts(12_731_000, 0) + // Minimum execution time: 12_605_000 picoseconds. + Weight::from_parts(12_796_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_set_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `266` - // Estimated: `3731` - // Minimum execution time: 14_306_000 picoseconds. - Weight::from_parts(15_011_000, 3731) + // Measured: `300` + // Estimated: `3765` + // Minimum execution time: 16_377_000 picoseconds. + Weight::from_parts(16_932_000, 3765) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1606,10 +1711,10 @@ impl WeightInfo for () { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn lock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `303` - // Estimated: `3768` - // Minimum execution time: 10_208_000 picoseconds. - Weight::from_parts(10_514_000, 3768) + // Measured: `338` + // Estimated: `3803` + // Minimum execution time: 11_499_000 picoseconds. + Weight::from_parts(12_104_000, 3803) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1617,10 +1722,10 @@ impl WeightInfo for () { /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) fn unlock_delegate_dependency() -> Weight { // Proof Size summary in bytes: - // Measured: `303` + // Measured: `338` // Estimated: `3561` - // Minimum execution time: 9_062_000 picoseconds. - Weight::from_parts(9_414_000, 3561) + // Minimum execution time: 10_308_000 picoseconds. + Weight::from_parts(11_000_000, 3561) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1629,9 +1734,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_074_000 picoseconds. - Weight::from_parts(9_646_158, 0) - // Standard Error: 58 - .saturating_add(Weight::from_parts(84_694, 0).saturating_mul(r.into())) + // Minimum execution time: 8_162_000 picoseconds. + Weight::from_parts(9_180_011, 0) + // Standard Error: 63 + .saturating_add(Weight::from_parts(84_822, 0).saturating_mul(r.into())) } } From efd660309f2ee944718a6302627bbb956ada3729 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 25 Oct 2024 11:31:21 +0200 Subject: [PATCH 13/15] Fix migrations for pallet-xcm (#6148) Relates to: https://github.com/paritytech/polkadot-sdk/pull/4826 Relates to: https://github.com/paritytech/polkadot-sdk/issues/3214 ## Description `pallet-xcm` stores some operational data that uses `Versioned*` XCM types. When we add a new XCM version (XV), we deprecate XV-2 and remove XV-3. Without proper migration, this can lead to issues with [undecodable storage](https://github.com/paritytech/polkadot-sdk/actions/runs/11381324568/job/31662577532?pr=6092), as was identified on the XCMv5 branch where XCMv2 was removed. This PR extends the existing `MigrateToLatestXcmVersion` to include migration for the `Queries`, `LockedFungibles`, and `RemoteLockedFungibles` storage types. Additionally, more checks were added to `try_state` for these types. ## TODO - [x] create tracking issue for `polkadot-fellows` https://github.com/polkadot-fellows/runtimes/issues/492 - [x] Add missing `MigrateToLatestXcmVersion` for westend - [x] fix pallet-xcm `Queries` - fails for Westend https://github.com/paritytech/polkadot-sdk/actions/runs/11381324568/job/31662577532?pr=6092 - `V2` was removed from `Versioned*` stuff, but we have a live data with V2 e.g. Queries - e.g. Kusama or Polkadot relay chains ``` VersionNotifier: { origin: { V2: { parents: 0 interior: { X1: { Parachain: 2,124 } } } } isActive: true } ``` ![image](https://github.com/user-attachments/assets/f59f761b-46a7-4def-8aea-45c4e41c0a00) - [x] fix also for `RemoteLockedFungibles` - [x] fix also for `LockedFungibles` ## Follow-ups - [ ] deploy on Westend chains before XCMv5 - [ ] https://github.com/paritytech/polkadot-sdk/issues/6188 --------- Co-authored-by: command-bot <> Co-authored-by: GitHub Action Co-authored-by: Francisco Aguirre --- polkadot/runtime/westend/src/lib.rs | 2 + .../parachain/xcm_config.rs | 2 +- .../relay_chain/xcm_config.rs | 2 +- polkadot/xcm/pallet-xcm/src/lib.rs | 42 +- polkadot/xcm/pallet-xcm/src/migration.rs | 379 +++++++++++++++++- polkadot/xcm/pallet-xcm/src/tests/mod.rs | 172 +++++++- .../single_asset_adapter/mock.rs | 2 +- .../xcm/xcm-builder/src/tests/pay/mock.rs | 3 +- polkadot/xcm/xcm-runtime-apis/tests/mock.rs | 3 +- prdoc/pr_6148.prdoc | 17 + 10 files changed, 610 insertions(+), 14 deletions(-) create mode 100644 prdoc/pr_6148.prdoc diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index a91ca399db41..4941d91df57d 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1809,6 +1809,8 @@ pub mod migrations { >, parachains_shared::migration::MigrateToV1, parachains_scheduler::migration::MigrateV2ToV3, + // permanent + pallet_xcm::migration::MigrateToLatestXcmVersion, ); } diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs index 7cb230f6e006..f8a1826b8ab1 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs @@ -168,7 +168,7 @@ impl pallet_xcm::Config for Runtime { type UniversalLocation = UniversalLocation; // No version discovery needed const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; - type AdvertisedXcmVersion = frame::traits::ConstU32<3>; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type AdminOrigin = frame_system::EnsureRoot; // No locking type TrustedLockers = (); diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs index a31e664d8216..e7b602df7338 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs @@ -142,7 +142,7 @@ impl pallet_xcm::Config for Runtime { type UniversalLocation = UniversalLocation; // No version discovery needed const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; - type AdvertisedXcmVersion = frame::traits::ConstU32<3>; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type AdminOrigin = frame_system::EnsureRoot; // No locking type TrustedLockers = (); diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 254bc2c7b83d..9b8f735b478f 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -2807,6 +2807,44 @@ impl Pallet { /// set. #[cfg(any(feature = "try-runtime", test))] pub fn do_try_state() -> Result<(), TryRuntimeError> { + use migration::data::NeedsMigration; + + // Take the minimum version between `SafeXcmVersion` and `latest - 1` and ensure that the + // operational data is stored at least at that version, for example, to prevent issues when + // removing older XCM versions. + let minimal_allowed_xcm_version = if let Some(safe_xcm_version) = SafeXcmVersion::::get() + { + XCM_VERSION.saturating_sub(1).min(safe_xcm_version) + } else { + XCM_VERSION.saturating_sub(1) + }; + + // check `Queries` + ensure!( + !Queries::::iter_values() + .any(|data| data.needs_migration(minimal_allowed_xcm_version)), + TryRuntimeError::Other("`Queries` data should be migrated to the higher xcm version!") + ); + + // check `LockedFungibles` + ensure!( + !LockedFungibles::::iter_values() + .any(|data| data.needs_migration(minimal_allowed_xcm_version)), + TryRuntimeError::Other( + "`LockedFungibles` data should be migrated to the higher xcm version!" + ) + ); + + // check `RemoteLockedFungibles` + ensure!( + !RemoteLockedFungibles::::iter() + .any(|(key, data)| key.needs_migration(minimal_allowed_xcm_version) || + data.needs_migration(minimal_allowed_xcm_version)), + TryRuntimeError::Other( + "`RemoteLockedFungibles` data should be migrated to the higher xcm version!" + ) + ); + // if migration has been already scheduled, everything is ok and data will be eventually // migrated if CurrentMigration::::exists() { @@ -2887,7 +2925,7 @@ impl xcm_executor::traits::Enact for UnlockTicket { let mut maybe_remove_index = None; let mut locked = BalanceOf::::zero(); let mut found = false; - // We could just as well do with with an into_iter, filter_map and collect, however this way + // We could just as well do with an into_iter, filter_map and collect, however this way // avoids making an allocation. for (i, x) in locks.iter_mut().enumerate() { if x.1.try_as::<_>().defensive() == Ok(&self.unlocker) { @@ -3268,7 +3306,7 @@ impl OnResponse for Pallet { }); return Weight::zero() } - return match maybe_notify { + match maybe_notify { Some((pallet_index, call_index)) => { // This is a bit horrible, but we happen to know that the `Call` will // be built by `(pallet_index: u8, call_index: u8, QueryId, Response)`. diff --git a/polkadot/xcm/pallet-xcm/src/migration.rs b/polkadot/xcm/pallet-xcm/src/migration.rs index 2c5b2620f535..80154f57ddfb 100644 --- a/polkadot/xcm/pallet-xcm/src/migration.rs +++ b/polkadot/xcm/pallet-xcm/src/migration.rs @@ -15,7 +15,8 @@ // along with Polkadot. If not, see . use crate::{ - pallet::CurrentMigration, Config, Pallet, VersionMigrationStage, VersionNotifyTargets, + pallet::CurrentMigration, Config, CurrentXcmVersion, Pallet, VersionMigrationStage, + VersionNotifyTargets, }; use frame_support::{ pallet_prelude::*, @@ -25,6 +26,307 @@ use frame_support::{ const DEFAULT_PROOF_SIZE: u64 = 64 * 1024; +/// Utilities for handling XCM version migration for the relevant data. +pub mod data { + use crate::*; + + /// A trait for handling XCM versioned data migration for the requested `XcmVersion`. + pub(crate) trait NeedsMigration { + type MigratedData; + + /// Returns true if data does not match `minimal_allowed_xcm_version`. + fn needs_migration(&self, minimal_allowed_xcm_version: XcmVersion) -> bool; + + /// Attempts to migrate data. `Ok(None)` means no migration is needed. + /// `Ok(Some(Self::MigratedData))` should contain the migrated data. + fn try_migrate(self, to_xcm_version: XcmVersion) -> Result, ()>; + } + + /// Implementation of `NeedsMigration` for `LockedFungibles` data. + impl NeedsMigration for BoundedVec<(B, VersionedLocation), M> { + type MigratedData = Self; + + fn needs_migration(&self, minimal_allowed_xcm_version: XcmVersion) -> bool { + self.iter() + .any(|(_, unlocker)| unlocker.identify_version() < minimal_allowed_xcm_version) + } + + fn try_migrate( + mut self, + to_xcm_version: XcmVersion, + ) -> Result, ()> { + let mut was_modified = false; + for locked in self.iter_mut() { + if locked.1.identify_version() < to_xcm_version { + let Ok(new_unlocker) = locked.1.clone().into_version(to_xcm_version) else { + return Err(()) + }; + locked.1 = new_unlocker; + was_modified = true; + } + } + + if was_modified { + Ok(Some(self)) + } else { + Ok(None) + } + } + } + + /// Implementation of `NeedsMigration` for `Queries` data. + impl NeedsMigration for QueryStatus { + type MigratedData = Self; + + fn needs_migration(&self, minimal_allowed_xcm_version: XcmVersion) -> bool { + match &self { + QueryStatus::Pending { responder, maybe_match_querier, .. } => + responder.identify_version() < minimal_allowed_xcm_version || + maybe_match_querier + .as_ref() + .map(|v| v.identify_version() < minimal_allowed_xcm_version) + .unwrap_or(false), + QueryStatus::VersionNotifier { origin, .. } => + origin.identify_version() < minimal_allowed_xcm_version, + QueryStatus::Ready { response, .. } => + response.identify_version() < minimal_allowed_xcm_version, + } + } + + fn try_migrate(self, to_xcm_version: XcmVersion) -> Result, ()> { + if !self.needs_migration(to_xcm_version) { + return Ok(None) + } + + // do migration + match self { + QueryStatus::Pending { responder, maybe_match_querier, maybe_notify, timeout } => { + let Ok(responder) = responder.into_version(to_xcm_version) else { + return Err(()) + }; + let Ok(maybe_match_querier) = + maybe_match_querier.map(|mmq| mmq.into_version(to_xcm_version)).transpose() + else { + return Err(()) + }; + Ok(Some(QueryStatus::Pending { + responder, + maybe_match_querier, + maybe_notify, + timeout, + })) + }, + QueryStatus::VersionNotifier { origin, is_active } => origin + .into_version(to_xcm_version) + .map(|origin| Some(QueryStatus::VersionNotifier { origin, is_active })), + QueryStatus::Ready { response, at } => response + .into_version(to_xcm_version) + .map(|response| Some(QueryStatus::Ready { response, at })), + } + } + } + + /// Implementation of `NeedsMigration` for `RemoteLockedFungibles` key type. + impl NeedsMigration for (XcmVersion, A, VersionedAssetId) { + type MigratedData = Self; + + fn needs_migration(&self, minimal_allowed_xcm_version: XcmVersion) -> bool { + self.0 < minimal_allowed_xcm_version || + self.2.identify_version() < minimal_allowed_xcm_version + } + + fn try_migrate(self, to_xcm_version: XcmVersion) -> Result, ()> { + if !self.needs_migration(to_xcm_version) { + return Ok(None) + } + + let Ok(asset_id) = self.2.into_version(to_xcm_version) else { return Err(()) }; + Ok(Some((to_xcm_version, self.1, asset_id))) + } + } + + /// Implementation of `NeedsMigration` for `RemoteLockedFungibles` data. + impl> NeedsMigration + for RemoteLockedFungibleRecord + { + type MigratedData = Self; + + fn needs_migration(&self, minimal_allowed_xcm_version: XcmVersion) -> bool { + self.owner.identify_version() < minimal_allowed_xcm_version || + self.locker.identify_version() < minimal_allowed_xcm_version + } + + fn try_migrate(self, to_xcm_version: XcmVersion) -> Result, ()> { + if !self.needs_migration(to_xcm_version) { + return Ok(None) + } + + let RemoteLockedFungibleRecord { amount, owner, locker, consumers } = self; + + let Ok(owner) = owner.into_version(to_xcm_version) else { return Err(()) }; + let Ok(locker) = locker.into_version(to_xcm_version) else { return Err(()) }; + + Ok(Some(RemoteLockedFungibleRecord { amount, owner, locker, consumers })) + } + } + + impl Pallet { + /// Migrates relevant data to the `required_xcm_version`. + pub(crate) fn migrate_data_to_xcm_version( + weight: &mut Weight, + required_xcm_version: XcmVersion, + ) { + const LOG_TARGET: &str = "runtime::xcm::pallet_xcm::migrate_data_to_xcm_version"; + + // check and migrate `Queries` + let queries_to_migrate = Queries::::iter().filter_map(|(id, data)| { + weight.saturating_add(T::DbWeight::get().reads(1)); + match data.try_migrate(required_xcm_version) { + Ok(Some(new_data)) => Some((id, new_data)), + Ok(None) => None, + Err(_) => { + tracing::error!( + target: LOG_TARGET, + ?id, + ?required_xcm_version, + "`Queries` cannot be migrated!" + ); + None + }, + } + }); + for (id, new_data) in queries_to_migrate { + tracing::info!( + target: LOG_TARGET, + query_id = ?id, + ?new_data, + "Migrating `Queries`" + ); + Queries::::insert(id, new_data); + weight.saturating_add(T::DbWeight::get().writes(1)); + } + + // check and migrate `LockedFungibles` + let locked_fungibles_to_migrate = + LockedFungibles::::iter().filter_map(|(id, data)| { + weight.saturating_add(T::DbWeight::get().reads(1)); + match data.try_migrate(required_xcm_version) { + Ok(Some(new_data)) => Some((id, new_data)), + Ok(None) => None, + Err(_) => { + tracing::error!( + target: LOG_TARGET, + ?id, + ?required_xcm_version, + "`LockedFungibles` cannot be migrated!" + ); + None + }, + } + }); + for (id, new_data) in locked_fungibles_to_migrate { + tracing::info!( + target: LOG_TARGET, + account_id = ?id, + ?new_data, + "Migrating `LockedFungibles`" + ); + LockedFungibles::::insert(id, new_data); + weight.saturating_add(T::DbWeight::get().writes(1)); + } + + // check and migrate `RemoteLockedFungibles` - 1. step - just data + let remote_locked_fungibles_to_migrate = + RemoteLockedFungibles::::iter().filter_map(|(id, data)| { + weight.saturating_add(T::DbWeight::get().reads(1)); + match data.try_migrate(required_xcm_version) { + Ok(Some(new_data)) => Some((id, new_data)), + Ok(None) => None, + Err(_) => { + tracing::error!( + target: LOG_TARGET, + ?id, + ?required_xcm_version, + "`RemoteLockedFungibles` data cannot be migrated!" + ); + None + }, + } + }); + for (id, new_data) in remote_locked_fungibles_to_migrate { + tracing::info!( + target: LOG_TARGET, + key = ?id, + amount = ?new_data.amount, + locker = ?new_data.locker, + owner = ?new_data.owner, + consumers_count = ?new_data.consumers.len(), + "Migrating `RemoteLockedFungibles` data" + ); + RemoteLockedFungibles::::insert(id, new_data); + weight.saturating_add(T::DbWeight::get().writes(1)); + } + + // check and migrate `RemoteLockedFungibles` - 2. step - key + let remote_locked_fungibles_keys_to_migrate = RemoteLockedFungibles::::iter_keys() + .filter_map(|key| { + if key.needs_migration(required_xcm_version) { + let old_key = key.clone(); + match key.try_migrate(required_xcm_version) { + Ok(Some(new_key)) => Some((old_key, new_key)), + Ok(None) => None, + Err(_) => { + tracing::error!( + target: LOG_TARGET, + id = ?old_key, + ?required_xcm_version, + "`RemoteLockedFungibles` key cannot be migrated!" + ); + None + }, + } + } else { + None + } + }); + for (old_key, new_key) in remote_locked_fungibles_keys_to_migrate { + weight.saturating_add(T::DbWeight::get().reads(1)); + // make sure, that we don't override accidentally other data + if RemoteLockedFungibles::::get(&new_key).is_some() { + tracing::error!( + target: LOG_TARGET, + ?old_key, + ?new_key, + "`RemoteLockedFungibles` already contains data for a `new_key`!" + ); + // let's just skip for now, could be potentially caused with missing this + // migration before (manual clean-up?). + continue; + } + + tracing::info!( + target: LOG_TARGET, + ?old_key, + ?new_key, + "Migrating `RemoteLockedFungibles` key" + ); + + // now we can swap the keys + RemoteLockedFungibles::::swap::< + ( + NMapKey, + NMapKey, + NMapKey, + ), + _, + _, + >(&old_key, &new_key); + weight.saturating_add(T::DbWeight::get().writes(1)); + } + } + } +} + pub mod v1 { use super::*; use crate::{CurrentMigration, VersionMigrationStage}; @@ -84,7 +386,80 @@ pub mod v1 { pub struct MigrateToLatestXcmVersion(core::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToLatestXcmVersion { fn on_runtime_upgrade() -> Weight { + let mut weight = T::DbWeight::get().reads(1); + + // trigger expensive/lazy migration (kind of multi-block) CurrentMigration::::put(VersionMigrationStage::default()); - T::DbWeight::get().writes(1) + weight.saturating_accrue(T::DbWeight::get().writes(1)); + + // migrate other operational data to the latest XCM version in-place + let latest = CurrentXcmVersion::get(); + Pallet::::migrate_data_to_xcm_version(&mut weight, latest); + + weight + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: alloc::vec::Vec) -> Result<(), sp_runtime::TryRuntimeError> { + use data::NeedsMigration; + const LOG_TARGET: &str = "runtime::xcm::pallet_xcm::migrate_to_latest"; + + let latest = CurrentXcmVersion::get(); + + let number_of_queries_to_migrate = crate::Queries::::iter() + .filter(|(id, data)| { + let needs_migration = data.needs_migration(latest); + if needs_migration { + tracing::warn!( + target: LOG_TARGET, + query_id = ?id, + query = ?data, + "Query was not migrated!" + ) + } + needs_migration + }) + .count(); + + let number_of_locked_fungibles_to_migrate = crate::LockedFungibles::::iter() + .filter_map(|(id, data)| { + if data.needs_migration(latest) { + tracing::warn!( + target: LOG_TARGET, + ?id, + ?data, + "LockedFungibles item was not migrated!" + ); + Some(true) + } else { + None + } + }) + .count(); + + let number_of_remote_locked_fungibles_to_migrate = + crate::RemoteLockedFungibles::::iter() + .filter_map(|(key, data)| { + if key.needs_migration(latest) || data.needs_migration(latest) { + tracing::warn!( + target: LOG_TARGET, + ?key, + "RemoteLockedFungibles item was not migrated!" + ); + Some(true) + } else { + None + } + }) + .count(); + + ensure!(number_of_queries_to_migrate == 0, "must migrate all `Queries`."); + ensure!(number_of_locked_fungibles_to_migrate == 0, "must migrate all `LockedFungibles`."); + ensure!( + number_of_remote_locked_fungibles_to_migrate == 0, + "must migrate all `RemoteLockedFungibles`." + ); + + Ok(()) } } diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs index c16c1a1ba986..e98a8f8d2ce7 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/mod.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -19,11 +19,15 @@ pub(crate) mod assets_transfer; use crate::{ - mock::*, pallet::SupportedVersion, AssetTraps, Config, CurrentMigration, Error, - ExecuteControllerWeightInfo, LatestVersionedLocation, Pallet, Queries, QueryStatus, - RecordedXcm, ShouldRecordXcm, VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, + migration::data::NeedsMigration, + mock::*, + pallet::{LockedFungibles, RemoteLockedFungibles, SupportedVersion}, + AssetTraps, Config, CurrentMigration, Error, ExecuteControllerWeightInfo, + LatestVersionedLocation, Pallet, Queries, QueryStatus, RecordedXcm, RemoteLockedFungibleRecord, + ShouldRecordXcm, VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, VersionNotifyTargets, WeightInfo, }; +use bounded_collections::BoundedVec; use frame_support::{ assert_err_ignore_postinfo, assert_noop, assert_ok, traits::{Currency, Hooks}, @@ -1258,6 +1262,168 @@ fn multistage_migration_works() { }) } +#[test] +fn migrate_data_to_xcm_version_works() { + new_test_ext_with_balances(vec![]).execute_with(|| { + // check `try-state` + assert!(Pallet::::do_try_state().is_ok()); + + let latest_version = XCM_VERSION; + let previous_version = XCM_VERSION - 1; + + // `Queries` migration + { + let origin = VersionedLocation::from(Location::parent()); + let query_id1 = 0; + let query_id2 = 2; + let query_as_latest = + QueryStatus::VersionNotifier { origin: origin.clone(), is_active: true }; + let query_as_previous = QueryStatus::VersionNotifier { + origin: origin.into_version(previous_version).unwrap(), + is_active: true, + }; + assert_ne!(query_as_latest, query_as_previous); + assert!(!query_as_latest.needs_migration(latest_version)); + assert!(!query_as_latest.needs_migration(previous_version)); + assert!(query_as_previous.needs_migration(latest_version)); + assert!(!query_as_previous.needs_migration(previous_version)); + + // store two queries: migrated and not migrated + Queries::::insert(query_id1, query_as_latest.clone()); + Queries::::insert(query_id2, query_as_previous); + assert!(Pallet::::do_try_state().is_ok()); + + // trigger migration + Pallet::::migrate_data_to_xcm_version(&mut Weight::zero(), latest_version); + + // no change for query_id1 + assert_eq!(Queries::::get(query_id1), Some(query_as_latest.clone())); + // change for query_id2 + assert_eq!(Queries::::get(query_id2), Some(query_as_latest)); + assert!(Pallet::::do_try_state().is_ok()); + } + + // `LockedFungibles` migration + { + let account1 = AccountId::new([13u8; 32]); + let account2 = AccountId::new([58u8; 32]); + let unlocker = VersionedLocation::from(Location::parent()); + let lockeds_as_latest = BoundedVec::truncate_from(vec![(0, unlocker.clone())]); + let lockeds_as_previous = BoundedVec::truncate_from(vec![( + 0, + unlocker.into_version(previous_version).unwrap(), + )]); + assert_ne!(lockeds_as_latest, lockeds_as_previous); + assert!(!lockeds_as_latest.needs_migration(latest_version)); + assert!(!lockeds_as_latest.needs_migration(previous_version)); + assert!(lockeds_as_previous.needs_migration(latest_version)); + assert!(!lockeds_as_previous.needs_migration(previous_version)); + + // store two lockeds: migrated and not migrated + LockedFungibles::::insert(&account1, lockeds_as_latest.clone()); + LockedFungibles::::insert(&account2, lockeds_as_previous); + assert!(Pallet::::do_try_state().is_ok()); + + // trigger migration + Pallet::::migrate_data_to_xcm_version(&mut Weight::zero(), latest_version); + + // no change for account1 + assert_eq!(LockedFungibles::::get(&account1), Some(lockeds_as_latest.clone())); + // change for account2 + assert_eq!(LockedFungibles::::get(&account2), Some(lockeds_as_latest)); + assert!(Pallet::::do_try_state().is_ok()); + } + + // `RemoteLockedFungibles` migration + { + let account1 = AccountId::new([13u8; 32]); + let account2 = AccountId::new([58u8; 32]); + let account3 = AccountId::new([97u8; 32]); + let asset_id = VersionedAssetId::from(AssetId(Location::parent())); + let owner = VersionedLocation::from(Location::parent()); + let locker = VersionedLocation::from(Location::parent()); + let key1_as_latest = (latest_version, account1, asset_id.clone()); + let key2_as_latest = (latest_version, account2, asset_id.clone()); + let key3_as_previous = ( + previous_version, + account3.clone(), + asset_id.clone().into_version(previous_version).unwrap(), + ); + let expected_key3_as_latest = (latest_version, account3, asset_id); + let data_as_latest = RemoteLockedFungibleRecord { + amount: Default::default(), + owner: owner.clone(), + locker: locker.clone(), + consumers: Default::default(), + }; + let data_as_previous = RemoteLockedFungibleRecord { + amount: Default::default(), + owner: owner.into_version(previous_version).unwrap(), + locker: locker.into_version(previous_version).unwrap(), + consumers: Default::default(), + }; + assert_ne!(data_as_latest.owner, data_as_previous.owner); + assert_ne!(data_as_latest.locker, data_as_previous.locker); + assert!(!key1_as_latest.needs_migration(latest_version)); + assert!(!key1_as_latest.needs_migration(previous_version)); + assert!(!key2_as_latest.needs_migration(latest_version)); + assert!(!key2_as_latest.needs_migration(previous_version)); + assert!(key3_as_previous.needs_migration(latest_version)); + assert!(!key3_as_previous.needs_migration(previous_version)); + assert!(!expected_key3_as_latest.needs_migration(latest_version)); + assert!(!expected_key3_as_latest.needs_migration(previous_version)); + assert!(!data_as_latest.needs_migration(latest_version)); + assert!(!data_as_latest.needs_migration(previous_version)); + assert!(data_as_previous.needs_migration(latest_version)); + assert!(!data_as_previous.needs_migration(previous_version)); + + // store three lockeds: + // fully migrated + RemoteLockedFungibles::::insert(&key1_as_latest, data_as_latest.clone()); + // only key migrated + RemoteLockedFungibles::::insert(&key2_as_latest, data_as_previous.clone()); + // neither key nor data migrated + RemoteLockedFungibles::::insert(&key3_as_previous, data_as_previous); + assert!(Pallet::::do_try_state().is_ok()); + + // trigger migration + Pallet::::migrate_data_to_xcm_version(&mut Weight::zero(), latest_version); + + let assert_locked_eq = + |left: Option>, + right: Option>| { + match (left, right) { + (None, Some(_)) | (Some(_), None) => + assert!(false, "Received unexpected message"), + (None, None) => (), + (Some(l), Some(r)) => { + assert_eq!(l.owner, r.owner); + assert_eq!(l.locker, r.locker); + }, + } + }; + + // no change + assert_locked_eq( + RemoteLockedFungibles::::get(&key1_as_latest), + Some(data_as_latest.clone()), + ); + // change - data migrated + assert_locked_eq( + RemoteLockedFungibles::::get(&key2_as_latest), + Some(data_as_latest.clone()), + ); + // fully migrated + assert_locked_eq(RemoteLockedFungibles::::get(&key3_as_previous), None); + assert_locked_eq( + RemoteLockedFungibles::::get(&expected_key3_as_latest), + Some(data_as_latest.clone()), + ); + assert!(Pallet::::do_try_state().is_ok()); + } + }) +} + #[test] fn record_xcm_works() { let balances = vec![(ALICE, INITIAL_BALANCE)]; diff --git a/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs b/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs index 4d9809e84f88..e6fe8e45c265 100644 --- a/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs +++ b/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs @@ -312,7 +312,7 @@ impl pallet_xcm::Config for Runtime { type UniversalLocation = UniversalLocation; // No version discovery needed const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; - type AdvertisedXcmVersion = frame_support::traits::ConstU32<3>; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type AdminOrigin = frame_system::EnsureRoot; // No locking type TrustedLockers = (); diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index d76ff21b8597..26ea226313f0 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -126,7 +126,6 @@ parameter_types! { pub const AnyNetwork: Option = None; pub UniversalLocation: InteriorLocation = (ByGenesis([0; 32]), Parachain(42)).into(); pub UnitWeightCost: u64 = 1_000; - pub static AdvertisedXcmVersion: u32 = 3; pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (AssetId(RelayLocation::get()), 1, 1); pub TrustedAssets: (AssetFilter, Location) = (All.into(), Here.into()); @@ -267,7 +266,7 @@ impl pallet_xcm::Config for Test { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = AdvertisedXcmVersion; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type TrustedLockers = (); type SovereignAccountOf = SovereignAccountOf; type Currency = Balances; diff --git a/polkadot/xcm/xcm-runtime-apis/tests/mock.rs b/polkadot/xcm/xcm-runtime-apis/tests/mock.rs index b3afa23503e3..4a5de8875007 100644 --- a/polkadot/xcm/xcm-runtime-apis/tests/mock.rs +++ b/polkadot/xcm/xcm-runtime-apis/tests/mock.rs @@ -145,7 +145,6 @@ parameter_types! { pub const MaxInstructions: u32 = 100; pub const NativeTokenPerSecondPerByte: (AssetId, u128, u128) = (AssetId(HereLocation::get()), 1, 1); pub UniversalLocation: InteriorLocation = [GlobalConsensus(NetworkId::Westend), Parachain(2000)].into(); - pub static AdvertisedXcmVersion: XcmVersion = 4; pub const HereLocation: Location = Location::here(); pub const RelayLocation: Location = Location::parent(); pub const MaxAssetsIntoHolding: u32 = 64; @@ -349,7 +348,7 @@ impl pallet_xcm::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = AdvertisedXcmVersion; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type AdminOrigin = EnsureRoot; type TrustedLockers = (); type SovereignAccountOf = (); diff --git a/prdoc/pr_6148.prdoc b/prdoc/pr_6148.prdoc new file mode 100644 index 000000000000..430a58dfefbb --- /dev/null +++ b/prdoc/pr_6148.prdoc @@ -0,0 +1,17 @@ +title: Fix migrations for pallet-xcm +doc: +- audience: Runtime Dev + description: |- + `pallet-xcm` stores some operational data that uses `Versioned*` XCM types. When we add a new XCM version (XV), we deprecate XV-2 and remove XV-3. + This PR extends the existing `MigrateToLatestXcmVersion` to include migration for the `Queries`, `LockedFungibles`, and `RemoteLockedFungibles` storage types. + Additionally, more checks were added to `try_state` for these types. + +crates: +- name: westend-runtime + bump: patch +- name: staging-xcm-builder + bump: none +- name: xcm-runtime-apis + bump: none +- name: pallet-xcm + bump: patch From a072ce81d2118a67e6ffbc417ae0815d0a56185f Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 25 Oct 2024 17:40:42 +0300 Subject: [PATCH 14/15] asset-hubs: simplify xcm-config (#6222) `ForeignCreatorsSovereignAccountOf` is used by `ForeignCreators` filter to convert location to `AccountId`, _after_ `ForeignCreators::IsForeign` filter passes for an (asset, location) pair. The `IsForeign` filter is the actual differentiator, so if a location passes it, we should support converting it to an `AccountId`. As such, this commit replaces `ForeignCreatorsSovereignAccountOf` converter with the more general `LocationToAccountId` converter. Signed-off-by: Adrian Catangiu --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 4 ++-- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 8 -------- .../runtimes/assets/asset-hub-rococo/tests/tests.rs | 8 ++++---- .../runtimes/assets/asset-hub-westend/src/lib.rs | 8 ++++---- .../runtimes/assets/asset-hub-westend/src/xcm_config.rs | 8 -------- .../runtimes/assets/asset-hub-westend/tests/tests.rs | 9 ++++----- 6 files changed, 14 insertions(+), 31 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index f768f803aeaf..420fa67f41f3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -82,7 +82,7 @@ use parachains_common::{ use sp_runtime::{Perbill, RuntimeDebug}; use testnet_parachains_constants::rococo::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ - ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, GovernanceLocation, + ForeignAssetsConvertedConcreteId, GovernanceLocation, LocationToAccountId, PoolAssetsConvertedConcreteId, TokenLocation, TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocation, }; @@ -424,7 +424,7 @@ impl pallet_assets::Config for Runtime { FromNetwork, xcm_config::bridging::to_westend::WestendOrEthereumAssetFromAssetHubWestend, ), - ForeignCreatorsSovereignAccountOf, + LocationToAccountId, AccountId, xcm::v4::Location, >; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 32fbfb6d0199..637c5900f7da 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -512,14 +512,6 @@ impl cumulus_pallet_xcm::Config for Runtime { type XcmExecutor = XcmExecutor; } -pub type ForeignCreatorsSovereignAccountOf = ( - SiblingParachainConvertsVia, - AccountId32Aliases, - ParentIsPreset, - GlobalConsensusEthereumConvertsFor, - GlobalConsensusParachainConvertsFor, -); - /// Simple conversion of `u32` into an `AssetId` for use in benchmarking. pub struct XcmBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 6e10f9168990..814323135325 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -21,8 +21,8 @@ use asset_hub_rococo_runtime::{ xcm_config, xcm_config::{ bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf, - LocationToAccountId, StakingPot, TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, LocationToAccountId, StakingPot, + TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig, }, AllPalletsWithoutSystem, AssetConversion, AssetDeposit, Assets, Balances, CollatorSelection, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, @@ -941,7 +941,7 @@ asset_test_utils::include_teleports_for_foreign_assets_works!( CheckingAccount, WeightToFee, ParachainSystem, - ForeignCreatorsSovereignAccountOf, + LocationToAccountId, ForeignAssetsInstance, collator_session_keys(), slot_durations(), @@ -1015,7 +1015,7 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p Runtime, XcmConfig, WeightToFee, - ForeignCreatorsSovereignAccountOf, + LocationToAccountId, ForeignAssetsInstance, Location, WithLatestLocationConverter, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index adfa2b74df65..066a1c2bdfdc 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -79,9 +79,9 @@ use testnet_parachains_constants::westend::{ consensus::*, currency::*, fee::WeightToFee, snowbridge::EthereumNetwork, time::*, }; use xcm_config::{ - ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, - PoolAssetsConvertedConcreteId, TrustBackedAssetsConvertedConcreteId, - TrustBackedAssetsPalletLocation, WestendLocation, XcmOriginToTransactDispatchOrigin, + ForeignAssetsConvertedConcreteId, LocationToAccountId, PoolAssetsConvertedConcreteId, + TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocation, WestendLocation, + XcmOriginToTransactDispatchOrigin, }; #[cfg(any(feature = "std", test))] @@ -423,7 +423,7 @@ impl pallet_assets::Config for Runtime { FromNetwork, xcm_config::bridging::to_rococo::RococoAssetFromAssetHubRococo, ), - ForeignCreatorsSovereignAccountOf, + LocationToAccountId, AccountId, xcm::v4::Location, >; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index cfd9fd2fd463..b554d00508be 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -535,14 +535,6 @@ impl cumulus_pallet_xcm::Config for Runtime { type XcmExecutor = XcmExecutor; } -pub type ForeignCreatorsSovereignAccountOf = ( - SiblingParachainConvertsVia, - AccountId32Aliases, - ParentIsPreset, - GlobalConsensusEthereumConvertsFor, - GlobalConsensusParachainConvertsFor, -); - /// Simple conversion of `u32` into an `AssetId` for use in benchmarking. pub struct XcmBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index ff84bdea69f4..6a48b19ce946 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -21,9 +21,8 @@ use asset_hub_westend_runtime::{ xcm_config, xcm_config::{ bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf, - LocationToAccountId, StakingPot, TrustBackedAssetsPalletLocation, WestendLocation, - XcmConfig, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, LocationToAccountId, StakingPot, + TrustBackedAssetsPalletLocation, WestendLocation, XcmConfig, }, AllPalletsWithoutSystem, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, @@ -966,7 +965,7 @@ asset_test_utils::include_teleports_for_foreign_assets_works!( CheckingAccount, WeightToFee, ParachainSystem, - ForeignCreatorsSovereignAccountOf, + LocationToAccountId, ForeignAssetsInstance, collator_session_keys(), slot_durations(), @@ -1044,7 +1043,7 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p Runtime, XcmConfig, WeightToFee, - ForeignCreatorsSovereignAccountOf, + LocationToAccountId, ForeignAssetsInstance, xcm::v4::Location, WithLatestLocationConverter, From 4c618a83d33281fe96f0e2b68a111ed227af22c0 Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:21:29 +0300 Subject: [PATCH 15/15] Switch node side to v2 candidate receipts (#5679) on top of https://github.com/paritytech/polkadot-sdk/pull/5423 This PR implements the plumbing work required for https://github.com/paritytech/polkadot-sdk/issues/5047 . I also added additional helper methods gated by feature "test" in primitives. TODO: - [x] PRDoc --------- Signed-off-by: Andrei Sandu Co-authored-by: GitHub Action --- cumulus/client/consensus/common/src/tests.rs | 2 +- cumulus/client/network/src/lib.rs | 12 +- cumulus/client/network/src/tests.rs | 22 ++- cumulus/client/pov-recovery/src/lib.rs | 6 +- cumulus/client/pov-recovery/src/tests.rs | 5 +- .../src/lib.rs | 5 +- .../client/relay-chain-interface/src/lib.rs | 6 +- .../src/blockchain_rpc_client.rs | 28 ++- .../relay-chain-rpc-interface/src/lib.rs | 5 +- .../src/rpc_client.rs | 19 +- polkadot/node/collation-generation/Cargo.toml | 1 + polkadot/node/collation-generation/src/lib.rs | 10 +- .../node/collation-generation/src/tests.rs | 84 ++++----- polkadot/node/core/approval-voting/Cargo.toml | 1 + .../approval-voting/src/approval_checking.rs | 10 +- .../approval-voting/src/approval_db/v1/mod.rs | 4 +- .../approval-voting/src/approval_db/v2/mod.rs | 4 +- .../src/approval_db/v2/tests.rs | 14 +- .../approval-voting/src/approval_db/v3/mod.rs | 4 +- .../src/approval_db/v3/tests.rs | 17 +- .../node/core/approval-voting/src/import.rs | 41 +++-- polkadot/node/core/approval-voting/src/lib.rs | 25 +-- polkadot/node/core/approval-voting/src/ops.rs | 4 +- .../approval-voting/src/persisted_entries.rs | 4 +- .../node/core/approval-voting/src/tests.rs | 107 +++++------ polkadot/node/core/av-store/src/lib.rs | 4 +- polkadot/node/core/av-store/src/tests.rs | 4 +- polkadot/node/core/backing/Cargo.toml | 1 + polkadot/node/core/backing/src/error.rs | 2 +- polkadot/node/core/backing/src/lib.rs | 46 ++--- polkadot/node/core/backing/src/tests/mod.rs | 35 ++-- .../src/tests/prospective_parachains.rs | 22 +-- .../node/core/bitfield-signing/src/lib.rs | 2 +- .../node/core/bitfield-signing/src/tests.rs | 6 +- .../node/core/candidate-validation/src/lib.rs | 17 +- .../core/candidate-validation/src/tests.rs | 51 ++++-- .../node/core/dispute-coordinator/Cargo.toml | 1 + .../core/dispute-coordinator/src/db/v1.rs | 25 +-- .../core/dispute-coordinator/src/import.rs | 6 +- .../dispute-coordinator/src/initialized.rs | 15 +- .../node/core/dispute-coordinator/src/lib.rs | 2 +- .../src/participation/mod.rs | 9 +- .../src/participation/queues/mod.rs | 5 +- .../src/participation/queues/tests.rs | 4 +- .../src/participation/tests.rs | 3 +- .../dispute-coordinator/src/scraping/mod.rs | 5 +- .../dispute-coordinator/src/scraping/tests.rs | 8 +- .../core/dispute-coordinator/src/tests.rs | 30 +-- .../node/core/parachains-inherent/src/lib.rs | 2 +- .../core/prospective-parachains/Cargo.toml | 1 + .../src/fragment_chain/mod.rs | 20 +- .../src/fragment_chain/tests.rs | 20 +- .../core/prospective-parachains/src/lib.rs | 13 +- .../core/prospective-parachains/src/tests.rs | 25 +-- polkadot/node/core/provisioner/Cargo.toml | 2 + .../disputes/prioritized_selection/tests.rs | 14 +- polkadot/node/core/provisioner/src/lib.rs | 20 +- polkadot/node/core/provisioner/src/tests.rs | 58 +++--- polkadot/node/core/runtime-api/src/cache.rs | 22 ++- polkadot/node/core/runtime-api/src/tests.rs | 22 ++- polkadot/node/malus/src/variants/common.rs | 10 +- .../variants/dispute_finalized_candidates.rs | 2 +- .../src/variants/suggest_garbage_candidate.rs | 13 +- .../src/requester/fetch_task/mod.rs | 8 +- .../src/requester/mod.rs | 2 +- .../src/requester/tests.rs | 2 +- .../src/tests/mock.rs | 8 +- .../src/tests/mod.rs | 2 +- .../src/tests/state.rs | 2 +- .../network/availability-recovery/src/lib.rs | 8 +- .../availability-recovery/src/tests.rs | 34 ++-- .../src/collator_side/collation.rs | 4 +- .../src/collator_side/mod.rs | 13 +- .../src/validator_side/collation.rs | 13 +- .../src/validator_side/mod.rs | 26 +-- .../src/validator_side/tests/mod.rs | 44 +++-- .../tests/prospective_parachains.rs | 20 +- .../src/receiver/batches/batch.rs | 2 +- .../src/receiver/batches/mod.rs | 2 +- .../dispute-distribution/src/receiver/mod.rs | 2 +- .../src/sender/send_task.rs | 2 +- .../dispute-distribution/src/tests/mock.rs | 8 +- .../dispute-distribution/src/tests/mod.rs | 4 +- .../protocol/src/request_response/v1.rs | 7 +- .../protocol/src/request_response/v2.rs | 4 +- .../network/statement-distribution/Cargo.toml | 1 + .../src/legacy_v1/mod.rs | 9 +- .../src/legacy_v1/requester.rs | 4 +- .../src/legacy_v1/responder.rs | 4 +- .../src/legacy_v1/tests.rs | 41 +++-- .../src/v2/candidates.rs | 12 +- .../statement-distribution/src/v2/mod.rs | 16 +- .../statement-distribution/src/v2/requests.rs | 22 ++- .../src/v2/tests/mod.rs | 6 +- .../node/overseer/examples/minimal-example.rs | 6 +- polkadot/node/overseer/src/tests.rs | 19 +- .../node/primitives/src/disputes/message.rs | 3 +- polkadot/node/primitives/src/disputes/mod.rs | 6 +- polkadot/node/primitives/src/lib.rs | 8 +- .../node/service/src/parachains_db/upgrade.rs | 6 +- polkadot/node/subsystem-bench/Cargo.toml | 2 +- .../src/lib/approval/helpers.rs | 6 +- .../src/lib/approval/message_generator.rs | 4 +- .../subsystem-bench/src/lib/approval/mod.rs | 5 +- .../src/lib/availability/mod.rs | 2 +- .../src/lib/availability/test_state.rs | 14 +- .../src/lib/mock/runtime_api.rs | 7 +- .../src/lib/statement/test_state.rs | 21 ++- polkadot/node/subsystem-types/src/messages.rs | 37 ++-- .../subsystem-types/src/runtime_client.rs | 56 ++---- .../src/inclusion_emulator/mod.rs | 4 +- polkadot/node/subsystem-util/src/lib.rs | 15 +- .../node/subsystem-util/src/runtime/mod.rs | 12 +- .../test-parachains/adder/collator/src/lib.rs | 2 +- .../undying/collator/src/lib.rs | 2 +- polkadot/primitives/src/v8/mod.rs | 2 +- polkadot/primitives/src/vstaging/mod.rs | 173 ++++++++++++++++-- polkadot/primitives/test-helpers/src/lib.rs | 36 +++- .../runtime/parachains/src/inclusion/tests.rs | 2 +- .../parachains/src/paras_inherent/tests.rs | 4 +- polkadot/statement-table/src/lib.rs | 4 +- prdoc/pr_5679.prdoc | 80 ++++++++ 122 files changed, 1136 insertions(+), 721 deletions(-) create mode 100644 prdoc/pr_5679.prdoc diff --git a/cumulus/client/consensus/common/src/tests.rs b/cumulus/client/consensus/common/src/tests.rs index 94e2304011be..79e620db3bfa 100644 --- a/cumulus/client/consensus/common/src/tests.rs +++ b/cumulus/client/consensus/common/src/tests.rs @@ -20,7 +20,7 @@ use async_trait::async_trait; use codec::Encode; use cumulus_client_pov_recovery::RecoveryKind; use cumulus_primitives_core::{ - relay_chain::{BlockId, BlockNumber, CoreState}, + relay_chain::{vstaging::CoreState, BlockId, BlockNumber}, CumulusDigestItem, InboundDownwardMessage, InboundHrmpMessage, }; use cumulus_relay_chain_interface::{ diff --git a/cumulus/client/network/src/lib.rs b/cumulus/client/network/src/lib.rs index 01ad15bed4da..3b9c0fc81ece 100644 --- a/cumulus/client/network/src/lib.rs +++ b/cumulus/client/network/src/lib.rs @@ -32,8 +32,8 @@ use polkadot_node_primitives::{CollationSecondedSignal, Statement}; use polkadot_node_subsystem::messages::RuntimeApiRequest; use polkadot_parachain_primitives::primitives::HeadData; use polkadot_primitives::{ - CandidateReceipt, CompactStatement, Hash as PHash, Id as ParaId, OccupiedCoreAssumption, - SigningContext, UncheckedSigned, + vstaging::CandidateReceiptV2 as CandidateReceipt, CompactStatement, Hash as PHash, + Id as ParaId, OccupiedCoreAssumption, SigningContext, UncheckedSigned, }; use codec::{Decode, DecodeAll, Encode}; @@ -79,7 +79,7 @@ impl Decode for BlockAnnounceData { let relay_parent = match PHash::decode(input) { Ok(p) => p, // For being backwards compatible, we support missing relay-chain parent. - Err(_) => receipt.descriptor.relay_parent, + Err(_) => receipt.descriptor.relay_parent(), }; Ok(Self { receipt, statement, relay_parent }) @@ -108,7 +108,7 @@ impl BlockAnnounceData { return Err(Validation::Failure { disconnect: true }) } - if HeadData(encoded_header).hash() != self.receipt.descriptor.para_head { + if HeadData(encoded_header).hash() != self.receipt.descriptor.para_head() { tracing::debug!( target: LOG_TARGET, "Receipt para head hash doesn't match the hash of the header in the block announcement", @@ -302,7 +302,7 @@ where } .map_err(|e| Box::new(BlockAnnounceError(format!("{:?}", e))) as Box<_>)?; - Ok(candidate_receipts.into_iter().map(|cr| cr.descriptor.para_head)) + Ok(candidate_receipts.into_iter().map(|cr| cr.descriptor.para_head())) } /// Handle a block announcement with empty data (no statement) attached to it. @@ -399,7 +399,7 @@ where return Ok(e) } - let relay_parent = block_announce_data.receipt.descriptor.relay_parent; + let relay_parent = block_announce_data.receipt.descriptor.relay_parent(); relay_chain_interface .wait_for_block(relay_parent) diff --git a/cumulus/client/network/src/tests.rs b/cumulus/client/network/src/tests.rs index 4b3473645210..009f922008b1 100644 --- a/cumulus/client/network/src/tests.rs +++ b/cumulus/client/network/src/tests.rs @@ -26,10 +26,11 @@ use futures::{executor::block_on, poll, task::Poll, FutureExt, Stream, StreamExt use parking_lot::Mutex; use polkadot_node_primitives::{SignedFullStatement, Statement}; use polkadot_primitives::{ + vstaging::{CommittedCandidateReceiptV2, CoreState}, BlockNumber, CandidateCommitments, CandidateDescriptor, CollatorPair, - CommittedCandidateReceipt, CoreState, Hash as PHash, HeadData, InboundDownwardMessage, - InboundHrmpMessage, OccupiedCoreAssumption, PersistedValidationData, SessionIndex, - SigningContext, ValidationCodeHash, ValidatorId, + CommittedCandidateReceipt, Hash as PHash, HeadData, InboundDownwardMessage, InboundHrmpMessage, + OccupiedCoreAssumption, PersistedValidationData, SessionIndex, SigningContext, + ValidationCodeHash, ValidatorId, }; use polkadot_test_client::{ Client as PClient, ClientBlockImportExt, DefaultTestClientBuilderExt, FullBackend as PBackend, @@ -166,7 +167,7 @@ impl RelayChainInterface for DummyRelayChainInterface { &self, _: PHash, _: ParaId, - ) -> RelayChainResult> { + ) -> RelayChainResult> { if self.data.lock().runtime_version >= RuntimeApiRequest::CANDIDATES_PENDING_AVAILABILITY_RUNTIME_REQUIREMENT { @@ -174,7 +175,7 @@ impl RelayChainInterface for DummyRelayChainInterface { } if self.data.lock().has_pending_availability { - Ok(Some(dummy_candidate())) + Ok(Some(dummy_candidate().into())) } else { Ok(None) } @@ -184,7 +185,7 @@ impl RelayChainInterface for DummyRelayChainInterface { &self, _: PHash, _: ParaId, - ) -> RelayChainResult> { + ) -> RelayChainResult> { if self.data.lock().runtime_version < RuntimeApiRequest::CANDIDATES_PENDING_AVAILABILITY_RUNTIME_REQUIREMENT { @@ -192,7 +193,7 @@ impl RelayChainInterface for DummyRelayChainInterface { } if self.data.lock().has_pending_availability { - Ok(vec![dummy_candidate()]) + Ok(vec![dummy_candidate().into()]) } else { Ok(vec![]) } @@ -412,7 +413,7 @@ async fn make_gossip_message_and_header( validation_code_hash: ValidationCodeHash::from(PHash::random()), }, }; - let statement = Statement::Seconded(candidate_receipt); + let statement = Statement::Seconded(candidate_receipt.into()); let signed = SignedFullStatement::sign( &keystore, statement, @@ -525,7 +526,7 @@ fn legacy_block_announce_data_handling() { let block_data = BlockAnnounceData::decode(&mut &data[..]).expect("Decoding works from legacy works"); - assert_eq!(receipt.descriptor.relay_parent, block_data.relay_parent); + assert_eq!(receipt.descriptor.relay_parent(), block_data.relay_parent); let data = block_data.encode(); LegacyBlockAnnounceData::decode(&mut &data[..]).expect("Decoding works"); @@ -600,7 +601,8 @@ async fn check_statement_seconded() { erasure_root: PHash::random(), signature: sp_core::sr25519::Signature::default().into(), validation_code_hash: ValidationCodeHash::from(PHash::random()), - }, + } + .into(), }, statement: signed_statement.convert_payload().into(), relay_parent, diff --git a/cumulus/client/pov-recovery/src/lib.rs b/cumulus/client/pov-recovery/src/lib.rs index 043cba12d193..87349aef0c93 100644 --- a/cumulus/client/pov-recovery/src/lib.rs +++ b/cumulus/client/pov-recovery/src/lib.rs @@ -56,7 +56,11 @@ use polkadot_node_primitives::{PoV, POV_BOMB_LIMIT}; use polkadot_node_subsystem::messages::{AvailabilityRecoveryMessage, RuntimeApiRequest}; use polkadot_overseer::Handle as OverseerHandle; use polkadot_primitives::{ - CandidateReceipt, CommittedCandidateReceipt, Id as ParaId, SessionIndex, + vstaging::{ + CandidateReceiptV2 as CandidateReceipt, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, + }, + Id as ParaId, SessionIndex, }; use cumulus_primitives_core::ParachainBlockData; diff --git a/cumulus/client/pov-recovery/src/tests.rs b/cumulus/client/pov-recovery/src/tests.rs index 94dec32485cc..d528a92a52a8 100644 --- a/cumulus/client/pov-recovery/src/tests.rs +++ b/cumulus/client/pov-recovery/src/tests.rs @@ -18,7 +18,7 @@ use super::*; use assert_matches::assert_matches; use codec::{Decode, Encode}; use cumulus_primitives_core::relay_chain::{ - BlockId, CandidateCommitments, CandidateDescriptor, CoreIndex, CoreState, + vstaging::CoreState, BlockId, CandidateCommitments, CandidateDescriptor, CoreIndex, }; use cumulus_relay_chain_interface::{ InboundDownwardMessage, InboundHrmpMessage, OccupiedCoreAssumption, PHash, PHeader, @@ -532,7 +532,8 @@ fn make_candidate_chain(candidate_number_range: Range) -> Vec Result>, sp_api::ApiError> { + ) -> Result< + Vec>, + sp_api::ApiError, + > { Ok(self.rpc_client.parachain_host_availability_cores(at).await?) } @@ -212,8 +215,11 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { async fn candidate_pending_availability( &self, at: Hash, - para_id: ParaId, - ) -> Result>, sp_api::ApiError> { + para_id: cumulus_primitives_core::ParaId, + ) -> Result< + Option>, + sp_api::ApiError, + > { Ok(self .rpc_client .parachain_host_candidate_pending_availability(at, para_id) @@ -223,7 +229,7 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { async fn candidate_events( &self, at: Hash, - ) -> Result>, sp_api::ApiError> { + ) -> Result>, sp_api::ApiError> { Ok(self.rpc_client.parachain_host_candidate_events(at).await?) } @@ -266,7 +272,8 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { async fn on_chain_votes( &self, at: Hash, - ) -> Result>, sp_api::ApiError> { + ) -> Result>, sp_api::ApiError> + { Ok(self.rpc_client.parachain_host_on_chain_votes(at).await?) } @@ -437,8 +444,11 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { async fn candidates_pending_availability( &self, at: Hash, - para_id: ParaId, - ) -> Result>, sp_api::ApiError> { + para_id: cumulus_primitives_core::ParaId, + ) -> Result< + Vec>, + sp_api::ApiError, + > { Ok(self .rpc_client .parachain_host_candidates_pending_availability(at, para_id) diff --git a/cumulus/client/relay-chain-rpc-interface/src/lib.rs b/cumulus/client/relay-chain-rpc-interface/src/lib.rs index f53cdeffea94..0e2f6c054c40 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/lib.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/lib.rs @@ -18,8 +18,9 @@ use async_trait::async_trait; use core::time::Duration; use cumulus_primitives_core::{ relay_chain::{ - CommittedCandidateReceipt, Hash as RelayHash, Header as RelayHeader, InboundHrmpMessage, - OccupiedCoreAssumption, SessionIndex, ValidationCodeHash, ValidatorId, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, Hash as RelayHash, + Header as RelayHeader, InboundHrmpMessage, OccupiedCoreAssumption, SessionIndex, + ValidationCodeHash, ValidatorId, }, InboundDownwardMessage, ParaId, PersistedValidationData, }; diff --git a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs index d8e5abaddc6b..d7785d92c73a 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs @@ -32,13 +32,18 @@ use codec::{Decode, Encode}; use cumulus_primitives_core::{ relay_chain::{ - async_backing::{AsyncBackingParams, BackingState}, - slashing, ApprovalVotingParams, BlockNumber, CandidateCommitments, CandidateEvent, - CandidateHash, CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, - ExecutorParams, GroupRotationInfo, Hash as RelayHash, Header as RelayHeader, - InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, PvfCheckStatement, - ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, - ValidatorId, ValidatorIndex, ValidatorSignature, + async_backing::AsyncBackingParams, + slashing, + vstaging::{ + async_backing::BackingState, CandidateEvent, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + ScrapedOnChainVotes, + }, + ApprovalVotingParams, BlockNumber, CandidateCommitments, CandidateHash, CoreIndex, + DisputeState, ExecutorParams, GroupRotationInfo, Hash as RelayHash, Header as RelayHeader, + InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, PvfCheckStatement, SessionIndex, + SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, }, InboundDownwardMessage, ParaId, PersistedValidationData, }; diff --git a/polkadot/node/collation-generation/Cargo.toml b/polkadot/node/collation-generation/Cargo.toml index 4b0a5f7248ab..855b6b0e86eb 100644 --- a/polkadot/node/collation-generation/Cargo.toml +++ b/polkadot/node/collation-generation/Cargo.toml @@ -28,3 +28,4 @@ polkadot-primitives-test-helpers = { workspace = true } assert_matches = { workspace = true } rstest = { workspace = true } sp-keyring = { workspace = true, default-features = true } +polkadot-primitives = { workspace = true, features = ["test"] } diff --git a/polkadot/node/collation-generation/src/lib.rs b/polkadot/node/collation-generation/src/lib.rs index 50adbddea413..f04f69cbd380 100644 --- a/polkadot/node/collation-generation/src/lib.rs +++ b/polkadot/node/collation-generation/src/lib.rs @@ -48,9 +48,10 @@ use polkadot_node_subsystem_util::{ request_validators, runtime::fetch_claim_queue, }; use polkadot_primitives::{ - collator_signature_payload, CandidateCommitments, CandidateDescriptor, CandidateReceipt, - CollatorPair, CoreIndex, CoreState, Hash, Id as ParaId, OccupiedCoreAssumption, - PersistedValidationData, ScheduledCore, ValidationCodeHash, + collator_signature_payload, + vstaging::{CandidateReceiptV2 as CandidateReceipt, CoreState}, + CandidateCommitments, CandidateDescriptor, CollatorPair, CoreIndex, Hash, Id as ParaId, + OccupiedCoreAssumption, PersistedValidationData, ScheduledCore, ValidationCodeHash, }; use sp_core::crypto::Pair; use std::sync::Arc; @@ -607,7 +608,8 @@ async fn construct_and_distribute_receipt( erasure_root, para_head: commitments.head_data.hash(), validation_code_hash, - }, + } + .into(), }; gum::debug!( diff --git a/polkadot/node/collation-generation/src/tests.rs b/polkadot/node/collation-generation/src/tests.rs index 7f76988bb035..78b35fde0ea2 100644 --- a/polkadot/node/collation-generation/src/tests.rs +++ b/polkadot/node/collation-generation/src/tests.rs @@ -30,12 +30,12 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers::{subsystem_test_harness, TestSubsystemContextHandle}; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ - async_backing::{BackingState, CandidatePendingAvailability}, + vstaging::async_backing::{BackingState, CandidatePendingAvailability}, AsyncBackingParams, BlockNumber, CollatorPair, HeadData, PersistedValidationData, ScheduledCore, ValidationCode, }; use polkadot_primitives_test_helpers::{ - dummy_candidate_descriptor, dummy_hash, dummy_head_data, dummy_validator, make_candidate, + dummy_candidate_descriptor_v2, dummy_hash, dummy_head_data, dummy_validator, make_candidate, }; use rstest::rstest; use sp_keyring::sr25519::Keyring as Sr25519Keyring; @@ -504,22 +504,22 @@ fn sends_distribute_collation_message(#[case] runtime_version: u32) { // descriptor has a valid signature, then just copy in the generated signature // and check the rest of the fields for equality. assert!(CollatorPair::verify( - &descriptor.signature, + &descriptor.signature().unwrap(), &collator_signature_payload( - &descriptor.relay_parent, - &descriptor.para_id, - &descriptor.persisted_validation_data_hash, - &descriptor.pov_hash, - &descriptor.validation_code_hash, + &descriptor.relay_parent(), + &descriptor.para_id(), + &descriptor.persisted_validation_data_hash(), + &descriptor.pov_hash(), + &descriptor.validation_code_hash(), ) .as_ref(), - &descriptor.collator, + &descriptor.collator().unwrap(), )); let expect_descriptor = { let mut expect_descriptor = expect_descriptor; - expect_descriptor.signature = descriptor.signature.clone(); - expect_descriptor.erasure_root = descriptor.erasure_root; - expect_descriptor + expect_descriptor.signature = descriptor.signature().clone().unwrap(); + expect_descriptor.erasure_root = descriptor.erasure_root(); + expect_descriptor.into() }; assert_eq!(descriptor, expect_descriptor); }, @@ -658,7 +658,7 @@ fn fallback_when_no_validation_code_hash_api(#[case] runtime_version: u32) { .. }) => { let CandidateReceipt { descriptor, .. } = candidate_receipt; - assert_eq!(expect_validation_code_hash, descriptor.validation_code_hash); + assert_eq!(expect_validation_code_hash, descriptor.validation_code_hash()); }, _ => panic!("received wrong message type"), } @@ -752,9 +752,9 @@ fn submit_collation_leads_to_distribution() { }) => { let CandidateReceipt { descriptor, .. } = candidate_receipt; assert_eq!(parent_head_data_hash, parent_head.hash()); - assert_eq!(descriptor.persisted_validation_data_hash, expected_pvd.hash()); - assert_eq!(descriptor.para_head, dummy_head_data().hash()); - assert_eq!(descriptor.validation_code_hash, validation_code_hash); + assert_eq!(descriptor.persisted_validation_data_hash(), expected_pvd.hash()); + assert_eq!(descriptor.para_head(), dummy_head_data().hash()); + assert_eq!(descriptor.validation_code_hash(), validation_code_hash); } ); @@ -772,16 +772,17 @@ fn distribute_collation_for_occupied_core_with_async_backing_enabled(#[case] run let para_id = ParaId::from(5); // One core, in occupied state. The data in `CoreState` and `ClaimQueue` should match. - let cores: Vec = vec![CoreState::Occupied(polkadot_primitives::OccupiedCore { - next_up_on_available: Some(ScheduledCore { para_id, collator: None }), - occupied_since: 1, - time_out_at: 10, - next_up_on_time_out: Some(ScheduledCore { para_id, collator: None }), - availability: Default::default(), // doesn't matter - group_responsible: polkadot_primitives::GroupIndex(0), - candidate_hash: Default::default(), - candidate_descriptor: dummy_candidate_descriptor(dummy_hash()), - })]; + let cores: Vec = + vec![CoreState::Occupied(polkadot_primitives::vstaging::OccupiedCore { + next_up_on_available: Some(ScheduledCore { para_id, collator: None }), + occupied_since: 1, + time_out_at: 10, + next_up_on_time_out: Some(ScheduledCore { para_id, collator: None }), + availability: Default::default(), // doesn't matter + group_responsible: polkadot_primitives::GroupIndex(0), + candidate_hash: Default::default(), + candidate_descriptor: dummy_candidate_descriptor_v2(dummy_hash()), + })]; let claim_queue = BTreeMap::from([(CoreIndex::from(0), VecDeque::from([para_id]))]).into(); test_harness(|mut virtual_overseer| async move { @@ -882,7 +883,7 @@ fn distribute_collation_for_occupied_cores_with_async_backing_enabled_and_elasti let cores = (0..3) .into_iter() .map(|idx| { - CoreState::Occupied(polkadot_primitives::OccupiedCore { + CoreState::Occupied(polkadot_primitives::vstaging::OccupiedCore { next_up_on_available: Some(ScheduledCore { para_id, collator: None }), occupied_since: 0, time_out_at: 10, @@ -890,7 +891,7 @@ fn distribute_collation_for_occupied_cores_with_async_backing_enabled_and_elasti availability: Default::default(), // doesn't matter group_responsible: polkadot_primitives::GroupIndex(idx as u32), candidate_hash: Default::default(), - candidate_descriptor: dummy_candidate_descriptor(dummy_hash()), + candidate_descriptor: dummy_candidate_descriptor_v2(dummy_hash()), }) }) .collect::>(); @@ -1008,16 +1009,17 @@ fn no_collation_is_distributed_for_occupied_core_with_async_backing_disabled( let para_id = ParaId::from(5); // One core, in occupied state. The data in `CoreState` and `ClaimQueue` should match. - let cores: Vec = vec![CoreState::Occupied(polkadot_primitives::OccupiedCore { - next_up_on_available: Some(ScheduledCore { para_id, collator: None }), - occupied_since: 1, - time_out_at: 10, - next_up_on_time_out: Some(ScheduledCore { para_id, collator: None }), - availability: Default::default(), // doesn't matter - group_responsible: polkadot_primitives::GroupIndex(0), - candidate_hash: Default::default(), - candidate_descriptor: dummy_candidate_descriptor(dummy_hash()), - })]; + let cores: Vec = + vec![CoreState::Occupied(polkadot_primitives::vstaging::OccupiedCore { + next_up_on_available: Some(ScheduledCore { para_id, collator: None }), + occupied_since: 1, + time_out_at: 10, + next_up_on_time_out: Some(ScheduledCore { para_id, collator: None }), + availability: Default::default(), // doesn't matter + group_responsible: polkadot_primitives::GroupIndex(0), + candidate_hash: Default::default(), + candidate_descriptor: dummy_candidate_descriptor_v2(dummy_hash()), + })]; let claim_queue = BTreeMap::from([(CoreIndex::from(0), VecDeque::from([para_id]))]).into(); test_harness(|mut virtual_overseer| async move { @@ -1248,9 +1250,9 @@ mod helpers { .. }) => { assert_eq!(parent_head_data_hash, parent_head.hash()); - assert_eq!(candidate_receipt.descriptor().persisted_validation_data_hash, pvd.hash()); - assert_eq!(candidate_receipt.descriptor().para_head, dummy_head_data().hash()); - assert_eq!(candidate_receipt.descriptor().validation_code_hash, validation_code_hash); + assert_eq!(candidate_receipt.descriptor().persisted_validation_data_hash(), pvd.hash()); + assert_eq!(candidate_receipt.descriptor().para_head(), dummy_head_data().hash()); + assert_eq!(candidate_receipt.descriptor().validation_code_hash(), validation_code_hash); } ); } diff --git a/polkadot/node/core/approval-voting/Cargo.toml b/polkadot/node/core/approval-voting/Cargo.toml index 2c3db866566c..f9754d2babc9 100644 --- a/polkadot/node/core/approval-voting/Cargo.toml +++ b/polkadot/node/core/approval-voting/Cargo.toml @@ -53,6 +53,7 @@ kvdb-memorydb = { workspace = true } polkadot-primitives-test-helpers = { workspace = true } log = { workspace = true, default-features = true } sp-tracing = { workspace = true } +polkadot-primitives = { workspace = true, features = ["test"] } polkadot-subsystem-bench = { workspace = true } diff --git a/polkadot/node/core/approval-voting/src/approval_checking.rs b/polkadot/node/core/approval-voting/src/approval_checking.rs index 3774edc69981..3b7262a46826 100644 --- a/polkadot/node/core/approval-voting/src/approval_checking.rs +++ b/polkadot/node/core/approval-voting/src/approval_checking.rs @@ -509,13 +509,13 @@ mod tests { use crate::{approval_db, BTreeMap}; use bitvec::{bitvec, order::Lsb0 as BitOrderLsb0, vec::BitVec}; use polkadot_primitives::GroupIndex; - use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; + use polkadot_primitives_test_helpers::{dummy_candidate_receipt_v2, dummy_hash}; #[test] fn pending_is_not_approved() { let candidate = CandidateEntry::from_v1( approval_db::v1::CandidateEntry { - candidate: dummy_candidate_receipt(dummy_hash()), + candidate: dummy_candidate_receipt_v2(dummy_hash()), session: 0, block_assignments: BTreeMap::default(), approvals: BitVec::default(), @@ -550,7 +550,7 @@ mod tests { fn exact_takes_only_assignments_up_to() { let mut candidate: CandidateEntry = CandidateEntry::from_v1( approval_db::v1::CandidateEntry { - candidate: dummy_candidate_receipt(dummy_hash()), + candidate: dummy_candidate_receipt_v2(dummy_hash()), session: 0, block_assignments: BTreeMap::default(), approvals: bitvec![u8, BitOrderLsb0; 0; 10], @@ -624,7 +624,7 @@ mod tests { fn one_honest_node_always_approves() { let mut candidate: CandidateEntry = CandidateEntry::from_v1( approval_db::v1::CandidateEntry { - candidate: dummy_candidate_receipt(dummy_hash()), + candidate: dummy_candidate_receipt_v2(dummy_hash()), session: 0, block_assignments: BTreeMap::default(), approvals: bitvec![u8, BitOrderLsb0; 0; 10], @@ -1097,7 +1097,7 @@ mod tests { let mut candidate: CandidateEntry = CandidateEntry::from_v1( approval_db::v1::CandidateEntry { - candidate: dummy_candidate_receipt(dummy_hash()), + candidate: dummy_candidate_receipt_v2(dummy_hash()), session: 0, block_assignments: BTreeMap::default(), approvals: bitvec![u8, BitOrderLsb0; 0; 3], diff --git a/polkadot/node/core/approval-voting/src/approval_db/v1/mod.rs b/polkadot/node/core/approval-voting/src/approval_db/v1/mod.rs index 53e9db64f636..87a1d20b92f5 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v1/mod.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v1/mod.rs @@ -25,8 +25,8 @@ use codec::{Decode, Encode}; use polkadot_node_primitives::approval::v1::{AssignmentCert, DelayTranche}; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateReceipt, CoreIndex, GroupIndex, Hash, SessionIndex, - ValidatorIndex, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, CoreIndex, + GroupIndex, Hash, SessionIndex, ValidatorIndex, ValidatorSignature, }; use sp_consensus_slots::Slot; use std::collections::BTreeMap; diff --git a/polkadot/node/core/approval-voting/src/approval_db/v2/mod.rs b/polkadot/node/core/approval-voting/src/approval_db/v2/mod.rs index cd9256a5d47e..63c6cbf40b89 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v2/mod.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v2/mod.rs @@ -21,8 +21,8 @@ use polkadot_node_primitives::approval::{v1::DelayTranche, v2::AssignmentCertV2} use polkadot_node_subsystem::{SubsystemError, SubsystemResult}; use polkadot_node_subsystem_util::database::{DBTransaction, Database}; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateIndex, CandidateReceipt, CoreIndex, GroupIndex, Hash, - SessionIndex, ValidatorIndex, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, CandidateIndex, + CoreIndex, GroupIndex, Hash, SessionIndex, ValidatorIndex, ValidatorSignature, }; use sp_consensus_slots::Slot; diff --git a/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs b/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs index 06a3cc1e306b..866702f861c1 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs @@ -26,7 +26,8 @@ use crate::{ ops::{add_block_entry, canonicalize, force_approve, NewCandidateInfo}, }; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateReceipt, CoreIndex, GroupIndex, Hash, + vstaging::{CandidateReceiptV2 as CandidateReceipt, MutateDescriptorV2}, + BlockNumber, CandidateHash, CoreIndex, GroupIndex, Hash, }; use polkadot_node_subsystem_util::database::Database; @@ -35,7 +36,8 @@ use sp_consensus_slots::Slot; use std::{collections::HashMap, sync::Arc}; use polkadot_primitives_test_helpers::{ - dummy_candidate_receipt, dummy_candidate_receipt_bad_sig, dummy_hash, + dummy_candidate_receipt_bad_sig, dummy_candidate_receipt_v2, + dummy_candidate_receipt_v2_bad_sig, dummy_hash, }; const DATA_COL: u32 = 0; @@ -72,10 +74,10 @@ fn make_block_entry( } fn make_candidate(para_id: ParaId, relay_parent: Hash) -> CandidateReceipt { - let mut c = dummy_candidate_receipt(dummy_hash()); + let mut c = dummy_candidate_receipt_v2(dummy_hash()); - c.descriptor.para_id = para_id; - c.descriptor.relay_parent = relay_parent; + c.descriptor.set_para_id(para_id); + c.descriptor.set_relay_parent(relay_parent); c } @@ -95,7 +97,7 @@ fn read_write() { make_block_entry(hash_a, Default::default(), 1, vec![(CoreIndex(0), candidate_hash)]); let candidate_entry = CandidateEntry { - candidate: dummy_candidate_receipt_bad_sig(dummy_hash(), None), + candidate: dummy_candidate_receipt_v2_bad_sig(dummy_hash(), None), session: 5, block_assignments: vec![( hash_a, diff --git a/polkadot/node/core/approval-voting/src/approval_db/v3/mod.rs b/polkadot/node/core/approval-voting/src/approval_db/v3/mod.rs index 7118fb6770fd..bc34f88af80a 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v3/mod.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v3/mod.rs @@ -25,8 +25,8 @@ use polkadot_node_subsystem::SubsystemResult; use polkadot_node_subsystem_util::database::{DBTransaction, Database}; use polkadot_overseer::SubsystemError; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateIndex, CandidateReceipt, CoreIndex, GroupIndex, Hash, - SessionIndex, ValidatorIndex, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, CandidateIndex, + CoreIndex, GroupIndex, Hash, SessionIndex, ValidatorIndex, ValidatorSignature, }; use sp_consensus_slots::Slot; diff --git a/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs b/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs index d2a1d7d400b1..372dd49803cb 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs @@ -25,7 +25,8 @@ use crate::{ ops::{add_block_entry, canonicalize, force_approve, NewCandidateInfo}, }; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateReceipt, CoreIndex, GroupIndex, Hash, + vstaging::{CandidateReceiptV2 as CandidateReceipt, MutateDescriptorV2}, + BlockNumber, CandidateHash, CoreIndex, GroupIndex, Hash, }; use polkadot_node_subsystem_util::database::Database; @@ -34,7 +35,7 @@ use sp_consensus_slots::Slot; use std::{collections::HashMap, sync::Arc}; use polkadot_primitives_test_helpers::{ - dummy_candidate_receipt, dummy_candidate_receipt_bad_sig, dummy_hash, + dummy_candidate_receipt_v2, dummy_candidate_receipt_v2_bad_sig, dummy_hash, }; const DATA_COL: u32 = 0; @@ -72,12 +73,12 @@ fn make_block_entry( } fn make_candidate(para_id: ParaId, relay_parent: Hash) -> CandidateReceipt { - let mut c = dummy_candidate_receipt(dummy_hash()); + let mut c = dummy_candidate_receipt_v2(dummy_hash()); - c.descriptor.para_id = para_id; - c.descriptor.relay_parent = relay_parent; + c.descriptor.set_para_id(para_id); + c.descriptor.set_relay_parent(relay_parent); - c + c.into() } #[test] @@ -86,7 +87,7 @@ fn read_write() { let hash_a = Hash::repeat_byte(1); let hash_b = Hash::repeat_byte(2); - let candidate_hash = dummy_candidate_receipt_bad_sig(dummy_hash(), None).hash(); + let candidate_hash = dummy_candidate_receipt_v2_bad_sig(dummy_hash(), None).hash(); let range = StoredBlockRange(10, 20); let at_height = vec![hash_a, hash_b]; @@ -95,7 +96,7 @@ fn read_write() { make_block_entry(hash_a, Default::default(), 1, vec![(CoreIndex(0), candidate_hash)]); let candidate_entry = CandidateEntry { - candidate: dummy_candidate_receipt_bad_sig(dummy_hash(), None), + candidate: dummy_candidate_receipt_v2_bad_sig(dummy_hash(), None), session: 5, block_assignments: vec![( hash_a, diff --git a/polkadot/node/core/approval-voting/src/import.rs b/polkadot/node/core/approval-voting/src/import.rs index e50a2f911489..be7b3103ab13 100644 --- a/polkadot/node/core/approval-voting/src/import.rs +++ b/polkadot/node/core/approval-voting/src/import.rs @@ -45,8 +45,9 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::{determine_new_blocks, runtime::RuntimeInfo}; use polkadot_overseer::SubsystemSender; use polkadot_primitives::{ - node_features, BlockNumber, CandidateEvent, CandidateHash, CandidateReceipt, ConsensusLog, - CoreIndex, GroupIndex, Hash, Header, SessionIndex, + node_features, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt}, + BlockNumber, CandidateHash, ConsensusLog, CoreIndex, GroupIndex, Hash, Header, SessionIndex, }; use sc_keystore::LocalKeystore; use sp_consensus_slots::Slot; @@ -618,10 +619,10 @@ pub(crate) mod tests { use polkadot_node_subsystem_test_helpers::make_subsystem_context; use polkadot_node_subsystem_util::database::Database; use polkadot_primitives::{ - node_features::FeatureIndex, ExecutorParams, Id as ParaId, IndexedVec, NodeFeatures, - SessionInfo, ValidatorId, ValidatorIndex, + node_features::FeatureIndex, vstaging::MutateDescriptorV2, ExecutorParams, Id as ParaId, + IndexedVec, NodeFeatures, SessionInfo, ValidatorId, ValidatorIndex, }; - use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; + use polkadot_primitives_test_helpers::{dummy_candidate_receipt_v2, dummy_hash}; use schnellru::{ByLength, LruMap}; pub(crate) use sp_consensus_babe::{ digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest}, @@ -764,9 +765,9 @@ pub(crate) mod tests { let hash = header.hash(); let make_candidate = |para_id| { - let mut r = dummy_candidate_receipt(dummy_hash()); - r.descriptor.para_id = para_id; - r.descriptor.relay_parent = hash; + let mut r = dummy_candidate_receipt_v2(dummy_hash()); + r.descriptor.set_para_id(para_id); + r.descriptor.set_relay_parent(hash); r }; let candidates = vec![ @@ -917,9 +918,9 @@ pub(crate) mod tests { let hash = header.hash(); let make_candidate = |para_id| { - let mut r = dummy_candidate_receipt(dummy_hash()); - r.descriptor.para_id = para_id; - r.descriptor.relay_parent = hash; + let mut r = dummy_candidate_receipt_v2(dummy_hash()); + r.descriptor.set_para_id(para_id); + r.descriptor.set_relay_parent(hash); r }; let candidates = vec![ @@ -1056,9 +1057,9 @@ pub(crate) mod tests { let hash = header.hash(); let make_candidate = |para_id| { - let mut r = dummy_candidate_receipt(dummy_hash()); - r.descriptor.para_id = para_id; - r.descriptor.relay_parent = hash; + let mut r = dummy_candidate_receipt_v2(dummy_hash()); + r.descriptor.set_para_id(para_id); + r.descriptor.set_relay_parent(hash); r }; let candidates = vec![ @@ -1150,9 +1151,9 @@ pub(crate) mod tests { let hash = header.hash(); let make_candidate = |para_id| { - let mut r = dummy_candidate_receipt(dummy_hash()); - r.descriptor.para_id = para_id; - r.descriptor.relay_parent = hash; + let mut r = dummy_candidate_receipt_v2(dummy_hash()); + r.descriptor.set_para_id(para_id); + r.descriptor.set_relay_parent(hash); r }; let candidates = vec![ @@ -1340,9 +1341,9 @@ pub(crate) mod tests { let hash = header.hash(); let make_candidate = |para_id| { - let mut r = dummy_candidate_receipt(dummy_hash()); - r.descriptor.para_id = para_id; - r.descriptor.relay_parent = hash; + let mut r = dummy_candidate_receipt_v2(dummy_hash()); + r.descriptor.set_para_id(para_id); + r.descriptor.set_relay_parent(hash); r }; let candidates = vec![ diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 0cb977c58021..2176cc7675be 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -52,9 +52,10 @@ use polkadot_node_subsystem_util::{ TimeoutExt, }; use polkadot_primitives::{ - ApprovalVoteMultipleCandidates, ApprovalVotingParams, BlockNumber, CandidateHash, - CandidateIndex, CandidateReceipt, CoreIndex, ExecutorParams, GroupIndex, Hash, SessionIndex, - SessionInfo, ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, ApprovalVoteMultipleCandidates, + ApprovalVotingParams, BlockNumber, CandidateHash, CandidateIndex, CoreIndex, ExecutorParams, + GroupIndex, Hash, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, ValidatorPair, + ValidatorSignature, }; use sc_keystore::LocalKeystore; use sp_application_crypto::Pair; @@ -2824,7 +2825,7 @@ where target: LOG_TARGET, validator_index = approval.validator.0, candidate_hash = ?approved_candidate_hash, - para_id = ?candidate_entry.candidate_receipt().descriptor.para_id, + para_id = ?candidate_entry.candidate_receipt().descriptor.para_id(), "Importing approval vote", ); @@ -2923,7 +2924,7 @@ where let block_hash = block_entry.block_hash(); let block_number = block_entry.block_number(); let session_index = block_entry.session(); - let para_id = candidate_entry.candidate_receipt().descriptor().para_id; + let para_id = candidate_entry.candidate_receipt().descriptor().para_id(); let tick_now = state.clock.tick_now(); let (is_approved, status) = if let Some((approval_entry, status)) = state @@ -3221,7 +3222,7 @@ async fn process_wakeup>( gum::trace!( target: LOG_TARGET, ?candidate_hash, - para_id = ?candidate_receipt.descriptor.para_id, + para_id = ?candidate_receipt.descriptor.para_id(), block_hash = ?relay_block, "Launching approval work.", ); @@ -3352,7 +3353,7 @@ async fn launch_approval< } let candidate_hash = candidate.hash(); - let para_id = candidate.descriptor.para_id; + let para_id = candidate.descriptor.para_id(); gum::trace!(target: LOG_TARGET, ?candidate_hash, ?para_id, "Recovering data."); let timer = metrics.time_recover_and_approve(); @@ -3370,7 +3371,7 @@ async fn launch_approval< .send_message(RuntimeApiMessage::Request( block_hash, RuntimeApiRequest::ValidationCodeByHash( - candidate.descriptor.validation_code_hash, + candidate.descriptor.validation_code_hash(), code_tx, ), )) @@ -3393,7 +3394,7 @@ async fn launch_approval< ?para_id, ?candidate_hash, "Data unavailable for candidate {:?}", - (candidate_hash, candidate.descriptor.para_id), + (candidate_hash, candidate.descriptor.para_id()), ); // do nothing. we'll just be a no-show and that'll cause others to rise up. metrics_guard.take().on_approval_unavailable(); @@ -3404,7 +3405,7 @@ async fn launch_approval< ?para_id, ?candidate_hash, "Channel closed while recovering data for candidate {:?}", - (candidate_hash, candidate.descriptor.para_id), + (candidate_hash, candidate.descriptor.para_id()), ); // do nothing. we'll just be a no-show and that'll cause others to rise up. metrics_guard.take().on_approval_unavailable(); @@ -3415,7 +3416,7 @@ async fn launch_approval< ?para_id, ?candidate_hash, "Data recovery invalid for candidate {:?}", - (candidate_hash, candidate.descriptor.para_id), + (candidate_hash, candidate.descriptor.para_id()), ); issue_local_invalid_statement( &mut sender, @@ -3438,7 +3439,7 @@ async fn launch_approval< gum::warn!( target: LOG_TARGET, "Validation code unavailable for block {:?} in the state of block {:?} (a recent descendant)", - candidate.descriptor.relay_parent, + candidate.descriptor.relay_parent(), block_hash, ); diff --git a/polkadot/node/core/approval-voting/src/ops.rs b/polkadot/node/core/approval-voting/src/ops.rs index 2a8fdba5aa36..f105580009fa 100644 --- a/polkadot/node/core/approval-voting/src/ops.rs +++ b/polkadot/node/core/approval-voting/src/ops.rs @@ -20,7 +20,9 @@ use polkadot_node_subsystem::{SubsystemError, SubsystemResult}; use bitvec::order::Lsb0 as BitOrderLsb0; -use polkadot_primitives::{BlockNumber, CandidateHash, CandidateReceipt, GroupIndex, Hash}; +use polkadot_primitives::{ + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, GroupIndex, Hash, +}; use std::collections::{hash_map::Entry, BTreeMap, HashMap}; diff --git a/polkadot/node/core/approval-voting/src/persisted_entries.rs b/polkadot/node/core/approval-voting/src/persisted_entries.rs index 16e231aa1a2d..d891af01c3ab 100644 --- a/polkadot/node/core/approval-voting/src/persisted_entries.rs +++ b/polkadot/node/core/approval-voting/src/persisted_entries.rs @@ -26,8 +26,8 @@ use polkadot_node_primitives::approval::{ v2::{AssignmentCertV2, CandidateBitfield}, }; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateIndex, CandidateReceipt, CoreIndex, GroupIndex, Hash, - SessionIndex, ValidatorIndex, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, CandidateIndex, + CoreIndex, GroupIndex, Hash, SessionIndex, ValidatorIndex, ValidatorSignature, }; use sp_consensus_slots::Slot; diff --git a/polkadot/node/core/approval-voting/src/tests.rs b/polkadot/node/core/approval-voting/src/tests.rs index db5ffd441c0d..099ab419dfbf 100644 --- a/polkadot/node/core/approval-voting/src/tests.rs +++ b/polkadot/node/core/approval-voting/src/tests.rs @@ -42,8 +42,9 @@ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_overseer::SpawnGlue; use polkadot_primitives::{ - ApprovalVote, CandidateCommitments, CandidateEvent, CoreIndex, DisputeStatement, GroupIndex, - Header, Id as ParaId, IndexedVec, NodeFeatures, ValidDisputeStatementKind, ValidationCode, + vstaging::{CandidateEvent, MutateDescriptorV2}, + ApprovalVote, CandidateCommitments, CoreIndex, DisputeStatement, GroupIndex, Header, + Id as ParaId, IndexedVec, NodeFeatures, ValidDisputeStatementKind, ValidationCode, ValidatorSignature, }; use std::{cmp::max, time::Duration}; @@ -69,7 +70,9 @@ use super::{ }, }; -use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_candidate_receipt_bad_sig}; +use polkadot_primitives_test_helpers::{ + dummy_candidate_receipt_v2, dummy_candidate_receipt_v2_bad_sig, +}; const SLOT_DURATION_MILLIS: u64 = 5000; @@ -638,8 +641,8 @@ where } fn make_candidate(para_id: ParaId, hash: &Hash) -> CandidateReceipt { - let mut r = dummy_candidate_receipt_bad_sig(*hash, Some(Default::default())); - r.descriptor.para_id = para_id; + let mut r = dummy_candidate_receipt_v2_bad_sig(*hash, Some(Default::default())); + r.descriptor.set_para_id(para_id); r } @@ -1282,7 +1285,7 @@ fn subsystem_rejects_approval_if_no_block_entry() { let block_hash = Hash::repeat_byte(0x01); let candidate_index = 0; let validator = ValidatorIndex(0); - let candidate_hash = dummy_candidate_receipt(block_hash).hash(); + let candidate_hash = dummy_candidate_receipt_v2(block_hash).hash(); let session_index = 1; let rx = import_approval( @@ -1324,9 +1327,9 @@ fn subsystem_rejects_approval_before_assignment() { let candidate_hash = { let mut candidate_receipt = - dummy_candidate_receipt_bad_sig(block_hash, Some(Default::default())); - candidate_receipt.descriptor.para_id = ParaId::from(0_u32); - candidate_receipt.descriptor.relay_parent = block_hash; + dummy_candidate_receipt_v2_bad_sig(block_hash, Some(Default::default())); + candidate_receipt.descriptor.set_para_id(ParaId::from(0_u32)); + candidate_receipt.descriptor.set_relay_parent(block_hash); candidate_receipt.hash() }; @@ -1390,15 +1393,17 @@ fn subsystem_accepts_duplicate_assignment() { let block_hash = Hash::repeat_byte(0x01); let candidate_receipt1 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(1_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(1_u32)); receipt - }; + } + .into(); let candidate_receipt2 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(2_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(2_u32)); receipt - }; + } + .into(); let candidate_index1 = 0; let candidate_index2 = 1; @@ -1572,9 +1577,9 @@ fn subsystem_accepts_and_imports_approval_after_assignment() { let candidate_hash = { let mut candidate_receipt = - dummy_candidate_receipt_bad_sig(block_hash, Some(Default::default())); - candidate_receipt.descriptor.para_id = ParaId::from(0_u32); - candidate_receipt.descriptor.relay_parent = block_hash; + dummy_candidate_receipt_v2_bad_sig(block_hash, Some(Default::default())); + candidate_receipt.descriptor.set_para_id(ParaId::from(0_u32)); + candidate_receipt.descriptor.set_relay_parent(block_hash); candidate_receipt.hash() }; @@ -1643,9 +1648,9 @@ fn subsystem_second_approval_import_only_schedules_wakeups() { let candidate_hash = { let mut candidate_receipt = - dummy_candidate_receipt_bad_sig(block_hash, Some(Default::default())); - candidate_receipt.descriptor.para_id = ParaId::from(0_u32); - candidate_receipt.descriptor.relay_parent = block_hash; + dummy_candidate_receipt_v2_bad_sig(block_hash, Some(Default::default())); + candidate_receipt.descriptor.set_para_id(ParaId::from(0_u32)); + candidate_receipt.descriptor.set_relay_parent(block_hash); candidate_receipt.hash() }; @@ -2402,13 +2407,13 @@ fn subsystem_import_checked_approval_sets_one_block_bit_at_a_time() { let block_hash = Hash::repeat_byte(0x01); let candidate_receipt1 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(1_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(1_u32)); receipt }; let candidate_receipt2 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(2_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(2_u32)); receipt }; let candidate_hash1 = candidate_receipt1.hash(); @@ -2566,18 +2571,18 @@ fn inclusion_events_can_be_unordered_by_core_index() { let block_hash = Hash::repeat_byte(0x01); let candidate_receipt0 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(0_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(0_u32)); receipt }; let candidate_receipt1 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(1_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(1_u32)); receipt }; let candidate_receipt2 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(2_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(2_u32)); receipt }; let candidate_index0 = 0; @@ -2710,8 +2715,8 @@ fn approved_ancestor_test( .iter() .enumerate() .map(|(i, hash)| { - let mut candidate_receipt = dummy_candidate_receipt(*hash); - candidate_receipt.descriptor.para_id = i.into(); + let mut candidate_receipt = dummy_candidate_receipt_v2(*hash); + candidate_receipt.descriptor.set_para_id(i.into()); candidate_receipt }) .collect(); @@ -2882,7 +2887,7 @@ fn subsystem_validate_approvals_cache() { let block_hash = Hash::repeat_byte(0x01); let fork_block_hash = Hash::repeat_byte(0x02); let candidate_commitments = CandidateCommitments::default(); - let mut candidate_receipt = dummy_candidate_receipt(block_hash); + let mut candidate_receipt = dummy_candidate_receipt_v2(block_hash); candidate_receipt.commitments_hash = candidate_commitments.hash(); let candidate_hash = candidate_receipt.hash(); let slot = Slot::from(1); @@ -3012,13 +3017,13 @@ fn subsystem_doesnt_distribute_duplicate_compact_assignments() { let block_hash = Hash::repeat_byte(0x01); let candidate_receipt1 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(1_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(1_u32)); receipt }; let candidate_receipt2 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(2_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(2_u32)); receipt }; let candidate_index1 = 0; @@ -3263,7 +3268,7 @@ where ); let block_hash = Hash::repeat_byte(0x01); - let candidate_receipt = dummy_candidate_receipt(block_hash); + let candidate_receipt = dummy_candidate_receipt_v2(block_hash); let candidate_hash = candidate_receipt.hash(); let slot = Slot::from(1); let candidate_index = 0; @@ -3965,8 +3970,8 @@ fn test_approval_is_sent_on_max_approval_coalesce_count() { let candidate_commitments = CandidateCommitments::default(); let candidate_receipt1 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(1_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(1_u32)); receipt.commitments_hash = candidate_commitments.hash(); receipt }; @@ -3974,8 +3979,8 @@ fn test_approval_is_sent_on_max_approval_coalesce_count() { let candidate_hash1 = candidate_receipt1.hash(); let candidate_receipt2 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(2_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(2_u32)); receipt.commitments_hash = candidate_commitments.hash(); receipt }; @@ -4266,8 +4271,8 @@ fn test_approval_is_sent_on_max_approval_coalesce_wait() { let candidate_commitments = CandidateCommitments::default(); let candidate_receipt1 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(1_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(1_u32)); receipt.commitments_hash = candidate_commitments.hash(); receipt }; @@ -4275,8 +4280,8 @@ fn test_approval_is_sent_on_max_approval_coalesce_wait() { let candidate_hash1 = candidate_receipt1.hash(); let candidate_receipt2 = { - let mut receipt = dummy_candidate_receipt(block_hash); - receipt.descriptor.para_id = ParaId::from(2_u32); + let mut receipt = dummy_candidate_receipt_v2(block_hash); + receipt.descriptor.set_para_id(ParaId::from(2_u32)); receipt.commitments_hash = candidate_commitments.hash(); receipt }; @@ -4420,7 +4425,7 @@ async fn setup_overseer_with_two_blocks_each_with_one_assignment_triggered( let block_hash = Hash::repeat_byte(0x01); let fork_block_hash = Hash::repeat_byte(0x02); let candidate_commitments = CandidateCommitments::default(); - let mut candidate_receipt = dummy_candidate_receipt(block_hash); + let mut candidate_receipt = dummy_candidate_receipt_v2(block_hash); candidate_receipt.commitments_hash = candidate_commitments.hash(); let candidate_hash = candidate_receipt.hash(); let slot = Slot::from(1); @@ -4549,7 +4554,7 @@ fn subsystem_relaunches_approval_work_on_restart() { let block_hash = Hash::repeat_byte(0x01); let fork_block_hash = Hash::repeat_byte(0x02); let candidate_commitments = CandidateCommitments::default(); - let mut candidate_receipt = dummy_candidate_receipt(block_hash); + let mut candidate_receipt = dummy_candidate_receipt_v2(block_hash); candidate_receipt.commitments_hash = candidate_commitments.hash(); let slot = Slot::from(1); clock.inner.lock().set_tick(slot_to_tick(slot + 2)); @@ -4805,7 +4810,7 @@ fn subsystem_sends_pending_approvals_on_approval_restart() { let block_hash = Hash::repeat_byte(0x01); let fork_block_hash = Hash::repeat_byte(0x02); let candidate_commitments = CandidateCommitments::default(); - let mut candidate_receipt = dummy_candidate_receipt(block_hash); + let mut candidate_receipt = dummy_candidate_receipt_v2(block_hash); candidate_receipt.commitments_hash = candidate_commitments.hash(); let slot = Slot::from(1); @@ -4815,7 +4820,7 @@ fn subsystem_sends_pending_approvals_on_approval_restart() { fork_block_hash, slot, sync_oracle_handle, - candidate_receipt, + candidate_receipt.into(), ) .await; chain_builder.build(&mut virtual_overseer).await; diff --git a/polkadot/node/core/av-store/src/lib.rs b/polkadot/node/core/av-store/src/lib.rs index 9473040e8f5e..9da2973773a0 100644 --- a/polkadot/node/core/av-store/src/lib.rs +++ b/polkadot/node/core/av-store/src/lib.rs @@ -47,8 +47,8 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_util as util; use polkadot_primitives::{ - BlockNumber, CandidateEvent, CandidateHash, CandidateReceipt, ChunkIndex, CoreIndex, Hash, - Header, NodeFeatures, ValidatorIndex, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt}, + BlockNumber, CandidateHash, ChunkIndex, CoreIndex, Hash, Header, NodeFeatures, ValidatorIndex, }; use util::availability_chunks::availability_chunk_indices; diff --git a/polkadot/node/core/av-store/src/tests.rs b/polkadot/node/core/av-store/src/tests.rs index 958917a3104f..80043e56976b 100644 --- a/polkadot/node/core/av-store/src/tests.rs +++ b/polkadot/node/core/av-store/src/tests.rs @@ -31,8 +31,8 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{database::Database, TimeoutExt}; use polkadot_primitives::{ - node_features, CandidateHash, CandidateReceipt, CoreIndex, GroupIndex, HeadData, Header, - PersistedValidationData, ValidatorId, + node_features, vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, CoreIndex, + GroupIndex, HeadData, Header, PersistedValidationData, ValidatorId, }; use polkadot_primitives_test_helpers::TestCandidateBuilder; use sp_keyring::Sr25519Keyring; diff --git a/polkadot/node/core/backing/Cargo.toml b/polkadot/node/core/backing/Cargo.toml index bd56a3ad693b..cd1acf9daa93 100644 --- a/polkadot/node/core/backing/Cargo.toml +++ b/polkadot/node/core/backing/Cargo.toml @@ -36,3 +36,4 @@ assert_matches = { workspace = true } rstest = { workspace = true } polkadot-node-subsystem-test-helpers = { workspace = true } polkadot-primitives-test-helpers = { workspace = true } +polkadot-primitives = { workspace = true, features = ["test"] } diff --git a/polkadot/node/core/backing/src/error.rs b/polkadot/node/core/backing/src/error.rs index 568f71402644..e09d8425f78a 100644 --- a/polkadot/node/core/backing/src/error.rs +++ b/polkadot/node/core/backing/src/error.rs @@ -24,7 +24,7 @@ use polkadot_node_subsystem::{ RuntimeApiError, SubsystemError, }; use polkadot_node_subsystem_util::{runtime, Error as UtilError}; -use polkadot_primitives::{BackedCandidate, ValidationCodeHash}; +use polkadot_primitives::{vstaging::BackedCandidate, ValidationCodeHash}; use crate::{ParaId, LOG_TARGET}; diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 4463fb34b510..b5362d32ad88 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -108,10 +108,14 @@ use polkadot_node_subsystem_util::{ }; use polkadot_parachain_primitives::primitives::IsSystem; use polkadot_primitives::{ - node_features::FeatureIndex, BackedCandidate, CandidateCommitments, CandidateHash, - CandidateReceipt, CommittedCandidateReceipt, CoreIndex, CoreState, ExecutorParams, GroupIndex, - GroupRotationInfo, Hash, Id as ParaId, IndexedVec, NodeFeatures, PersistedValidationData, - SessionIndex, SigningContext, ValidationCode, ValidatorId, ValidatorIndex, ValidatorSignature, + node_features::FeatureIndex, + vstaging::{ + BackedCandidate, CandidateReceiptV2 as CandidateReceipt, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + }, + CandidateCommitments, CandidateHash, CoreIndex, ExecutorParams, GroupIndex, GroupRotationInfo, + Hash, Id as ParaId, IndexedVec, NodeFeatures, PersistedValidationData, SessionIndex, + SigningContext, ValidationCode, ValidatorId, ValidatorIndex, ValidatorSignature, ValidityAttestation, }; use polkadot_statement_table::{ @@ -627,7 +631,7 @@ async fn request_candidate_validation( executor_params: ExecutorParams, ) -> Result { let (tx, rx) = oneshot::channel(); - let is_system = candidate_receipt.descriptor.para_id.is_system(); + let is_system = candidate_receipt.descriptor.para_id().is_system(); sender .send_message(CandidateValidationMessage::ValidateFromExhaustive { @@ -692,7 +696,7 @@ async fn validate_and_make_available( } = params; let validation_code = { - let validation_code_hash = candidate.descriptor().validation_code_hash; + let validation_code_hash = candidate.descriptor().validation_code_hash(); let (tx, rx) = oneshot::channel(); sender .send_message(RuntimeApiMessage::Request( @@ -725,7 +729,7 @@ async fn validate_and_make_available( &mut sender, relay_parent, from_validator, - candidate.descriptor.para_id, + candidate.descriptor.para_id(), candidate_hash, pov_hash, ) @@ -772,7 +776,7 @@ async fn validate_and_make_available( pov.clone(), candidate.hash(), validation_data.clone(), - candidate.descriptor.erasure_root, + candidate.descriptor.erasure_root(), core_index, node_features, ) @@ -1054,7 +1058,7 @@ fn core_index_from_statement( } if let StatementWithPVD::Seconded(candidate, _pvd) = statement.payload() { - let candidate_para_id = candidate.descriptor.para_id; + let candidate_para_id = candidate.descriptor.para_id(); let mut assigned_paras = claim_queue.iter_claims_for_core(&core_index); if !assigned_paras.any(|id| id == &candidate_para_id) { @@ -1445,14 +1449,14 @@ async fn handle_validated_candidate_command( let candidate_hash = candidate.hash(); gum::debug!( target: LOG_TARGET, - relay_parent = ?candidate.descriptor().relay_parent, + relay_parent = ?candidate.descriptor().relay_parent(), ?candidate_hash, "Attempted to second candidate but was rejected by prospective parachains", ); // Ensure the collator is reported. ctx.send_message(CollatorProtocolMessage::Invalid( - candidate.descriptor().relay_parent, + candidate.descriptor().relay_parent(), candidate, )) .await; @@ -1487,7 +1491,7 @@ async fn handle_validated_candidate_command( Some(d) => d, }; - leaf_data.add_seconded_candidate(candidate.descriptor().para_id); + leaf_data.add_seconded_candidate(candidate.descriptor().para_id()); } rp_state.issued_statements.insert(candidate_hash); @@ -1636,7 +1640,7 @@ async fn import_statement( let (tx, rx) = oneshot::channel(); ctx.send_message(ProspectiveParachainsMessage::IntroduceSecondedCandidate( IntroduceSecondedCandidateRequest { - candidate_para: candidate.descriptor().para_id, + candidate_para: candidate.descriptor.para_id(), candidate_receipt: candidate.clone(), persisted_validation_data: pvd.clone(), }, @@ -1665,7 +1669,7 @@ async fn import_statement( persisted_validation_data: pvd.clone(), // This is set after importing when seconding locally. seconded_locally: false, - relay_parent: candidate.descriptor().relay_parent, + relay_parent: candidate.descriptor.relay_parent(), }, ); } @@ -1709,7 +1713,7 @@ async fn post_import_statement_actions( &rp_state.table_context, rp_state.inject_core_index, ) { - let para_id = backed.candidate().descriptor.para_id; + let para_id = backed.candidate().descriptor.para_id(); gum::debug!( target: LOG_TARGET, candidate_hash = ?candidate_hash, @@ -1967,7 +1971,7 @@ async fn maybe_validate_and_import( .get_candidate(&candidate_hash) .ok_or(Error::CandidateNotFound)? .to_plain(), - pov_hash: receipt.descriptor.pov_hash, + pov_hash: receipt.descriptor.pov_hash(), from_validator: statement.validator_index(), backing: Vec::new(), }; @@ -2068,9 +2072,9 @@ async fn handle_second_message( let _timer = metrics.time_process_second(); let candidate_hash = candidate.hash(); - let relay_parent = candidate.descriptor().relay_parent; + let relay_parent = candidate.descriptor().relay_parent(); - if candidate.descriptor().persisted_validation_data_hash != persisted_validation_data.hash() { + if candidate.descriptor().persisted_validation_data_hash() != persisted_validation_data.hash() { gum::warn!( target: LOG_TARGET, ?candidate_hash, @@ -2104,12 +2108,12 @@ async fn handle_second_message( let assigned_paras = rp_state.assigned_core.and_then(|core| rp_state.claim_queue.0.get(&core)); // Sanity check that candidate is from our assignment. - if !matches!(assigned_paras, Some(paras) if paras.contains(&candidate.descriptor().para_id)) { + if !matches!(assigned_paras, Some(paras) if paras.contains(&candidate.descriptor().para_id())) { gum::debug!( target: LOG_TARGET, our_assignment_core = ?rp_state.assigned_core, our_assignment_paras = ?assigned_paras, - collation = ?candidate.descriptor().para_id, + collation = ?candidate.descriptor().para_id(), "Subsystem asked to second for para outside of our assignment", ); return Ok(()); @@ -2119,7 +2123,7 @@ async fn handle_second_message( target: LOG_TARGET, our_assignment_core = ?rp_state.assigned_core, our_assignment_paras = ?assigned_paras, - collation = ?candidate.descriptor().para_id, + collation = ?candidate.descriptor().para_id(), "Current assignments vs collation", ); diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index d9c1fc9499e5..dbb974a634fe 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -22,19 +22,19 @@ use polkadot_node_primitives::{BlockData, InvalidCandidate, SignedFullStatement, use polkadot_node_subsystem::{ errors::RuntimeApiError, messages::{ - AllMessages, CollatorProtocolMessage, RuntimeApiMessage, RuntimeApiRequest, + AllMessages, CollatorProtocolMessage, PvfExecKind, RuntimeApiMessage, RuntimeApiRequest, ValidationFailed, }, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, TimeoutExt, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ - node_features, CandidateDescriptor, GroupRotationInfo, HeadData, PersistedValidationData, - ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES, + node_features, vstaging::MutateDescriptorV2, CandidateDescriptor, GroupRotationInfo, HeadData, + PersistedValidationData, ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES, }; use polkadot_primitives_test_helpers::{ dummy_candidate_receipt_bad_sig, dummy_collator, dummy_collator_signature, - dummy_committed_candidate_receipt, dummy_hash, validator_pubkeys, + dummy_committed_candidate_receipt_v2, dummy_hash, validator_pubkeys, }; use polkadot_statement_table::v2::Misbehavior; use rstest::rstest; @@ -236,7 +236,8 @@ impl TestCandidateBuilder { para_head: self.head_data.hash(), validation_code_hash: ValidationCode(self.validation_code).hash(), persisted_validation_data_hash: self.persisted_validation_data_hash, - }, + } + .into(), commitments: CandidateCommitments { head_data: self.head_data, upward_messages: Default::default(), @@ -433,7 +434,7 @@ async fn assert_validate_from_exhaustive( }, ) if validation_data == *assert_pvd && validation_code == *assert_validation_code && - *pov == *assert_pov && &candidate_receipt.descriptor == assert_candidate.descriptor() && + *pov == *assert_pov && candidate_receipt.descriptor == assert_candidate.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_receipt.commitments_hash == assert_candidate.commitments.hash() => { @@ -650,7 +651,7 @@ fn backing_works(#[case] elastic_scaling_mvp: bool) { }, ) if validation_data == pvd_ab && validation_code == validation_code_ab && - *pov == pov_ab && &candidate_receipt.descriptor == candidate_a.descriptor() && + *pov == pov_ab && candidate_receipt.descriptor == candidate_a.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_receipt.commitments_hash == candidate_a_commitments_hash => { @@ -1121,7 +1122,7 @@ fn extract_core_index_from_statement_works() { .flatten() .expect("should be signed"); - candidate.descriptor.para_id = test_state.chain_ids[1]; + candidate.descriptor.set_para_id(test_state.chain_ids[1]); let signed_statement_3 = SignedFullStatementWithPVD::sign( &test_state.keystore, @@ -1286,7 +1287,7 @@ fn backing_works_while_validation_ongoing() { }, ) if validation_data == pvd_abc && validation_code == validation_code_abc && - *pov == pov_abc && &candidate_receipt.descriptor == candidate_a.descriptor() && + *pov == pov_abc && candidate_receipt.descriptor == candidate_a.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_a_commitments_hash == candidate_receipt.commitments_hash => { @@ -1453,7 +1454,7 @@ fn backing_misbehavior_works() { }, ) if validation_data == pvd_a && validation_code == validation_code_a && - *pov == pov_a && &candidate_receipt.descriptor == candidate_a.descriptor() && + *pov == pov_a && candidate_receipt.descriptor == candidate_a.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_a_commitments_hash == candidate_receipt.commitments_hash => { @@ -1620,7 +1621,7 @@ fn backing_dont_second_invalid() { }, ) if validation_data == pvd_a && validation_code == validation_code_a && - *pov == pov_block_a && &candidate_receipt.descriptor == candidate_a.descriptor() && + *pov == pov_block_a && candidate_receipt.descriptor == candidate_a.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_a.commitments.hash() == candidate_receipt.commitments_hash => { @@ -1660,7 +1661,7 @@ fn backing_dont_second_invalid() { }, ) if validation_data == pvd_b && validation_code == validation_code_b && - *pov == pov_block_b && &candidate_receipt.descriptor == candidate_b.descriptor() && + *pov == pov_block_b && candidate_receipt.descriptor == candidate_b.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_b.commitments.hash() == candidate_receipt.commitments_hash => { @@ -1787,7 +1788,7 @@ fn backing_second_after_first_fails_works() { }, ) if validation_data == pvd_a && validation_code == validation_code_a && - *pov == pov_a && &candidate_receipt.descriptor == candidate.descriptor() && + *pov == pov_a && candidate_receipt.descriptor == candidate.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash => { @@ -1931,7 +1932,7 @@ fn backing_works_after_failed_validation() { }, ) if validation_data == pvd_a && validation_code == validation_code_a && - *pov == pov_a && &candidate_receipt.descriptor == candidate.descriptor() && + *pov == pov_a && candidate_receipt.descriptor == candidate.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash => { @@ -1999,7 +2000,7 @@ fn candidate_backing_reorders_votes() { }; let attested = TableAttestedCandidate { - candidate: dummy_committed_candidate_receipt(dummy_hash()), + candidate: dummy_committed_candidate_receipt_v2(dummy_hash()), validity_votes: vec![ (ValidatorIndex(5), fake_attestation(5)), (ValidatorIndex(3), fake_attestation(3)), @@ -2210,7 +2211,7 @@ fn retry_works() { }, ) if validation_data == pvd_a && validation_code == validation_code_a && - *pov == pov_a && &candidate_receipt.descriptor == candidate.descriptor() && + *pov == pov_a && candidate_receipt.descriptor == candidate.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash ); @@ -2752,7 +2753,7 @@ fn validator_ignores_statements_from_disabled_validators() { } ) if validation_data == pvd && validation_code == expected_validation_code && - *pov == expected_pov && &candidate_receipt.descriptor == candidate.descriptor() && + *pov == expected_pov && candidate_receipt.descriptor == candidate.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate_commitments_hash == candidate_receipt.commitments_hash => { diff --git a/polkadot/node/core/backing/src/tests/prospective_parachains.rs b/polkadot/node/core/backing/src/tests/prospective_parachains.rs index 57b2fabd43b0..caddd2408057 100644 --- a/polkadot/node/core/backing/src/tests/prospective_parachains.rs +++ b/polkadot/node/core/backing/src/tests/prospective_parachains.rs @@ -20,7 +20,7 @@ use polkadot_node_subsystem::{ messages::{ChainApiMessage, HypotheticalMembership}, ActivatedLeaf, TimeoutExt, }; -use polkadot_primitives::{AsyncBackingParams, BlockNumber, Header, OccupiedCore}; +use polkadot_primitives::{vstaging::OccupiedCore, AsyncBackingParams, BlockNumber, Header}; use super::*; @@ -275,7 +275,7 @@ async fn assert_validate_seconded_candidate( }) if &validation_data == assert_pvd && &validation_code == assert_validation_code && &*pov == assert_pov && - &candidate_receipt.descriptor == candidate.descriptor() && + candidate_receipt.descriptor == candidate.descriptor && exec_kind == PvfExecKind::BackingSystemParas && candidate.commitments.hash() == candidate_receipt.commitments_hash => { @@ -890,7 +890,7 @@ fn prospective_parachains_reject_candidate() { AllMessages::CollatorProtocol(CollatorProtocolMessage::Invalid( relay_parent, candidate_receipt, - )) if candidate_receipt.descriptor() == candidate.descriptor() && + )) if candidate_receipt.descriptor == candidate.descriptor && candidate_receipt.commitments_hash == candidate.commitments.hash() && relay_parent == leaf_a_parent ); @@ -1011,7 +1011,7 @@ fn second_multiple_candidates_per_relay_parent() { assert_validate_seconded_candidate( &mut virtual_overseer, - candidate.descriptor().relay_parent, + candidate.descriptor.relay_parent(), &candidate, &pov, &pvd, @@ -1064,13 +1064,13 @@ fn second_multiple_candidates_per_relay_parent() { parent_hash, _signed_statement, ) - ) if parent_hash == candidate.descriptor().relay_parent => {} + ) if parent_hash == candidate.descriptor.relay_parent() => {} ); assert_matches!( virtual_overseer.recv().await, AllMessages::CollatorProtocol(CollatorProtocolMessage::Seconded(hash, statement)) => { - assert_eq!(candidate.descriptor().relay_parent, hash); + assert_eq!(candidate.descriptor.relay_parent(), hash); assert_matches!(statement.payload(), Statement::Seconded(_)); } ); @@ -1179,7 +1179,7 @@ fn backing_works() { assert_validate_seconded_candidate( &mut virtual_overseer, - candidate_a.descriptor().relay_parent, + candidate_a.descriptor.relay_parent(), &candidate_a, &pov, &pvd, @@ -1544,7 +1544,7 @@ fn seconding_sanity_check_occupy_same_depth() { assert_validate_seconded_candidate( &mut virtual_overseer, - candidate.descriptor().relay_parent, + candidate.descriptor.relay_parent(), &candidate, &pov, &pvd, @@ -1599,13 +1599,13 @@ fn seconding_sanity_check_occupy_same_depth() { parent_hash, _signed_statement, ) - ) if parent_hash == candidate.descriptor().relay_parent => {} + ) if parent_hash == candidate.descriptor.relay_parent() => {} ); assert_matches!( virtual_overseer.recv().await, AllMessages::CollatorProtocol(CollatorProtocolMessage::Seconded(hash, statement)) => { - assert_eq!(candidate.descriptor().relay_parent, hash); + assert_eq!(candidate.descriptor.relay_parent(), hash); assert_matches!(statement.payload(), Statement::Seconded(_)); } ); @@ -1637,7 +1637,7 @@ fn occupied_core_assignment() { time_out_at: 200_u32, next_up_on_time_out: None, availability: Default::default(), - candidate_descriptor, + candidate_descriptor: candidate_descriptor.into(), candidate_hash: Default::default(), }); diff --git a/polkadot/node/core/bitfield-signing/src/lib.rs b/polkadot/node/core/bitfield-signing/src/lib.rs index 474de1c66abd..7c67853503f6 100644 --- a/polkadot/node/core/bitfield-signing/src/lib.rs +++ b/polkadot/node/core/bitfield-signing/src/lib.rs @@ -34,7 +34,7 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::{ self as util, request_availability_cores, runtime::recv_runtime, Validator, }; -use polkadot_primitives::{AvailabilityBitfield, CoreState, Hash, ValidatorIndex}; +use polkadot_primitives::{vstaging::CoreState, AvailabilityBitfield, Hash, ValidatorIndex}; use sp_keystore::{Error as KeystoreError, KeystorePtr}; use std::{collections::HashMap, time::Duration}; use wasm_timer::{Delay, Instant}; diff --git a/polkadot/node/core/bitfield-signing/src/tests.rs b/polkadot/node/core/bitfield-signing/src/tests.rs index c08018375cf3..9123414844a6 100644 --- a/polkadot/node/core/bitfield-signing/src/tests.rs +++ b/polkadot/node/core/bitfield-signing/src/tests.rs @@ -17,8 +17,8 @@ use super::*; use futures::{executor::block_on, pin_mut, StreamExt}; use polkadot_node_subsystem::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}; -use polkadot_primitives::{CandidateHash, OccupiedCore}; -use polkadot_primitives_test_helpers::dummy_candidate_descriptor; +use polkadot_primitives::{vstaging::OccupiedCore, CandidateHash}; +use polkadot_primitives_test_helpers::dummy_candidate_descriptor_v2; fn occupied_core(para_id: u32, candidate_hash: CandidateHash) -> CoreState { CoreState::Occupied(OccupiedCore { @@ -29,7 +29,7 @@ fn occupied_core(para_id: u32, candidate_hash: CandidateHash) -> CoreState { next_up_on_time_out: None, availability: Default::default(), candidate_hash, - candidate_descriptor: dummy_candidate_descriptor(Hash::zero()), + candidate_descriptor: dummy_candidate_descriptor_v2(Hash::zero()), }) } diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs index e875be9b5df9..a48669c24825 100644 --- a/polkadot/node/core/candidate-validation/src/lib.rs +++ b/polkadot/node/core/candidate-validation/src/lib.rs @@ -45,8 +45,11 @@ use polkadot_primitives::{ DEFAULT_APPROVAL_EXECUTION_TIMEOUT, DEFAULT_BACKING_EXECUTION_TIMEOUT, DEFAULT_LENIENT_PREPARATION_TIMEOUT, DEFAULT_PRECHECK_PREPARATION_TIMEOUT, }, - AuthorityDiscoveryId, CandidateCommitments, CandidateDescriptor, CandidateEvent, - CandidateReceipt, ExecutorParams, Hash, PersistedValidationData, + vstaging::{ + CandidateDescriptorV2 as CandidateDescriptor, CandidateEvent, + CandidateReceiptV2 as CandidateReceipt, + }, + AuthorityDiscoveryId, CandidateCommitments, ExecutorParams, Hash, PersistedValidationData, PvfExecKind as RuntimePvfExecKind, PvfPrepKind, SessionIndex, ValidationCode, ValidationCodeHash, ValidatorId, }; @@ -437,7 +440,7 @@ where .into_iter() .filter_map(|e| match e { CandidateEvent::CandidateBacked(receipt, ..) => { - let h = receipt.descriptor.validation_code_hash; + let h = receipt.descriptor.validation_code_hash(); if already_prepared.contains(&h) { None } else { @@ -646,7 +649,7 @@ async fn validate_candidate_exhaustive( let _timer = metrics.time_validate_candidate_exhaustive(); let validation_code_hash = validation_code.hash(); - let para_id = candidate_receipt.descriptor.para_id; + let para_id = candidate_receipt.descriptor.para_id(); gum::debug!( target: LOG_TARGET, ?validation_code_hash, @@ -747,7 +750,7 @@ async fn validate_candidate_exhaustive( Err(ValidationFailed(e.to_string())) }, Ok(res) => - if res.head_data.hash() != candidate_receipt.descriptor.para_head { + if res.head_data.hash() != candidate_receipt.descriptor.para_head() { gum::info!(target: LOG_TARGET, ?para_id, "Invalid candidate (para_head)"); Ok(ValidationResult::Invalid(InvalidCandidate::ParaHeadHashMismatch)) } else { @@ -992,11 +995,11 @@ fn perform_basic_checks( return Err(InvalidCandidate::ParamsTooLarge(encoded_pov_size as u64)) } - if pov_hash != candidate.pov_hash { + if pov_hash != candidate.pov_hash() { return Err(InvalidCandidate::PoVHashMismatch) } - if *validation_code_hash != candidate.validation_code_hash { + if *validation_code_hash != candidate.validation_code_hash() { return Err(InvalidCandidate::CodeHashMismatch) } diff --git a/polkadot/node/core/candidate-validation/src/tests.rs b/polkadot/node/core/candidate-validation/src/tests.rs index 2f7baf4abb61..997a347631a0 100644 --- a/polkadot/node/core/candidate-validation/src/tests.rs +++ b/polkadot/node/core/candidate-validation/src/tests.rs @@ -26,8 +26,8 @@ use polkadot_node_subsystem::messages::AllMessages; use polkadot_node_subsystem_util::reexports::SubsystemContext; use polkadot_overseer::ActivatedLeaf; use polkadot_primitives::{ - CoreIndex, GroupIndex, HeadData, Id as ParaId, OccupiedCoreAssumption, SessionInfo, - UpwardMessage, ValidatorId, + vstaging::CandidateDescriptorV2, CandidateDescriptor, CoreIndex, GroupIndex, HeadData, + Id as ParaId, OccupiedCoreAssumption, SessionInfo, UpwardMessage, ValidatorId, }; use polkadot_primitives_test_helpers::{ dummy_collator, dummy_collator_signature, dummy_hash, make_valid_candidate_descriptor, @@ -106,7 +106,8 @@ fn correctly_checks_included_assumption() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let pool = TaskExecutor::new(); let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< @@ -180,7 +181,8 @@ fn correctly_checks_timed_out_assumption() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let pool = TaskExecutor::new(); let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< @@ -252,7 +254,8 @@ fn check_is_bad_request_if_no_validation_data() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let pool = TaskExecutor::new(); let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< @@ -308,7 +311,8 @@ fn check_is_bad_request_if_no_validation_code() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let pool = TaskExecutor::new(); let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< @@ -376,7 +380,8 @@ fn check_does_not_match() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let pool = TaskExecutor::new(); let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< @@ -478,7 +483,8 @@ fn candidate_validation_ok_is_ok() { head_data.hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let check = perform_basic_checks( &descriptor, @@ -546,7 +552,8 @@ fn candidate_validation_bad_return_is_invalid() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let check = perform_basic_checks( &descriptor, @@ -580,7 +587,7 @@ fn perform_basic_checks_on_valid_candidate( validation_code: &ValidationCode, validation_data: &PersistedValidationData, head_data_hash: Hash, -) -> CandidateDescriptor { +) -> CandidateDescriptorV2 { let descriptor = make_valid_candidate_descriptor( ParaId::from(1_u32), dummy_hash(), @@ -590,7 +597,8 @@ fn perform_basic_checks_on_valid_candidate( head_data_hash, head_data_hash, Sr25519Keyring::Alice, - ); + ) + .into(); let check = perform_basic_checks( &descriptor, @@ -784,7 +792,8 @@ fn candidate_validation_retry_on_error_helper( dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let check = perform_basic_checks( &descriptor, @@ -824,7 +833,8 @@ fn candidate_validation_timeout_is_internal_error() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let check = perform_basic_checks( &descriptor, @@ -869,9 +879,11 @@ fn candidate_validation_commitment_hash_mismatch_is_invalid() { head_data.hash(), dummy_hash(), Sr25519Keyring::Alice, - ), + ) + .into(), commitments_hash: Hash::zero(), - }; + } + .into(); // This will result in different commitments for this candidate. let validation_result = WasmValidationResult { @@ -915,7 +927,8 @@ fn candidate_validation_code_mismatch_is_invalid() { dummy_hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let check = perform_basic_checks( &descriptor, @@ -970,7 +983,8 @@ fn compressed_code_works() { head_data.hash(), dummy_hash(), Sr25519Keyring::Alice, - ); + ) + .into(); let validation_result = WasmValidationResult { head_data, @@ -1239,7 +1253,8 @@ fn dummy_candidate_backed( signature: dummy_collator_signature(), para_head: zeros, validation_code_hash, - }; + } + .into(); CandidateEvent::CandidateBacked( CandidateReceipt { descriptor, commitments_hash: zeros }, diff --git a/polkadot/node/core/dispute-coordinator/Cargo.toml b/polkadot/node/core/dispute-coordinator/Cargo.toml index eb4600b235b9..344b66af1933 100644 --- a/polkadot/node/core/dispute-coordinator/Cargo.toml +++ b/polkadot/node/core/dispute-coordinator/Cargo.toml @@ -37,6 +37,7 @@ polkadot-primitives-test-helpers = { workspace = true } futures-timer = { workspace = true } sp-application-crypto = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } +polkadot-primitives = { workspace = true, features = ["test"] } [features] # If not enabled, the dispute coordinator will do nothing. diff --git a/polkadot/node/core/dispute-coordinator/src/db/v1.rs b/polkadot/node/core/dispute-coordinator/src/db/v1.rs index 0101791550ee..962dfcbbcfac 100644 --- a/polkadot/node/core/dispute-coordinator/src/db/v1.rs +++ b/polkadot/node/core/dispute-coordinator/src/db/v1.rs @@ -25,8 +25,9 @@ use polkadot_node_primitives::DisputeStatus; use polkadot_node_subsystem_util::database::{DBTransaction, Database}; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, Hash, InvalidDisputeStatementKind, SessionIndex, - ValidDisputeStatementKind, ValidatorIndex, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, Hash, + InvalidDisputeStatementKind, SessionIndex, ValidDisputeStatementKind, ValidatorIndex, + ValidatorSignature, }; use std::sync::Arc; @@ -377,7 +378,9 @@ mod tests { use super::*; use polkadot_node_primitives::DISPUTE_WINDOW; use polkadot_primitives::{Hash, Id as ParaId}; - use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; + use polkadot_primitives_test_helpers::{ + dummy_candidate_receipt, dummy_candidate_receipt_v2, dummy_hash, + }; fn make_db() -> DbBackend { let db = kvdb_memorydb::create(1); @@ -403,7 +406,7 @@ mod tests { session, candidate_hash, CandidateVotes { - candidate_receipt: dummy_candidate_receipt(dummy_hash()), + candidate_receipt: dummy_candidate_receipt_v2(dummy_hash()), valid: Vec::new(), invalid: Vec::new(), }, @@ -495,7 +498,7 @@ mod tests { 1, CandidateHash(Hash::repeat_byte(1)), CandidateVotes { - candidate_receipt: dummy_candidate_receipt(dummy_hash()), + candidate_receipt: dummy_candidate_receipt_v2(dummy_hash()), valid: Vec::new(), invalid: Vec::new(), }, @@ -508,7 +511,7 @@ mod tests { let mut receipt = dummy_candidate_receipt(dummy_hash()); receipt.descriptor.para_id = ParaId::from(5_u32); - receipt + receipt.into() }, valid: Vec::new(), invalid: Vec::new(), @@ -532,7 +535,7 @@ mod tests { .unwrap() .candidate_receipt .descriptor - .para_id, + .para_id(), ParaId::from(5), ); @@ -556,7 +559,7 @@ mod tests { .unwrap() .candidate_receipt .descriptor - .para_id, + .para_id(), ParaId::from(5), ); } @@ -571,13 +574,13 @@ mod tests { 1, CandidateHash(Hash::repeat_byte(1)), CandidateVotes { - candidate_receipt: dummy_candidate_receipt(Hash::random()), + candidate_receipt: dummy_candidate_receipt_v2(Hash::random()), valid: Vec::new(), invalid: Vec::new(), }, ); - let receipt = dummy_candidate_receipt(dummy_hash()); + let receipt = dummy_candidate_receipt_v2(dummy_hash()); overlay_db.write_candidate_votes( 1, @@ -621,7 +624,7 @@ mod tests { let very_recent = current_session - 1; let blank_candidate_votes = || CandidateVotes { - candidate_receipt: dummy_candidate_receipt(dummy_hash()), + candidate_receipt: dummy_candidate_receipt_v2(dummy_hash()), valid: Vec::new(), invalid: Vec::new(), }; diff --git a/polkadot/node/core/dispute-coordinator/src/import.rs b/polkadot/node/core/dispute-coordinator/src/import.rs index d3a4625f0d24..4263dda54b9b 100644 --- a/polkadot/node/core/dispute-coordinator/src/import.rs +++ b/polkadot/node/core/dispute-coordinator/src/import.rs @@ -34,9 +34,9 @@ use polkadot_node_primitives::{ use polkadot_node_subsystem::overseer; use polkadot_node_subsystem_util::runtime::RuntimeInfo; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, DisputeStatement, ExecutorParams, Hash, IndexedVec, - SessionIndex, SessionInfo, ValidDisputeStatementKind, ValidatorId, ValidatorIndex, - ValidatorPair, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, DisputeStatement, + ExecutorParams, Hash, IndexedVec, SessionIndex, SessionInfo, ValidDisputeStatementKind, + ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, }; use sc_keystore::LocalKeystore; diff --git a/polkadot/node/core/dispute-coordinator/src/initialized.rs b/polkadot/node/core/dispute-coordinator/src/initialized.rs index 9cf9047b7273..7fc22d5904c5 100644 --- a/polkadot/node/core/dispute-coordinator/src/initialized.rs +++ b/polkadot/node/core/dispute-coordinator/src/initialized.rs @@ -44,9 +44,10 @@ use polkadot_node_subsystem_util::runtime::{ self, key_ownership_proof, submit_report_dispute_lost, RuntimeInfo, }; use polkadot_primitives::{ - slashing, BlockNumber, CandidateHash, CandidateReceipt, CompactStatement, DisputeStatement, - DisputeStatementSet, Hash, ScrapedOnChainVotes, SessionIndex, ValidDisputeStatementKind, - ValidatorId, ValidatorIndex, + slashing, + vstaging::{CandidateReceiptV2 as CandidateReceipt, ScrapedOnChainVotes}, + BlockNumber, CandidateHash, CompactStatement, DisputeStatement, DisputeStatementSet, Hash, + SessionIndex, ValidDisputeStatementKind, ValidatorId, ValidatorIndex, }; use schnellru::{LruMap, UnlimitedCompact}; @@ -607,7 +608,7 @@ impl Initialized { // the new active leaf as if we received them via gossip. for (candidate_receipt, backers) in backing_validators_per_candidate { // Obtain the session info, for sake of `ValidatorId`s - let relay_parent = candidate_receipt.descriptor.relay_parent; + let relay_parent = candidate_receipt.descriptor.relay_parent(); let session_info = match self .runtime_info .get_session_info_by_index(ctx.sender(), relay_parent, session) @@ -958,9 +959,9 @@ impl Initialized { let votes_in_db = overlay_db.load_candidate_votes(session, &candidate_hash)?; let relay_parent = match &candidate_receipt { MaybeCandidateReceipt::Provides(candidate_receipt) => - candidate_receipt.descriptor().relay_parent, + candidate_receipt.descriptor().relay_parent(), MaybeCandidateReceipt::AssumeBackingVotePresent(candidate_hash) => match &votes_in_db { - Some(votes) => votes.candidate_receipt.descriptor().relay_parent, + Some(votes) => votes.candidate_receipt.descriptor().relay_parent(), None => { gum::warn!( target: LOG_TARGET, @@ -1451,7 +1452,7 @@ impl Initialized { ctx, &mut self.runtime_info, session, - candidate_receipt.descriptor.relay_parent, + candidate_receipt.descriptor.relay_parent(), self.offchain_disabled_validators.iter(session), ) .await diff --git a/polkadot/node/core/dispute-coordinator/src/lib.rs b/polkadot/node/core/dispute-coordinator/src/lib.rs index 84408eb96305..3078ada5d53f 100644 --- a/polkadot/node/core/dispute-coordinator/src/lib.rs +++ b/polkadot/node/core/dispute-coordinator/src/lib.rs @@ -46,7 +46,7 @@ use polkadot_node_subsystem_util::{ runtime::{Config as RuntimeInfoConfig, RuntimeInfo}, }; use polkadot_primitives::{ - DisputeStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidatorIndex, + vstaging::ScrapedOnChainVotes, DisputeStatement, SessionIndex, SessionInfo, ValidatorIndex, }; use crate::{ diff --git a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs index 2220f65e20a7..770c44f7d609 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs @@ -31,7 +31,10 @@ use polkadot_node_subsystem::{ overseer, ActiveLeavesUpdate, RecoveryError, }; use polkadot_node_subsystem_util::runtime::get_validation_code_by_hash; -use polkadot_primitives::{BlockNumber, CandidateHash, CandidateReceipt, Hash, SessionIndex}; +use polkadot_primitives::{ + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, Hash, + SessionIndex, +}; use crate::LOG_TARGET; @@ -348,7 +351,7 @@ async fn participate( let validation_code = match get_validation_code_by_hash( &mut sender, block_hash, - req.candidate_receipt().descriptor.validation_code_hash, + req.candidate_receipt().descriptor.validation_code_hash(), ) .await { @@ -357,7 +360,7 @@ async fn participate( gum::warn!( target: LOG_TARGET, "Validation code unavailable for code hash {:?} in the state of block {:?}", - req.candidate_receipt().descriptor.validation_code_hash, + req.candidate_receipt().descriptor.validation_code_hash(), block_hash, ); diff --git a/polkadot/node/core/dispute-coordinator/src/participation/queues/mod.rs b/polkadot/node/core/dispute-coordinator/src/participation/queues/mod.rs index d9e86def168c..4d317d38590a 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/queues/mod.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/queues/mod.rs @@ -22,7 +22,8 @@ use std::{ use futures::channel::oneshot; use polkadot_node_subsystem::{messages::ChainApiMessage, overseer}; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateReceipt, ExecutorParams, Hash, SessionIndex, + vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, ExecutorParams, + Hash, SessionIndex, }; use crate::{ @@ -405,7 +406,7 @@ impl CandidateComparator { candidate: &CandidateReceipt, ) -> FatalResult { let candidate_hash = candidate.hash(); - let n = get_block_number(sender, candidate.descriptor().relay_parent).await?; + let n = get_block_number(sender, candidate.descriptor().relay_parent()).await?; if n.is_none() { gum::warn!( diff --git a/polkadot/node/core/dispute-coordinator/src/participation/queues/tests.rs b/polkadot/node/core/dispute-coordinator/src/participation/queues/tests.rs index 9176d00b2f5c..a25387a7eb5a 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/queues/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/queues/tests.rs @@ -17,13 +17,13 @@ use crate::{metrics::Metrics, ParticipationPriority}; use assert_matches::assert_matches; use polkadot_primitives::{BlockNumber, Hash}; -use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; +use polkadot_primitives_test_helpers::{dummy_candidate_receipt_v2, dummy_hash}; use super::{CandidateComparator, ParticipationRequest, QueueError, Queues}; /// Make a `ParticipationRequest` based on the given commitments hash. fn make_participation_request(hash: Hash) -> ParticipationRequest { - let mut receipt = dummy_candidate_receipt(dummy_hash()); + let mut receipt = dummy_candidate_receipt_v2(dummy_hash()); // make it differ: receipt.commitments_hash = hash; let request_timer = Metrics::default().time_participation_pipeline(); diff --git a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs index a6ab6f16df05..23f7984965b3 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/tests.rs @@ -68,7 +68,8 @@ async fn participate_with_commitments_hash( let mut receipt = dummy_candidate_receipt_bad_sig(dummy_hash(), dummy_hash()); receipt.commitments_hash = commitments_hash; receipt - }; + } + .into(); let session = 1; let request_timer = participation.metrics.time_participation_pipeline(); diff --git a/polkadot/node/core/dispute-coordinator/src/scraping/mod.rs b/polkadot/node/core/dispute-coordinator/src/scraping/mod.rs index 4c45d9dcc220..9aaad9d1c528 100644 --- a/polkadot/node/core/dispute-coordinator/src/scraping/mod.rs +++ b/polkadot/node/core/dispute-coordinator/src/scraping/mod.rs @@ -28,8 +28,9 @@ use polkadot_node_subsystem_util::runtime::{ self, get_candidate_events, get_on_chain_votes, get_unapplied_slashes, }; use polkadot_primitives::{ - slashing::PendingSlashes, BlockNumber, CandidateEvent, CandidateHash, CandidateReceipt, Hash, - ScrapedOnChainVotes, SessionIndex, + slashing::PendingSlashes, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt, ScrapedOnChainVotes}, + BlockNumber, CandidateHash, Hash, SessionIndex, }; use crate::{ diff --git a/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs b/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs index ed2400387ef7..fe04193014c6 100644 --- a/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs @@ -36,8 +36,9 @@ use polkadot_node_subsystem_test_helpers::{ }; use polkadot_node_subsystem_util::{reexports::SubsystemContext, TimeoutExt}; use polkadot_primitives::{ - BlakeTwo256, BlockNumber, CandidateDescriptor, CandidateEvent, CandidateReceipt, CoreIndex, - GroupIndex, Hash, HashT, HeadData, Id as ParaId, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt}, + BlakeTwo256, BlockNumber, CandidateDescriptor, CoreIndex, GroupIndex, Hash, HashT, HeadData, + Id as ParaId, }; use polkadot_primitives_test_helpers::{dummy_collator, dummy_collator_signature, dummy_hash}; @@ -135,7 +136,8 @@ fn make_candidate_receipt(relay_parent: Hash) -> CandidateReceipt { signature: dummy_collator_signature(), para_head: zeros, validation_code_hash: zeros.into(), - }; + } + .into(); CandidateReceipt { descriptor, commitments_hash: zeros } } diff --git a/polkadot/node/core/dispute-coordinator/src/tests.rs b/polkadot/node/core/dispute-coordinator/src/tests.rs index 48762a1d80be..9383f71804ed 100644 --- a/polkadot/node/core/dispute-coordinator/src/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/tests.rs @@ -60,13 +60,18 @@ use polkadot_node_subsystem_test_helpers::{ make_buffered_subsystem_context, mock::new_leaf, TestSubsystemContextHandle, }; use polkadot_primitives::{ - ApprovalVote, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, - CandidateReceipt, CoreIndex, DisputeStatement, ExecutorParams, GroupIndex, Hash, HeadData, - Header, IndexedVec, MultiDisputeStatementSet, NodeFeatures, ScrapedOnChainVotes, SessionIndex, - SessionInfo, SigningContext, ValidDisputeStatementKind, ValidatorId, ValidatorIndex, - ValidatorSignature, + vstaging::{ + CandidateEvent, CandidateReceiptV2 as CandidateReceipt, MutateDescriptorV2, + ScrapedOnChainVotes, + }, + ApprovalVote, BlockNumber, CandidateCommitments, CandidateHash, CoreIndex, DisputeStatement, + ExecutorParams, GroupIndex, Hash, HeadData, Header, IndexedVec, MultiDisputeStatementSet, + NodeFeatures, SessionIndex, SessionInfo, SigningContext, ValidDisputeStatementKind, + ValidatorId, ValidatorIndex, ValidatorSignature, +}; +use polkadot_primitives_test_helpers::{ + dummy_candidate_receipt_v2_bad_sig, dummy_digest, dummy_hash, }; -use polkadot_primitives_test_helpers::{dummy_candidate_receipt_bad_sig, dummy_digest, dummy_hash}; use crate::{ backend::Backend, @@ -648,11 +653,11 @@ fn make_valid_candidate_receipt() -> CandidateReceipt { } fn make_invalid_candidate_receipt() -> CandidateReceipt { - dummy_candidate_receipt_bad_sig(Default::default(), Some(Default::default())) + dummy_candidate_receipt_v2_bad_sig(Default::default(), Some(Default::default())) } fn make_another_valid_candidate_receipt(relay_parent: Hash) -> CandidateReceipt { - let mut candidate_receipt = dummy_candidate_receipt_bad_sig(relay_parent, dummy_hash()); + let mut candidate_receipt = dummy_candidate_receipt_v2_bad_sig(relay_parent, dummy_hash()); candidate_receipt.commitments_hash = CandidateCommitments::default().hash(); candidate_receipt } @@ -3858,14 +3863,15 @@ fn participation_requests_reprioritized_for_newly_included() { for repetition in 1..=3u8 { // Building candidate receipts let mut candidate_receipt = make_valid_candidate_receipt(); - candidate_receipt.descriptor.pov_hash = Hash::from( + candidate_receipt.descriptor.set_pov_hash(Hash::from( [repetition; 32], // Altering this receipt so its hash will be changed - ); + )); // Set consecutive parents (starting from zero). They will order the candidates for // participation. let parent_block_num: BlockNumber = repetition as BlockNumber - 1; - candidate_receipt.descriptor.relay_parent = - *test_state.block_num_to_header.get(&parent_block_num).unwrap(); + candidate_receipt.descriptor.set_relay_parent( + *test_state.block_num_to_header.get(&parent_block_num).unwrap(), + ); receipts.push(candidate_receipt.clone()); } diff --git a/polkadot/node/core/parachains-inherent/src/lib.rs b/polkadot/node/core/parachains-inherent/src/lib.rs index 1de3cab32bed..5f3092f6a881 100644 --- a/polkadot/node/core/parachains-inherent/src/lib.rs +++ b/polkadot/node/core/parachains-inherent/src/lib.rs @@ -29,7 +29,7 @@ use futures::{select, FutureExt}; use polkadot_node_subsystem::{ errors::SubsystemError, messages::ProvisionerMessage, overseer::Handle, }; -use polkadot_primitives::{Block, Hash, InherentData as ParachainsInherentData}; +use polkadot_primitives::{vstaging::InherentData as ParachainsInherentData, Block, Hash}; use std::{sync::Arc, time}; pub(crate) const LOG_TARGET: &str = "parachain::parachains-inherent"; diff --git a/polkadot/node/core/prospective-parachains/Cargo.toml b/polkadot/node/core/prospective-parachains/Cargo.toml index 705014e67a05..5629e4ef7fbe 100644 --- a/polkadot/node/core/prospective-parachains/Cargo.toml +++ b/polkadot/node/core/prospective-parachains/Cargo.toml @@ -23,6 +23,7 @@ polkadot-node-subsystem-util = { workspace = true, default-features = true } assert_matches = { workspace = true } polkadot-node-subsystem-test-helpers = { workspace = true } polkadot-primitives-test-helpers = { workspace = true } +polkadot-primitives = { workspace = true, features = ["test"] } sp-tracing = { workspace = true } sp-core = { workspace = true, default-features = true } rand = { workspace = true } diff --git a/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs b/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs index b060897d4391..265d1498ee96 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs @@ -136,8 +136,9 @@ use polkadot_node_subsystem_util::inclusion_emulator::{ ProspectiveCandidate, RelayChainBlockInfo, }; use polkadot_primitives::{ - BlockNumber, CandidateCommitments, CandidateHash, CommittedCandidateReceipt, Hash, HeadData, - PersistedValidationData, ValidationCodeHash, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, BlockNumber, + CandidateCommitments, CandidateHash, Hash, HeadData, PersistedValidationData, + ValidationCodeHash, }; use thiserror::Error; @@ -371,7 +372,8 @@ impl CandidateEntry { persisted_validation_data: PersistedValidationData, state: CandidateState, ) -> Result { - if persisted_validation_data.hash() != candidate.descriptor.persisted_validation_data_hash { + if persisted_validation_data.hash() != candidate.descriptor.persisted_validation_data_hash() + { return Err(CandidateEntryError::PersistedValidationDataMismatch) } @@ -386,13 +388,13 @@ impl CandidateEntry { candidate_hash, parent_head_data_hash, output_head_data_hash, - relay_parent: candidate.descriptor.relay_parent, + relay_parent: candidate.descriptor.relay_parent(), state, candidate: Arc::new(ProspectiveCandidate { commitments: candidate.commitments, persisted_validation_data, - pov_hash: candidate.descriptor.pov_hash, - validation_code_hash: candidate.descriptor.validation_code_hash, + pov_hash: candidate.descriptor.pov_hash(), + validation_code_hash: candidate.descriptor.validation_code_hash(), }), }) } @@ -407,8 +409,8 @@ impl HypotheticalOrConcreteCandidate for CandidateEntry { Some(&self.candidate.persisted_validation_data) } - fn validation_code_hash(&self) -> Option<&ValidationCodeHash> { - Some(&self.candidate.validation_code_hash) + fn validation_code_hash(&self) -> Option { + Some(self.candidate.validation_code_hash) } fn parent_head_data_hash(&self) -> Hash { @@ -1090,7 +1092,7 @@ impl FragmentChain { &relay_parent, &constraints, commitments, - validation_code_hash, + &validation_code_hash, pvd, ) .map_err(Error::CheckAgainstConstraints)?; diff --git a/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs b/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs index 3332cbeb03cb..9708b0871c2a 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs @@ -18,7 +18,8 @@ use super::*; use assert_matches::assert_matches; use polkadot_node_subsystem_util::inclusion_emulator::InboundHrmpLimitations; use polkadot_primitives::{ - BlockNumber, CandidateCommitments, CandidateDescriptor, HeadData, Id as ParaId, + vstaging::MutateDescriptorV2, BlockNumber, CandidateCommitments, CandidateDescriptor, HeadData, + Id as ParaId, }; use polkadot_primitives_test_helpers as test_helpers; use rand::{seq::SliceRandom, thread_rng}; @@ -73,7 +74,8 @@ fn make_committed_candidate( signature: test_helpers::dummy_collator_signature(), para_head: para_head.hash(), validation_code_hash: Hash::repeat_byte(42).into(), - }, + } + .into(), commitments: CandidateCommitments { upward_messages: Default::default(), horizontal_messages: Default::default(), @@ -283,7 +285,7 @@ fn candidate_storage_methods() { candidate.commitments.head_data = HeadData(vec![1; 10]); let mut pvd = pvd.clone(); pvd.parent_head = HeadData(vec![1; 10]); - candidate.descriptor.persisted_validation_data_hash = pvd.hash(); + candidate.descriptor.set_persisted_validation_data_hash(pvd.hash()); assert_matches!( CandidateEntry::new_seconded(candidate_hash, candidate, pvd), Err(CandidateEntryError::ZeroLengthCycle) @@ -291,7 +293,7 @@ fn candidate_storage_methods() { } assert!(!storage.contains(&candidate_hash)); assert_eq!(storage.possible_backed_para_children(&parent_head_hash).count(), 0); - assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head), None); + assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head()), None); assert_eq!(storage.head_data_by_hash(&parent_head_hash), None); // Add a valid candidate. @@ -305,9 +307,9 @@ fn candidate_storage_methods() { storage.add_candidate_entry(candidate_entry.clone()).unwrap(); assert!(storage.contains(&candidate_hash)); assert_eq!(storage.possible_backed_para_children(&parent_head_hash).count(), 0); - assert_eq!(storage.possible_backed_para_children(&candidate.descriptor.para_head).count(), 0); + assert_eq!(storage.possible_backed_para_children(&candidate.descriptor.para_head()).count(), 0); assert_eq!( - storage.head_data_by_hash(&candidate.descriptor.para_head).unwrap(), + storage.head_data_by_hash(&candidate.descriptor.para_head()).unwrap(), &candidate.commitments.head_data ); assert_eq!(storage.head_data_by_hash(&parent_head_hash).unwrap(), &pvd.parent_head); @@ -323,7 +325,7 @@ fn candidate_storage_methods() { .collect::>(), vec![candidate_hash] ); - assert_eq!(storage.possible_backed_para_children(&candidate.descriptor.para_head).count(), 0); + assert_eq!(storage.possible_backed_para_children(&candidate.descriptor.para_head()).count(), 0); // Re-adding a candidate fails. assert_matches!( @@ -339,7 +341,7 @@ fn candidate_storage_methods() { storage.remove_candidate(&candidate_hash); assert!(!storage.contains(&candidate_hash)); assert_eq!(storage.possible_backed_para_children(&parent_head_hash).count(), 0); - assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head), None); + assert_eq!(storage.head_data_by_hash(&candidate.descriptor.para_head()), None); assert_eq!(storage.head_data_by_hash(&parent_head_hash), None); storage @@ -354,7 +356,7 @@ fn candidate_storage_methods() { .collect::>(), vec![candidate_hash] ); - assert_eq!(storage.possible_backed_para_children(&candidate.descriptor.para_head).count(), 0); + assert_eq!(storage.possible_backed_para_children(&candidate.descriptor.para_head()).count(), 0); // Now add a second candidate in Seconded state. This will be a fork. let (pvd_2, candidate_2) = make_committed_candidate( diff --git a/polkadot/node/core/prospective-parachains/src/lib.rs b/polkadot/node/core/prospective-parachains/src/lib.rs index b8b5f159e71c..34c1d8823bfc 100644 --- a/polkadot/node/core/prospective-parachains/src/lib.rs +++ b/polkadot/node/core/prospective-parachains/src/lib.rs @@ -49,9 +49,11 @@ use polkadot_node_subsystem_util::{ runtime::{fetch_claim_queue, prospective_parachains_mode, ProspectiveParachainsMode}, }; use polkadot_primitives::{ - async_backing::CandidatePendingAvailability, BlockNumber, CandidateHash, - CommittedCandidateReceipt, CoreState, Hash, HeadData, Header, Id as ParaId, - PersistedValidationData, + vstaging::{ + async_backing::CandidatePendingAvailability, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + }, + BlockNumber, CandidateHash, Hash, HeadData, Header, Id as ParaId, PersistedValidationData, }; use crate::{ @@ -453,12 +455,13 @@ async fn preprocess_candidates_pending_availability( for (i, pending) in pending_availability.into_iter().enumerate() { let Some(relay_parent) = - fetch_block_info(ctx, cache, pending.descriptor.relay_parent).await? + fetch_block_info(ctx, cache, pending.descriptor.relay_parent()).await? else { + let para_id = pending.descriptor.para_id(); gum::debug!( target: LOG_TARGET, ?pending.candidate_hash, - ?pending.descriptor.para_id, + ?para_id, index = ?i, ?expected_count, "Had to stop processing pending candidates early due to missing info.", diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index 14a093239e8e..3f1eaa4e41ed 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -25,9 +25,12 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ - async_backing::{AsyncBackingParams, BackingState, Constraints, InboundHrmpLimitations}, - CommittedCandidateReceipt, CoreIndex, HeadData, Header, PersistedValidationData, ScheduledCore, - ValidationCodeHash, + async_backing::{AsyncBackingParams, Constraints, InboundHrmpLimitations}, + vstaging::{ + async_backing::BackingState, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, + MutateDescriptorV2, + }, + CoreIndex, HeadData, Header, PersistedValidationData, ScheduledCore, ValidationCodeHash, }; use polkadot_primitives_test_helpers::make_candidate; use rstest::rstest; @@ -393,15 +396,15 @@ async fn handle_leaf_activation( ); for pending in pending_availability { - if !used_relay_parents.contains(&pending.descriptor.relay_parent) { + if !used_relay_parents.contains(&pending.descriptor.relay_parent()) { send_block_header( virtual_overseer, - pending.descriptor.relay_parent, + pending.descriptor.relay_parent(), pending.relay_parent_number, ) .await; - used_relay_parents.insert(pending.descriptor.relay_parent); + used_relay_parents.insert(pending.descriptor.relay_parent()); } } } @@ -436,7 +439,7 @@ async fn introduce_seconded_candidate( pvd: PersistedValidationData, ) { let req = IntroduceSecondedCandidateRequest { - candidate_para: candidate.descriptor().para_id, + candidate_para: candidate.descriptor.para_id(), candidate_receipt: candidate, persisted_validation_data: pvd, }; @@ -455,7 +458,7 @@ async fn introduce_seconded_candidate_failed( pvd: PersistedValidationData, ) { let req = IntroduceSecondedCandidateRequest { - candidate_para: candidate.descriptor().para_id, + candidate_para: candidate.descriptor.para_id(), candidate_receipt: candidate, persisted_validation_data: pvd, }; @@ -476,7 +479,7 @@ async fn back_candidate( virtual_overseer .send(overseer::FromOrchestra::Communication { msg: ProspectiveParachainsMessage::CandidateBacked( - candidate.descriptor.para_id, + candidate.descriptor.para_id(), candidate_hash, ), }) @@ -568,7 +571,7 @@ macro_rules! make_and_back_candidate { $test_state.validation_code_hash, ); // Set a field to make this candidate unique. - candidate.descriptor.para_head = Hash::from_low_u64_le($index); + candidate.descriptor.set_para_head(Hash::from_low_u64_le($index)); let candidate_hash = candidate.hash(); introduce_seconded_candidate(&mut $virtual_overseer, candidate.clone(), pvd).await; back_candidate(&mut $virtual_overseer, &candidate, candidate_hash).await; @@ -1378,7 +1381,7 @@ fn check_backable_query_single_candidate() { test_state.validation_code_hash, ); // Set a field to make this candidate unique. - candidate_b.descriptor.para_head = Hash::from_low_u64_le(1000); + candidate_b.descriptor.set_para_head(Hash::from_low_u64_le(1000)); let candidate_hash_b = candidate_b.hash(); // Introduce candidates. diff --git a/polkadot/node/core/provisioner/Cargo.toml b/polkadot/node/core/provisioner/Cargo.toml index 5869e494c70f..64a598b420f7 100644 --- a/polkadot/node/core/provisioner/Cargo.toml +++ b/polkadot/node/core/provisioner/Cargo.toml @@ -27,4 +27,6 @@ sp-application-crypto = { workspace = true, default-features = true } sp-keystore = { workspace = true, default-features = true } polkadot-node-subsystem-test-helpers = { workspace = true } polkadot-primitives-test-helpers = { workspace = true } +polkadot-primitives = { workspace = true, features = ["test"] } + rstest = { workspace = true } diff --git a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs index ecb7aac78396..8c0d478b67df 100644 --- a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs +++ b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs @@ -427,7 +427,7 @@ impl TestDisputes { let onchain_votes_count = self.validators_count * 80 / 100; let session_idx = 0; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); @@ -445,7 +445,7 @@ impl TestDisputes { let onchain_votes_count = self.validators_count * 40 / 100; let session_idx = 1; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); @@ -462,7 +462,7 @@ impl TestDisputes { let local_votes_count = self.validators_count * 90 / 100; let session_idx = 2; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Confirmed); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); @@ -478,7 +478,7 @@ impl TestDisputes { let onchain_votes_count = self.validators_count * 75 / 100; let session_idx = 3; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::ConcludedFor(0)); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); @@ -494,7 +494,7 @@ impl TestDisputes { let local_votes_count = self.validators_count * 90 / 100; let session_idx = 4; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::ConcludedFor(0)); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); @@ -510,7 +510,7 @@ impl TestDisputes { let onchain_votes_count = self.validators_count * 10 / 100; let session_idx = 5; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); @@ -527,7 +527,7 @@ impl TestDisputes { let local_votes_count = self.validators_count * 10 / 100; let session_idx = 6; let lf = leaf(); - let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt(lf.hash); + let dummy_receipt = polkadot_primitives_test_helpers::dummy_candidate_receipt_v2(lf.hash); for _ in 0..dispute_count { let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); self.add_offchain_dispute(d, local_votes_count, dummy_receipt.clone()); diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index 9a06d9cff0cc..a95df6c5f880 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -41,9 +41,10 @@ use polkadot_node_subsystem_util::{ TimeoutExt, }; use polkadot_primitives::{ - node_features::FeatureIndex, BackedCandidate, BlockNumber, CandidateHash, CandidateReceipt, - CoreIndex, CoreState, Hash, Id as ParaId, NodeFeatures, OccupiedCoreAssumption, SessionIndex, - SignedAvailabilityBitfield, ValidatorIndex, + node_features::FeatureIndex, + vstaging::{BackedCandidate, CandidateReceiptV2 as CandidateReceipt, CoreState}, + BlockNumber, CandidateHash, CoreIndex, Hash, Id as ParaId, NodeFeatures, + OccupiedCoreAssumption, SessionIndex, SignedAvailabilityBitfield, ValidatorIndex, }; use std::collections::{BTreeMap, HashMap}; @@ -361,10 +362,9 @@ fn note_provisionable_data( gum::trace!( target: LOG_TARGET, ?candidate_hash, - para = ?backed_candidate.descriptor().para_id, + para = ?backed_candidate.descriptor().para_id(), "noted backed candidate", ); - per_relay_parent.backed_candidates.push(backed_candidate); }, // We choose not to punish these forms of misbehavior for the time being. @@ -650,22 +650,22 @@ async fn select_candidate_hashes_from_tracked( // selection criteria if let Some(candidate) = candidates.iter().find(|backed_candidate| { let descriptor = &backed_candidate.descriptor; - descriptor.para_id == scheduled_core.para_id && - descriptor.persisted_validation_data_hash == computed_validation_data_hash + descriptor.para_id() == scheduled_core.para_id && + descriptor.persisted_validation_data_hash() == computed_validation_data_hash }) { let candidate_hash = candidate.hash(); gum::trace!( target: LOG_TARGET, leaf_hash=?relay_parent, ?candidate_hash, - para = ?candidate.descriptor.para_id, + para = ?candidate.descriptor.para_id(), core = core_idx, "Selected candidate receipt", ); selected_candidates.insert( - candidate.descriptor.para_id, - vec![(candidate_hash, candidate.descriptor.relay_parent)], + candidate.descriptor.para_id(), + vec![(candidate_hash, candidate.descriptor.relay_parent())], ); } } diff --git a/polkadot/node/core/provisioner/src/tests.rs b/polkadot/node/core/provisioner/src/tests.rs index b38459302c8f..a09b243f3ab1 100644 --- a/polkadot/node/core/provisioner/src/tests.rs +++ b/polkadot/node/core/provisioner/src/tests.rs @@ -16,14 +16,17 @@ use super::*; use bitvec::bitvec; -use polkadot_primitives::{OccupiedCore, ScheduledCore}; -use polkadot_primitives_test_helpers::{dummy_candidate_descriptor, dummy_hash}; +use polkadot_primitives::{ + vstaging::{MutateDescriptorV2, OccupiedCore}, + ScheduledCore, +}; +use polkadot_primitives_test_helpers::{dummy_candidate_descriptor_v2, dummy_hash}; const MOCK_GROUP_SIZE: usize = 5; pub fn occupied_core(para_id: u32) -> CoreState { - let mut candidate_descriptor = dummy_candidate_descriptor(dummy_hash()); - candidate_descriptor.para_id = para_id.into(); + let mut candidate_descriptor = dummy_candidate_descriptor_v2(dummy_hash()); + candidate_descriptor.set_para_id(para_id.into()); CoreState::Occupied(OccupiedCore { group_responsible: para_id.into(), @@ -32,7 +35,7 @@ pub fn occupied_core(para_id: u32) -> CoreState { time_out_at: 200_u32, next_up_on_time_out: None, availability: bitvec![u8, bitvec::order::Lsb0; 0; 32], - candidate_descriptor, + candidate_descriptor: candidate_descriptor.into(), candidate_hash: Default::default(), }) } @@ -254,9 +257,10 @@ mod select_candidates { use polkadot_node_subsystem_test_helpers::TestSubsystemSender; use polkadot_node_subsystem_util::runtime::ProspectiveParachainsMode; use polkadot_primitives::{ - BlockNumber, CandidateCommitments, CommittedCandidateReceipt, PersistedValidationData, + vstaging::{CommittedCandidateReceiptV2 as CommittedCandidateReceipt, MutateDescriptorV2}, + BlockNumber, CandidateCommitments, PersistedValidationData, }; - use polkadot_primitives_test_helpers::{dummy_candidate_descriptor, dummy_hash}; + use polkadot_primitives_test_helpers::{dummy_candidate_descriptor_v2, dummy_hash}; use rstest::rstest; use std::ops::Not; use CoreState::{Free, Scheduled}; @@ -266,8 +270,8 @@ mod select_candidates { fn dummy_candidate_template() -> CandidateReceipt { let empty_hash = PersistedValidationData::::default().hash(); - let mut descriptor_template = dummy_candidate_descriptor(dummy_hash()); - descriptor_template.persisted_validation_data_hash = empty_hash; + let mut descriptor_template = dummy_candidate_descriptor_v2(dummy_hash()); + descriptor_template.set_persisted_validation_data_hash(empty_hash); CandidateReceipt { descriptor: descriptor_template, commitments_hash: CandidateCommitments::default().hash(), @@ -283,7 +287,7 @@ mod select_candidates { .take(core_count) .enumerate() .map(|(idx, mut candidate)| { - candidate.descriptor.para_id = idx.into(); + candidate.descriptor.set_para_id(idx.into()); candidate }) .collect(); @@ -559,14 +563,14 @@ mod select_candidates { use RuntimeApiMessage::Request; let mut backed = expected.clone().into_iter().fold(HashMap::new(), |mut acc, candidate| { - acc.entry(candidate.descriptor().para_id).or_insert(vec![]).push(candidate); + acc.entry(candidate.descriptor().para_id()).or_insert(vec![]).push(candidate); acc }); - expected.sort_by_key(|c| c.candidate().descriptor.para_id); + expected.sort_by_key(|c| c.candidate().descriptor.para_id()); let mut candidates_iter = expected .iter() - .map(|candidate| (candidate.hash(), candidate.descriptor().relay_parent)); + .map(|candidate| (candidate.hash(), candidate.descriptor().relay_parent())); while let Some(from_job) = receiver.next().await { match from_job { @@ -601,7 +605,7 @@ mod select_candidates { candidates .iter() .map(|candidate| { - (candidate.hash(), candidate.descriptor().relay_parent) + (candidate.hash(), candidate.descriptor().relay_parent()) }) .collect(), ) @@ -707,7 +711,7 @@ mod select_candidates { .take(mock_cores.len()) .enumerate() .map(|(idx, mut candidate)| { - candidate.descriptor.para_id = idx.into(); + candidate.descriptor.set_para_id(idx.into()); candidate }) .cycle() @@ -719,11 +723,11 @@ mod select_candidates { candidate } else if idx < mock_cores.len() * 2 { // for the second repetition of the candidates, give them the wrong hash - candidate.descriptor.persisted_validation_data_hash = Default::default(); + candidate.descriptor.set_persisted_validation_data_hash(Default::default()); candidate } else { // third go-around: right hash, wrong para_id - candidate.descriptor.para_id = idx.into(); + candidate.descriptor.set_para_id(idx.into()); candidate } }) @@ -807,9 +811,9 @@ mod select_candidates { let committed_receipts: Vec<_> = (0..=mock_cores.len()) .map(|i| { - let mut descriptor = dummy_candidate_descriptor(dummy_hash()); - descriptor.para_id = i.into(); - descriptor.persisted_validation_data_hash = empty_hash; + let mut descriptor = dummy_candidate_descriptor_v2(dummy_hash()); + descriptor.set_para_id(i.into()); + descriptor.set_persisted_validation_data_hash(empty_hash); CommittedCandidateReceipt { descriptor, commitments: CandidateCommitments { @@ -917,14 +921,14 @@ mod select_candidates { let committed_receipts: Vec<_> = (0..mock_cores.len()) .map(|i| { - let mut descriptor = dummy_candidate_descriptor(dummy_hash()); - descriptor.para_id = if let Scheduled(scheduled_core) = &mock_cores[i] { + let mut descriptor = dummy_candidate_descriptor_v2(dummy_hash()); + descriptor.set_para_id(if let Scheduled(scheduled_core) = &mock_cores[i] { scheduled_core.para_id } else { panic!("`mock_cores` is not initialized with `Scheduled`?") - }; - descriptor.persisted_validation_data_hash = empty_hash; - descriptor.pov_hash = Hash::from_low_u64_be(i as u64); + }); + descriptor.set_persisted_validation_data_hash(empty_hash); + descriptor.set_pov_hash(Hash::from_low_u64_be(i as u64)); CommittedCandidateReceipt { descriptor, commitments: CandidateCommitments { @@ -1222,8 +1226,8 @@ mod select_candidates { .take(mock_cores.len() + 1) .enumerate() .map(|(idx, mut candidate)| { - candidate.descriptor.para_id = idx.into(); - candidate.descriptor.relay_parent = Hash::repeat_byte(idx as u8); + candidate.descriptor.set_para_id(idx.into()); + candidate.descriptor.set_relay_parent(Hash::repeat_byte(idx as u8)); candidate }) .collect(); diff --git a/polkadot/node/core/runtime-api/src/cache.rs b/polkadot/node/core/runtime-api/src/cache.rs index 05efbc533d02..7246010711e4 100644 --- a/polkadot/node/core/runtime-api/src/cache.rs +++ b/polkadot/node/core/runtime-api/src/cache.rs @@ -20,12 +20,16 @@ use schnellru::{ByLength, LruMap}; use sp_consensus_babe::Epoch; use polkadot_primitives::{ - async_backing, slashing, ApprovalVotingParams, AuthorityDiscoveryId, BlockNumber, - CandidateCommitments, CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreIndex, - CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash, Id as ParaId, + async_backing, slashing, vstaging, + vstaging::{ + CandidateEvent, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + ScrapedOnChainVotes, + }, + ApprovalVotingParams, AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateHash, + CoreIndex, DisputeState, ExecutorParams, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, - PersistedValidationData, ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, - ValidationCodeHash, ValidatorId, ValidatorIndex, + PersistedValidationData, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, + ValidatorId, ValidatorIndex, }; /// For consistency we have the same capacity for all caches. We use 128 as we'll only need that @@ -66,7 +70,7 @@ pub(crate) struct RequestResultCache { key_ownership_proof: LruMap<(Hash, ValidatorId), Option>, minimum_backing_votes: LruMap, disabled_validators: LruMap>, - para_backing_state: LruMap<(Hash, ParaId), Option>, + para_backing_state: LruMap<(Hash, ParaId), Option>, async_backing_params: LruMap, node_features: LruMap, approval_voting_params: LruMap, @@ -499,14 +503,14 @@ impl RequestResultCache { pub(crate) fn para_backing_state( &mut self, key: (Hash, ParaId), - ) -> Option<&Option> { + ) -> Option<&Option> { self.para_backing_state.get(&key).map(|v| &*v) } pub(crate) fn cache_para_backing_state( &mut self, key: (Hash, ParaId), - value: Option, + value: Option, ) { self.para_backing_state.insert(key, value); } @@ -601,7 +605,7 @@ pub(crate) enum RequestResult { SubmitReportDisputeLost(Option<()>), ApprovalVotingParams(Hash, SessionIndex, ApprovalVotingParams), DisabledValidators(Hash, Vec), - ParaBackingState(Hash, ParaId, Option), + ParaBackingState(Hash, ParaId, Option), AsyncBackingParams(Hash, async_backing::AsyncBackingParams), NodeFeatures(SessionIndex, NodeFeatures), ClaimQueue(Hash, BTreeMap>), diff --git a/polkadot/node/core/runtime-api/src/tests.rs b/polkadot/node/core/runtime-api/src/tests.rs index 7c382707264f..d4fa07323886 100644 --- a/polkadot/node/core/runtime-api/src/tests.rs +++ b/polkadot/node/core/runtime-api/src/tests.rs @@ -20,14 +20,20 @@ use polkadot_node_primitives::{BabeAllowedSlots, BabeEpoch, BabeEpochConfigurati use polkadot_node_subsystem::SpawnGlue; use polkadot_node_subsystem_test_helpers::make_subsystem_context; use polkadot_primitives::{ - async_backing, slashing, ApprovalVotingParams, AuthorityDiscoveryId, BlockNumber, - CandidateCommitments, CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreIndex, - CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Id as ParaId, + async_backing, slashing, vstaging, + vstaging::{ + CandidateEvent, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + ScrapedOnChainVotes, + }, + ApprovalVotingParams, AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateHash, + CoreIndex, DisputeState, ExecutorParams, GroupRotationInfo, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, - PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, - Slot, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + PersistedValidationData, PvfCheckStatement, SessionIndex, SessionInfo, Slot, ValidationCode, + ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, +}; +use polkadot_primitives_test_helpers::{ + dummy_committed_candidate_receipt_v2, dummy_validation_code, }; -use polkadot_primitives_test_helpers::{dummy_committed_candidate_receipt, dummy_validation_code}; use sp_api::ApiError; use sp_core::testing::TaskExecutor; use std::{ @@ -279,7 +285,7 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient { &self, _: Hash, _: ParaId, - ) -> Result, ApiError> { + ) -> Result, ApiError> { todo!("Not required for tests") } @@ -699,7 +705,7 @@ fn requests_candidate_pending_availability() { let para_a = ParaId::from(5_u32); let para_b = ParaId::from(6_u32); let spawner = sp_core::testing::TaskExecutor::new(); - let candidate_receipt = dummy_committed_candidate_receipt(relay_parent); + let candidate_receipt = dummy_committed_candidate_receipt_v2(relay_parent); let mut subsystem_client = MockSubsystemClient::default(); subsystem_client diff --git a/polkadot/node/malus/src/variants/common.rs b/polkadot/node/malus/src/variants/common.rs index 66926f48c5e7..7415e6c79df5 100644 --- a/polkadot/node/malus/src/variants/common.rs +++ b/polkadot/node/malus/src/variants/common.rs @@ -24,8 +24,10 @@ use crate::{ use polkadot_node_primitives::{InvalidCandidate, ValidationResult}; use polkadot_primitives::{ - CandidateCommitments, CandidateDescriptor, CandidateReceipt, PersistedValidationData, - PvfExecKind, + vstaging::{ + CandidateDescriptorV2 as CandidateDescriptor, CandidateReceiptV2 as CandidateReceipt, + }, + CandidateCommitments, PersistedValidationData, PvfExecKind, }; use futures::channel::oneshot; @@ -203,7 +205,7 @@ fn create_validation_response( gum::debug!( target: MALUS, - para_id = ?candidate_receipt.descriptor.para_id, + para_id = ?candidate_receipt.descriptor.para_id(), candidate_hash = ?candidate_receipt.hash(), "ValidationResult: {:?}", &result @@ -308,7 +310,7 @@ where gum::info!( target: MALUS, ?behave_maliciously, - para_id = ?candidate_receipt.descriptor.para_id, + para_id = ?candidate_receipt.descriptor.para_id(), "😈 Maliciously sending invalid validation result: {:?}.", &validation_result, ); diff --git a/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs b/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs index 7a95bdaead26..309be9e46d82 100644 --- a/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs +++ b/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs @@ -42,7 +42,7 @@ use polkadot_cli::{ use polkadot_node_subsystem::SpawnGlue; use polkadot_node_subsystem_types::{ChainApiBackend, OverseerSignal, RuntimeApiSubsystemClient}; use polkadot_node_subsystem_util::request_candidate_events; -use polkadot_primitives::CandidateEvent; +use polkadot_primitives::vstaging::CandidateEvent; use sp_core::traits::SpawnNamed; // Filter wrapping related types. diff --git a/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs b/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs index ab2d380fbaf4..2fe08c8a1c49 100644 --- a/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs +++ b/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs @@ -32,7 +32,7 @@ use polkadot_cli::{ }; use polkadot_node_primitives::{AvailableData, BlockData, PoV}; use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; -use polkadot_primitives::{CandidateDescriptor, CandidateReceipt}; +use polkadot_primitives::{vstaging::CandidateReceiptV2, CandidateDescriptor}; use polkadot_node_subsystem_util::request_validators; use sp_core::traits::SpawnNamed; @@ -127,7 +127,7 @@ where let validation_code = { let validation_code_hash = - _candidate.descriptor().validation_code_hash; + _candidate.descriptor().validation_code_hash(); let (tx, rx) = oneshot::channel(); new_sender .send_message(RuntimeApiMessage::Request( @@ -214,7 +214,7 @@ where let collator_pair = CollatorPair::generate().0; let signature_payload = polkadot_primitives::collator_signature_payload( &relay_parent, - &candidate.descriptor().para_id, + &candidate.descriptor().para_id(), &validation_data_hash, &pov_hash, &validation_code_hash, @@ -227,9 +227,9 @@ where &malicious_available_data.validation_data, ); - let malicious_candidate = CandidateReceipt { + let malicious_candidate = CandidateReceiptV2 { descriptor: CandidateDescriptor { - para_id: candidate.descriptor().para_id, + para_id: candidate.descriptor.para_id(), relay_parent, collator: collator_id, persisted_validation_data_hash: validation_data_hash, @@ -238,7 +238,8 @@ where signature: collator_signature, para_head: malicious_commitments.head_data.hash(), validation_code_hash, - }, + } + .into(), commitments_hash: malicious_commitments.hash(), }; let malicious_candidate_hash = malicious_candidate.hash(); diff --git a/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs b/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs index 5be6f2d223a8..c4654b843c44 100644 --- a/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs +++ b/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs @@ -35,8 +35,8 @@ use polkadot_node_subsystem::{ overseer, }; use polkadot_primitives::{ - AuthorityDiscoveryId, BlakeTwo256, CandidateHash, ChunkIndex, GroupIndex, Hash, HashT, - OccupiedCore, SessionIndex, + vstaging::OccupiedCore, AuthorityDiscoveryId, BlakeTwo256, CandidateHash, ChunkIndex, + GroupIndex, Hash, HashT, SessionIndex, }; use sc_network::ProtocolName; @@ -170,8 +170,8 @@ impl FetchTaskConfig { candidate_hash: core.candidate_hash, index: session_info.our_index, }, - erasure_root: core.candidate_descriptor.erasure_root, - relay_parent: core.candidate_descriptor.relay_parent, + erasure_root: core.candidate_descriptor.erasure_root(), + relay_parent: core.candidate_descriptor.relay_parent(), metrics, sender, chunk_index, diff --git a/polkadot/node/network/availability-distribution/src/requester/mod.rs b/polkadot/node/network/availability-distribution/src/requester/mod.rs index 233825032724..613a514269ee 100644 --- a/polkadot/node/network/availability-distribution/src/requester/mod.rs +++ b/polkadot/node/network/availability-distribution/src/requester/mod.rs @@ -38,7 +38,7 @@ use polkadot_node_subsystem_util::{ availability_chunks::availability_chunk_index, runtime::{get_occupied_cores, RuntimeInfo}, }; -use polkadot_primitives::{CandidateHash, CoreIndex, Hash, OccupiedCore, SessionIndex}; +use polkadot_primitives::{vstaging::OccupiedCore, CandidateHash, CoreIndex, Hash, SessionIndex}; use super::{FatalError, Metrics, Result, LOG_TARGET}; diff --git a/polkadot/node/network/availability-distribution/src/requester/tests.rs b/polkadot/node/network/availability-distribution/src/requester/tests.rs index 021f6da7e2e9..ebcba2a038bc 100644 --- a/polkadot/node/network/availability-distribution/src/requester/tests.rs +++ b/polkadot/node/network/availability-distribution/src/requester/tests.rs @@ -21,7 +21,7 @@ use polkadot_node_network_protocol::request_response::ReqProtocolNames; use polkadot_node_primitives::{BlockData, ErasureChunk, PoV}; use polkadot_node_subsystem_util::runtime::RuntimeInfo; use polkadot_primitives::{ - BlockNumber, ChunkIndex, CoreState, ExecutorParams, GroupIndex, Hash, Id as ParaId, + vstaging::CoreState, BlockNumber, ChunkIndex, ExecutorParams, GroupIndex, Hash, Id as ParaId, ScheduledCore, SessionIndex, SessionInfo, }; use sp_core::{testing::TaskExecutor, traits::SpawnNamed}; diff --git a/polkadot/node/network/availability-distribution/src/tests/mock.rs b/polkadot/node/network/availability-distribution/src/tests/mock.rs index b41c493a1072..f900cb6e6156 100644 --- a/polkadot/node/network/availability-distribution/src/tests/mock.rs +++ b/polkadot/node/network/availability-distribution/src/tests/mock.rs @@ -23,8 +23,9 @@ use sp_keyring::Sr25519Keyring; use polkadot_erasure_coding::{branches, obtain_chunks_v1 as obtain_chunks}; use polkadot_node_primitives::{AvailableData, BlockData, ErasureChunk, PoV, Proof}; use polkadot_primitives::{ + vstaging::{CommittedCandidateReceiptV2, OccupiedCore}, CandidateCommitments, CandidateDescriptor, CandidateHash, ChunkIndex, - CommittedCandidateReceipt, GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, OccupiedCore, + CommittedCandidateReceipt, GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, PersistedValidationData, SessionInfo, ValidatorIndex, }; use polkadot_primitives_test_helpers::{ @@ -101,7 +102,7 @@ impl OccupiedCoreBuilder { availability: Default::default(), group_responsible: self.group_responsible, candidate_hash: candidate_receipt.hash(), - candidate_descriptor: candidate_receipt.descriptor().clone(), + candidate_descriptor: candidate_receipt.descriptor.clone(), }; (core, (candidate_receipt.hash(), chunk)) } @@ -117,7 +118,7 @@ pub struct TestCandidateBuilder { } impl TestCandidateBuilder { - pub fn build(self) -> CommittedCandidateReceipt { + pub fn build(self) -> CommittedCandidateReceiptV2 { CommittedCandidateReceipt { descriptor: CandidateDescriptor { para_id: self.para_id, @@ -132,6 +133,7 @@ impl TestCandidateBuilder { }, commitments: CandidateCommitments { head_data: self.head_data, ..Default::default() }, } + .into() } } diff --git a/polkadot/node/network/availability-distribution/src/tests/mod.rs b/polkadot/node/network/availability-distribution/src/tests/mod.rs index 078220607c37..d4abd4e32d9b 100644 --- a/polkadot/node/network/availability-distribution/src/tests/mod.rs +++ b/polkadot/node/network/availability-distribution/src/tests/mod.rs @@ -22,7 +22,7 @@ use rstest::rstest; use polkadot_node_network_protocol::request_response::{ IncomingRequest, Protocol, ReqProtocolNames, }; -use polkadot_primitives::{node_features, Block, CoreState, Hash, NodeFeatures}; +use polkadot_primitives::{node_features, vstaging::CoreState, Block, Hash, NodeFeatures}; use sp_keystore::KeystorePtr; use super::*; diff --git a/polkadot/node/network/availability-distribution/src/tests/state.rs b/polkadot/node/network/availability-distribution/src/tests/state.rs index 53d6fd2c530f..c6dd17a344e0 100644 --- a/polkadot/node/network/availability-distribution/src/tests/state.rs +++ b/polkadot/node/network/availability-distribution/src/tests/state.rs @@ -47,7 +47,7 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ - CandidateHash, ChunkIndex, CoreIndex, CoreState, ExecutorParams, GroupIndex, Hash, + vstaging::CoreState, CandidateHash, ChunkIndex, CoreIndex, ExecutorParams, GroupIndex, Hash, Id as ParaId, NodeFeatures, ScheduledCore, SessionInfo, ValidatorIndex, }; use test_helpers::mock::{make_ferdie_keystore, new_leaf}; diff --git a/polkadot/node/network/availability-recovery/src/lib.rs b/polkadot/node/network/availability-recovery/src/lib.rs index 114faa2859c4..eb54d9657d83 100644 --- a/polkadot/node/network/availability-recovery/src/lib.rs +++ b/polkadot/node/network/availability-recovery/src/lib.rs @@ -66,8 +66,8 @@ use polkadot_node_subsystem_util::{ runtime::{ExtendedSessionInfo, RuntimeInfo}, }; use polkadot_primitives::{ - node_features, BlockNumber, CandidateHash, CandidateReceipt, ChunkIndex, CoreIndex, GroupIndex, - Hash, SessionIndex, ValidatorIndex, + node_features, vstaging::CandidateReceiptV2 as CandidateReceipt, BlockNumber, CandidateHash, + ChunkIndex, CoreIndex, GroupIndex, Hash, SessionIndex, ValidatorIndex, }; mod error; @@ -540,11 +540,11 @@ async fn handle_recover( threshold: recovery_threshold(n_validators)?, systematic_threshold, candidate_hash, - erasure_root: receipt.descriptor.erasure_root, + erasure_root: receipt.descriptor.erasure_root(), metrics: metrics.clone(), bypass_availability_store, post_recovery_check, - pov_hash: receipt.descriptor.pov_hash, + pov_hash: receipt.descriptor.pov_hash(), req_v1_protocol_name, req_v2_protocol_name, chunk_mapping_enabled, diff --git a/polkadot/node/network/availability-recovery/src/tests.rs b/polkadot/node/network/availability-recovery/src/tests.rs index 4fd9ede40ff6..9a46d5420782 100644 --- a/polkadot/node/network/availability-recovery/src/tests.rs +++ b/polkadot/node/network/availability-recovery/src/tests.rs @@ -41,8 +41,8 @@ use polkadot_node_subsystem_test_helpers::{ }; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ - node_features, AuthorityDiscoveryId, Block, ExecutorParams, Hash, HeadData, IndexedVec, - NodeFeatures, PersistedValidationData, SessionInfo, ValidatorId, + node_features, vstaging::MutateDescriptorV2, AuthorityDiscoveryId, Block, ExecutorParams, Hash, + HeadData, IndexedVec, NodeFeatures, PersistedValidationData, SessionInfo, ValidatorId, }; use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; use sc_network::{IfDisconnected, OutboundFailure, ProtocolName, RequestFailure}; @@ -346,7 +346,7 @@ impl TestState { ) .unwrap(), current, - candidate, + candidate: candidate.into(), session_index, core_index, node_features, @@ -800,12 +800,12 @@ fn availability_is_recovered_from_chunks_if_no_group_provided(#[case] systematic // Test another candidate, send no chunks. let mut new_candidate = dummy_candidate_receipt(dummy_hash()); - new_candidate.descriptor.relay_parent = test_state.candidate.descriptor.relay_parent; + new_candidate.descriptor.relay_parent = test_state.candidate.descriptor.relay_parent(); overseer_send( &mut virtual_overseer, AvailabilityRecoveryMessage::RecoverAvailableData( - new_candidate.clone(), + new_candidate.clone().into(), test_state.session_index, None, Some(test_state.core_index), @@ -929,12 +929,12 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk // Test another candidate, send no chunks. let mut new_candidate = dummy_candidate_receipt(dummy_hash()); - new_candidate.descriptor.relay_parent = test_state.candidate.descriptor.relay_parent; + new_candidate.descriptor.relay_parent = test_state.candidate.descriptor.relay_parent(); overseer_send( &mut virtual_overseer, AvailabilityRecoveryMessage::RecoverAvailableData( - new_candidate.clone(), + new_candidate.clone().into(), test_state.session_index, Some(GroupIndex(1)), Some(test_state.core_index), @@ -1218,7 +1218,7 @@ fn invalid_erasure_coding_leads_to_invalid_error(#[case] systematic_recovery: bo test_state.validators.len(), test_state.core_index, ); - test_state.candidate.descriptor.erasure_root = bad_erasure_root; + test_state.candidate.descriptor.set_erasure_root(bad_erasure_root); let candidate_hash = test_state.candidate.hash(); @@ -1283,7 +1283,7 @@ fn invalid_pov_hash_leads_to_invalid_error() { test_harness(subsystem, |mut virtual_overseer| async move { let pov = PoV { block_data: BlockData(vec![69; 64]) }; - test_state.candidate.descriptor.pov_hash = pov.hash(); + test_state.candidate.descriptor.set_pov_hash(pov.hash()); let candidate_hash = test_state.candidate.hash(); @@ -1420,7 +1420,10 @@ fn recovers_from_only_chunks_if_pov_large( test_state.threshold(), ), (false, true) => { - test_state.candidate.descriptor.pov_hash = test_state.available_data.pov.hash(); + test_state + .candidate + .descriptor + .set_pov_hash(test_state.available_data.pov.hash()); ( AvailabilityRecoverySubsystem::for_collator( None, @@ -1497,12 +1500,12 @@ fn recovers_from_only_chunks_if_pov_large( // Test another candidate, send no chunks. let mut new_candidate = dummy_candidate_receipt(dummy_hash()); - new_candidate.descriptor.relay_parent = test_state.candidate.descriptor.relay_parent; + new_candidate.descriptor.relay_parent = test_state.candidate.descriptor.relay_parent(); overseer_send( &mut virtual_overseer, AvailabilityRecoveryMessage::RecoverAvailableData( - new_candidate.clone(), + new_candidate.clone().into(), test_state.session_index, Some(GroupIndex(1)), Some(test_state.core_index), @@ -1593,7 +1596,10 @@ fn fast_path_backing_group_recovers_if_pov_small( Metrics::new_dummy(), ), (false, true) => { - test_state.candidate.descriptor.pov_hash = test_state.available_data.pov.hash(); + test_state + .candidate + .descriptor + .set_pov_hash(test_state.available_data.pov.hash()); AvailabilityRecoverySubsystem::for_collator( None, request_receiver(&req_protocol_names), @@ -2635,7 +2641,7 @@ fn number_of_request_retries_is_bounded( ); test_state.chunks = map_chunks(chunks, &test_state.node_features, n_validators, test_state.core_index); - test_state.candidate.descriptor.erasure_root = erasure_root; + test_state.candidate.descriptor.set_erasure_root(erasure_root); let (subsystem, retry_limit) = match systematic_recovery { false => ( diff --git a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs index 57e1479a449b..6a570331f710 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs @@ -28,7 +28,9 @@ use polkadot_node_network_protocol::{ }; use polkadot_node_primitives::PoV; use polkadot_node_subsystem::messages::ParentHeadData; -use polkadot_primitives::{CandidateHash, CandidateReceipt, Hash, Id as ParaId}; +use polkadot_primitives::{ + vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, Hash, Id as ParaId, +}; /// The status of a collation as seen from the collator. pub enum CollationStatus { diff --git a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs index af9beb535f46..504b0d716043 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs @@ -54,8 +54,9 @@ use polkadot_node_subsystem_util::{ TimeoutExt, }; use polkadot_primitives::{ - AuthorityDiscoveryId, CandidateHash, CandidateReceipt, CollatorPair, CoreIndex, CoreState, - GroupIndex, Hash, HeadData, Id as ParaId, SessionIndex, + vstaging::{CandidateReceiptV2 as CandidateReceipt, CoreState}, + AuthorityDiscoveryId, CandidateHash, CollatorPair, CoreIndex, GroupIndex, Hash, HeadData, + Id as ParaId, SessionIndex, }; use super::LOG_TARGET; @@ -374,7 +375,7 @@ async fn distribute_collation( result_sender: Option>, core_index: CoreIndex, ) -> Result<()> { - let candidate_relay_parent = receipt.descriptor.relay_parent; + let candidate_relay_parent = receipt.descriptor.relay_parent(); let candidate_hash = receipt.hash(); let per_relay_parent = match state.per_relay_parent.get_mut(&candidate_relay_parent) { @@ -850,12 +851,12 @@ async fn process_msg( core_index, } => { match state.collating_on { - Some(id) if candidate_receipt.descriptor.para_id != id => { + Some(id) if candidate_receipt.descriptor.para_id() != id => { // If the ParaId of a collation requested to be distributed does not match // the one we expect, we ignore the message. gum::warn!( target: LOG_TARGET, - para_id = %candidate_receipt.descriptor.para_id, + para_id = %candidate_receipt.descriptor.para_id(), collating_on = %id, "DistributeCollation for unexpected para_id", ); @@ -879,7 +880,7 @@ async fn process_msg( None => { gum::warn!( target: LOG_TARGET, - para_id = %candidate_receipt.descriptor.para_id, + para_id = %candidate_receipt.descriptor.para_id(), "DistributeCollation message while not collating on any", ); }, diff --git a/polkadot/node/network/collator-protocol/src/validator_side/collation.rs b/polkadot/node/network/collator-protocol/src/validator_side/collation.rs index 58d9ebc57726..0b3e9f4b3431 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/collation.rs @@ -40,8 +40,8 @@ use polkadot_node_subsystem_util::{ metrics::prometheus::prometheus::HistogramTimer, runtime::ProspectiveParachainsMode, }; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CollatorId, Hash, HeadData, Id as ParaId, - PersistedValidationData, + vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, CollatorId, Hash, HeadData, + Id as ParaId, PersistedValidationData, }; use tokio_util::sync::CancellationToken; @@ -71,18 +71,15 @@ pub struct FetchedCollation { pub para_id: ParaId, /// Candidate hash. pub candidate_hash: CandidateHash, - /// Id of the collator the collation was fetched from. - pub collator_id: CollatorId, } impl From<&CandidateReceipt> for FetchedCollation { fn from(receipt: &CandidateReceipt) -> Self { let descriptor = receipt.descriptor(); Self { - relay_parent: descriptor.relay_parent, - para_id: descriptor.para_id, + relay_parent: descriptor.relay_parent(), + para_id: descriptor.para_id(), candidate_hash: receipt.hash(), - collator_id: descriptor.collator.clone(), } } } @@ -141,7 +138,7 @@ pub fn fetched_collation_sanity_check( persisted_validation_data: &PersistedValidationData, maybe_parent_head_and_hash: Option<(HeadData, Hash)>, ) -> Result<(), SecondingError> { - if persisted_validation_data.hash() != fetched.descriptor().persisted_validation_data_hash { + if persisted_validation_data.hash() != fetched.descriptor().persisted_validation_data_hash() { Err(SecondingError::PersistedValidationDataMismatch) } else if advertised .prospective_candidate diff --git a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs index deb6ce03f43e..51e987d59ce8 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs @@ -52,8 +52,8 @@ use polkadot_node_subsystem_util::{ runtime::{fetch_claim_queue, prospective_parachains_mode, ProspectiveParachainsMode}, }; use polkadot_primitives::{ - CandidateHash, CollatorId, CoreState, Hash, HeadData, Id as ParaId, OccupiedCoreAssumption, - PersistedValidationData, + vstaging::CoreState, CandidateHash, CollatorId, Hash, HeadData, Id as ParaId, + OccupiedCoreAssumption, PersistedValidationData, }; use crate::error::{Error, FetchError, Result, SecondingError}; @@ -1021,7 +1021,7 @@ async fn second_unblocked_collations( for mut unblocked_collation in unblocked_collations { unblocked_collation.maybe_parent_head_data = Some(head_data.clone()); let peer_id = unblocked_collation.collation_event.pending_collation.peer_id; - let relay_parent = unblocked_collation.candidate_receipt.descriptor.relay_parent; + let relay_parent = unblocked_collation.candidate_receipt.descriptor.relay_parent(); if let Err(err) = kick_off_seconding(ctx, state, unblocked_collation).await { gum::warn!( @@ -1328,7 +1328,7 @@ where collations.retain(|collation| { state .per_relay_parent - .contains_key(&collation.candidate_receipt.descriptor.relay_parent) + .contains_key(&collation.candidate_receipt.descriptor.relay_parent()) }); !collations.is_empty() @@ -1470,7 +1470,7 @@ async fn process_msg( }, }; let output_head_data = receipt.commitments.head_data.clone(); - let output_head_data_hash = receipt.descriptor.para_head; + let output_head_data_hash = receipt.descriptor.para_head(); let fetched_collation = FetchedCollation::from(&receipt.to_plain()); if let Some(CollationEvent { collator_id, pending_collation, .. }) = state.fetched_candidates.remove(&fetched_collation) @@ -1531,8 +1531,8 @@ async fn process_msg( Invalid(parent, candidate_receipt) => { // Remove collations which were blocked from seconding and had this candidate as parent. state.blocked_from_seconding.remove(&BlockedCollationId { - para_id: candidate_receipt.descriptor.para_id, - parent_head_data_hash: candidate_receipt.descriptor.para_head, + para_id: candidate_receipt.descriptor.para_id(), + parent_head_data_hash: candidate_receipt.descriptor.para_head(), }); let fetched_collation = FetchedCollation::from(&candidate_receipt); @@ -1843,8 +1843,8 @@ async fn kick_off_seconding( (CollationVersion::V2, Some(_)) | (CollationVersion::V1, _) => { let pvd = request_persisted_validation_data( ctx.sender(), - candidate_receipt.descriptor().relay_parent, - candidate_receipt.descriptor().para_id, + candidate_receipt.descriptor().relay_parent(), + candidate_receipt.descriptor().para_id(), ) .await?; ( @@ -1874,14 +1874,14 @@ async fn kick_off_seconding( gum::debug!( target: LOG_TARGET, candidate_hash = ?blocked_collation.candidate_receipt.hash(), - relay_parent = ?blocked_collation.candidate_receipt.descriptor.relay_parent, + relay_parent = ?blocked_collation.candidate_receipt.descriptor.relay_parent(), "Collation having parent head data hash {} is blocked from seconding. Waiting on its parent to be validated.", parent_head_data_hash ); state .blocked_from_seconding .entry(BlockedCollationId { - para_id: blocked_collation.candidate_receipt.descriptor.para_id, + para_id: blocked_collation.candidate_receipt.descriptor.para_id(), parent_head_data_hash, }) .or_insert_with(Vec::new) @@ -2025,11 +2025,11 @@ async fn handle_collation_fetch_response( Ok( request_v1::CollationFetchingResponse::Collation(receipt, _) | request_v1::CollationFetchingResponse::CollationWithParentHeadData { receipt, .. }, - ) if receipt.descriptor().para_id != pending_collation.para_id => { + ) if receipt.descriptor().para_id() != pending_collation.para_id => { gum::debug!( target: LOG_TARGET, expected_para_id = ?pending_collation.para_id, - got_para_id = ?receipt.descriptor().para_id, + got_para_id = ?receipt.descriptor().para_id(), peer_id = ?pending_collation.peer_id, "Got wrong para ID for requested collation." ); diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs index 86c8bcb6bdcd..290c4db901d5 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs @@ -42,8 +42,9 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{reputation::add_reputation, TimeoutExt}; use polkadot_primitives::{ - CandidateReceipt, CollatorPair, CoreIndex, CoreState, GroupIndex, GroupRotationInfo, HeadData, - OccupiedCore, PersistedValidationData, ScheduledCore, ValidatorId, ValidatorIndex, + vstaging::{CandidateReceiptV2 as CandidateReceipt, CoreState, OccupiedCore}, + CollatorPair, CoreIndex, GroupIndex, GroupRotationInfo, HeadData, PersistedValidationData, + ScheduledCore, ValidatorId, ValidatorIndex, }; use polkadot_primitives_test_helpers::{ dummy_candidate_descriptor, dummy_candidate_receipt_bad_sig, dummy_hash, @@ -121,7 +122,7 @@ impl Default for TestState { let mut d = dummy_candidate_descriptor(dummy_hash()); d.para_id = chain_ids[1]; - d + d.into() }, }), ]; @@ -341,7 +342,7 @@ async fn assert_candidate_backing_second( incoming_pov, )) => { assert_eq!(expected_relay_parent, relay_parent); - assert_eq!(expected_para_id, candidate_receipt.descriptor.para_id); + assert_eq!(expected_para_id, candidate_receipt.descriptor.para_id()); assert_eq!(*expected_pov, incoming_pov); assert_eq!(pvd, received_pvd); candidate_receipt @@ -591,8 +592,11 @@ fn act_on_advertisement_v2() { response_channel .send(Ok(( - request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()) - .encode(), + request_v1::CollationFetchingResponse::Collation( + candidate_a.clone().into(), + pov.clone(), + ) + .encode(), ProtocolName::from(""), ))) .expect("Sending response should succeed"); @@ -793,8 +797,11 @@ fn fetch_one_collation_at_a_time() { candidate_a.descriptor.persisted_validation_data_hash = dummy_pvd().hash(); response_channel .send(Ok(( - request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()) - .encode(), + request_v1::CollationFetchingResponse::Collation( + candidate_a.clone().into(), + pov.clone(), + ) + .encode(), ProtocolName::from(""), ))) .expect("Sending response should succeed"); @@ -917,16 +924,22 @@ fn fetches_next_collation() { // First request finishes now: response_channel_non_exclusive .send(Ok(( - request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()) - .encode(), + request_v1::CollationFetchingResponse::Collation( + candidate_a.clone().into(), + pov.clone(), + ) + .encode(), ProtocolName::from(""), ))) .expect("Sending response should succeed"); response_channel .send(Ok(( - request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()) - .encode(), + request_v1::CollationFetchingResponse::Collation( + candidate_a.clone().into(), + pov.clone(), + ) + .encode(), ProtocolName::from(""), ))) .expect("Sending response should succeed"); @@ -1055,8 +1068,11 @@ fn fetch_next_collation_on_invalid_collation() { candidate_a.descriptor.persisted_validation_data_hash = dummy_pvd().hash(); response_channel .send(Ok(( - request_v1::CollationFetchingResponse::Collation(candidate_a.clone(), pov.clone()) - .encode(), + request_v1::CollationFetchingResponse::Collation( + candidate_a.clone().into(), + pov.clone(), + ) + .encode(), ProtocolName::from(""), ))) .expect("Sending response should succeed"); diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs index dff98e22e3db..e040163cd905 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs @@ -20,8 +20,8 @@ use super::*; use polkadot_node_subsystem::messages::ChainApiMessage; use polkadot_primitives::{ - AsyncBackingParams, BlockNumber, CandidateCommitments, CommittedCandidateReceipt, Header, - SigningContext, ValidatorId, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, AsyncBackingParams, + BlockNumber, CandidateCommitments, Header, SigningContext, ValidatorId, }; use rstest::rstest; @@ -225,7 +225,7 @@ async fn send_seconded_statement( overseer_send( virtual_overseer, - CollatorProtocolMessage::Seconded(candidate.descriptor.relay_parent, stmt), + CollatorProtocolMessage::Seconded(candidate.descriptor.relay_parent(), stmt), ) .await; } @@ -374,7 +374,7 @@ fn v1_advertisement_accepted_and_seconded() { hrmp_watermark: 0, }; candidate.commitments_hash = commitments.hash(); - + let candidate: CandidateReceipt = candidate.into(); let pov = PoV { block_data: BlockData(vec![1]) }; response_channel @@ -595,6 +595,7 @@ fn second_multiple_candidates_per_relay_parent() { hrmp_watermark: 0, }; candidate.commitments_hash = commitments.hash(); + let candidate: CandidateReceipt = candidate.into(); let candidate_hash = candidate.hash(); let parent_head_data_hash = Hash::zero(); @@ -750,7 +751,7 @@ fn fetched_collation_sanity_check() { hrmp_watermark: 0, }; candidate.commitments_hash = commitments.hash(); - + let candidate: CandidateReceipt = candidate.into(); let candidate_hash = CandidateHash(Hash::zero()); let parent_head_data_hash = Hash::zero(); @@ -845,7 +846,6 @@ fn sanity_check_invalid_parent_head_data() { let mut candidate = dummy_candidate_receipt_bad_sig(head_c, Some(Default::default())); candidate.descriptor.para_id = test_state.chain_ids[0]; - let commitments = CandidateCommitments { head_data: HeadData(vec![1, 2, 3]), horizontal_messages: Default::default(), @@ -864,6 +864,7 @@ fn sanity_check_invalid_parent_head_data() { pvd.parent_head = parent_head_data; candidate.descriptor.persisted_validation_data_hash = pvd.hash(); + let candidate: CandidateReceipt = candidate.into(); let candidate_hash = candidate.hash(); @@ -1068,6 +1069,7 @@ fn child_blocked_from_seconding_by_parent(#[case] valid_parent: bool) { processed_downward_messages: 0, hrmp_watermark: 0, }; + let mut candidate_b: CandidateReceipt = candidate_b.into(); candidate_b.commitments_hash = candidate_b_commitments.hash(); let candidate_b_hash = candidate_b.hash(); @@ -1134,6 +1136,7 @@ fn child_blocked_from_seconding_by_parent(#[case] valid_parent: bool) { relay_parent_storage_root: Default::default(), } .hash(); + let mut candidate_a: CandidateReceipt = candidate_a.into(); let candidate_a_commitments = CandidateCommitments { head_data: HeadData(vec![1]), horizontal_messages: Default::default(), @@ -1144,6 +1147,7 @@ fn child_blocked_from_seconding_by_parent(#[case] valid_parent: bool) { }; candidate_a.commitments_hash = candidate_a_commitments.hash(); + let candidate_a: CandidateReceipt = candidate_a.into(); let candidate_a_hash = candidate_a.hash(); advertise_collation( @@ -1208,7 +1212,7 @@ fn child_blocked_from_seconding_by_parent(#[case] valid_parent: bool) { incoming_pov, )) => { assert_eq!(head_c, relay_parent); - assert_eq!(test_state.chain_ids[0], candidate_receipt.descriptor.para_id); + assert_eq!(test_state.chain_ids[0], candidate_receipt.descriptor.para_id()); assert_eq!(PoV { block_data: BlockData(vec![2]) }, incoming_pov); assert_eq!(PersistedValidationData:: { parent_head: HeadData(vec![0]), @@ -1261,7 +1265,7 @@ fn child_blocked_from_seconding_by_parent(#[case] valid_parent: bool) { incoming_pov, )) => { assert_eq!(head_c, relay_parent); - assert_eq!(test_state.chain_ids[0], candidate_receipt.descriptor.para_id); + assert_eq!(test_state.chain_ids[0], candidate_receipt.descriptor.para_id()); assert_eq!(PoV { block_data: BlockData(vec![1]) }, incoming_pov); assert_eq!(PersistedValidationData:: { parent_head: HeadData(vec![1]), diff --git a/polkadot/node/network/dispute-distribution/src/receiver/batches/batch.rs b/polkadot/node/network/dispute-distribution/src/receiver/batches/batch.rs index 11380b7c072e..c911b4bc4ae6 100644 --- a/polkadot/node/network/dispute-distribution/src/receiver/batches/batch.rs +++ b/polkadot/node/network/dispute-distribution/src/receiver/batches/batch.rs @@ -22,7 +22,7 @@ use polkadot_node_network_protocol::{ PeerId, }; use polkadot_node_primitives::SignedDisputeStatement; -use polkadot_primitives::{CandidateReceipt, ValidatorIndex}; +use polkadot_primitives::{vstaging::CandidateReceiptV2 as CandidateReceipt, ValidatorIndex}; use crate::receiver::{BATCH_COLLECTING_INTERVAL, MIN_KEEP_BATCH_ALIVE_VOTES}; diff --git a/polkadot/node/network/dispute-distribution/src/receiver/batches/mod.rs b/polkadot/node/network/dispute-distribution/src/receiver/batches/mod.rs index 76c7683d1574..13b42aff1f30 100644 --- a/polkadot/node/network/dispute-distribution/src/receiver/batches/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/receiver/batches/mod.rs @@ -22,7 +22,7 @@ use std::{ use futures::future::pending; use polkadot_node_network_protocol::request_response::DISPUTE_REQUEST_TIMEOUT; -use polkadot_primitives::{CandidateHash, CandidateReceipt}; +use polkadot_primitives::{vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash}; use crate::{ receiver::batches::{batch::TickResult, waiting_queue::PendingWake}, diff --git a/polkadot/node/network/dispute-distribution/src/receiver/mod.rs b/polkadot/node/network/dispute-distribution/src/receiver/mod.rs index 77c1e41aac05..b21965fc7004 100644 --- a/polkadot/node/network/dispute-distribution/src/receiver/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/receiver/mod.rs @@ -334,7 +334,7 @@ where .runtime .get_session_info_by_index( &mut self.sender, - payload.0.candidate_receipt.descriptor.relay_parent, + payload.0.candidate_receipt.descriptor.relay_parent(), payload.0.session_index, ) .await?; diff --git a/polkadot/node/network/dispute-distribution/src/sender/send_task.rs b/polkadot/node/network/dispute-distribution/src/sender/send_task.rs index 54ccd10789d0..f607c9431513 100644 --- a/polkadot/node/network/dispute-distribution/src/sender/send_task.rs +++ b/polkadot/node/network/dispute-distribution/src/sender/send_task.rs @@ -234,7 +234,7 @@ impl SendTask { runtime: &mut RuntimeInfo, active_sessions: &HashMap, ) -> Result> { - let ref_head = self.request.0.candidate_receipt.descriptor.relay_parent; + let ref_head = self.request.0.candidate_receipt.descriptor.relay_parent(); // Retrieve all authorities which participated in the parachain consensus of the session // in which the candidate was backed. let info = runtime diff --git a/polkadot/node/network/dispute-distribution/src/tests/mock.rs b/polkadot/node/network/dispute-distribution/src/tests/mock.rs index baa857e2eb68..52659ae9e002 100644 --- a/polkadot/node/network/dispute-distribution/src/tests/mock.rs +++ b/polkadot/node/network/dispute-distribution/src/tests/mock.rs @@ -33,10 +33,10 @@ use sp_keystore::{Keystore, KeystorePtr}; use polkadot_node_primitives::{DisputeMessage, SignedDisputeStatement}; use polkadot_primitives::{ - AuthorityDiscoveryId, CandidateHash, CandidateReceipt, Hash, SessionIndex, SessionInfo, - ValidatorId, ValidatorIndex, + vstaging::CandidateReceiptV2 as CandidateReceipt, AuthorityDiscoveryId, CandidateHash, Hash, + SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, }; -use polkadot_primitives_test_helpers::dummy_candidate_descriptor; +use polkadot_primitives_test_helpers::dummy_candidate_descriptor_v2; use crate::LOG_TARGET; @@ -116,7 +116,7 @@ pub static MOCK_NEXT_SESSION_INFO: LazyLock = LazyLock::new(|| Sess pub fn make_candidate_receipt(relay_parent: Hash) -> CandidateReceipt { CandidateReceipt { - descriptor: dummy_candidate_descriptor(relay_parent), + descriptor: dummy_candidate_descriptor_v2(relay_parent), commitments_hash: Hash::random(), } } diff --git a/polkadot/node/network/dispute-distribution/src/tests/mod.rs b/polkadot/node/network/dispute-distribution/src/tests/mod.rs index 60820e62ca2d..5306b22828cc 100644 --- a/polkadot/node/network/dispute-distribution/src/tests/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/tests/mod.rs @@ -57,8 +57,8 @@ use polkadot_node_subsystem_test_helpers::{ subsystem_test_harness, TestSubsystemContextHandle, }; use polkadot_primitives::{ - AuthorityDiscoveryId, Block, CandidateHash, CandidateReceipt, ExecutorParams, Hash, - NodeFeatures, SessionIndex, SessionInfo, + vstaging::CandidateReceiptV2 as CandidateReceipt, AuthorityDiscoveryId, Block, CandidateHash, + ExecutorParams, Hash, NodeFeatures, SessionIndex, SessionInfo, }; use self::mock::{ diff --git a/polkadot/node/network/protocol/src/request_response/v1.rs b/polkadot/node/network/protocol/src/request_response/v1.rs index 80721f1884af..4f28d4cbf2d8 100644 --- a/polkadot/node/network/protocol/src/request_response/v1.rs +++ b/polkadot/node/network/protocol/src/request_response/v1.rs @@ -22,8 +22,11 @@ use polkadot_node_primitives::{ AvailableData, DisputeMessage, ErasureChunk, PoV, Proof, UncheckedDisputeMessage, }; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CommittedCandidateReceipt, Hash, HeadData, Id as ParaId, - ValidatorIndex, + vstaging::{ + CandidateReceiptV2 as CandidateReceipt, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, + }, + CandidateHash, Hash, HeadData, Id as ParaId, ValidatorIndex, }; use super::{IsRequest, Protocol}; diff --git a/polkadot/node/network/protocol/src/request_response/v2.rs b/polkadot/node/network/protocol/src/request_response/v2.rs index ae65b39cd406..834870e5b908 100644 --- a/polkadot/node/network/protocol/src/request_response/v2.rs +++ b/polkadot/node/network/protocol/src/request_response/v2.rs @@ -20,8 +20,8 @@ use codec::{Decode, Encode}; use polkadot_node_primitives::ErasureChunk; use polkadot_primitives::{ - CandidateHash, CommittedCandidateReceipt, Hash, Id as ParaId, PersistedValidationData, - UncheckedSignedStatement, ValidatorIndex, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CandidateHash, Hash, + Id as ParaId, PersistedValidationData, UncheckedSignedStatement, ValidatorIndex, }; use super::{v1, IsRequest, Protocol}; diff --git a/polkadot/node/network/statement-distribution/Cargo.toml b/polkadot/node/network/statement-distribution/Cargo.toml index 2a9773ddde4b..08059353033d 100644 --- a/polkadot/node/network/statement-distribution/Cargo.toml +++ b/polkadot/node/network/statement-distribution/Cargo.toml @@ -40,6 +40,7 @@ sp-tracing = { workspace = true, default-features = true } sc-keystore = { workspace = true, default-features = true } sc-network = { workspace = true, default-features = true } futures-timer = { workspace = true } +polkadot-primitives = { workspace = true, features = ["test"] } polkadot-primitives-test-helpers = { workspace = true } rand_chacha = { workspace = true, default-features = true } polkadot-subsystem-bench = { workspace = true } diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs index 8270b9809194..bd6d4ebe755c 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs @@ -37,9 +37,10 @@ use polkadot_node_subsystem::{ overseer, ActivatedLeaf, StatementDistributionSenderTrait, }; use polkadot_primitives::{ - AuthorityDiscoveryId, CandidateHash, CommittedCandidateReceipt, CompactStatement, Hash, - Id as ParaId, IndexedVec, OccupiedCoreAssumption, PersistedValidationData, SignedStatement, - SigningContext, UncheckedSignedStatement, ValidatorId, ValidatorIndex, ValidatorSignature, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, AuthorityDiscoveryId, + CandidateHash, CompactStatement, Hash, Id as ParaId, IndexedVec, OccupiedCoreAssumption, + PersistedValidationData, SignedStatement, SigningContext, UncheckedSignedStatement, + ValidatorId, ValidatorIndex, ValidatorSignature, }; use futures::{ @@ -1641,7 +1642,7 @@ async fn handle_incoming_message<'a, Context>( // In case of `Valid` we should have it cached prior, therefore this performs // no Runtime API calls and always returns `Ok(Some(_))`. let pvd = if let Statement::Seconded(receipt) = statement.payload() { - let para_id = receipt.descriptor.para_id; + let para_id = receipt.descriptor.para_id(); // Either call the Runtime API or check that validation data is cached. let result = active_head .fetch_persisted_validation_data(ctx.sender(), relay_parent, para_id) diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/requester.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/requester.rs index c0346adfe101..69bcbac76b70 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/requester.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/requester.rs @@ -29,7 +29,9 @@ use polkadot_node_network_protocol::{ PeerId, UnifiedReputationChange, }; use polkadot_node_subsystem_util::TimeoutExt; -use polkadot_primitives::{CandidateHash, CommittedCandidateReceipt, Hash}; +use polkadot_primitives::{ + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CandidateHash, Hash, +}; use crate::{ legacy_v1::{COST_WRONG_HASH, LOG_TARGET}, diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs index 8d1683759a03..03e1dc059989 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs @@ -29,7 +29,9 @@ use polkadot_node_network_protocol::{ }, PeerId, UnifiedReputationChange as Rep, }; -use polkadot_primitives::{CandidateHash, CommittedCandidateReceipt, Hash}; +use polkadot_primitives::{ + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CandidateHash, Hash, +}; use crate::LOG_TARGET; diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs index 5e00fb96d74f..d2fd016ec2f1 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs @@ -47,7 +47,8 @@ use polkadot_primitives::{ SessionInfo, ValidationCode, }; use polkadot_primitives_test_helpers::{ - dummy_committed_candidate_receipt, dummy_hash, AlwaysZeroRng, + dummy_committed_candidate_receipt, dummy_committed_candidate_receipt_v2, dummy_hash, + AlwaysZeroRng, }; use sc_keystore::LocalKeystore; use sc_network::ProtocolName; @@ -140,7 +141,7 @@ fn active_head_accepts_only_2_seconded_per_validator() { // note A let a_seconded_val_0 = SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate_a.clone()), + Statement::Seconded(candidate_a.into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -167,7 +168,7 @@ fn active_head_accepts_only_2_seconded_per_validator() { // note B let statement = SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate_b.clone()), + Statement::Seconded(candidate_b.clone().into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -184,7 +185,7 @@ fn active_head_accepts_only_2_seconded_per_validator() { // note C (beyond 2 - ignored) let statement = SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate_c.clone()), + Statement::Seconded(candidate_c.clone().into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -202,7 +203,7 @@ fn active_head_accepts_only_2_seconded_per_validator() { // note B (new validator) let statement = SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate_b.clone()), + Statement::Seconded(candidate_b.into()), &signing_context, ValidatorIndex(1), &bob_public.into(), @@ -219,7 +220,7 @@ fn active_head_accepts_only_2_seconded_per_validator() { // note C (new validator) let statement = SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate_c.clone()), + Statement::Seconded(candidate_c.into()), &signing_context, ValidatorIndex(1), &bob_public.into(), @@ -470,7 +471,7 @@ fn peer_view_update_sends_messages() { let statement = SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate.clone()), + Statement::Seconded(candidate.clone().into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -612,7 +613,7 @@ fn circulated_statement_goes_to_all_peers_with_view() { let mut c = dummy_committed_candidate_receipt(dummy_hash()); c.descriptor.relay_parent = hash_b; c.descriptor.para_id = ParaId::from(1_u32); - c + c.into() }; let peer_a = PeerId::random(); @@ -746,7 +747,7 @@ fn receiving_from_one_sends_to_another_and_to_candidate_backing() { let mut c = dummy_committed_candidate_receipt(dummy_hash()); c.descriptor.relay_parent = hash_a; c.descriptor.para_id = PARA_ID; - c + c.into() }; let peer_a = PeerId::random(); @@ -1199,7 +1200,7 @@ fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing( SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate.clone()), + Statement::Seconded(candidate.clone().into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -1337,7 +1338,7 @@ fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing( let bad_candidate = { let mut bad = candidate.clone(); bad.descriptor.para_id = 0xeadbeaf.into(); - bad + bad.into() }; let response = StatementFetchingResponse::Statement(bad_candidate); outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); @@ -1391,7 +1392,7 @@ fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing( assert_eq!(req.candidate_hash, metadata.candidate_hash); // On retry, we should have reverse order: assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - let response = StatementFetchingResponse::Statement(candidate.clone()); + let response = StatementFetchingResponse::Statement(candidate.clone().into()); outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); } ); @@ -1517,7 +1518,7 @@ fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing( req_cfg.inbound_queue.as_mut().unwrap().send(req).await.unwrap(); let StatementFetchingResponse::Statement(committed) = Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); - assert_eq!(committed, candidate); + assert_eq!(committed, candidate.into()); handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; }; @@ -1744,7 +1745,7 @@ fn delay_reputation_changes() { SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate.clone()), + Statement::Seconded(candidate.clone().into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -1884,7 +1885,7 @@ fn delay_reputation_changes() { bad.descriptor.para_id = 0xeadbeaf.into(); bad }; - let response = StatementFetchingResponse::Statement(bad_candidate); + let response = StatementFetchingResponse::Statement(bad_candidate.into()); outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); } ); @@ -1928,7 +1929,7 @@ fn delay_reputation_changes() { assert_eq!(req.candidate_hash, metadata.candidate_hash); // On retry, we should have reverse order: assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - let response = StatementFetchingResponse::Statement(candidate.clone()); + let response = StatementFetchingResponse::Statement(candidate.clone().into()); outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); } ); @@ -2288,7 +2289,7 @@ fn share_prioritizes_backing_group() { SignedFullStatementWithPVD::sign( &keystore, - Statement::Seconded(candidate.clone()).supply_pvd(pvd), + Statement::Seconded(candidate.clone().into()).supply_pvd(pvd), &signing_context, ValidatorIndex(4), &ferdie_public.into(), @@ -2352,7 +2353,7 @@ fn share_prioritizes_backing_group() { req_cfg.inbound_queue.as_mut().unwrap().send(req).await.unwrap(); let StatementFetchingResponse::Statement(committed) = Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); - assert_eq!(committed, candidate); + assert_eq!(committed, candidate.into()); handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; }; @@ -2514,7 +2515,7 @@ fn peer_cant_flood_with_large_statements() { SignedFullStatement::sign( &keystore, - Statement::Seconded(candidate.clone()), + Statement::Seconded(candidate.clone().into()), &signing_context, ValidatorIndex(0), &alice_public.into(), @@ -2595,7 +2596,7 @@ fn handle_multiple_seconded_statements() { let relay_parent_hash = Hash::repeat_byte(1); let pvd = dummy_pvd(); - let candidate = dummy_committed_candidate_receipt(relay_parent_hash); + let candidate = dummy_committed_candidate_receipt_v2(relay_parent_hash); let candidate_hash = candidate.hash(); // We want to ensure that our peers are not lucky diff --git a/polkadot/node/network/statement-distribution/src/v2/candidates.rs b/polkadot/node/network/statement-distribution/src/v2/candidates.rs index a4f2455c2840..1a37d2ea086a 100644 --- a/polkadot/node/network/statement-distribution/src/v2/candidates.rs +++ b/polkadot/node/network/statement-distribution/src/v2/candidates.rs @@ -28,8 +28,8 @@ use polkadot_node_network_protocol::PeerId; use polkadot_node_subsystem::messages::HypotheticalCandidate; use polkadot_primitives::{ - CandidateHash, CommittedCandidateReceipt, GroupIndex, Hash, Id as ParaId, - PersistedValidationData, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CandidateHash, GroupIndex, + Hash, Id as ParaId, PersistedValidationData, }; use std::{ @@ -154,8 +154,8 @@ impl Candidates { assigned_group: GroupIndex, ) -> Option { let parent_hash = persisted_validation_data.parent_head.hash(); - let relay_parent = candidate_receipt.descriptor().relay_parent; - let para_id = candidate_receipt.descriptor().para_id; + let relay_parent = candidate_receipt.descriptor.relay_parent(); + let para_id = candidate_receipt.descriptor.para_id(); let prev_state = self.candidates.insert( candidate_hash, @@ -530,12 +530,12 @@ pub struct ConfirmedCandidate { impl ConfirmedCandidate { /// Get the relay-parent of the candidate. pub fn relay_parent(&self) -> Hash { - self.receipt.descriptor().relay_parent + self.receipt.descriptor.relay_parent() } /// Get the para-id of the candidate. pub fn para_id(&self) -> ParaId { - self.receipt.descriptor().para_id + self.receipt.descriptor.para_id() } /// Get the underlying candidate receipt. diff --git a/polkadot/node/network/statement-distribution/src/v2/mod.rs b/polkadot/node/network/statement-distribution/src/v2/mod.rs index f9c2d0ddbae8..c79ae3953ad9 100644 --- a/polkadot/node/network/statement-distribution/src/v2/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/mod.rs @@ -50,9 +50,9 @@ use polkadot_node_subsystem_util::{ }, }; use polkadot_primitives::{ - AuthorityDiscoveryId, CandidateHash, CompactStatement, CoreIndex, CoreState, GroupIndex, - GroupRotationInfo, Hash, Id as ParaId, IndexedVec, SessionIndex, SessionInfo, SignedStatement, - SigningContext, UncheckedSignedStatement, ValidatorId, ValidatorIndex, + vstaging::CoreState, AuthorityDiscoveryId, CandidateHash, CompactStatement, CoreIndex, + GroupIndex, GroupRotationInfo, Hash, Id as ParaId, IndexedVec, SessionIndex, SessionInfo, + SignedStatement, SigningContext, UncheckedSignedStatement, ValidatorId, ValidatorIndex, }; use sp_keystore::KeystorePtr; @@ -1201,7 +1201,7 @@ pub(crate) async fn share_local_statement( // have the candidate. Sanity: check the para-id is valid. let expected = match statement.payload() { FullStatementWithPVD::Seconded(ref c, _) => - Some((c.descriptor().para_id, c.descriptor().relay_parent)), + Some((c.descriptor.para_id(), c.descriptor.relay_parent())), FullStatementWithPVD::Valid(hash) => state.candidates.get_confirmed(&hash).map(|c| (c.para_id(), c.relay_parent())), }; @@ -2277,13 +2277,13 @@ async fn fragment_chain_update_inner( } = hypo { let confirmed_candidate = state.candidates.get_confirmed(&candidate_hash); - let prs = state.per_relay_parent.get_mut(&receipt.descriptor().relay_parent); + let prs = state.per_relay_parent.get_mut(&receipt.descriptor.relay_parent()); if let (Some(confirmed), Some(prs)) = (confirmed_candidate, prs) { let per_session = state.per_session.get(&prs.session); let group_index = confirmed.group_index(); // Sanity check if group_index is valid for this para at relay parent. - let Some(expected_groups) = prs.groups_per_para.get(&receipt.descriptor().para_id) + let Some(expected_groups) = prs.groups_per_para.get(&receipt.descriptor.para_id()) else { continue }; @@ -2296,7 +2296,7 @@ async fn fragment_chain_update_inner( ctx, candidate_hash, confirmed.group_index(), - &receipt.descriptor().relay_parent, + &receipt.descriptor.relay_parent(), prs, confirmed, per_session, @@ -2888,7 +2888,7 @@ pub(crate) async fn handle_backed_candidate_message( ctx, state, confirmed.para_id(), - confirmed.candidate_receipt().descriptor().para_head, + confirmed.candidate_receipt().descriptor.para_head(), ) .await; } diff --git a/polkadot/node/network/statement-distribution/src/v2/requests.rs b/polkadot/node/network/statement-distribution/src/v2/requests.rs index b8ed34d26c8a..74f29710956f 100644 --- a/polkadot/node/network/statement-distribution/src/v2/requests.rs +++ b/polkadot/node/network/statement-distribution/src/v2/requests.rs @@ -47,9 +47,9 @@ use polkadot_node_network_protocol::{ PeerId, UnifiedReputationChange as Rep, }; use polkadot_primitives::{ - CandidateHash, CommittedCandidateReceipt, CompactStatement, GroupIndex, Hash, Id as ParaId, - PersistedValidationData, SessionIndex, SignedStatement, SigningContext, ValidatorId, - ValidatorIndex, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CandidateHash, + CompactStatement, GroupIndex, Hash, Id as ParaId, PersistedValidationData, SessionIndex, + SignedStatement, SigningContext, ValidatorId, ValidatorIndex, }; use futures::{future::BoxFuture, prelude::*, stream::FuturesUnordered}; @@ -696,18 +696,18 @@ fn validate_complete_response( // sanity-check candidate response. // note: roughly ascending cost of operations { - if response.candidate_receipt.descriptor.relay_parent != identifier.relay_parent { + if response.candidate_receipt.descriptor.relay_parent() != identifier.relay_parent { return invalid_candidate_output() } - if response.candidate_receipt.descriptor.persisted_validation_data_hash != + if response.candidate_receipt.descriptor.persisted_validation_data_hash() != response.persisted_validation_data.hash() { return invalid_candidate_output() } if !allowed_para_lookup( - response.candidate_receipt.descriptor.para_id, + response.candidate_receipt.descriptor.para_id(), identifier.group_index, ) { return invalid_candidate_output() @@ -1019,6 +1019,7 @@ mod tests { candidate_receipt.descriptor.persisted_validation_data_hash = persisted_validation_data.hash(); let candidate = candidate_receipt.hash(); + let candidate_receipt: CommittedCandidateReceipt = candidate_receipt.into(); let requested_peer_1 = PeerId::random(); let requested_peer_2 = PeerId::random(); @@ -1074,7 +1075,7 @@ mod tests { requested_peer: requested_peer_1, props: request_properties.clone(), response: Ok(AttestedCandidateResponse { - candidate_receipt: candidate_receipt.clone(), + candidate_receipt: candidate_receipt.clone().into(), persisted_validation_data: persisted_validation_data.clone(), statements, }), @@ -1114,7 +1115,7 @@ mod tests { requested_peer: requested_peer_2, props: request_properties, response: Ok(AttestedCandidateResponse { - candidate_receipt: candidate_receipt.clone(), + candidate_receipt: candidate_receipt.clone().into(), persisted_validation_data: persisted_validation_data.clone(), statements, }), @@ -1197,7 +1198,7 @@ mod tests { requested_peer, props: request_properties, response: Ok(AttestedCandidateResponse { - candidate_receipt: candidate_receipt.clone(), + candidate_receipt: candidate_receipt.clone().into(), persisted_validation_data: persisted_validation_data.clone(), statements, }), @@ -1236,6 +1237,7 @@ mod tests { candidate_receipt.descriptor.persisted_validation_data_hash = persisted_validation_data.hash(); let candidate = candidate_receipt.hash(); + let candidate_receipt: CommittedCandidateReceipt = candidate_receipt.into(); let requested_peer = PeerId::random(); let identifier = request_manager @@ -1417,7 +1419,7 @@ mod tests { requested_peer: requested_peer_1, props: request_properties.clone(), response: Ok(AttestedCandidateResponse { - candidate_receipt: candidate_receipt_1.clone(), + candidate_receipt: candidate_receipt_1.clone().into(), persisted_validation_data: persisted_validation_data_1.clone(), statements, }), diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs index 119dc832d13a..9f2c36ad1018 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs @@ -33,9 +33,9 @@ use polkadot_node_subsystem::messages::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ - AssignmentPair, AsyncBackingParams, Block, BlockNumber, CommittedCandidateReceipt, CoreState, - GroupRotationInfo, HeadData, Header, IndexedVec, PersistedValidationData, ScheduledCore, - SessionIndex, SessionInfo, ValidatorPair, + vstaging::{CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState}, + AssignmentPair, AsyncBackingParams, Block, BlockNumber, GroupRotationInfo, HeadData, Header, + IndexedVec, PersistedValidationData, ScheduledCore, SessionIndex, SessionInfo, ValidatorPair, }; use sc_keystore::LocalKeystore; use sc_network::ProtocolName; diff --git a/polkadot/node/overseer/examples/minimal-example.rs b/polkadot/node/overseer/examples/minimal-example.rs index 807e7405ff1b..e1b2af733b47 100644 --- a/polkadot/node/overseer/examples/minimal-example.rs +++ b/polkadot/node/overseer/examples/minimal-example.rs @@ -31,7 +31,9 @@ use polkadot_overseer::{ gen::{FromOrchestra, SpawnedSubsystem}, HeadSupportsParachains, SubsystemError, }; -use polkadot_primitives::{CandidateReceipt, Hash, PersistedValidationData}; +use polkadot_primitives::{ + vstaging::CandidateReceiptV2 as CandidateReceipt, Hash, PersistedValidationData, +}; use polkadot_primitives_test_helpers::{ dummy_candidate_descriptor, dummy_hash, dummy_validation_code, }; @@ -71,7 +73,7 @@ impl Subsystem1 { let (tx, _) = oneshot::channel(); let candidate_receipt = CandidateReceipt { - descriptor: dummy_candidate_descriptor(dummy_hash()), + descriptor: dummy_candidate_descriptor(dummy_hash()).into(), commitments_hash: Hash::zero(), }; diff --git a/polkadot/node/overseer/src/tests.rs b/polkadot/node/overseer/src/tests.rs index 46864a482e2a..c3c47335cd3e 100644 --- a/polkadot/node/overseer/src/tests.rs +++ b/polkadot/node/overseer/src/tests.rs @@ -28,11 +28,12 @@ use polkadot_node_subsystem_types::messages::{ NetworkBridgeEvent, PvfExecKind, ReportPeerMessage, RuntimeApiRequest, }; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CollatorPair, Id as ParaId, InvalidDisputeStatementKind, - PersistedValidationData, SessionIndex, ValidDisputeStatementKind, ValidatorIndex, + vstaging::CandidateReceiptV2, CandidateHash, CollatorPair, Id as ParaId, + InvalidDisputeStatementKind, PersistedValidationData, SessionIndex, ValidDisputeStatementKind, + ValidatorIndex, }; use polkadot_primitives_test_helpers::{ - dummy_candidate_descriptor, dummy_candidate_receipt, dummy_hash, dummy_validation_code, + dummy_candidate_descriptor, dummy_candidate_receipt_v2, dummy_hash, dummy_validation_code, }; use crate::{ @@ -98,8 +99,8 @@ where let mut c: usize = 0; loop { if c < 10 { - let candidate_receipt = CandidateReceipt { - descriptor: dummy_candidate_descriptor(dummy_hash()), + let candidate_receipt = CandidateReceiptV2 { + descriptor: dummy_candidate_descriptor(dummy_hash()).into(), commitments_hash: dummy_hash(), }; @@ -799,8 +800,8 @@ where fn test_candidate_validation_msg() -> CandidateValidationMessage { let (response_sender, _) = oneshot::channel(); let pov = Arc::new(PoV { block_data: BlockData(Vec::new()) }); - let candidate_receipt = CandidateReceipt { - descriptor: dummy_candidate_descriptor(dummy_hash()), + let candidate_receipt = CandidateReceiptV2 { + descriptor: dummy_candidate_descriptor(dummy_hash()).into(), commitments_hash: Hash::zero(), }; @@ -859,7 +860,7 @@ fn test_statement_distribution_msg() -> StatementDistributionMessage { fn test_availability_recovery_msg() -> AvailabilityRecoveryMessage { let (sender, _) = oneshot::channel(); AvailabilityRecoveryMessage::RecoverAvailableData( - dummy_candidate_receipt(dummy_hash()), + dummy_candidate_receipt_v2(dummy_hash()), Default::default(), None, None, @@ -918,7 +919,7 @@ fn test_dispute_coordinator_msg() -> DisputeCoordinatorMessage { fn test_dispute_distribution_msg() -> DisputeDistributionMessage { let dummy_dispute_message = UncheckedDisputeMessage { - candidate_receipt: dummy_candidate_receipt(dummy_hash()), + candidate_receipt: dummy_candidate_receipt_v2(dummy_hash()), session_index: 0, invalid_vote: InvalidDisputeVote { validator_index: ValidatorIndex(0), diff --git a/polkadot/node/primitives/src/disputes/message.rs b/polkadot/node/primitives/src/disputes/message.rs index f9dec073bf50..d32ed4dadb6e 100644 --- a/polkadot/node/primitives/src/disputes/message.rs +++ b/polkadot/node/primitives/src/disputes/message.rs @@ -25,7 +25,8 @@ use codec::{Decode, Encode}; use super::{InvalidDisputeVote, SignedDisputeStatement, ValidDisputeVote}; use polkadot_primitives::{ - CandidateReceipt, DisputeStatement, SessionIndex, SessionInfo, ValidatorIndex, + vstaging::CandidateReceiptV2 as CandidateReceipt, DisputeStatement, SessionIndex, SessionInfo, + ValidatorIndex, }; /// A dispute initiating/participating message that have been built from signed diff --git a/polkadot/node/primitives/src/disputes/mod.rs b/polkadot/node/primitives/src/disputes/mod.rs index 0f08b4733654..71e2f0b16be3 100644 --- a/polkadot/node/primitives/src/disputes/mod.rs +++ b/polkadot/node/primitives/src/disputes/mod.rs @@ -25,9 +25,9 @@ use sp_application_crypto::AppCrypto; use sp_keystore::{Error as KeystoreError, KeystorePtr}; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CompactStatement, DisputeStatement, EncodeAs, - InvalidDisputeStatementKind, SessionIndex, SigningContext, UncheckedSigned, - ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, CompactStatement, + DisputeStatement, EncodeAs, InvalidDisputeStatementKind, SessionIndex, SigningContext, + UncheckedSigned, ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorSignature, }; /// `DisputeMessage` and related types. diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index a525b2bc9776..e2e7aa92b11c 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -30,10 +30,10 @@ use futures::Future; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use polkadot_primitives::{ - BlakeTwo256, BlockNumber, CandidateCommitments, CandidateHash, ChunkIndex, CollatorPair, - CommittedCandidateReceipt, CompactStatement, CoreIndex, EncodeAs, Hash, HashT, HeadData, - Id as ParaId, PersistedValidationData, SessionIndex, Signed, UncheckedSigned, ValidationCode, - ValidationCodeHash, MAX_CODE_SIZE, MAX_POV_SIZE, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, BlakeTwo256, BlockNumber, + CandidateCommitments, CandidateHash, ChunkIndex, CollatorPair, CompactStatement, CoreIndex, + EncodeAs, Hash, HashT, HeadData, Id as ParaId, PersistedValidationData, SessionIndex, Signed, + UncheckedSigned, ValidationCode, ValidationCodeHash, MAX_CODE_SIZE, MAX_POV_SIZE, }; pub use sp_consensus_babe::{ AllowedSlots as BabeAllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch, diff --git a/polkadot/node/service/src/parachains_db/upgrade.rs b/polkadot/node/service/src/parachains_db/upgrade.rs index 808acf04b4e7..52b010f0b5d0 100644 --- a/polkadot/node/service/src/parachains_db/upgrade.rs +++ b/polkadot/node/service/src/parachains_db/upgrade.rs @@ -463,7 +463,7 @@ mod tests { v3::migration_helpers::{v1_to_latest_sanity_check, v2_fill_test_data}, }; use polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter; - use polkadot_primitives_test_helpers::dummy_candidate_receipt; + use polkadot_primitives_test_helpers::dummy_candidate_receipt_v2; #[test] fn test_paritydb_migrate_0_to_1() { @@ -617,7 +617,7 @@ mod tests { assert_eq!(db.num_columns(), super::columns::v3::NUM_COLUMNS as u32); let db = DbAdapter::new(db, columns::v3::ORDERED_COL); // Fill the approval voting column with test data. - v1_fill_test_data(std::sync::Arc::new(db), approval_cfg, dummy_candidate_receipt) + v1_fill_test_data(std::sync::Arc::new(db), approval_cfg, dummy_candidate_receipt_v2) .unwrap() }; @@ -648,7 +648,7 @@ mod tests { assert_eq!(db.num_columns(), super::columns::v3::NUM_COLUMNS as u32); let db = DbAdapter::new(db, columns::v3::ORDERED_COL); // Fill the approval voting column with test data. - v2_fill_test_data(std::sync::Arc::new(db), approval_cfg, dummy_candidate_receipt) + v2_fill_test_data(std::sync::Arc::new(db), approval_cfg, dummy_candidate_receipt_v2) .unwrap() }; diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 293df9f6e6d5..8633818e775d 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -28,7 +28,7 @@ polkadot-node-subsystem = { workspace = true, default-features = true } polkadot-node-subsystem-util = { workspace = true, default-features = true } polkadot-node-subsystem-types = { workspace = true, default-features = true } polkadot-node-primitives = { workspace = true, default-features = true } -polkadot-primitives = { workspace = true, default-features = true } +polkadot-primitives = { workspace = true, features = ["test"] } polkadot-node-network-protocol = { workspace = true, default-features = true } polkadot-availability-recovery = { features = ["subsystem-benchmarks"], workspace = true, default-features = true } polkadot-availability-distribution = { workspace = true, default-features = true } diff --git a/polkadot/node/subsystem-bench/src/lib/approval/helpers.rs b/polkadot/node/subsystem-bench/src/lib/approval/helpers.rs index a3a475ac6b98..24cd734c6ae5 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/helpers.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/helpers.rs @@ -29,8 +29,8 @@ use polkadot_node_subsystem_types::messages::{ }; use polkadot_overseer::AllMessages; use polkadot_primitives::{ - BlockNumber, CandidateEvent, CandidateReceipt, CoreIndex, GroupIndex, Hash, Header, - Id as ParaId, Slot, ValidatorIndex, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt}, + BlockNumber, CoreIndex, GroupIndex, Hash, Header, Id as ParaId, Slot, ValidatorIndex, }; use polkadot_primitives_test_helpers::dummy_candidate_receipt_bad_sig; use rand::{seq::SliceRandom, SeedableRng}; @@ -189,7 +189,7 @@ pub fn make_header(parent_hash: Hash, slot: Slot, number: u32) -> Header { fn make_candidate(para_id: ParaId, hash: &Hash) -> CandidateReceipt { let mut r = dummy_candidate_receipt_bad_sig(*hash, Some(Default::default())); r.descriptor.para_id = para_id; - r + r.into() } /// Helper function to create a list of candidates that are included in the block diff --git a/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs index 807afb0438c9..79de6e72fc88 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs @@ -40,8 +40,8 @@ use polkadot_node_primitives::approval::{ v2::{CoreBitfield, IndirectAssignmentCertV2, IndirectSignedApprovalVoteV2}, }; use polkadot_primitives::{ - ApprovalVoteMultipleCandidates, CandidateEvent, CandidateHash, CandidateIndex, CoreIndex, Hash, - SessionInfo, Slot, ValidatorId, ValidatorIndex, ASSIGNMENT_KEY_TYPE_ID, + vstaging::CandidateEvent, ApprovalVoteMultipleCandidates, CandidateHash, CandidateIndex, + CoreIndex, Hash, SessionInfo, Slot, ValidatorId, ValidatorIndex, ASSIGNMENT_KEY_TYPE_ID, }; use rand::{seq::SliceRandom, RngCore, SeedableRng}; use rand_chacha::ChaCha20Rng; diff --git a/polkadot/node/subsystem-bench/src/lib/approval/mod.rs b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs index 29ebc4a419ae..1b20960a3f8a 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs @@ -66,8 +66,9 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers::mock::new_block_import_info; use polkadot_overseer::Handle as OverseerHandleReal; use polkadot_primitives::{ - BlockNumber, CandidateEvent, CandidateIndex, CandidateReceipt, Hash, Header, Slot, ValidatorId, - ValidatorIndex, ASSIGNMENT_KEY_TYPE_ID, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt}, + BlockNumber, CandidateIndex, Hash, Header, Slot, ValidatorId, ValidatorIndex, + ASSIGNMENT_KEY_TYPE_ID, }; use prometheus::Registry; use sc_keystore::LocalKeystore; diff --git a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs index a99f013195fa..8ac9796acb62 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs @@ -391,7 +391,7 @@ pub async fn benchmark_availability_write( candidate_hash: backed_candidate.hash(), n_validators: config.n_validators as u32, available_data, - expected_erasure_root: backed_candidate.descriptor().erasure_root, + expected_erasure_root: backed_candidate.descriptor().erasure_root(), tx, core_index: CoreIndex(core_index as u32), node_features: node_features_with_chunk_mapping_enabled(), diff --git a/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs b/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs index 173b23f6b76e..511795970e6c 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs @@ -34,8 +34,9 @@ use polkadot_node_subsystem_test_helpers::{ use polkadot_node_subsystem_util::availability_chunks::availability_chunk_indices; use polkadot_overseer::BlockInfo; use polkadot_primitives::{ - AvailabilityBitfield, BlockNumber, CandidateHash, CandidateReceipt, ChunkIndex, CoreIndex, - Hash, HeadData, Header, PersistedValidationData, Signed, SigningContext, ValidatorIndex, + vstaging::{CandidateReceiptV2 as CandidateReceipt, MutateDescriptorV2}, + AvailabilityBitfield, BlockNumber, CandidateHash, ChunkIndex, CoreIndex, Hash, HeadData, + Header, PersistedValidationData, Signed, SigningContext, ValidatorIndex, }; use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; use sp_core::H256; @@ -148,7 +149,10 @@ impl TestState { test_state.chunks.push(new_chunks); test_state.available_data.push(new_available_data); test_state.pov_size_to_candidate.insert(pov_size, index); - test_state.candidate_receipt_templates.push(candidate_receipt); + test_state.candidate_receipt_templates.push(CandidateReceipt { + descriptor: candidate_receipt.descriptor.into(), + commitments_hash: candidate_receipt.commitments_hash, + }); } test_state.block_infos = (1..=config.num_blocks) @@ -189,7 +193,9 @@ impl TestState { test_state.candidate_receipt_templates[candidate_index].clone(); // Make it unique. - candidate_receipt.descriptor.relay_parent = Hash::from_low_u64_be(index as u64); + candidate_receipt + .descriptor + .set_relay_parent(Hash::from_low_u64_be(index as u64)); // Store the new candidate in the state test_state.candidate_hashes.insert(candidate_receipt.hash(), candidate_index); diff --git a/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs index 61523de1f1b5..6c54d14448a1 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs @@ -26,9 +26,10 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_types::OverseerSignal; use polkadot_primitives::{ - node_features, ApprovalVotingParams, AsyncBackingParams, CandidateEvent, CandidateReceipt, - CoreState, GroupIndex, GroupRotationInfo, IndexedVec, NodeFeatures, OccupiedCore, - ScheduledCore, SessionIndex, SessionInfo, ValidationCode, ValidatorIndex, + node_features, + vstaging::{CandidateEvent, CandidateReceiptV2 as CandidateReceipt, CoreState, OccupiedCore}, + ApprovalVotingParams, AsyncBackingParams, GroupIndex, GroupRotationInfo, IndexedVec, + NodeFeatures, ScheduledCore, SessionIndex, SessionInfo, ValidationCode, ValidatorIndex, }; use sp_consensus_babe::Epoch as BabeEpoch; use sp_core::H256; diff --git a/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs b/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs index 88b5e8b76b62..2d2e9434b767 100644 --- a/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs +++ b/polkadot/node/subsystem-bench/src/lib/statement/test_state.rs @@ -41,12 +41,15 @@ use polkadot_node_subsystem_test_helpers::{ }; use polkadot_overseer::BlockInfo; use polkadot_primitives::{ - BlockNumber, CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CompactStatement, - Hash, Header, Id, PersistedValidationData, SessionInfo, SignedStatement, SigningContext, - UncheckedSigned, ValidatorIndex, ValidatorPair, + vstaging::{ + CandidateReceiptV2 as CandidateReceipt, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, MutateDescriptorV2, + }, + BlockNumber, CandidateHash, CompactStatement, Hash, Header, Id, PersistedValidationData, + SessionInfo, SignedStatement, SigningContext, UncheckedSigned, ValidatorIndex, ValidatorPair, }; use polkadot_primitives_test_helpers::{ - dummy_committed_candidate_receipt, dummy_hash, dummy_head_data, dummy_pvd, + dummy_committed_candidate_receipt_v2, dummy_hash, dummy_head_data, dummy_pvd, }; use sc_network::{config::IncomingRequest, ProtocolName}; use sp_core::{Pair, H256}; @@ -125,8 +128,8 @@ impl TestState { let candidate_index = *pov_size_to_candidate.get(pov_size).expect("pov_size always exists; qed"); let mut receipt = receipt_templates[candidate_index].clone(); - receipt.descriptor.para_id = Id::new(core_idx as u32 + 1); - receipt.descriptor.relay_parent = block_info.hash; + receipt.descriptor.set_para_id(Id::new(core_idx as u32 + 1)); + receipt.descriptor.set_relay_parent(block_info.hash); state.candidate_receipts.entry(block_info.hash).or_default().push( CandidateReceipt { @@ -240,7 +243,7 @@ fn generate_receipt_templates( pov_size_to_candidate .iter() .map(|(&pov_size, &index)| { - let mut receipt = dummy_committed_candidate_receipt(dummy_hash()); + let mut receipt = dummy_committed_candidate_receipt_v2(dummy_hash()); let (_, erasure_root) = derive_erasure_chunks_with_proofs_and_root( n_validators, &AvailableData { @@ -249,8 +252,8 @@ fn generate_receipt_templates( }, |_, _| {}, ); - receipt.descriptor.persisted_validation_data_hash = pvd.hash(); - receipt.descriptor.erasure_root = erasure_root; + receipt.descriptor.set_persisted_validation_data_hash(pvd.hash()); + receipt.descriptor.set_erasure_root(erasure_root); receipt }) .collect() diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 0017adb45568..ba1ba5755be0 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -43,15 +43,18 @@ use polkadot_node_primitives::{ ValidationResult, }; use polkadot_primitives::{ - async_backing, slashing, ApprovalVotingParams, AuthorityDiscoveryId, BackedCandidate, - BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, CandidateIndex, - CandidateReceipt, CollatorId, CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, - ExecutorParams, GroupIndex, GroupRotationInfo, Hash, HeadData, Header as BlockHeader, - Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, MultiDisputeStatementSet, - NodeFeatures, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, - PvfExecKind as RuntimePvfExecKind, SessionIndex, SessionInfo, SignedAvailabilityBitfield, - SignedAvailabilityBitfields, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, - ValidatorSignature, + async_backing, slashing, vstaging, + vstaging::{ + BackedCandidate, CandidateReceiptV2 as CandidateReceipt, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + }, + ApprovalVotingParams, AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateHash, + CandidateIndex, CollatorId, CoreIndex, DisputeState, ExecutorParams, GroupIndex, + GroupRotationInfo, Hash, HeadData, Header as BlockHeader, Id as ParaId, InboundDownwardMessage, + InboundHrmpMessage, MultiDisputeStatementSet, NodeFeatures, OccupiedCoreAssumption, + PersistedValidationData, PvfCheckStatement, PvfExecKind as RuntimePvfExecKind, SessionIndex, + SessionInfo, SignedAvailabilityBitfield, SignedAvailabilityBitfields, ValidationCode, + ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }; use polkadot_statement_table::v2::Misbehavior; use std::{ @@ -708,7 +711,7 @@ pub enum RuntimeApiRequest { CandidatePendingAvailability(ParaId, RuntimeApiSender>), /// Get all events concerning candidates (backing, inclusion, time-out) in the parent of /// the block in whose state this request is executed. - CandidateEvents(RuntimeApiSender>), + CandidateEvents(RuntimeApiSender>), /// Get the execution environment parameter set by session index SessionExecutorParams(SessionIndex, RuntimeApiSender>), /// Get the session info for the given session, if stored. @@ -724,7 +727,7 @@ pub enum RuntimeApiRequest { /// Get information about the BABE epoch the block was included in. CurrentBabeEpoch(RuntimeApiSender), /// Get all disputes in relation to a relay parent. - FetchOnChainVotes(RuntimeApiSender>), + FetchOnChainVotes(RuntimeApiSender>), /// Submits a PVF pre-checking statement into the transaction pool. SubmitPvfCheckStatement(PvfCheckStatement, ValidatorSignature, RuntimeApiSender<()>), /// Returns code hashes of PVFs that require pre-checking by validators in the active set. @@ -759,7 +762,7 @@ pub enum RuntimeApiRequest { /// Returns all disabled validators at a given block height. DisabledValidators(RuntimeApiSender>), /// Get the backing state of the given para. - ParaBackingState(ParaId, RuntimeApiSender>), + ParaBackingState(ParaId, RuntimeApiSender>), /// Get candidate's acceptance limitations for asynchronous backing for a relay parent. /// /// If it's not supported by the Runtime, the async backing is said to be disabled. @@ -1256,7 +1259,7 @@ impl HypotheticalCandidate { /// Get the `ParaId` of the hypothetical candidate. pub fn candidate_para(&self) -> ParaId { match *self { - HypotheticalCandidate::Complete { ref receipt, .. } => receipt.descriptor().para_id, + HypotheticalCandidate::Complete { ref receipt, .. } => receipt.descriptor.para_id(), HypotheticalCandidate::Incomplete { candidate_para, .. } => candidate_para, } } @@ -1275,7 +1278,7 @@ impl HypotheticalCandidate { pub fn relay_parent(&self) -> Hash { match *self { HypotheticalCandidate::Complete { ref receipt, .. } => - receipt.descriptor().relay_parent, + receipt.descriptor.relay_parent(), HypotheticalCandidate::Incomplete { candidate_relay_parent, .. } => candidate_relay_parent, } @@ -1285,7 +1288,7 @@ impl HypotheticalCandidate { pub fn output_head_data_hash(&self) -> Option { match *self { HypotheticalCandidate::Complete { ref receipt, .. } => - Some(receipt.descriptor.para_head), + Some(receipt.descriptor.para_head()), HypotheticalCandidate::Incomplete { .. } => None, } } @@ -1308,10 +1311,10 @@ impl HypotheticalCandidate { } /// Get the validation code hash, if the candidate is complete. - pub fn validation_code_hash(&self) -> Option<&ValidationCodeHash> { + pub fn validation_code_hash(&self) -> Option { match *self { HypotheticalCandidate::Complete { ref receipt, .. } => - Some(&receipt.descriptor.validation_code_hash), + Some(receipt.descriptor.validation_code_hash()), HypotheticalCandidate::Incomplete { .. } => None, } } diff --git a/polkadot/node/subsystem-types/src/runtime_client.rs b/polkadot/node/subsystem-types/src/runtime_client.rs index a8af8b7996f9..4b96009f44bf 100644 --- a/polkadot/node/subsystem-types/src/runtime_client.rs +++ b/polkadot/node/subsystem-types/src/runtime_client.rs @@ -16,12 +16,18 @@ use async_trait::async_trait; use polkadot_primitives::{ - async_backing, runtime_api::ParachainHost, slashing, ApprovalVotingParams, Block, BlockNumber, - CandidateCommitments, CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreIndex, - CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash, Header, Id, - InboundDownwardMessage, InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, - PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, - ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + async_backing, + runtime_api::ParachainHost, + slashing, vstaging, + vstaging::{ + CandidateEvent, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, + ScrapedOnChainVotes, + }, + ApprovalVotingParams, Block, BlockNumber, CandidateCommitments, CandidateHash, CoreIndex, + DisputeState, ExecutorParams, GroupRotationInfo, Hash, Header, Id, InboundDownwardMessage, + InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, PersistedValidationData, + PvfCheckStatement, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, + ValidatorIndex, ValidatorSignature, }; use sc_client_api::{AuxStore, HeaderBackend}; use sc_transaction_pool_api::OffchainTransactionPoolFactory; @@ -311,7 +317,7 @@ pub trait RuntimeApiSubsystemClient { &self, at: Hash, para_id: Id, - ) -> Result, ApiError>; + ) -> Result, ApiError>; // === v8 === @@ -380,10 +386,7 @@ where &self, at: Hash, ) -> Result>, ApiError> { - self.client - .runtime_api() - .availability_cores(at) - .map(|cores| cores.into_iter().map(|core| core.into()).collect::>()) + self.client.runtime_api().availability_cores(at) } async fn persisted_validation_data( @@ -436,10 +439,7 @@ where at: Hash, para_id: Id, ) -> Result>, ApiError> { - self.client - .runtime_api() - .candidate_pending_availability(at, para_id) - .map(|maybe_candidate| maybe_candidate.map(|candidate| candidate.into())) + self.client.runtime_api().candidate_pending_availability(at, para_id) } async fn candidates_pending_availability( @@ -447,19 +447,11 @@ where at: Hash, para_id: Id, ) -> Result>, ApiError> { - self.client - .runtime_api() - .candidates_pending_availability(at, para_id) - .map(|candidates| { - candidates.into_iter().map(|candidate| candidate.into()).collect::>() - }) + self.client.runtime_api().candidates_pending_availability(at, para_id) } async fn candidate_events(&self, at: Hash) -> Result>, ApiError> { - self.client - .runtime_api() - .candidate_events(at) - .map(|events| events.into_iter().map(|event| event.into()).collect::>()) + self.client.runtime_api().candidate_events(at) } async fn dmq_contents( @@ -490,10 +482,7 @@ where &self, at: Hash, ) -> Result>, ApiError> { - self.client - .runtime_api() - .on_chain_votes(at) - .map(|maybe_votes| maybe_votes.map(|votes| votes.into())) + self.client.runtime_api().on_chain_votes(at) } async fn session_executor_params( @@ -604,13 +593,8 @@ where &self, at: Hash, para_id: Id, - ) -> Result, ApiError> { - self.client - .runtime_api() - .para_backing_state(at, para_id) - .map(|maybe_backing_state| { - maybe_backing_state.map(|backing_state| backing_state.into()) - }) + ) -> Result, ApiError> { + self.client.runtime_api().para_backing_state(at, para_id) } async fn async_backing_params( diff --git a/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs b/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs index 0c3b40743495..a2a6095b765c 100644 --- a/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs +++ b/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs @@ -770,7 +770,7 @@ pub trait HypotheticalOrConcreteCandidate { /// Return a reference to the persisted validation data, if present. fn persisted_validation_data(&self) -> Option<&PersistedValidationData>; /// Return a reference to the validation code hash, if present. - fn validation_code_hash(&self) -> Option<&ValidationCodeHash>; + fn validation_code_hash(&self) -> Option; /// Return the parent head hash. fn parent_head_data_hash(&self) -> Hash; /// Return the output head hash, if present. @@ -790,7 +790,7 @@ impl HypotheticalOrConcreteCandidate for HypotheticalCandidate { self.persisted_validation_data() } - fn validation_code_hash(&self) -> Option<&ValidationCodeHash> { + fn validation_code_hash(&self) -> Option { self.validation_code_hash() } diff --git a/polkadot/node/subsystem-util/src/lib.rs b/polkadot/node/subsystem-util/src/lib.rs index 4bab4e80fe50..3bed18558941 100644 --- a/polkadot/node/subsystem-util/src/lib.rs +++ b/polkadot/node/subsystem-util/src/lib.rs @@ -41,12 +41,15 @@ use codec::Encode; use futures::channel::{mpsc, oneshot}; use polkadot_primitives::{ - async_backing::BackingState, slashing, AsyncBackingParams, AuthorityDiscoveryId, - CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreIndex, CoreState, EncodeAs, - ExecutorParams, GroupIndex, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, - PersistedValidationData, ScrapedOnChainVotes, SessionIndex, SessionInfo, Signed, - SigningContext, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, - ValidatorSignature, + slashing, + vstaging::{ + async_backing::BackingState, CandidateEvent, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, ScrapedOnChainVotes, + }, + AsyncBackingParams, AuthorityDiscoveryId, CandidateHash, CoreIndex, EncodeAs, ExecutorParams, + GroupIndex, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, + PersistedValidationData, SessionIndex, SessionInfo, Signed, SigningContext, ValidationCode, + ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }; pub use rand; use runtime::get_disabled_validators_with_fallback; diff --git a/polkadot/node/subsystem-util/src/runtime/mod.rs b/polkadot/node/subsystem-util/src/runtime/mod.rs index 2f9d3ed7b4f4..d84951ae1366 100644 --- a/polkadot/node/subsystem-util/src/runtime/mod.rs +++ b/polkadot/node/subsystem-util/src/runtime/mod.rs @@ -30,11 +30,13 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_types::UnpinHandle; use polkadot_primitives::{ - node_features::FeatureIndex, slashing, AsyncBackingParams, CandidateEvent, CandidateHash, - CoreIndex, CoreState, EncodeAs, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, - Id as ParaId, IndexedVec, NodeFeatures, OccupiedCore, ScrapedOnChainVotes, SessionIndex, - SessionInfo, Signed, SigningContext, UncheckedSigned, ValidationCode, ValidationCodeHash, - ValidatorId, ValidatorIndex, LEGACY_MIN_BACKING_VOTES, + node_features::FeatureIndex, + slashing, + vstaging::{CandidateEvent, CoreState, OccupiedCore, ScrapedOnChainVotes}, + AsyncBackingParams, CandidateHash, CoreIndex, EncodeAs, ExecutorParams, GroupIndex, + GroupRotationInfo, Hash, Id as ParaId, IndexedVec, NodeFeatures, SessionIndex, SessionInfo, + Signed, SigningContext, UncheckedSigned, ValidationCode, ValidationCodeHash, ValidatorId, + ValidatorIndex, LEGACY_MIN_BACKING_VOTES, }; use std::collections::{BTreeMap, VecDeque}; diff --git a/polkadot/parachain/test-parachains/adder/collator/src/lib.rs b/polkadot/parachain/test-parachains/adder/collator/src/lib.rs index daeb8bc915dd..a2fb623331a0 100644 --- a/polkadot/parachain/test-parachains/adder/collator/src/lib.rs +++ b/polkadot/parachain/test-parachains/adder/collator/src/lib.rs @@ -236,7 +236,7 @@ impl Collator { if let Ok(res) = recv.await { if !matches!( res.statement.payload(), - Statement::Seconded(s) if s.descriptor.pov_hash == compressed_pov.hash(), + Statement::Seconded(s) if s.descriptor.pov_hash() == compressed_pov.hash(), ) { log::error!( "Seconded statement should match our collation: {:?}", diff --git a/polkadot/parachain/test-parachains/undying/collator/src/lib.rs b/polkadot/parachain/test-parachains/undying/collator/src/lib.rs index 920099f4499d..448c181ae062 100644 --- a/polkadot/parachain/test-parachains/undying/collator/src/lib.rs +++ b/polkadot/parachain/test-parachains/undying/collator/src/lib.rs @@ -282,7 +282,7 @@ impl Collator { if let Ok(res) = recv.await { if !matches!( res.statement.payload(), - Statement::Seconded(s) if s.descriptor.pov_hash == compressed_pov.hash(), + Statement::Seconded(s) if s.descriptor.pov_hash() == compressed_pov.hash(), ) { log::error!( "Seconded statement should match our collation: {:?}", diff --git a/polkadot/primitives/src/v8/mod.rs b/polkadot/primitives/src/v8/mod.rs index cca327df42c9..fdcb9fe8fb7e 100644 --- a/polkadot/primitives/src/v8/mod.rs +++ b/polkadot/primitives/src/v8/mod.rs @@ -484,7 +484,7 @@ pub fn collator_signature_payload>( payload } -fn check_collator_signature>( +pub(crate) fn check_collator_signature>( relay_parent: &H, para_id: &Id, persisted_validation_data_hash: &Hash, diff --git a/polkadot/primitives/src/vstaging/mod.rs b/polkadot/primitives/src/vstaging/mod.rs index bc687f7e2fbe..265fcd899d74 100644 --- a/polkadot/primitives/src/vstaging/mod.rs +++ b/polkadot/primitives/src/vstaging/mod.rs @@ -107,14 +107,42 @@ impl From> for CandidateDescriptor { } } -#[cfg(any(feature = "runtime-benchmarks", feature = "test"))] -impl From> for CandidateDescriptorV2 { +fn clone_into_array(slice: &[T]) -> A +where + A: Default + AsMut<[T]>, + T: Clone, +{ + let mut a = A::default(); + >::as_mut(&mut a).clone_from_slice(slice); + a +} + +impl From> for CandidateDescriptorV2 { fn from(value: CandidateDescriptor) -> Self { - Decode::decode(&mut value.encode().as_slice()).unwrap() + let collator = value.collator.as_slice(); + + Self { + para_id: value.para_id, + relay_parent: value.relay_parent, + // Use first byte of the `collator` field. + version: InternalVersion(collator[0]), + // Use next 2 bytes of the `collator` field. + core_index: u16::from_ne_bytes(clone_into_array(&collator[1..=2])), + // Use next 4 bytes of the `collator` field. + session_index: SessionIndex::from_ne_bytes(clone_into_array(&collator[3..=6])), + // Use remaing 25 bytes of the `collator` field. + reserved1: clone_into_array(&collator[7..]), + persisted_validation_data_hash: value.persisted_validation_data_hash, + pov_hash: value.pov_hash, + erasure_root: value.erasure_root, + reserved2: value.signature.into_inner().0, + para_head: value.para_head, + validation_code_hash: value.validation_code_hash, + } } } -impl CandidateDescriptorV2 { +impl> CandidateDescriptorV2 { /// Constructor pub fn new( para_id: Id, @@ -143,17 +171,74 @@ impl CandidateDescriptorV2 { } } - /// Set the PoV size in the descriptor. Only for tests. - #[cfg(feature = "test")] - pub fn set_pov_hash(&mut self, pov_hash: Hash) { + /// Check the signature of the collator within this descriptor. + pub fn check_collator_signature(&self) -> Result<(), ()> { + // Return `Ok` if collator signature is not included (v2+ descriptor). + let Some(collator) = self.collator() else { return Ok(()) }; + + let Some(signature) = self.signature() else { return Ok(()) }; + + super::v8::check_collator_signature( + &self.relay_parent, + &self.para_id, + &self.persisted_validation_data_hash, + &self.pov_hash, + &self.validation_code_hash, + &collator, + &signature, + ) + } +} + +/// A trait to allow changing the descriptor field values in tests. +#[cfg(feature = "test")] + +pub trait MutateDescriptorV2 { + /// Set the relay parent of the descriptor. + fn set_relay_parent(&mut self, relay_parent: H); + /// Set the `ParaId` of the descriptor. + fn set_para_id(&mut self, para_id: Id); + /// Set the PoV hash of the descriptor. + fn set_pov_hash(&mut self, pov_hash: Hash); + /// Set the version field of the descriptor. + fn set_version(&mut self, version: InternalVersion); + /// Set the PVD of the descriptor. + fn set_persisted_validation_data_hash(&mut self, persisted_validation_data_hash: Hash); + /// Set the erasure root of the descriptor. + fn set_erasure_root(&mut self, erasure_root: Hash); + /// Set the para head of the descriptor. + fn set_para_head(&mut self, para_head: Hash); +} + +#[cfg(feature = "test")] +impl MutateDescriptorV2 for CandidateDescriptorV2 { + fn set_para_id(&mut self, para_id: Id) { + self.para_id = para_id; + } + + fn set_relay_parent(&mut self, relay_parent: H) { + self.relay_parent = relay_parent; + } + + fn set_pov_hash(&mut self, pov_hash: Hash) { self.pov_hash = pov_hash; } - /// Set the version in the descriptor. Only for tests. - #[cfg(feature = "test")] - pub fn set_version(&mut self, version: InternalVersion) { + fn set_version(&mut self, version: InternalVersion) { self.version = version; } + + fn set_persisted_validation_data_hash(&mut self, persisted_validation_data_hash: Hash) { + self.persisted_validation_data_hash = persisted_validation_data_hash; + } + + fn set_erasure_root(&mut self, erasure_root: Hash) { + self.erasure_root = erasure_root; + } + + fn set_para_head(&mut self, para_head: Hash) { + self.para_head = para_head; + } } /// A candidate-receipt at version 2. @@ -233,6 +318,24 @@ impl CandidateReceiptV2 { } } +impl From> for CandidateReceiptV2 { + fn from(value: super::v8::CandidateReceipt) -> Self { + CandidateReceiptV2 { + descriptor: value.descriptor.into(), + commitments_hash: value.commitments_hash, + } + } +} + +impl From> for CommittedCandidateReceiptV2 { + fn from(value: super::v8::CommittedCandidateReceipt) -> Self { + CommittedCandidateReceiptV2 { + descriptor: value.descriptor.into(), + commitments: value.commitments, + } + } +} + impl CommittedCandidateReceiptV2 { /// Transforms this into a plain `CandidateReceipt`. pub fn to_plain(&self) -> CandidateReceiptV2 { @@ -368,7 +471,7 @@ pub enum CandidateReceiptError { macro_rules! impl_getter { ($field:ident, $type:ident) => { - /// Returns the value of $field field. + /// Returns the value of `$field` field. pub fn $field(&self) -> $type { self.$field } @@ -703,6 +806,13 @@ pub struct OccupiedCore { pub candidate_descriptor: CandidateDescriptorV2, } +impl OccupiedCore { + /// Get the Para currently occupying this core. + pub fn para_id(&self) -> Id { + self.candidate_descriptor.para_id + } +} + /// The state of a particular availability core. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] #[cfg_attr(feature = "std", derive(PartialEq))] @@ -724,6 +834,28 @@ pub enum CoreState { Free, } +impl CoreState { + /// Returns the scheduled `ParaId` for the core or `None` if nothing is scheduled. + /// + /// This function is deprecated. `ClaimQueue` should be used to obtain the scheduled `ParaId`s + /// for each core. + #[deprecated( + note = "`para_id` will be removed. Use `ClaimQueue` to query the scheduled `para_id` instead." + )] + pub fn para_id(&self) -> Option { + match self { + Self::Occupied(ref core) => core.next_up_on_available.as_ref().map(|n| n.para_id), + Self::Scheduled(core) => Some(core.para_id), + Self::Free => None, + } + } + + /// Is this core state `Self::Occupied`? + pub fn is_occupied(&self) -> bool { + matches!(self, Self::Occupied(_)) + } +} + impl From> for super::v8::OccupiedCore { fn from(value: OccupiedCore) -> Self { Self { @@ -841,6 +973,25 @@ mod tests { assert_eq!(old_ccr.hash(), new_ccr.hash()); } + #[test] + fn test_from_v1_descriptor() { + let mut old_ccr = dummy_old_committed_candidate_receipt().to_plain(); + old_ccr.descriptor.collator = dummy_collator_id(); + old_ccr.descriptor.signature = dummy_collator_signature(); + + let mut new_ccr = dummy_committed_candidate_receipt_v2().to_plain(); + + // Override descriptor from old candidate receipt. + new_ccr.descriptor = old_ccr.descriptor.clone().into(); + + // We get same candidate hash. + assert_eq!(old_ccr.hash(), new_ccr.hash()); + + assert_eq!(new_ccr.descriptor.version(), CandidateDescriptorVersion::V1); + assert_eq!(old_ccr.descriptor.collator, new_ccr.descriptor.collator().unwrap()); + assert_eq!(old_ccr.descriptor.signature, new_ccr.descriptor.signature().unwrap()); + } + #[test] fn invalid_version_descriptor() { let mut new_ccr = dummy_committed_candidate_receipt_v2(); diff --git a/polkadot/primitives/test-helpers/src/lib.rs b/polkadot/primitives/test-helpers/src/lib.rs index b0f78717dd97..c2eccafef788 100644 --- a/polkadot/primitives/test-helpers/src/lib.rs +++ b/polkadot/primitives/test-helpers/src/lib.rs @@ -44,7 +44,7 @@ pub fn dummy_candidate_receipt>(relay_parent: H) -> CandidateRece } /// Creates a v2 candidate receipt with filler data. -pub fn dummy_candidate_receipt_v2>(relay_parent: H) -> CandidateReceiptV2 { +pub fn dummy_candidate_receipt_v2 + Copy>(relay_parent: H) -> CandidateReceiptV2 { CandidateReceiptV2:: { commitments_hash: dummy_candidate_commitments(dummy_head_data()).hash(), descriptor: dummy_candidate_descriptor_v2(relay_parent), @@ -62,7 +62,7 @@ pub fn dummy_committed_candidate_receipt>( } /// Creates a v2 committed candidate receipt with filler data. -pub fn dummy_committed_candidate_receipt_v2>( +pub fn dummy_committed_candidate_receipt_v2 + Copy>( relay_parent: H, ) -> CommittedCandidateReceiptV2 { CommittedCandidateReceiptV2 { @@ -88,6 +88,23 @@ pub fn dummy_candidate_receipt_bad_sig( } } +/// Create a candidate receipt with a bogus signature and filler data. Optionally set the commitment +/// hash with the `commitments` arg. +pub fn dummy_candidate_receipt_v2_bad_sig( + relay_parent: Hash, + commitments: impl Into>, +) -> CandidateReceiptV2 { + let commitments_hash = if let Some(commitments) = commitments.into() { + commitments + } else { + dummy_candidate_commitments(dummy_head_data()).hash() + }; + CandidateReceiptV2:: { + commitments_hash, + descriptor: dummy_candidate_descriptor_bad_sig(relay_parent).into(), + } +} + /// Create candidate commitments with filler data. pub fn dummy_candidate_commitments(head_data: impl Into>) -> CandidateCommitments { CandidateCommitments { @@ -144,7 +161,9 @@ pub fn dummy_candidate_descriptor>(relay_parent: H) -> CandidateD } /// Create a v2 candidate descriptor with filler data. -pub fn dummy_candidate_descriptor_v2>(relay_parent: H) -> CandidateDescriptorV2 { +pub fn dummy_candidate_descriptor_v2 + Copy>( + relay_parent: H, +) -> CandidateDescriptorV2 { let invalid = Hash::zero(); let descriptor = make_valid_candidate_descriptor_v2( 1.into(), @@ -208,7 +227,7 @@ pub fn make_candidate( parent_head: HeadData, head_data: HeadData, validation_code_hash: ValidationCodeHash, -) -> (CommittedCandidateReceipt, PersistedValidationData) { +) -> (CommittedCandidateReceiptV2, PersistedValidationData) { let pvd = dummy_pvd(parent_head, relay_parent_number); let commitments = CandidateCommitments { head_data, @@ -225,7 +244,8 @@ pub fn make_candidate( candidate.descriptor.para_id = para_id; candidate.descriptor.persisted_validation_data_hash = pvd.hash(); candidate.descriptor.validation_code_hash = validation_code_hash; - let candidate = CommittedCandidateReceipt { descriptor: candidate.descriptor, commitments }; + let candidate = + CommittedCandidateReceiptV2 { descriptor: candidate.descriptor.into(), commitments }; (candidate, pvd) } @@ -269,7 +289,7 @@ pub fn make_valid_candidate_descriptor>( } /// Create a v2 candidate descriptor. -pub fn make_valid_candidate_descriptor_v2>( +pub fn make_valid_candidate_descriptor_v2 + Copy>( para_id: ParaId, relay_parent: H, core_index: CoreIndex, @@ -335,11 +355,11 @@ impl std::default::Default for TestCandidateBuilder { impl TestCandidateBuilder { /// Build a `CandidateReceipt`. - pub fn build(self) -> CandidateReceipt { + pub fn build(self) -> CandidateReceiptV2 { let mut descriptor = dummy_candidate_descriptor(self.relay_parent); descriptor.para_id = self.para_id; descriptor.pov_hash = self.pov_hash; - CandidateReceipt { descriptor, commitments_hash: self.commitments_hash } + CandidateReceipt { descriptor, commitments_hash: self.commitments_hash }.into() } } diff --git a/polkadot/runtime/parachains/src/inclusion/tests.rs b/polkadot/runtime/parachains/src/inclusion/tests.rs index 188ba4995d83..8513d2dad91d 100644 --- a/polkadot/runtime/parachains/src/inclusion/tests.rs +++ b/polkadot/runtime/parachains/src/inclusion/tests.rs @@ -39,7 +39,7 @@ use assert_matches::assert_matches; use codec::DecodeAll; use frame_support::assert_noop; use polkadot_primitives::{ - BlockNumber, CandidateCommitments, CollatorId, CollatorSignature, + vstaging::MutateDescriptorV2, BlockNumber, CandidateCommitments, CollatorId, CollatorSignature, CompactStatement as Statement, Hash, SignedAvailabilityBitfield, SignedStatement, ValidationCode, ValidatorId, ValidityAttestation, PARACHAIN_KEY_TYPE_ID, }; diff --git a/polkadot/runtime/parachains/src/paras_inherent/tests.rs b/polkadot/runtime/parachains/src/paras_inherent/tests.rs index 2c65298baf01..eef26b83368f 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/tests.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/tests.rs @@ -61,7 +61,9 @@ mod enter { use frame_support::assert_ok; use frame_system::limits; use polkadot_primitives::{ - vstaging::{CandidateDescriptorV2, CommittedCandidateReceiptV2, InternalVersion}, + vstaging::{ + CandidateDescriptorV2, CommittedCandidateReceiptV2, InternalVersion, MutateDescriptorV2, + }, AvailabilityBitfield, CandidateDescriptor, UncheckedSigned, }; use sp_runtime::Perbill; diff --git a/polkadot/statement-table/src/lib.rs b/polkadot/statement-table/src/lib.rs index 469c877eafc9..68febf76feb3 100644 --- a/polkadot/statement-table/src/lib.rs +++ b/polkadot/statement-table/src/lib.rs @@ -35,8 +35,8 @@ pub use generic::{Config, Context, Table}; pub mod v2 { use crate::generic; use polkadot_primitives::{ - CandidateHash, CommittedCandidateReceipt, CompactStatement as PrimitiveStatement, - CoreIndex, ValidatorIndex, ValidatorSignature, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CandidateHash, + CompactStatement as PrimitiveStatement, CoreIndex, ValidatorIndex, ValidatorSignature, }; /// Statements about candidates on the network. diff --git a/prdoc/pr_5679.prdoc b/prdoc/pr_5679.prdoc new file mode 100644 index 000000000000..59c36ecb933d --- /dev/null +++ b/prdoc/pr_5679.prdoc @@ -0,0 +1,80 @@ +title: Switch to new `CandidateReceipt` primitives +doc: +- audience: + - Node Dev + - Runtime Dev + description: | + This change is just plumbing work and updates all crate interfaces to use the new primitives. + It doesn't alter any functionality and is required before implementing RFC103 on the + node side. +crates: +- name: polkadot-primitives + bump: major +- name: polkadot-runtime-parachains + bump: patch +- name: rococo-runtime + bump: patch +- name: westend-runtime + bump: patch +- name: cumulus-relay-chain-inprocess-interface + bump: major +- name: polkadot-service + bump: patch +- name: polkadot-node-subsystem-types + bump: major +- name: polkadot + bump: patch +- name: cumulus-client-network + bump: major +- name: cumulus-client-pov-recovery + bump: major +- name: cumulus-relay-chain-interface + bump: major +- name: cumulus-relay-chain-minimal-node + bump: major +- name: cumulus-relay-chain-rpc-interface + bump: major +- name: polkadot-node-collation-generation + bump: major +- name: polkadot-node-core-approval-voting + bump: major +- name: polkadot-node-core-av-store + bump: major +- name: polkadot-node-core-backing + bump: major +- name: polkadot-node-core-bitfield-signing + bump: major +- name: polkadot-node-core-candidate-validation + bump: major +- name: polkadot-node-core-dispute-coordinator + bump: major +- name: polkadot-node-core-parachains-inherent + bump: major +- name: polkadot-node-core-prospective-parachains + bump: major +- name: polkadot-node-core-provisioner + bump: major +- name: polkadot-node-core-runtime-api + bump: major +- name: polkadot-availability-distribution + bump: major +- name: polkadot-availability-recovery + bump: major +- name: polkadot-collator-protocol + bump: major +- name: polkadot-dispute-distribution + bump: major +- name: polkadot-node-network-protocol + bump: major +- name: polkadot-statement-distribution + bump: major +- name: polkadot-node-primitives + bump: major +- name: polkadot-node-subsystem-util + bump: major +- name: polkadot-statement-table + bump: major +- name: polkadot-overseer + bump: patch +- name: cumulus-client-consensus-common + bump: major