From a83415b114efaefe27c64a7ff60393e256b418fc Mon Sep 17 00:00:00 2001 From: Francisco Gamundi <52399794+fgamundi@users.noreply.github.com> Date: Thu, 9 May 2024 12:26:38 +0200 Subject: [PATCH 1/7] Services payment RPC (#545) * Services payment RPC * lint * typo --- Cargo.lock | 24 +++++ Cargo.toml | 2 + client/services-payment/Cargo.toml | 22 +++++ client/services-payment/src/lib.rs | 94 +++++++++++++++++++ node/Cargo.toml | 1 + node/src/rpc.rs | 10 +- .../rpc/runtime-api/Cargo.toml | 24 +++++ .../rpc/runtime-api/src/lib.rs | 30 ++++++ runtime/dancebox/Cargo.toml | 2 + runtime/dancebox/src/lib.rs | 12 +++ runtime/flashbox/Cargo.toml | 2 + runtime/flashbox/src/lib.rs | 12 +++ .../test_services_payment_rpc.ts | 25 +++++ 13 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 client/services-payment/Cargo.toml create mode 100644 client/services-payment/src/lib.rs create mode 100644 pallets/services-payment/rpc/runtime-api/Cargo.toml create mode 100644 pallets/services-payment/rpc/runtime-api/src/lib.rs create mode 100644 test/suites/common-tanssi/services-payment/test_services_payment_rpc.ts diff --git a/Cargo.lock b/Cargo.lock index ccfce12ee..2c9a3c7fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3051,6 +3051,7 @@ dependencies = [ "pallet-relay-storage-roots", "pallet-root-testing", "pallet-services-payment", + "pallet-services-payment-runtime-api", "pallet-session", "pallet-staking", "pallet-stream-payment", @@ -4310,6 +4311,7 @@ dependencies = [ "pallet-relay-storage-roots", "pallet-root-testing", "pallet-services-payment", + "pallet-services-payment-runtime-api", "pallet-session", "pallet-stream-payment", "pallet-stream-payment-runtime-api", @@ -9133,6 +9135,14 @@ dependencies = [ "tp-traits", ] +[[package]] +name = "pallet-services-payment-runtime-api" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "sp-api", +] + [[package]] name = "pallet-session" version = "4.0.0-dev" @@ -13634,6 +13644,19 @@ dependencies = [ "serde", ] +[[package]] +name = "services-payment-rpc" +version = "0.1.0" +dependencies = [ + "futures 0.3.30", + "jsonrpsee", + "pallet-services-payment-runtime-api", + "parity-scale-codec", + "sc-client-api", + "sp-api", + "sp-runtime", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -15428,6 +15451,7 @@ dependencies = [ "sc-transaction-pool-api", "serde", "serde_json", + "services-payment-rpc", "sp-api", "sp-block-builder", "sp-blockchain", diff --git a/Cargo.toml b/Cargo.toml index ae30811a2..f0da3bcf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ pallet-pooled-staking = { path = "pallets/pooled-staking", default-features = fa pallet-registrar = { path = "pallets/registrar", default-features = false } pallet-registrar-runtime-api = { path = "pallets/registrar/rpc/runtime-api", default-features = false } pallet-services-payment = { path = "pallets/services-payment", default-features = false } +pallet-services-payment-runtime-api = { path = "pallets/services-payment/rpc/runtime-api", default-features = false } pallet-stream-payment = { path = "pallets/stream-payment", default-features = false } pallet-stream-payment-runtime-api = { path = "pallets/stream-payment/rpc/runtime-api", default-features = false } pallet-xcm-core-buyer = { path = "pallets/xcm-core-buyer", default-features = false } @@ -73,6 +74,7 @@ flashbox-runtime = { path = "runtime/flashbox", default-features = false } manual-xcm-rpc = { path = "client/manual-xcm" } node-common = { path = "client/node-common" } runtime-common = { path = "runtime/common", default-features = false } +services-payment-rpc = { path = "client/services-payment" } stream-payment-rpc = { path = "client/stream-payment" } tanssi-relay-encoder = { path = "runtime/relay-encoder", default-features = false } tc-consensus = { path = "client/consensus" } diff --git a/client/services-payment/Cargo.toml b/client/services-payment/Cargo.toml new file mode 100644 index 000000000..f64681418 --- /dev/null +++ b/client/services-payment/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "services-payment-rpc" +authors = { workspace = true } +description = "RPC interface for the Services Payment pallet" +edition = "2021" +license = "GPL-3.0-only" +version = "0.1.0" + +[package.metadata.docs.rs] +targets = [ "x86_64-unknown-linux-gnu" ] + +[lints] +workspace = true + +[dependencies] +futures = { workspace = true } +jsonrpsee = { workspace = true } +pallet-services-payment-runtime-api = { workspace = true, features = [ "std" ] } +parity-scale-codec = { workspace = true } +sc-client-api = { workspace = true } +sp-api = { workspace = true, features = [ "std" ] } +sp-runtime = { workspace = true, features = [ "std" ] } diff --git a/client/services-payment/src/lib.rs b/client/services-payment/src/lib.rs new file mode 100644 index 000000000..7ff984d63 --- /dev/null +++ b/client/services-payment/src/lib.rs @@ -0,0 +1,94 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see + +//! RPC client for Services Payment pallet + +pub use pallet_services_payment_runtime_api::ServicesPaymentApi as ServicesPaymentRuntimeApi; +use { + core::marker::PhantomData, + jsonrpsee::{ + core::{async_trait, RpcResult}, + proc_macros::rpc, + }, + sc_client_api::UsageProvider, + sp_api::ProvideRuntimeApi, + sp_runtime::traits::Block as BlockT, + std::sync::Arc, +}; + +#[rpc(server)] +pub trait ServicesPaymentApi { + #[method(name = "tanssi_servicesPaymentBlockCost")] + async fn block_cost(&self, para_id: ParaId) -> RpcResult; + + #[method(name = "tanssi_servicesPaymentCollatorAssignmentCost")] + async fn collator_assignment_cost(&self, para_id: ParaId) -> RpcResult; +} + +pub struct ServicesPayment { + client: Arc, + _phantom: PhantomData, +} + +impl ServicesPayment { + pub fn new(client: Arc) -> Self { + Self { + client, + _phantom: PhantomData, + } + } +} + +#[async_trait] +impl ServicesPaymentApiServer + for ServicesPayment +where + Hash: Send + 'static, + Block: BlockT, + Client: ProvideRuntimeApi + Sync + Send + UsageProvider + 'static, + Client::Api: ServicesPaymentRuntimeApi, + Balance: parity_scale_codec::Codec + Send + 'static, + ParaId: parity_scale_codec::Codec + Send + 'static, +{ + async fn block_cost(&self, para_id: ParaId) -> RpcResult { + let cost = self + .client + .runtime_api() + .block_cost(self.client.usage_info().chain.best_hash, para_id) + .map_err(|e| internal_err(e))?; + Ok(cost) + } + + async fn collator_assignment_cost(&self, para_id: ParaId) -> RpcResult { + let cost = self + .client + .runtime_api() + .collator_assignment_cost(self.client.usage_info().chain.best_hash, para_id) + .map_err(|e| internal_err(e))?; + Ok(cost) + } +} + +pub fn internal_err(error: T) -> jsonrpsee::core::Error { + jsonrpsee::core::Error::Call(jsonrpsee::types::error::CallError::Custom( + jsonrpsee::types::error::ErrorObject::borrowed( + jsonrpsee::types::error::INTERNAL_ERROR_CODE, + &error.to_string(), + None, + ) + .into_owned(), + )) +} diff --git a/node/Cargo.toml b/node/Cargo.toml index 1ee7bdf1d..560c7a78a 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -36,6 +36,7 @@ pallet-author-noting-runtime-api = { workspace = true, features = [ "std" ] } pallet-collator-assignment-runtime-api = { workspace = true, features = [ "std" ] } pallet-configuration = { workspace = true, features = [ "std" ] } pallet-registrar-runtime-api = { workspace = true, features = [ "std" ] } +services-payment-rpc = { workspace = true } stream-payment-rpc = { workspace = true } tp-author-noting-inherent = { workspace = true, features = [ "std" ] } tp-container-chain-genesis-data = { workspace = true, features = [ "json", "std" ] } diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 52bfa98b0..3e2fdc9a2 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -27,12 +27,15 @@ use { dancebox_runtime::{opaque::Block, AccountId, Index as Nonce}, manual_xcm_rpc::{ManualXcm, ManualXcmApiServer}, polkadot_primitives::Hash, - sc_client_api::AuxStore, + sc_client_api::{AuxStore, UsageProvider}, sc_consensus_manual_seal::{ rpc::{ManualSeal, ManualSealApiServer}, EngineCommand, }, sc_transaction_pool_api::TransactionPool, + services_payment_rpc::{ + ServicesPayment, ServicesPaymentApiServer as _, ServicesPaymentRuntimeApi, + }, sp_api::ProvideRuntimeApi, sp_block_builder::BlockBuilder, sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}, @@ -68,10 +71,12 @@ where + HeaderMetadata + Send + Sync + + UsageProvider + 'static, C::Api: substrate_frame_rpc_system::AccountNonceApi, C::Api: BlockBuilder, C::Api: StreamPaymentRuntimeApi, + C::Api: ServicesPaymentRuntimeApi, P: TransactionPool + Sync + Send + 'static, { use substrate_frame_rpc_system::{System, SystemApiServer}; @@ -86,7 +91,8 @@ where } = deps; module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; - module.merge(StreamPayment::<_, Block>::new(client).into_rpc())?; + module.merge(StreamPayment::<_, Block>::new(client.clone()).into_rpc())?; + module.merge(ServicesPayment::<_, Block>::new(client).into_rpc())?; if let Some(command_sink) = command_sink { module.merge( diff --git a/pallets/services-payment/rpc/runtime-api/Cargo.toml b/pallets/services-payment/rpc/runtime-api/Cargo.toml new file mode 100644 index 000000000..ab0042e3f --- /dev/null +++ b/pallets/services-payment/rpc/runtime-api/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "pallet-services-payment-runtime-api" +authors = { workspace = true } +description = "Runtime API definition of pallet-services-payment" +edition = "2021" +license = "GPL-3.0-only" +version = "0.1.0" + +[package.metadata.docs.rs] +targets = [ "x86_64-unknown-linux-gnu" ] + +[lints] +workspace = true + +[dependencies] +parity-scale-codec = { workspace = true } +sp-api = { workspace = true } + +[features] +default = [ "std" ] +std = [ + "parity-scale-codec/std", + "sp-api/std", +] diff --git a/pallets/services-payment/rpc/runtime-api/src/lib.rs b/pallets/services-payment/rpc/runtime-api/src/lib.rs new file mode 100644 index 000000000..ce98778f5 --- /dev/null +++ b/pallets/services-payment/rpc/runtime-api/src/lib.rs @@ -0,0 +1,30 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see + +//! Runtime API for Services Payment pallet + +#![cfg_attr(not(feature = "std"), no_std)] + +sp_api::decl_runtime_apis! { + pub trait ServicesPaymentApi + where + Balance: parity_scale_codec::Codec, + ParaId: parity_scale_codec::Codec, + { + fn block_cost(para_id: ParaId) -> Balance; + fn collator_assignment_cost(para_id: ParaId) -> Balance; + } +} diff --git a/runtime/dancebox/Cargo.toml b/runtime/dancebox/Cargo.toml index ec8ffcb45..9dfe63023 100644 --- a/runtime/dancebox/Cargo.toml +++ b/runtime/dancebox/Cargo.toml @@ -40,6 +40,7 @@ pallet-registrar = { workspace = true } pallet-registrar-runtime-api = { workspace = true } pallet-relay-storage-roots = { workspace = true } pallet-services-payment = { workspace = true } +pallet-services-payment-runtime-api = { workspace = true } pallet-stream-payment = { workspace = true } pallet-stream-payment-runtime-api = { workspace = true } pallet-xcm-core-buyer = { workspace = true } @@ -209,6 +210,7 @@ std = [ "pallet-registrar/std", "pallet-relay-storage-roots/std", "pallet-root-testing/std", + "pallet-services-payment-runtime-api/std", "pallet-services-payment/std", "pallet-session/std", "pallet-staking/std", diff --git a/runtime/dancebox/src/lib.rs b/runtime/dancebox/src/lib.rs index 5cff4fc30..4d4185f2f 100644 --- a/runtime/dancebox/src/lib.rs +++ b/runtime/dancebox/src/lib.rs @@ -2342,6 +2342,18 @@ impl_runtime_apis! { SLOT_DURATION } } + + impl pallet_services_payment_runtime_api::ServicesPaymentApi for Runtime { + fn block_cost(para_id: ParaId) -> Balance { + let (block_production_costs, _) = ::ProvideBlockProductionCost::block_cost(¶_id); + block_production_costs + } + + fn collator_assignment_cost(para_id: ParaId) -> Balance { + let (collator_assignment_costs, _) = ::ProvideCollatorAssignmentCost::collator_assignment_cost(¶_id); + collator_assignment_costs + } + } } struct CheckInherents; diff --git a/runtime/flashbox/Cargo.toml b/runtime/flashbox/Cargo.toml index bfae454fb..301b1a371 100644 --- a/runtime/flashbox/Cargo.toml +++ b/runtime/flashbox/Cargo.toml @@ -38,6 +38,7 @@ pallet-registrar = { workspace = true } pallet-registrar-runtime-api = { workspace = true } pallet-relay-storage-roots = { workspace = true } pallet-services-payment = { workspace = true } +pallet-services-payment-runtime-api = { workspace = true } pallet-stream-payment = { workspace = true } pallet-stream-payment-runtime-api = { workspace = true } runtime-common = { workspace = true } @@ -167,6 +168,7 @@ std = [ "pallet-registrar/std", "pallet-relay-storage-roots/std", "pallet-root-testing/std", + "pallet-services-payment-runtime-api/std", "pallet-services-payment/std", "pallet-session/std", "pallet-stream-payment-runtime-api/std", diff --git a/runtime/flashbox/src/lib.rs b/runtime/flashbox/src/lib.rs index 960209c01..6bca44669 100644 --- a/runtime/flashbox/src/lib.rs +++ b/runtime/flashbox/src/lib.rs @@ -1907,6 +1907,18 @@ impl_runtime_apis! { SLOT_DURATION } } + + impl pallet_services_payment_runtime_api::ServicesPaymentApi for Runtime { + fn block_cost(para_id: ParaId) -> Balance { + let (block_production_costs, _) = ::ProvideBlockProductionCost::block_cost(¶_id); + block_production_costs + } + + fn collator_assignment_cost(para_id: ParaId) -> Balance { + let (collator_assignment_costs, _) = ::ProvideCollatorAssignmentCost::collator_assignment_cost(¶_id); + collator_assignment_costs + } + } } struct CheckInherents; diff --git a/test/suites/common-tanssi/services-payment/test_services_payment_rpc.ts b/test/suites/common-tanssi/services-payment/test_services_payment_rpc.ts new file mode 100644 index 000000000..ad79cdf78 --- /dev/null +++ b/test/suites/common-tanssi/services-payment/test_services_payment_rpc.ts @@ -0,0 +1,25 @@ +import "@tanssi/api-augment"; +import { describeSuite, expect, customDevRpcRequest } from "@moonwall/cli"; + +describeSuite({ + id: "CT0609", + title: "Services payment RPC", + foundationMethods: "dev", + testCases: ({ it }) => { + it({ + id: "E01", + title: "Services payment RPC", + test: async function () { + try { + await customDevRpcRequest("tanssi_servicesPaymentBlockCost", []); + throw { message: "Should have returned an error" }; + } catch (e: any) { + expect(e.message.toString()).to.eq("No more params"); + } + + expect(await customDevRpcRequest("tanssi_servicesPaymentBlockCost", [1000])).eq(1000000); + expect(await customDevRpcRequest("tanssi_servicesPaymentCollatorAssignmentCost", [1000])).eq(100000000); + }, + }); + }, +}); From a741030de4c66ea91f934460c57c1f874d3fded9 Mon Sep 17 00:00:00 2001 From: Francisco Gamundi <52399794+fgamundi@users.noreply.github.com> Date: Mon, 13 May 2024 12:21:18 +0200 Subject: [PATCH 2/7] Remove runtime-benchmark cargo check on CI (#548) --- .github/workflows/release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ce8bd643b..ee966ff7e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -264,8 +264,6 @@ jobs: with: name: binaries path: binaries - - name: Check runtime benchmarks - run: cargo check --features=runtime-benchmarks --release --all rust-test: runs-on: self-hosted From d5c40beae3a7acebc466c66230429f67545660ef Mon Sep 17 00:00:00 2001 From: girazoki Date: Mon, 13 May 2024 12:37:36 +0200 Subject: [PATCH 3/7] Make some smoke tests more consistent (#549) * make inflation rewards more consistent * fix a few leftovers * differnt functions --- .../test-inflation-rewards.ts | 33 ++++++++++++------- .../test-invulnerables-priority.ts | 2 +- .../test-randomness-consistency.ts | 2 +- test/util/block.ts | 10 ++++++ 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/test/suites/smoke-test-common/test-inflation-rewards.ts b/test/suites/smoke-test-common/test-inflation-rewards.ts index c70327cdc..7d69b945f 100644 --- a/test/suites/smoke-test-common/test-inflation-rewards.ts +++ b/test/suites/smoke-test-common/test-inflation-rewards.ts @@ -1,8 +1,9 @@ import { beforeAll, describeSuite, expect } from "@moonwall/cli"; - import { ApiPromise } from "@polkadot/api"; + +import { ApiDecoration } from "@polkadot/api/types"; import { getAuthorFromDigest } from "util/author"; -import { fetchIssuance, filterRewardFromOrchestrator, fetchRewardAuthorContainers } from "util/block"; +import { fetchIssuance, filterRewardFromOrchestratorWithFailure, fetchRewardAuthorContainers } from "util/block"; import { PARACHAIN_BOND } from "util/constants"; describeSuite({ @@ -10,11 +11,19 @@ describeSuite({ title: "Sample suite that only runs on Dancebox chains", foundationMethods: "read_only", testCases: ({ it, context }) => { + let apiAt: ApiDecoration<"promise">; let api: ApiPromise; + let runtimeVersion; - beforeAll(() => { + beforeAll(async () => { api = context.polkadotJs(); + const latestBlock = await api.rpc.chain.getBlock(); + const latestBlockHash = latestBlock.block.hash; + + // ApiAt to evaluate rewards, otherwise orchestrator reward might not be correct + apiAt = await api.at(latestBlockHash); + runtimeVersion = api.runtimeVersion.specVersion.toNumber(); }); @@ -25,18 +34,20 @@ describeSuite({ if (runtimeVersion < 300) { return; } - const author = await getAuthorFromDigest(api); + + const author = await getAuthorFromDigest(apiAt); + const events = await apiAt.query.system.events(); + // Fetch current session - const currentSession = await api.query.session.currentIndex(); - const keys = await api.query.authorityMapping.authorityIdMapping(currentSession); + const currentSession = await apiAt.query.session.currentIndex(); + const keys = await apiAt.query.authorityMapping.authorityIdMapping(currentSession); const account = keys.toJSON()[author]; // 70% is distributed across all rewards - const events = await api.query.system.events(); const issuance = await fetchIssuance(events).amount.toBigInt(); const chainRewards = (issuance * 7n) / 10n; - const numberOfChains = await api.query.registrar.registeredParaIds(); + const numberOfChains = await apiAt.query.registrar.registeredParaIds(); const expectedOrchestratorReward = chainRewards / BigInt(numberOfChains.length + 1); - const reward = await filterRewardFromOrchestrator(events, account); + const reward = await filterRewardFromOrchestratorWithFailure(events, account); // we know there might be rounding errors, so we always check it is in the range +-1 expect( reward >= expectedOrchestratorReward - 1n && reward <= expectedOrchestratorReward + 1n, @@ -53,10 +64,10 @@ describeSuite({ return; } // 70% is distributed across all rewards - const events = await api.query.system.events(); + const events = await apiAt.query.system.events(); const issuance = await fetchIssuance(events).amount.toBigInt(); const chainRewards = (issuance * 7n) / 10n; - const numberOfChains = await api.query.registrar.registeredParaIds(); + const numberOfChains = await apiAt.query.registrar.registeredParaIds(); const expectedChainReward = chainRewards / BigInt(numberOfChains.length + 1); const rewardEvents = await fetchRewardAuthorContainers(events); for (const index in rewardEvents) { diff --git a/test/suites/smoke-test-dancebox/test-invulnerables-priority.ts b/test/suites/smoke-test-dancebox/test-invulnerables-priority.ts index 4235f5625..47293c578 100644 --- a/test/suites/smoke-test-dancebox/test-invulnerables-priority.ts +++ b/test/suites/smoke-test-dancebox/test-invulnerables-priority.ts @@ -22,7 +22,7 @@ describeSuite({ return; } - const sessionLength = 300; + const sessionLength = 600; const currentBlock = await api.rpc.chain.getBlock(); const currentBlockNumber = currentBlock.block.header.number.toNumber(); diff --git a/test/suites/smoke-test-dancebox/test-randomness-consistency.ts b/test/suites/smoke-test-dancebox/test-randomness-consistency.ts index 325626e02..db70abcd6 100644 --- a/test/suites/smoke-test-dancebox/test-randomness-consistency.ts +++ b/test/suites/smoke-test-dancebox/test-randomness-consistency.ts @@ -22,7 +22,7 @@ describeSuite({ if (runtimeVersion < 300) { return; } - const sessionLength = 300; + const sessionLength = 600; const currentBlock = (await api.rpc.chain.getBlock()).block.header.number.toNumber(); const randomness = await api.query.collatorAssignment.randomness(); diff --git a/test/util/block.ts b/test/util/block.ts index ec3cd9621..1238275dd 100644 --- a/test/util/block.ts +++ b/test/util/block.ts @@ -200,6 +200,16 @@ export function fetchCollatorAssignmentTip(events: EventRecord[] = []) { return filtered[0]; } +export function filterRewardFromOrchestratorWithFailure(events: EventRecord[] = [], author: string) { + const reward = fetchRewardAuthorOrchestrator(events); + expect(reward, `orchestrator rewards event not found`).not.toBe(undefined); + expect( + reward.accountId.toString() === author, + `orchestrator author ${reward.accountId.toString()} does not match expected author ${author}` + ).to.be.true; + return reward.balance.toBigInt(); +} + export function filterRewardFromOrchestrator(events: EventRecord[] = [], author: string) { const reward = fetchRewardAuthorOrchestrator(events); if (reward === undefined || reward.accountId.toString() !== author) { From 35252a9c969e408bd3f4b20eddccd3c8acb70930 Mon Sep 17 00:00:00 2001 From: girazoki Date: Mon, 13 May 2024 14:18:17 +0200 Subject: [PATCH 4/7] increase rust toolchain (#502) * increase rust toolchain * fix runtime bench * allow deadcode * stablizie in v4 * comply with new rsut vers * fix tests * increment to 1.78 * fmt & clippy * new fixeS * remove tansis slot worker * changes2 * allow dead code in chec-inherents for now just in case * fmt * non-used * fmt --- client/consensus/src/collators.rs | 2 +- client/consensus/src/collators/lookahead.rs | 8 +-- .../consensus/src/consensus_orchestrator.rs | 16 ----- client/consensus/src/tests.rs | 20 +++---- container-chains/nodes/frontier/src/client.rs | 60 ------------------- container-chains/nodes/frontier/src/eth.rs | 33 ---------- container-chains/nodes/frontier/src/main.rs | 2 - .../runtime-templates/frontier/src/lib.rs | 1 + .../runtime-templates/simple/src/lib.rs | 1 + node/src/chain_spec/dancebox.rs | 19 ------ node/src/chain_spec/flashbox.rs | 19 ------ pallets/authority-assignment/src/mock.rs | 4 -- pallets/initializer/src/lib.rs | 20 +++---- pallets/invulnerables/src/benchmarking.rs | 1 + pallets/pooled-staking/src/pools.rs | 1 + pallets/registrar/src/benchmarks.rs | 2 +- pallets/registrar/src/lib.rs | 4 +- pallets/xcm-core-buyer/src/mock.rs | 22 +------ runtime/dancebox/src/lib.rs | 1 + runtime/flashbox/src/lib.rs | 1 + rust-toolchain | 2 +- 21 files changed, 36 insertions(+), 203 deletions(-) delete mode 100644 container-chains/nodes/frontier/src/client.rs delete mode 100644 container-chains/nodes/frontier/src/eth.rs diff --git a/client/consensus/src/collators.rs b/client/consensus/src/collators.rs index c916b954a..f5ac64b57 100644 --- a/client/consensus/src/collators.rs +++ b/client/consensus/src/collators.rs @@ -363,7 +363,7 @@ where } /// Attempt to claim a slot using a keystore. -pub fn claim_slot_inner( +pub fn claim_slot_inner

( slot: Slot, authorities: &Vec>, keystore: &KeystorePtr, diff --git a/client/consensus/src/collators/lookahead.rs b/client/consensus/src/collators/lookahead.rs index 8d9f6e11d..611ff3bfd 100644 --- a/client/consensus/src/collators/lookahead.rs +++ b/client/consensus/src/collators/lookahead.rs @@ -464,10 +464,10 @@ where // Here we lean on the property that building on an empty unincluded segment must always // be legal. Skipping the runtime API query here allows us to seamlessly run this // collator against chains which have not yet upgraded their runtime. - if parent_header.hash() != included_block { - if !runtime_api.can_build_upon(parent_header.hash(), included_block, slot)? { - return Ok(None); - } + if parent_header.hash() != included_block + && !runtime_api.can_build_upon(parent_header.hash(), included_block, slot)? + { + return Ok(None); } slot_claim diff --git a/client/consensus/src/consensus_orchestrator.rs b/client/consensus/src/consensus_orchestrator.rs index f941b8c98..04d938829 100644 --- a/client/consensus/src/consensus_orchestrator.rs +++ b/client/consensus/src/consensus_orchestrator.rs @@ -22,8 +22,6 @@ //! it implements the TanssiWorker to TanssiOnSlot trait. This trait is use { crate::{AuthorityId, Pair, Slot}, - sc_consensus_slots::{SimpleSlotWorker, SlotInfo, SlotResult}, - sp_consensus::Proposer, sp_runtime::traits::Block as BlockT, }; @@ -63,17 +61,3 @@ where pub authorities: Vec>, pub min_slot_freq: Option, } - -#[async_trait::async_trait] -pub trait TanssiSlotWorker: SimpleSlotWorker { - /// Called when a new slot is triggered. - /// - /// Returns a future that resolves to a [`SlotResult`] iff a block was successfully built in - /// the slot. Otherwise `None` is returned. - /// Accepts the orchestrator header as an input - async fn tanssi_on_slot( - &mut self, - slot_info: SlotInfo, - aux_data: Self::AuxData, - ) -> Option>::Proof>>; -} diff --git a/client/consensus/src/tests.rs b/client/consensus/src/tests.rs index 614364478..025ecac0b 100644 --- a/client/consensus/src/tests.rs +++ b/client/consensus/src/tests.rs @@ -133,7 +133,7 @@ sp_api::mock_impl_runtime_apis! { } #[derive(Clone)] -struct RelayChain(Arc); +struct RelayChain; #[async_trait] impl RelayChainInterface for RelayChain { @@ -252,7 +252,7 @@ impl RelayChainInterface for RelayChain { } #[derive(Clone)] -struct DummySpawner(Arc); +struct DummySpawner; impl SpawnNamed for DummySpawner { fn spawn_blocking( &self, @@ -271,7 +271,7 @@ impl SpawnNamed for DummySpawner { } } -struct DummyProposer(u64, Arc); +struct DummyProposer(Arc); // This is going to be our block verifier // It will mimic what the Nimbus verifier does, but again, Nimbus verifier is non-public @@ -354,8 +354,8 @@ impl Environment for DummyFactory { type CreateProposer = future::Ready>; type Error = Error; - fn init(&mut self, parent_header: &::Header) -> Self::CreateProposer { - future::ready(Ok(DummyProposer(parent_header.number + 1, self.0.clone()))) + fn init(&mut self, _parent_header: &::Header) -> Self::CreateProposer { + future::ready(Ok(DummyProposer(self.0.clone()))) } } @@ -373,9 +373,9 @@ impl Proposer for DummyProposer { _: Duration, _: Option, ) -> Self::Proposal { - let r = BlockBuilderBuilder::new(&*self.1) - .on_parent_block(self.1.chain_info().best_hash) - .fetch_parent_block_number(&*self.1) + let r = BlockBuilderBuilder::new(&*self.0) + .on_parent_block(self.0.chain_info().best_hash) + .fetch_parent_block_number(&*self.0) .unwrap() .with_inherent_digests(digests) .build() @@ -562,8 +562,8 @@ async fn collate_returns_correct_block() { let peer = net.peer(3); let client = peer.client().as_client(); let environ = DummyFactory(client.clone()); - let spawner = DummySpawner(client.clone()); - let relay_client = RelayChain(client.clone()); + let spawner = DummySpawner; + let relay_client = RelayChain; // Build the collator let mut collator = { diff --git a/container-chains/nodes/frontier/src/client.rs b/container-chains/nodes/frontier/src/client.rs deleted file mode 100644 index 49b3c41f9..000000000 --- a/container-chains/nodes/frontier/src/client.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) Moondance Labs Ltd. -// This file is part of Tanssi. - -// Tanssi is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Tanssi is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Tanssi. If not, see . - -// Substrate -use sp_consensus_aura::sr25519::AuthorityId as AuraId; -// Local -use container_chain_template_frontier_runtime::{opaque::Block, AccountId, Index}; - -use crate::eth::EthCompatRuntimeApiCollection; - -/// A set of APIs that every runtimes must implement. -pub trait BaseRuntimeApiCollection: - sp_api::ApiExt - + sp_api::Metadata - + sp_block_builder::BlockBuilder - + sp_offchain::OffchainWorkerApi - + sp_session::SessionKeys - + sp_transaction_pool::runtime_api::TaggedTransactionQueue -{ -} - -impl BaseRuntimeApiCollection for Api where - Api: sp_api::ApiExt - + sp_api::Metadata - + sp_block_builder::BlockBuilder - + sp_offchain::OffchainWorkerApi - + sp_session::SessionKeys - + sp_transaction_pool::runtime_api::TaggedTransactionQueue -{ -} - -/// A set of APIs that template runtime must implement. -pub trait RuntimeApiCollection: - BaseRuntimeApiCollection - + EthCompatRuntimeApiCollection - + sp_consensus_aura::AuraApi - + frame_system_rpc_runtime_api::AccountNonceApi -{ -} - -impl RuntimeApiCollection for Api where - Api: BaseRuntimeApiCollection - + EthCompatRuntimeApiCollection - + sp_consensus_aura::AuraApi - + frame_system_rpc_runtime_api::AccountNonceApi -{ -} diff --git a/container-chains/nodes/frontier/src/eth.rs b/container-chains/nodes/frontier/src/eth.rs deleted file mode 100644 index 2ddf51e76..000000000 --- a/container-chains/nodes/frontier/src/eth.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) Moondance Labs Ltd. -// This file is part of Tanssi. - -// Tanssi is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Tanssi is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Tanssi. If not, see . - -// Local -use container_chain_template_frontier_runtime::opaque::Block; - -/// A set of APIs that ethereum-compatible runtimes must implement. -pub trait EthCompatRuntimeApiCollection: - sp_api::ApiExt - + fp_rpc::EthereumRuntimeRPCApi - + fp_rpc::ConvertTransactionRuntimeApi -{ -} - -impl EthCompatRuntimeApiCollection for Api where - Api: sp_api::ApiExt - + fp_rpc::EthereumRuntimeRPCApi - + fp_rpc::ConvertTransactionRuntimeApi -{ -} diff --git a/container-chains/nodes/frontier/src/main.rs b/container-chains/nodes/frontier/src/main.rs index b5163b5df..984f332e0 100644 --- a/container-chains/nodes/frontier/src/main.rs +++ b/container-chains/nodes/frontier/src/main.rs @@ -20,9 +20,7 @@ mod chain_spec; mod cli; -mod client; mod command; -mod eth; mod rpc; mod service; diff --git a/container-chains/runtime-templates/frontier/src/lib.rs b/container-chains/runtime-templates/frontier/src/lib.rs index e55d56bb2..b369b3a0c 100644 --- a/container-chains/runtime-templates/frontier/src/lib.rs +++ b/container-chains/runtime-templates/frontier/src/lib.rs @@ -1524,6 +1524,7 @@ impl_runtime_apis! { } } +#[allow(dead_code)] struct CheckInherents; // TODO: this should be removed but currently if we remove it the relay does not check anything diff --git a/container-chains/runtime-templates/simple/src/lib.rs b/container-chains/runtime-templates/simple/src/lib.rs index 702981e5f..03a450db3 100644 --- a/container-chains/runtime-templates/simple/src/lib.rs +++ b/container-chains/runtime-templates/simple/src/lib.rs @@ -1099,6 +1099,7 @@ impl_runtime_apis! { } } +#[allow(dead_code)] struct CheckInherents; #[allow(deprecated)] diff --git a/node/src/chain_spec/dancebox.rs b/node/src/chain_spec/dancebox.rs index 29fbaacef..1d1c92671 100644 --- a/node/src/chain_spec/dancebox.rs +++ b/node/src/chain_spec/dancebox.rs @@ -288,22 +288,3 @@ fn mock_container_chain_genesis_data>( properties: Default::default(), } } - -/// Can be called for a `Configuration` to check if it is a configuration for -/// the `Tanssi` network. -pub trait IdentifyVariant { - /// Returns `true` if this is a configuration for the `Dancebox` network. - fn is_dancebox(&self) -> bool; - /// Returns `true` if this is a configuration for a dev network. - fn is_dev(&self) -> bool; -} - -impl IdentifyVariant for Box { - fn is_dancebox(&self) -> bool { - self.id().starts_with("dancebox") - } - - fn is_dev(&self) -> bool { - self.chain_type() == sc_chain_spec::ChainType::Development - } -} diff --git a/node/src/chain_spec/flashbox.rs b/node/src/chain_spec/flashbox.rs index ab45835cb..48593555c 100644 --- a/node/src/chain_spec/flashbox.rs +++ b/node/src/chain_spec/flashbox.rs @@ -286,22 +286,3 @@ fn mock_container_chain_genesis_data>( properties: Default::default(), } } - -/// Can be called for a `Configuration` to check if it is a configuration for -/// the `Tanssi` network. -pub trait IdentifyVariant { - /// Returns `true` if this is a configuration for the `Flashbox` network. - fn is_flashbox(&self) -> bool; - /// Returns `true` if this is a configuration for a dev network. - fn is_dev(&self) -> bool; -} - -impl IdentifyVariant for Box { - fn is_flashbox(&self) -> bool { - self.id().starts_with("flashbox") - } - - fn is_dev(&self) -> bool { - self.chain_type() == sc_chain_spec::ChainType::Development - } -} diff --git a/pallets/authority-assignment/src/mock.rs b/pallets/authority-assignment/src/mock.rs index 4e0d47b45..44bf6eac7 100644 --- a/pallets/authority-assignment/src/mock.rs +++ b/pallets/authority-assignment/src/mock.rs @@ -126,10 +126,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .into() } -pub trait GetCollators { - fn collators(session_index: SessionIndex) -> Vec; -} - pub const SESSION_LEN: u64 = 5; pub fn run_to_session(n: u32) { diff --git a/pallets/initializer/src/lib.rs b/pallets/initializer/src/lib.rs index 951a00205..60f622f04 100644 --- a/pallets/initializer/src/lib.rs +++ b/pallets/initializer/src/lib.rs @@ -73,13 +73,13 @@ pub mod pallet { impl Pallet { /// Should be called when a new session occurs. If `queued` is `None`, /// the `validators` are considered queued. - fn on_new_session<'a, I: 'a>( + fn on_new_session<'a, I>( changed: bool, session_index: T::SessionIndex, validators: I, queued: Option, ) where - I: Iterator, + I: Iterator + 'a, { let validators: Vec<_> = validators.map(|(k, v)| (k.clone(), v)).collect(); let queued: Vec<_> = if let Some(queued) = queued { @@ -93,9 +93,9 @@ impl Pallet { /// Should be called when a new session occurs. Buffers the session notification to be applied /// at the end of the block. If `queued` is `None`, the `validators` are considered queued. - fn on_genesis_session<'a, I: 'a>(validators: I) + fn on_genesis_session<'a, I>(validators: I) where - I: Iterator, + I: Iterator + 'a, { >::on_new_session(false, 0u32.into(), validators, None); } @@ -103,13 +103,13 @@ impl Pallet { // Allow to trigger `on_new_session` in tests, this is needed as long as `pallet_session` is not // implemented in mock. #[cfg(any(test, feature = "runtime-benchmarks"))] - pub(crate) fn test_trigger_on_new_session<'a, I: 'a>( + pub(crate) fn test_trigger_on_new_session<'a, I>( changed: bool, session_index: T::SessionIndex, validators: I, queued: Option, ) where - I: Iterator, + I: Iterator + 'a, { Self::on_new_session(changed, session_index, validators, queued) } @@ -122,16 +122,16 @@ impl sp_runtime::BoundToRuntimeAppPublic for Pallet { impl OneSessionHandler for Pallet { type Key = T::AuthorityId; - fn on_genesis_session<'a, I: 'a>(validators: I) + fn on_genesis_session<'a, I>(validators: I) where - I: Iterator, + I: Iterator + 'a, { >::on_genesis_session(validators); } - fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued: I) + fn on_new_session<'a, I>(changed: bool, validators: I, queued: I) where - I: Iterator, + I: Iterator + 'a, { let session_index = >::current_index(); >::on_new_session(changed, session_index.into(), validators, Some(queued)); diff --git a/pallets/invulnerables/src/benchmarking.rs b/pallets/invulnerables/src/benchmarking.rs index 1e92d253e..a80683a32 100644 --- a/pallets/invulnerables/src/benchmarking.rs +++ b/pallets/invulnerables/src/benchmarking.rs @@ -112,6 +112,7 @@ pub(crate) fn currency_issue( <::Currency as Balanced>::issue(amount) } +#[allow(clippy::multiple_bound_locations)] #[benchmarks(where T: session::Config + pallet_balances::Config, BalanceOf: AtLeast32BitUnsigned)] mod benchmarks { use super::*; diff --git a/pallets/pooled-staking/src/pools.rs b/pallets/pooled-staking/src/pools.rs index 081a46676..d230919de 100644 --- a/pallets/pooled-staking/src/pools.rs +++ b/pallets/pooled-staking/src/pools.rs @@ -30,6 +30,7 @@ use { tp_maths::{ErrAdd, ErrMul, ErrSub, MulDiv}, }; +#[allow(dead_code)] pub trait Pool { /// Get the amount of shares a delegator have for given candidate. fn shares(candidate: &Candidate, delegator: &Delegator) -> Shares; diff --git a/pallets/registrar/src/benchmarks.rs b/pallets/registrar/src/benchmarks.rs index 8b89541bb..8298d41ee 100644 --- a/pallets/registrar/src/benchmarks.rs +++ b/pallets/registrar/src/benchmarks.rs @@ -40,7 +40,7 @@ fn create_funded_user( let min_reserve_amount = T::DepositAmount::get(); let total = min_reserve_amount + extra; T::Currency::make_free_balance_be(&user, total); - T::Currency::issue(total); + let _ = T::Currency::issue(total); (user, total) } diff --git a/pallets/registrar/src/lib.rs b/pallets/registrar/src/lib.rs index de981de26..4a0b6dfda 100644 --- a/pallets/registrar/src/lib.rs +++ b/pallets/registrar/src/lib.rs @@ -625,7 +625,7 @@ pub mod pallet { const SEED: u32 = 0; let user = account(string, n, SEED); T::Currency::make_free_balance_be(&user, total); - T::Currency::issue(total); + let _ = T::Currency::issue(total); (user, total) } let new_balance = @@ -641,7 +641,7 @@ pub mod pallet { let new_balance = (T::Currency::minimum_balance() + T::DepositAmount::get()) * 2u32.into(); T::Currency::make_free_balance_be(&deposit_info.creator, new_balance); - T::Currency::issue(new_balance); + let _ = T::Currency::issue(new_balance); deposit_info.creator } diff --git a/pallets/xcm-core-buyer/src/mock.rs b/pallets/xcm-core-buyer/src/mock.rs index 418b453bb..4ea806213 100644 --- a/pallets/xcm-core-buyer/src/mock.rs +++ b/pallets/xcm-core-buyer/src/mock.rs @@ -29,7 +29,7 @@ use { sp_core::H256, sp_io::TestExternalities, sp_runtime::{ - traits::{BlakeTwo256, Convert, IdentityLookup}, + traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }, sp_std::collections::btree_map::BTreeMap, @@ -228,26 +228,6 @@ impl GetParathreadCollators for GetAssignedCollatorsImpl { } } -pub struct GetBlockNumber; - -impl Get for GetBlockNumber { - fn get() -> u32 { - System::block_number() as u32 - } -} - -pub struct ParaIdToAccount32; - -impl Convert for ParaIdToAccount32 { - fn convert(para_id: ParaId) -> [u8; 32] { - let mut res = [0; 32]; - - res[..4].copy_from_slice(&u32::from(para_id).to_le_bytes()); - - res - } -} - pub struct EncodedCallToBuyCore; impl GetPurchaseCoreCall<()> for EncodedCallToBuyCore { diff --git a/runtime/dancebox/src/lib.rs b/runtime/dancebox/src/lib.rs index 4d4185f2f..72f2cdc6a 100644 --- a/runtime/dancebox/src/lib.rs +++ b/runtime/dancebox/src/lib.rs @@ -2356,6 +2356,7 @@ impl_runtime_apis! { } } +#[allow(dead_code)] struct CheckInherents; // TODO: this should be removed but currently if we remove it the relay does not check anything diff --git a/runtime/flashbox/src/lib.rs b/runtime/flashbox/src/lib.rs index 6bca44669..5d75deea7 100644 --- a/runtime/flashbox/src/lib.rs +++ b/runtime/flashbox/src/lib.rs @@ -1921,6 +1921,7 @@ impl_runtime_apis! { } } +#[allow(dead_code)] struct CheckInherents; // TODO: this should be removed but currently if we remove it the relay does not check anything diff --git a/rust-toolchain b/rust-toolchain index fa4029d55..6d7617d1a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,5 +1,5 @@ [toolchain] -channel = "1.75.0" +channel = "1.78.0" components = [ "rustfmt", "clippy", "rust-src" ] targets = [ "wasm32-unknown-unknown" ] profile = "minimal" From d6f2905dc4c4f4827c5efbb9f5f5f088a2782e68 Mon Sep 17 00:00:00 2001 From: Parth Date: Mon, 13 May 2024 16:25:26 +0400 Subject: [PATCH 5/7] Modifying xcm-core-buyer to add reporting of the core purchase (#516) * modifying xcm-core-buyer to add reporting of the core purchase * add query id in BuyCoreXCMSent + add more tests for storage mutations * fix assert_expected_events macro + add xcm notification check * fix tests for delivery fees * use transaction status + add tests * add more unit tests + fix a bug regarding pending block production check * add proper constant for pending block map size * add accurate benchmarks * fix typescript test + api interfaces --------- Co-authored-by: girazoki --- Cargo.lock | 1 + pallets/xcm-core-buyer/Cargo.toml | 5 + pallets/xcm-core-buyer/src/benchmarks.rs | 130 ++++++- pallets/xcm-core-buyer/src/lib.rs | 314 ++++++++++++++-- pallets/xcm-core-buyer/src/mock.rs | 32 +- pallets/xcm-core-buyer/src/tests.rs | 347 +++++++++++++++++- pallets/xcm-core-buyer/src/weights.rs | 198 ++++++++-- runtime/dancebox/src/lib.rs | 4 +- .../src/weights/pallet_xcm_core_buyer.rs | 91 ++++- runtime/dancebox/src/xcm_config.rs | 42 ++- .../dancebox/tests/common/xcm/core_buyer.rs | 248 ++++++++++++- .../tests/common/xcm/delivery_fees.rs | 14 +- .../common/xcm/expected_event_checker.rs | 103 ++++++ .../xcm/foreign_signed_based_sovereign.rs | 1 + .../tests/common/xcm/foreign_sovereigns.rs | 1 + runtime/dancebox/tests/common/xcm/mod.rs | 5 +- .../xcm/reserver_transfers_polkadot_xcm.rs | 1 + ...derivative_reception_container_dancebox.rs | 1 + ...e_reception_dancebox_frontier_container.rs | 1 + ...ive_reception_dancebox_simple_container.rs | 1 + ...ken_derivative_reception_relay_dancebox.rs | 1 + ...tive_reception_relay_frontier_container.rs | 1 + ...vative_reception_relay_simple_container.rs | 1 + runtime/dancebox/tests/common/xcm/transact.rs | 1 + runtime/dancebox/tests/common/xcm/trap.rs | 1 + .../test_set_latest_author_data_weight.ts | 2 +- .../dancebox/interfaces/augment-api-consts.ts | 13 +- .../dancebox/interfaces/augment-api-errors.ts | 8 + .../dancebox/interfaces/augment-api-events.ts | 16 +- .../dancebox/interfaces/augment-api-query.ts | 23 +- .../src/dancebox/interfaces/augment-api-tx.ts | 30 ++ .../src/dancebox/interfaces/lookup.ts | 291 ++++++++------- .../src/dancebox/interfaces/registry.ts | 2 + .../src/dancebox/interfaces/types-lookup.ts | 319 +++++++++------- 34 files changed, 1841 insertions(+), 408 deletions(-) create mode 100644 runtime/dancebox/tests/common/xcm/expected_event_checker.rs diff --git a/Cargo.lock b/Cargo.lock index 2c9a3c7fd..a44d1c25d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9561,6 +9561,7 @@ dependencies = [ "nimbus-primitives", "num-traits", "pallet-balances", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", diff --git a/pallets/xcm-core-buyer/Cargo.toml b/pallets/xcm-core-buyer/Cargo.toml index fe4a69424..8e842dd17 100644 --- a/pallets/xcm-core-buyer/Cargo.toml +++ b/pallets/xcm-core-buyer/Cargo.toml @@ -17,6 +17,7 @@ serde = { workspace = true, optional = true } tp-traits = { workspace = true } # Polkadot +pallet-xcm = { workspace = true } staging-xcm = { workspace = true } # Substrate @@ -51,6 +52,7 @@ std = [ "log/std", "nimbus-primitives/std", "pallet-balances/std", + "pallet-xcm/std", "parity-scale-codec/std", "scale-info/std", "serde", @@ -60,6 +62,7 @@ std = [ "sp-runtime/std", "sp-std/std", "staging-xcm/std", + "staging-xcm/std", "tp-traits/std", ] runtime-benchmarks = [ @@ -69,6 +72,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "nimbus-primitives/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "tp-traits/runtime-benchmarks", ] @@ -77,5 +81,6 @@ try-runtime = [ "frame-system/try-runtime", "nimbus-primitives/try-runtime", "pallet-balances/try-runtime", + "pallet-xcm/try-runtime", "sp-runtime/try-runtime", ] diff --git a/pallets/xcm-core-buyer/src/benchmarks.rs b/pallets/xcm-core-buyer/src/benchmarks.rs index c8e9d62d2..70a6d55a0 100644 --- a/pallets/xcm-core-buyer/src/benchmarks.rs +++ b/pallets/xcm-core-buyer/src/benchmarks.rs @@ -24,21 +24,25 @@ use { }, core::marker::PhantomData, frame_benchmarking::{account, v2::*}, - frame_support::{assert_ok, pallet_prelude::Weight, BoundedBTreeSet}, + frame_support::{assert_ok, pallet_prelude::Weight, BoundedVec}, frame_system::RawOrigin, - sp_std::{collections::btree_set::BTreeSet, vec}, + sp_std::vec, tp_traits::{ParaId, ParathreadParams, SlotFrequency}, }; pub const BUY_EXECUTION_COST: u128 = 50_000_000; pub const PLACE_ORDER_WEIGHT_AT_MOST: Weight = Weight::from_parts(1_000_000_000, 100_000); -#[benchmarks] +#[benchmarks(where ::RuntimeOrigin: From)] mod benchmarks { use super::*; + use crate::{InFlightCoreBuyingOrder, PendingBlocks, QueryIdToParaId}; + use frame_system::pallet_prelude::BlockNumberFor; + use staging_xcm::latest::{MaybeErrorCode, QueryId}; + use staging_xcm::v3::{MultiLocation, Response}; #[benchmark] - fn force_buy_core(x: Linear<1, 99>) { + fn force_buy_core() { assert_ok!(Pallet::::set_relay_xcm_weight_config( RawOrigin::Root.into(), Some(RelayXcmWeightConfigInner { @@ -48,15 +52,24 @@ mod benchmarks { }), )); - let para_id = ParaId::from(x + 1); - assert_eq!(InFlightOrders::::get(), BTreeSet::new()); + let x = 1000u32; - // Mock `x` xcm messages already sent in this block - let bbs: BoundedBTreeSet = BTreeSet::from_iter((0..x).map(ParaId::from)) - .try_into() - .expect("x is greater than MaxParathreads"); - InFlightOrders::::put(bbs); - assert!(!InFlightOrders::::get().contains(¶_id)); + let para_id = ParaId::from(x + 1); + for i in 0..=x { + InFlightOrders::::set( + ParaId::from(i), + Some(InFlightCoreBuyingOrder { + para_id: ParaId::from(i), + query_id: QueryId::from(i), + ttl: >::block_number() + + BlockNumberFor::::from(100u32), + }), + ); + + QueryIdToParaId::::set(QueryId::from(i), Some(ParaId::from(i))); + } + + assert!(InFlightOrders::::get(para_id).is_none()); // For the extrinsic to succeed, we need to ensure that: // * the para_id is a parathread @@ -73,7 +86,98 @@ mod benchmarks { #[extrinsic_call] Pallet::::force_buy_core(RawOrigin::Root, para_id); - assert!(InFlightOrders::::get().contains(¶_id)); + assert!(InFlightOrders::::get(para_id).is_some()); + } + + #[benchmark] + fn query_response() { + let x = 1000u32; + + let para_id = ParaId::from(x); + for i in 0..=x { + InFlightOrders::::set( + ParaId::from(i), + Some(InFlightCoreBuyingOrder { + para_id: ParaId::from(i), + query_id: QueryId::from(i), + ttl: >::block_number() + + BlockNumberFor::::from(100u32), + }), + ); + + QueryIdToParaId::::set(QueryId::from(i), Some(ParaId::from(i))); + } + + assert!(InFlightOrders::::get(para_id).is_some()); + + let response = if x % 2 == 0 { + Response::DispatchResult(MaybeErrorCode::Success) + } else { + Response::DispatchResult(MaybeErrorCode::Error(BoundedVec::default())) + }; + let xcm_origin = pallet_xcm::Origin::Response(MultiLocation::here()); + + #[extrinsic_call] + Pallet::::query_response(xcm_origin, QueryId::from(x), response); + + assert!(InFlightOrders::::get(para_id).is_none()); + assert!(QueryIdToParaId::::get(QueryId::from(x)).is_none()); + + if x % 2 == 0 { + assert!(PendingBlocks::::get(para_id).is_some()); + } else { + assert!(PendingBlocks::::get(para_id).is_none()); + } + } + + #[benchmark] + fn clean_up_expired_in_flight_orders(x: Linear<1, 1000>) { + let caller: T::AccountId = whitelisted_caller(); + for i in 0..=x { + InFlightOrders::::set( + ParaId::from(i), + Some(InFlightCoreBuyingOrder { + para_id: ParaId::from(i), + query_id: QueryId::from(i), + ttl: BlockNumberFor::::from(0u32), + }), + ); + + QueryIdToParaId::::set(QueryId::from(i), Some(ParaId::from(i))); + } + + let para_ids_to_clean_up = (0..=x).map(ParaId::from).collect(); + + #[extrinsic_call] + Pallet::::clean_up_expired_in_flight_orders( + RawOrigin::Signed(caller), + para_ids_to_clean_up, + ); + + for i in 0..=x { + assert!(InFlightOrders::::get(ParaId::from(i)).is_none()); + assert!(QueryIdToParaId::::get(QueryId::from(i)).is_none()); + } + } + + #[benchmark] + fn clean_up_expired_pending_blocks(x: Linear<1, 1000>) { + let caller: T::AccountId = whitelisted_caller(); + for i in 0..=x { + PendingBlocks::::set(ParaId::from(i), Some(BlockNumberFor::::from(0u32))); + } + + let para_ids_to_clean_up = (0..=x).map(ParaId::from).collect(); + + #[extrinsic_call] + Pallet::::clean_up_expired_pending_blocks( + RawOrigin::Signed(caller), + para_ids_to_clean_up, + ); + + for i in 0..=x { + assert!(PendingBlocks::::get(ParaId::from(i)).is_none()); + } } #[benchmark] diff --git a/pallets/xcm-core-buyer/src/lib.rs b/pallets/xcm-core-buyer/src/lib.rs index 4cb44ee11..05acf15c9 100644 --- a/pallets/xcm-core-buyer/src/lib.rs +++ b/pallets/xcm-core-buyer/src/lib.rs @@ -20,6 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +use frame_support::{Deserialize, Serialize}; pub use pallet::*; #[cfg(test)] @@ -33,9 +34,11 @@ mod benchmarks; pub mod weights; pub use weights::WeightInfo; +use tp_traits::{AuthorNotingHook, BlockNumber}; use { dp_core::ParaId, frame_support::{ + dispatch::GetDispatchInfo, pallet_prelude::*, traits::fungible::{Balanced, Inspect}, }, @@ -43,6 +46,7 @@ use { parity_scale_codec::EncodeLike, sp_runtime::traits::{AccountIdConversion, Convert, Get}, sp_std::{vec, vec::Vec}, + staging_xcm::v3::Response, staging_xcm::{ prelude::*, v3::{InteriorMultiLocation, MultiAsset, MultiAssets, Xcm}, @@ -50,9 +54,51 @@ use { tp_traits::ParathreadParams, }; +pub trait XCMNotifier { + fn new_notify_query( + responder: impl Into, + notify: impl Into<::RuntimeCall>, + timeout: BlockNumberFor, + match_querier: impl Into, + ) -> u64; +} + +/// Dummy implementation. Should only be used for testing. +impl XCMNotifier for () { + fn new_notify_query( + _responder: impl Into, + _notify: impl Into<::RuntimeCall>, + _timeout: BlockNumberFor, + _match_querier: impl Into, + ) -> u64 { + 0 + } +} + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Clone, TypeInfo)] +pub struct InFlightCoreBuyingOrder { + para_id: ParaId, + query_id: QueryId, + ttl: BN, +} + +impl AuthorNotingHook for Pallet { + fn on_container_author_noted( + _author: &T::AccountId, + _block_number: BlockNumber, + para_id: ParaId, + ) -> Weight { + PendingBlocks::::remove(para_id); + + T::DbWeight::get().writes(1) + } +} + #[frame_support::pallet] pub mod pallet { use super::*; + use pallet_xcm::ensure_response; #[pallet::pallet] #[pallet::without_storage_info] pub struct Pallet(PhantomData); @@ -87,9 +133,7 @@ pub mod pallet { + Clone + PartialEq + sp_std::fmt::Debug; - /// Limit how many in-flight XCM requests can be sent to the relay chain in one block. - #[pallet::constant] - type MaxParathreads: Get; + /// Get the parathread params. Used to verify that the para id is a parathread. // TODO: and in the future to restrict the ability to buy a core depending on slot frequency type GetParathreadParams: GetParathreadParams; @@ -102,6 +146,31 @@ pub mod pallet { #[pallet::constant] type UnsignedPriority: Get; + /// TTL for pending blocks entry, which prevents anyone to submit another core buying xcm. + #[pallet::constant] + type PendingBlocksTtl: Get>; + + /// TTL to be used in xcm's notify query + #[pallet::constant] + type CoreBuyingXCMQueryTtl: Get>; + + /// Additional ttl for in flight orders (total would be CoreBuyingXCMQueryTtl + AdditionalTtlForInflightOrders) + /// after which the in flight orders can be cleaned up by anyone. + #[pallet::constant] + type AdditionalTtlForInflightOrders: Get>; + + #[pallet::constant] + type UniversalLocation: Get; + + type RuntimeOrigin: Into::RuntimeOrigin>> + + From<::RuntimeOrigin>; + + /// The overarching call type + type RuntimeCall: From> + Encode + GetDispatchInfo; + + /// Outcome notifier implements functionality to enable reporting back the outcome + type XCMNotifier: XCMNotifier; + type WeightInfo: WeightInfo; } @@ -109,7 +178,18 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// An XCM message to buy a core for this parathread has been sent to the relay chain. - BuyCoreXcmSent { para_id: ParaId }, + BuyCoreXcmSent { + para_id: ParaId, + transaction_status_query_id: QueryId, + }, + /// We received response for xcm + ReceivedBuyCoreXCMResult { para_id: ParaId, response: Response }, + + /// We cleaned up expired pending blocks entries. + CleanedUpExpiredPendingBlocksEntries { para_ids: Vec }, + + /// We cleaned up expired in flight orders entries. + CleanedUpExpiredInFlightOrderEntries { para_ids: Vec }, } #[pallet::error] @@ -133,6 +213,14 @@ pub mod pallet { XcmWeightStorageNotSet, /// Converting a multilocation into a relay relative multilocation failed ReanchorFailed, + /// Inverting location from destination point of view failed + LocationInversionFailed, + /// Modifying XCM to report the result of XCM failed + ReportNotifyingSetupFailed, + /// Unexpected XCM response + UnexpectedXCMResponse, + /// Block production is pending for para id with successfully placed order + BlockProductionPending, } /// Proof that I am a collator, assigned to a para_id, and I can buy a core for that para_id @@ -149,7 +237,16 @@ pub mod pallet { /// 1 core in 1 relay block for the same parathread. #[pallet::storage] pub type InFlightOrders = - StorageValue<_, BoundedBTreeSet, ValueQuery>; + StorageMap<_, Twox128, ParaId, InFlightCoreBuyingOrder>, OptionQuery>; + + /// Number of pending blocks + #[pallet::storage] + pub type PendingBlocks = + StorageMap<_, Twox128, ParaId, BlockNumberFor, OptionQuery>; + + /// Mapping of QueryId to ParaId + #[pallet::storage] + pub type QueryIdToParaId = StorageMap<_, Twox128, QueryId, ParaId, OptionQuery>; /// This must be set by root with the value of the relay chain xcm call weight and extrinsic /// weight limit. This is a storage item because relay chain weights can change, so we need to @@ -183,7 +280,7 @@ pub mod pallet { // state. #[pallet::call_index(0)] // TODO: weight - #[pallet::weight(T::WeightInfo::force_buy_core(T::MaxParathreads::get()))] + #[pallet::weight(T::WeightInfo::force_buy_core())] pub fn buy_core( origin: OriginFor, para_id: ParaId, @@ -213,7 +310,7 @@ pub mod pallet { /// Buy core for para id as root. Does not require any proof, useful in tests. #[pallet::call_index(1)] - #[pallet::weight(T::WeightInfo::force_buy_core(T::MaxParathreads::get()))] + #[pallet::weight(T::WeightInfo::force_buy_core())] pub fn force_buy_core(origin: OriginFor, para_id: ParaId) -> DispatchResult { ensure_root(origin)?; @@ -261,6 +358,107 @@ pub mod pallet { Ok(()) } + + #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::query_response())] + pub fn query_response( + origin: OriginFor, + query_id: QueryId, + response: Response, + ) -> DispatchResult { + let _responder = ensure_response(::RuntimeOrigin::from(origin))?; + + let maybe_para_id = QueryIdToParaId::::get(query_id); + + let para_id = if let Some(para_id) = maybe_para_id { + para_id + } else { + // Most probably entry was expired or removed in some other way. Let's return early. + return Ok(()); + }; + + QueryIdToParaId::::remove(query_id); + InFlightOrders::::remove(para_id); + + match response { + Response::DispatchResult(MaybeErrorCode::Success) => { + // Success. Add para id to pending block + let now = >::block_number(); + let ttl = T::PendingBlocksTtl::get(); + PendingBlocks::::insert(para_id, now + ttl); + } + Response::DispatchResult(_) => { + // We do not add paraid to pending block on failure + } + _ => { + // Unexpected. + return Err(Error::::UnexpectedXCMResponse.into()); + } + } + + Self::deposit_event(Event::ReceivedBuyCoreXCMResult { para_id, response }); + + Ok(()) + } + + #[pallet::call_index(5)] + #[pallet::weight(T::WeightInfo::clean_up_expired_in_flight_orders(expired_pending_blocks_para_id.len() as u32))] + pub fn clean_up_expired_pending_blocks( + origin: OriginFor, + expired_pending_blocks_para_id: Vec, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + let now = frame_system::Pallet::::block_number(); + let mut cleaned_up_para_ids = vec![]; + + for para_id in expired_pending_blocks_para_id { + let maybe_pending_block_ttl = PendingBlocks::::get(para_id); + if let Some(pending_block_ttl) = maybe_pending_block_ttl { + if pending_block_ttl < now { + PendingBlocks::::remove(para_id); + cleaned_up_para_ids.push(para_id); + } else { + // Ignore if not expired + } + } + } + + Self::deposit_event(Event::CleanedUpExpiredPendingBlocksEntries { + para_ids: cleaned_up_para_ids, + }); + + Ok(()) + } + + #[pallet::call_index(6)] + #[pallet::weight(T::WeightInfo::clean_up_expired_in_flight_orders(expired_in_flight_orders.len() as u32))] + pub fn clean_up_expired_in_flight_orders( + origin: OriginFor, + expired_in_flight_orders: Vec, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + let now = frame_system::Pallet::::block_number(); + let mut cleaned_up_para_ids = vec![]; + + for para_id in expired_in_flight_orders { + let maybe_in_flight_order = InFlightOrders::::get(para_id); + if let Some(in_flight_order) = maybe_in_flight_order { + if in_flight_order.ttl < now { + InFlightOrders::::remove(para_id); + QueryIdToParaId::::remove(in_flight_order.query_id); + cleaned_up_para_ids.push(para_id); + } else { + // Ignore if not expired + } + } + } + + Self::deposit_event(Event::CleanedUpExpiredInFlightOrderEntries { + para_ids: cleaned_up_para_ids, + }); + + Ok(()) + } } impl Pallet { @@ -293,13 +491,27 @@ pub mod pallet { /// Send an XCM message to the relay chain to try to buy a core for this para_id. fn on_collator_instantaneous_core_requested(para_id: ParaId) -> DispatchResult { - let mut in_flight_orders = InFlightOrders::::get(); - if in_flight_orders.contains(¶_id) { - return Err(Error::::OrderAlreadyExists.into()); + // If an in flight order is pending (i.e we did not receive the notification yet) and our + // record is not expired yet, we should not allow the collator to buy another core. + let maybe_in_flight_order = InFlightOrders::::get(para_id); + if let Some(in_flight_order) = maybe_in_flight_order { + if in_flight_order.ttl < >::block_number() { + InFlightOrders::::remove(para_id); + } else { + return Err(Error::::OrderAlreadyExists.into()); + } + } + + // If a block production is pending and our record is not expired yet, we should not allow + // the collator to buy another core yet. + let maybe_pending_blocks_ttl = PendingBlocks::::get(para_id); + if let Some(pending_blocks_ttl) = maybe_pending_blocks_ttl { + if pending_blocks_ttl < >::block_number() { + PendingBlocks::::remove(para_id); + } else { + return Err(Error::::BlockProductionPending.into()); + } } - in_flight_orders - .try_insert(para_id) - .map_err(|_| Error::::InFlightLimitReached)?; // Check that the para id is a parathread let parathread_params = T::GetParathreadParams::get_parathread_params(para_id); @@ -349,6 +561,25 @@ pub mod pallet { // We use `descend_origin` instead of wrapping the transact call in `utility.as_derivative` // because with `descend_origin` the parathread tank account will pay for fees, while // `utility.as_derivative` will make the tanssi sovereign account pay for fees. + + let notify_call = ::RuntimeCall::from(Call::::query_response { + query_id: 0, + response: Default::default(), + }); + let notify_call_weight = notify_call.get_dispatch_info().weight; + + let notify_query_ttl = + >::block_number() + T::CoreBuyingXCMQueryTtl::get(); + + // Send XCM to relay chain + let relay_chain = MultiLocation::parent(); + let query_id = T::XCMNotifier::new_notify_query( + relay_chain, + notify_call, + notify_query_ttl, + interior_multilocation, + ); + let message: Xcm<()> = Xcm::builder_unsafe() .descend_origin(interior_multilocation) .withdraw_asset(MultiAssets::from(vec![relay_asset_total.clone()])) @@ -356,6 +587,13 @@ pub mod pallet { // Both in case of error and in case of success, we want to refund the unused weight .set_appendix( Xcm::builder_unsafe() + .report_transact_status(QueryResponseInfo { + destination: T::UniversalLocation::get() + .invert_target(&relay_chain) + .map_err(|_| Error::::LocationInversionFailed)?, // This location from the point of view of destination + query_id, + max_weight: notify_call_weight, + }) .refund_surplus() .deposit_asset(refund_asset_filter, derived_account) .build(), @@ -363,42 +601,40 @@ pub mod pallet { .transact(origin, weight_at_most, call.into()) .build(); - // Send XCM to relay chain - let relay_chain = MultiLocation::parent(); // We intentionally do not charge any fees let (ticket, _price) = T::XcmSender::validate(&mut Some(relay_chain), &mut Some(message)) .map_err(|_| Error::::ErrorValidatingXCM)?; T::XcmSender::deliver(ticket).map_err(|_| Error::::ErrorDeliveringXCM)?; - Self::deposit_event(Event::BuyCoreXcmSent { para_id }); - InFlightOrders::::put(in_flight_orders); + Self::deposit_event(Event::BuyCoreXcmSent { + para_id, + transaction_status_query_id: query_id, + }); + + let in_flight_order_ttl = notify_query_ttl + T::AdditionalTtlForInflightOrders::get(); + InFlightOrders::::insert( + para_id, + InFlightCoreBuyingOrder { + para_id, + query_id, + ttl: in_flight_order_ttl, + }, + ); + + QueryIdToParaId::::insert(query_id, para_id); Ok(()) } - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(_n: BlockNumberFor) -> Weight { - let mut weight = Weight::zero(); - - // 1 write in on_finalize - weight += T::DbWeight::get().writes(1); - weight - } + pub fn para_deregistered(para_id: ParaId) { + // If para is deregistered we need to clean up in flight order, query id mapping + if let Some(in_flight_order) = InFlightOrders::::take(para_id) { + InFlightOrders::::remove(para_id); + QueryIdToParaId::::remove(in_flight_order.query_id); + } - fn on_finalize(_: BlockNumberFor) { - // We clear this storage item because we only need it to prevent collators from buying - // more than one core for the same parathread in the same relay block - // TODO: with async backing, it is possible that two tanssi blocks are included in the - // same relay block, so this kill is not correct, should only kill the storage if the - // relay block number has changed - // TODO: this allows collators to send N consecutive messages to buy 1 core for the same - // parathread, as long as the parathread block is not included in pallet_author_noting. - // So a malicious collator could drain the parathread tank account by buying cores on - // every tanssi block but not actually producing any block. - InFlightOrders::::kill(); + // We need to clean the pending block entry if any + PendingBlocks::::remove(para_id); } } diff --git a/pallets/xcm-core-buyer/src/mock.rs b/pallets/xcm-core-buyer/src/mock.rs index 4ea806213..10ea2e020 100644 --- a/pallets/xcm-core-buyer/src/mock.rs +++ b/pallets/xcm-core-buyer/src/mock.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Tanssi. If not, see +use pallet_xcm::Origin; +use staging_xcm::prelude::{GlobalConsensus, Parachain, X2}; +use staging_xcm::prelude::{InteriorMultiLocation, NetworkId}; use { crate::{ self as pallet_xcm_core_buyer, GetParathreadCollators, GetPurchaseCoreCall, @@ -54,6 +57,20 @@ frame_support::construct_runtime!( } ); +/// Only needed for benchmark test suite +impl From for RuntimeOrigin { + fn from(_value: Origin) -> Self { + RuntimeOrigin::root() + } +} + +/// Only needed for benchmark test suite +impl From for Result { + fn from(_value: RuntimeOrigin) -> Self { + Ok(Origin::Response(MultiLocation::parent())) + } +} + impl frame_system::Config for Test { type BaseCallFilter = Everything; type Block = Block; @@ -161,6 +178,13 @@ parameter_types! { pub const ParachainId: ParaId = ParaId::new(1000); } +parameter_types! { + pub const PendingBlocksTtl: u32 = 5; + pub const CoreBuyingXCMQueryTtl: u32 = 100; + pub const AdditionalTtlForInflightOrders: u32 = 5; + pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(NetworkId::Westend), Parachain(1000)); +} + impl pallet_xcm_core_buyer::Config for Test { type RuntimeEvent = RuntimeEvent; type Currency = Balances; @@ -171,10 +195,16 @@ impl pallet_xcm_core_buyer::Config for Test { type GetParathreadMaxCorePrice = (); type SelfParaId = ParachainId; type RelayChain = (); - type MaxParathreads = ConstU32<100>; type GetParathreadParams = GetParathreadParamsImpl; type GetAssignedCollators = GetAssignedCollatorsImpl; type UnsignedPriority = (); + type PendingBlocksTtl = PendingBlocksTtl; + type CoreBuyingXCMQueryTtl = CoreBuyingXCMQueryTtl; + type AdditionalTtlForInflightOrders = AdditionalTtlForInflightOrders; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type XCMNotifier = (); type WeightInfo = (); } diff --git a/pallets/xcm-core-buyer/src/tests.rs b/pallets/xcm-core-buyer/src/tests.rs index d64688aea..2d51ca3b1 100644 --- a/pallets/xcm-core-buyer/src/tests.rs +++ b/pallets/xcm-core-buyer/src/tests.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Tanssi. If not, see +use frame_support::assert_storage_noop; use { crate::{mock::*, *}, frame_support::{assert_noop, assert_ok}, @@ -31,7 +32,9 @@ fn root_origin_can_force_buy_xcm() { assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); - assert_eq!(events(), vec![Event::BuyCoreXcmSent { para_id }]); + let events = events(); + assert_eq!(events.len(), 1); + matches!(events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); }); } @@ -62,7 +65,9 @@ fn force_buy_two_messages_in_one_block_fails() { assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); - assert_eq!(events(), vec![Event::BuyCoreXcmSent { para_id }]); + let events = events(); + assert_eq!(events.len(), 1); + matches!(events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); assert_noop!( XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id), @@ -72,7 +77,7 @@ fn force_buy_two_messages_in_one_block_fails() { } #[test] -fn force_buy_two_messages_in_two_consecutive_blocks_works() { +fn force_buy_two_messages_in_two_consecutive_blocks_failes() { ExtBuilder::default() .with_balances([(ALICE, 1_000)].into()) .build() @@ -82,13 +87,345 @@ fn force_buy_two_messages_in_two_consecutive_blocks_works() { assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); - assert_eq!(events(), vec![Event::BuyCoreXcmSent { para_id }]); + let events = events(); + assert_eq!(events.len(), 1); + matches!(events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); run_to_block(2); + assert_noop!( + XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id), + Error::::OrderAlreadyExists + ); + }); +} + +#[test] +fn force_buy_two_messages_succeds_after_receiving_order_failure_response() { + ExtBuilder::default() + .with_balances([(ALICE, 1_000)].into()) + .build() + .execute_with(|| { + run_to_block(1); + let para_id = 3333.into(); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + let query_id = match system_events[0] { + Event::BuyCoreXcmSent { transaction_status_query_id, .. } => transaction_status_query_id, + _ => panic!("We checked for the event variant above; qed") + }; + + // QueryId -> ParaId mapping should exists + assert_eq!(QueryIdToParaId::::get(query_id), Some(para_id)); + + run_to_block(2); + + assert_noop!( + XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id), + Error::::OrderAlreadyExists + ); + + assert_ok!(XcmCoreBuyer::query_response(RuntimeOrigin::root(), query_id, Response::DispatchResult(MaybeErrorCode::Error(BoundedVec::new())))); + + // In flight order entry should be removed + assert!(InFlightOrders::::get(para_id).is_none()); + + // Query id to para id entry should not exists + assert!(QueryIdToParaId::::get(query_id).is_none()); + + // We should not be adding entry into pending blocks data structure + assert!(PendingBlocks::::get(para_id).is_none()); + + run_to_block(4); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + }); +} + +#[test] +fn force_buy_two_messages_fails_after_receiving_order_success_response() { + ExtBuilder::default() + .with_balances([(ALICE, 1_000)].into()) + .build() + .execute_with(|| { + run_to_block(2); + let para_id = 3333.into(); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + let query_id = match system_events[0] { + Event::BuyCoreXcmSent { transaction_status_query_id, .. } => transaction_status_query_id, + _ => panic!("We checked for the event variant above; qed") + }; + + // In flight order entry should exists + let maybe_in_flight_order = InFlightOrders::::get(para_id); + assert!(maybe_in_flight_order.is_some()); + let in_flight_order = maybe_in_flight_order.expect("Checked above for None; qed"); + assert_eq!(in_flight_order, InFlightCoreBuyingOrder { + para_id, + query_id, + ttl: 2 + ::AdditionalTtlForInflightOrders::get() as u64 + ::CoreBuyingXCMQueryTtl::get() as u64, + }); + + // QueryId -> ParaId mapping should exists + assert_eq!(QueryIdToParaId::::get(query_id), Some(para_id)); + + run_to_block(3); + + assert_noop!( + XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id), + Error::::OrderAlreadyExists + ); + + assert_ok!(XcmCoreBuyer::query_response(RuntimeOrigin::root(), query_id, Response::DispatchResult(MaybeErrorCode::Success))); + + // In flight order entry should be removed + assert!(InFlightOrders::::get(para_id).is_none()); + + // Query id to para id entry should not exists + assert!(QueryIdToParaId::::get(query_id).is_none()); + + // We should be adding entry into pending blocks data structure + // We should not be adding entry into pending blocks data structure + assert!(PendingBlocks::::get(para_id).is_some()); + + run_to_block(4); + + assert_noop!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,), Error::::BlockProductionPending); + + // Now if the pallet gets notification that pending block for that para id is incremented it is possible to buy again. + Pallet::::on_container_author_noted(&1u64, 5, para_id); + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + assert_ok!(XcmCoreBuyer::query_response(RuntimeOrigin::root(), query_id, Response::DispatchResult(MaybeErrorCode::Success))); + + // We should not be able to buy the core again since we have pending block + assert_noop!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,), Error::::BlockProductionPending); + + // We can buy again after pending block ttl is passed + let pending_blocks_ttl = PendingBlocks::::get(para_id).expect("We must have an entry for pending block ttl mapping as checked above; qed"); + run_to_block(4 + pending_blocks_ttl + 1); + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + }); +} + +#[test] +fn clean_up_in_flight_orders_extrinsic_works() { + ExtBuilder::default() + .with_balances([(ALICE, 1_000)].into()) + .build() + .execute_with(|| { + run_to_block(2); + let para_id = 3333.into(); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + let query_id = match system_events[0] { + Event::BuyCoreXcmSent { transaction_status_query_id, .. } => transaction_status_query_id, + _ => panic!("We checked for the event variant above; qed") + }; + + // In flight order entry should exists + let maybe_in_flight_order = InFlightOrders::::get(para_id); + assert!(maybe_in_flight_order.is_some()); + let in_flight_order = maybe_in_flight_order.expect("Checked above for None; qed"); + assert_eq!(in_flight_order, InFlightCoreBuyingOrder { + para_id, + query_id, + ttl: 2 + ::AdditionalTtlForInflightOrders::get() as u64 + ::CoreBuyingXCMQueryTtl::get() as u64, + }); + + // QueryId -> ParaId mapping should exists + assert_eq!(QueryIdToParaId::::get(query_id), Some(para_id)); + + run_to_block(3); + + // Cleaning up before ttl should be ignored + assert_ok!(XcmCoreBuyer::clean_up_expired_in_flight_orders(RuntimeOrigin::signed(AccountId::default()), vec![para_id])); + let system_events = events(); + assert_eq!(system_events.len(), 1); + let para_ids_cleaned_up = match &system_events[0] { + Event::CleanedUpExpiredInFlightOrderEntries { para_ids } => para_ids.clone(), + _ => panic!("We checked for the event variant above; qed") + }; + assert!(para_ids_cleaned_up.is_empty()); + + // In flight order entry should still exists + let maybe_in_flight_order = InFlightOrders::::get(para_id); + assert!(maybe_in_flight_order.is_some()); + let query_id = maybe_in_flight_order.expect("Already checked existance above; qed").query_id; + // Query id to para id entry should exists + assert!(QueryIdToParaId::::get(query_id).is_some()); + + // Cleaning up after ttl should work + run_to_block(3 + ::AdditionalTtlForInflightOrders::get() as u64 + ::CoreBuyingXCMQueryTtl::get() as u64 + 1); + assert_ok!(XcmCoreBuyer::clean_up_expired_in_flight_orders(RuntimeOrigin::signed(AccountId::default()), vec![para_id])); + let system_events = events(); + assert_eq!(system_events.len(), 1); + let para_ids_cleaned_up = match &system_events[0] { + Event::CleanedUpExpiredInFlightOrderEntries { para_ids } => para_ids.clone(), + _ => panic!("We checked for the event variant above; qed") + }; + assert_eq!(para_ids_cleaned_up, vec![para_id]); + + // In flight order entry should not exist anymore + let maybe_in_flight_order = InFlightOrders::::get(para_id); + assert!(maybe_in_flight_order.is_none()); + + // Query id to para id entry should not exists + assert!(QueryIdToParaId::::get(query_id).is_none()); + }); +} + +#[test] +fn clean_up_pending_block_entries_extrinsic_works() { + ExtBuilder::default() + .with_balances([(ALICE, 1_000)].into()) + .build() + .execute_with(|| { + run_to_block(2); + let para_id = 3333.into(); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + let query_id = match system_events[0] { + Event::BuyCoreXcmSent { transaction_status_query_id, .. } => transaction_status_query_id, + _ => panic!("We checked for the event variant above; qed") + }; + + // In flight order entry should exists + let maybe_in_flight_order = InFlightOrders::::get(para_id); + assert!(maybe_in_flight_order.is_some()); + let in_flight_order = maybe_in_flight_order.expect("Checked above for None; qed"); + assert_eq!(in_flight_order, InFlightCoreBuyingOrder { + para_id, + query_id, + ttl: 2 + ::AdditionalTtlForInflightOrders::get() as u64 + ::CoreBuyingXCMQueryTtl::get() as u64, + }); + + assert_ok!(XcmCoreBuyer::query_response(RuntimeOrigin::root(), query_id, Response::DispatchResult(MaybeErrorCode::Success))); + + run_to_block(3); + + // Cleaning up before ttl should be ignored + assert_ok!(XcmCoreBuyer::clean_up_expired_pending_blocks(RuntimeOrigin::signed(AccountId::default()), vec![para_id])); + let system_events = events(); + assert_eq!(system_events.len(), 1); + let para_ids_cleaned_up = match &system_events[0] { + Event::CleanedUpExpiredPendingBlocksEntries { para_ids } => para_ids.clone(), + _ => panic!("We checked for the event variant above; qed") + }; + assert!(para_ids_cleaned_up.is_empty()); + + // In flight order entry should still exists + let maybe_pending_block_ttl = PendingBlocks::::get(para_id); + assert!(maybe_pending_block_ttl.is_some()); + + // Cleaning up after ttl should work + run_to_block(3 + ::PendingBlocksTtl::get() as u64 + 1); + assert_ok!(XcmCoreBuyer::clean_up_expired_pending_blocks(RuntimeOrigin::signed(AccountId::default()), vec![para_id])); + let system_events = events(); + assert_eq!(system_events.len(), 1); + let para_ids_cleaned_up = match &system_events[0] { + Event::CleanedUpExpiredPendingBlocksEntries { para_ids } => para_ids.clone(), + _ => panic!("We checked for the event variant above; qed") + }; + assert_eq!(para_ids_cleaned_up, vec![para_id]); + + // In flight order entry should not exist anymore + let maybe_pending_block_ttl = PendingBlocks::::get(para_id); + assert!(maybe_pending_block_ttl.is_none()); + }); +} + +#[test] +fn core_order_expires_after_ttl() { + ExtBuilder::default() + .with_balances([(ALICE, 1_000)].into()) + .build() + .execute_with(|| { + run_to_block(1); + let para_id = 3333.into(); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + + run_to_block(2); + + assert_noop!( + XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id), + Error::::OrderAlreadyExists + ); + + // We run to the ttl + 1 block, now even without query response received the order should have been expired + let ttl = InFlightOrders::::get(para_id).expect("In flight order for para id must be there").ttl; + run_to_block(ttl + 1); + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + }); +} + +#[test] +fn paraid_data_is_cleaned_up_at_deregistration() { + ExtBuilder::default() + .with_balances([(ALICE, 1_000)].into()) + .build() + .execute_with(|| { + run_to_block(1); + let para_id = 3333.into(); + + assert_ok!(XcmCoreBuyer::force_buy_core(RuntimeOrigin::root(), para_id,)); + + let system_events = events(); + assert_eq!(system_events.len(), 1); + matches!(system_events[0], Event::BuyCoreXcmSent { para_id: event_para_id, .. } if event_para_id == para_id); + + run_to_block(2); + + let maybe_in_flight_order = InFlightOrders::::get(para_id); + assert!(maybe_in_flight_order.is_some()); + let query_id = maybe_in_flight_order.expect("We already asserted that the value exists.").query_id; + assert!(QueryIdToParaId::::get(query_id).is_some()); + + XcmCoreBuyer::para_deregistered(para_id); + + // After de-registration the in flight order should be cleared + assert!(InFlightOrders::::get(para_id).is_none()); + + // After de-registration query id to para id mapping should be cleared + assert!(QueryIdToParaId::::get(query_id).is_none()); + + // It is no-op when para id is already de-registered + assert_storage_noop!(XcmCoreBuyer::para_deregistered(para_id)); + + // Adding a dummy pending block entry for para id + PendingBlocks::::insert(para_id, 1u64); + + XcmCoreBuyer::para_deregistered(para_id); - assert_eq!(events(), vec![Event::BuyCoreXcmSent { para_id }]); + // After de-registration pending block entry should be cleared + assert!(PendingBlocks::::get(para_id).is_none()); }); } diff --git a/pallets/xcm-core-buyer/src/weights.rs b/pallets/xcm-core-buyer/src/weights.rs index a45d5a46d..a2253cb74 100644 --- a/pallets/xcm-core-buyer/src/weights.rs +++ b/pallets/xcm-core-buyer/src/weights.rs @@ -18,31 +18,32 @@ //! Autogenerated weights for pallet_xcm_core_buyer //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `tomasz-XPS-15-9520`, CPU: `12th Gen Intel(R) Core(TM) i7-12700H` +//! HOSTNAME: `Parths-MBP-Work`, CPU: `` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // ./target/release/tanssi-node // benchmark // pallet -// --execution=wasm -// --wasm-execution=compiled +// --chain +// dev // --pallet // pallet_xcm_core_buyer +// --wasm-execution +// compiled // --extrinsic // * -// --chain=dev // --steps // 50 // --repeat // 20 -// --template=./benchmarking/frame-weight-template.hbs +// --template=./benchmarking/frame-weight-pallet-template.hbs // --json-file // raw.json // --output -// tmp/pallet_xcm_core_buyer.rs +// pallets/xcm-core-buyer/src/weights.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -53,7 +54,10 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_xcm_core_buyer. pub trait WeightInfo { - fn force_buy_core(x: u32, ) -> Weight; + fn force_buy_core() -> Weight; + fn query_response() -> Weight; + fn clean_up_expired_in_flight_orders(x: u32, ) -> Weight; + fn clean_up_expired_pending_blocks(x: u32, ) -> Weight; fn set_relay_xcm_weight_config() -> Weight; fn set_relay_chain() -> Weight; } @@ -64,13 +68,21 @@ impl WeightInfo for SubstrateWeight { /// Storage: `CollatorAssignment::CollatorContainerChain` (r:1 w:0) /// Proof: `CollatorAssignment::CollatorContainerChain` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `XcmCoreBuyer::InFlightOrders` (r:1 w:1) - /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:1 w:0) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Registrar::ParathreadParams` (r:1 w:0) /// Proof: `Registrar::ParathreadParams` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `XcmCoreBuyer::RelayXcmWeightConfig` (r:1 w:0) /// Proof: `XcmCoreBuyer::RelayXcmWeightConfig` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ServicesPayment::MaxCorePrice` (r:1 w:0) + /// Proof: `ServicesPayment::MaxCorePrice` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `XcmCoreBuyer::RelayChain` (r:1 w:0) /// Proof: `XcmCoreBuyer::RelayChain` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) + /// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) @@ -81,18 +93,69 @@ impl WeightInfo for SubstrateWeight { /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// The range of component `x` is `[1, 99]`. - fn force_buy_core(x: u32, ) -> Weight { + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:0 w:1) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn force_buy_core() -> Weight { // Proof Size summary in bytes: - // Measured: `662 + x * (4 ±0)` - // Estimated: `4127 + x * (4 ±0)` - // Minimum execution time: 28_172_000 picoseconds. - Weight::from_parts(32_053_217, 4127) - // Standard Error: 1_129 - .saturating_add(Weight::from_parts(27_235, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(10_u64)) + // Measured: `1738` + // Estimated: `5203` + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 5203) + .saturating_add(T::DbWeight::get().reads(14_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:1 w:1) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:0 w:1) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::InFlightOrders` (r:0 w:1) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn query_response() -> Weight { + // Proof Size summary in bytes: + // Measured: `1221` + // Estimated: `4686` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 4686) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(x.into())) + } + /// Storage: `XcmCoreBuyer::InFlightOrders` (r:1000 w:1000) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:0 w:1000) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `x` is `[1, 1000]`. + fn clean_up_expired_in_flight_orders(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `205 + x * (36 ±0)` + // Estimated: `3684 + x * (2512 ±0)` + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(13_000_000, 3684) + // Standard Error: 5_624 + .saturating_add(Weight::from_parts(4_134_364, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2512).saturating_mul(x.into())) + } + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:1000 w:1000) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `x` is `[1, 1000]`. + fn clean_up_expired_pending_blocks(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `147 + x * (23 ±0)` + // Estimated: `3627 + x * (2499 ±0)` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3627) + // Standard Error: 1_312 + .saturating_add(Weight::from_parts(2_640_131, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2499).saturating_mul(x.into())) } /// Storage: `XcmCoreBuyer::RelayXcmWeightConfig` (r:0 w:1) /// Proof: `XcmCoreBuyer::RelayXcmWeightConfig` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -100,8 +163,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_714_000 picoseconds. - Weight::from_parts(1_805_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `XcmCoreBuyer::RelayChain` (r:0 w:1) @@ -110,8 +173,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_680_000 picoseconds. - Weight::from_parts(1_787_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } @@ -121,13 +184,21 @@ impl WeightInfo for () { /// Storage: `CollatorAssignment::CollatorContainerChain` (r:1 w:0) /// Proof: `CollatorAssignment::CollatorContainerChain` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `XcmCoreBuyer::InFlightOrders` (r:1 w:1) - /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:1 w:0) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Registrar::ParathreadParams` (r:1 w:0) /// Proof: `Registrar::ParathreadParams` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `XcmCoreBuyer::RelayXcmWeightConfig` (r:1 w:0) /// Proof: `XcmCoreBuyer::RelayXcmWeightConfig` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ServicesPayment::MaxCorePrice` (r:1 w:0) + /// Proof: `ServicesPayment::MaxCorePrice` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `XcmCoreBuyer::RelayChain` (r:1 w:0) /// Proof: `XcmCoreBuyer::RelayChain` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) + /// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) @@ -138,18 +209,69 @@ impl WeightInfo for () { /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// The range of component `x` is `[1, 99]`. - fn force_buy_core(x: u32, ) -> Weight { + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:0 w:1) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn force_buy_core() -> Weight { // Proof Size summary in bytes: - // Measured: `662 + x * (4 ±0)` - // Estimated: `4127 + x * (4 ±0)` - // Minimum execution time: 28_172_000 picoseconds. - Weight::from_parts(32_053_217, 4127) - // Standard Error: 1_129 - .saturating_add(Weight::from_parts(27_235, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(10_u64)) + // Measured: `1738` + // Estimated: `5203` + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 5203) + .saturating_add(RocksDbWeight::get().reads(14_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:1 w:1) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:0 w:1) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::InFlightOrders` (r:0 w:1) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn query_response() -> Weight { + // Proof Size summary in bytes: + // Measured: `1221` + // Estimated: `4686` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 4686) + .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(x.into())) + } + /// Storage: `XcmCoreBuyer::InFlightOrders` (r:1000 w:1000) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:0 w:1000) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `x` is `[1, 1000]`. + fn clean_up_expired_in_flight_orders(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `205 + x * (36 ±0)` + // Estimated: `3684 + x * (2512 ±0)` + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(13_000_000, 3684) + // Standard Error: 5_624 + .saturating_add(Weight::from_parts(4_134_364, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2512).saturating_mul(x.into())) + } + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:1000 w:1000) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `x` is `[1, 1000]`. + fn clean_up_expired_pending_blocks(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `147 + x * (23 ±0)` + // Estimated: `3627 + x * (2499 ±0)` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3627) + // Standard Error: 1_312 + .saturating_add(Weight::from_parts(2_640_131, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2499).saturating_mul(x.into())) } /// Storage: `XcmCoreBuyer::RelayXcmWeightConfig` (r:0 w:1) /// Proof: `XcmCoreBuyer::RelayXcmWeightConfig` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -157,8 +279,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_714_000 picoseconds. - Weight::from_parts(1_805_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `XcmCoreBuyer::RelayChain` (r:0 w:1) @@ -167,8 +289,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_680_000 picoseconds. - Weight::from_parts(1_787_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/runtime/dancebox/src/lib.rs b/runtime/dancebox/src/lib.rs index 72f2cdc6a..64c88ce6c 100644 --- a/runtime/dancebox/src/lib.rs +++ b/runtime/dancebox/src/lib.rs @@ -945,7 +945,7 @@ impl pallet_author_noting::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type AuthorNotingHook = (); #[cfg(not(feature = "runtime-benchmarks"))] - type AuthorNotingHook = (InflationRewards, ServicesPayment); + type AuthorNotingHook = (XcmCoreBuyer, InflationRewards, ServicesPayment); type WeightInfo = weights::pallet_author_noting::SubstrateWeight; } @@ -1016,6 +1016,8 @@ impl RegistrarHooks for DanceboxRegistrarHooks { ServicesPayment::para_deregistered(para_id); + XcmCoreBuyer::para_deregistered(para_id); + Weight::default() } diff --git a/runtime/dancebox/src/weights/pallet_xcm_core_buyer.rs b/runtime/dancebox/src/weights/pallet_xcm_core_buyer.rs index a03a4ca6e..1e84bf5c6 100644 --- a/runtime/dancebox/src/weights/pallet_xcm_core_buyer.rs +++ b/runtime/dancebox/src/weights/pallet_xcm_core_buyer.rs @@ -18,9 +18,9 @@ //! Autogenerated weights for pallet_xcm_core_buyer //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-04-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-05-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `benchmark-1`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! HOSTNAME: `Parths-MBP-Work`, CPU: `` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -42,7 +42,7 @@ // --json-file // raw.json // --output -// tmp/dancebox_weights/pallet_xcm_core_buyer.rs +// runtime/dancebox/src/weights/pallet_xcm_core_buyer.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,7 +57,9 @@ impl pallet_xcm_core_buyer::WeightInfo for SubstrateWei /// Storage: `CollatorAssignment::CollatorContainerChain` (r:1 w:0) /// Proof: `CollatorAssignment::CollatorContainerChain` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `XcmCoreBuyer::InFlightOrders` (r:1 w:1) - /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:1 w:0) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Registrar::ParathreadParams` (r:1 w:0) /// Proof: `Registrar::ParathreadParams` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `XcmCoreBuyer::RelayXcmWeightConfig` (r:1 w:0) @@ -66,6 +68,8 @@ impl pallet_xcm_core_buyer::WeightInfo for SubstrateWei /// Proof: `ServicesPayment::MaxCorePrice` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `XcmCoreBuyer::RelayChain` (r:1 w:0) /// Proof: `XcmCoreBuyer::RelayChain` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) + /// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) @@ -78,18 +82,69 @@ impl pallet_xcm_core_buyer::WeightInfo for SubstrateWei /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// The range of component `x` is `[1, 99]`. - fn force_buy_core(x: u32, ) -> Weight { + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:0 w:1) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn force_buy_core() -> Weight { // Proof Size summary in bytes: - // Measured: `737 + x * (4 ±0)` - // Estimated: `4202 + x * (4 ±0)` - // Minimum execution time: 58_791_000 picoseconds. - Weight::from_parts(61_490_774, 4202) - // Standard Error: 1_131 - .saturating_add(Weight::from_parts(39_945, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(12_u64)) + // Measured: `1738` + // Estimated: `5203` + // Minimum execution time: 49_000_000 picoseconds. + Weight::from_parts(77_000_000, 5203) + .saturating_add(T::DbWeight::get().reads(14_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:1 w:1) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:0 w:1) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::InFlightOrders` (r:0 w:1) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn query_response() -> Weight { + // Proof Size summary in bytes: + // Measured: `1221` + // Estimated: `4686` + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(22_000_000, 4686) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(x.into())) + } + /// Storage: `XcmCoreBuyer::InFlightOrders` (r:1000 w:1000) + /// Proof: `XcmCoreBuyer::InFlightOrders` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmCoreBuyer::QueryIdToParaId` (r:0 w:1000) + /// Proof: `XcmCoreBuyer::QueryIdToParaId` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `x` is `[1, 1000]`. + fn clean_up_expired_in_flight_orders(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `205 + x * (36 ±0)` + // Estimated: `3684 + x * (2512 ±0)` + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(13_000_000, 3684) + // Standard Error: 15_088 + .saturating_add(Weight::from_parts(4_689_139, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2512).saturating_mul(x.into())) + } + /// Storage: `XcmCoreBuyer::PendingBlocks` (r:1000 w:1000) + /// Proof: `XcmCoreBuyer::PendingBlocks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `x` is `[1, 1000]`. + fn clean_up_expired_pending_blocks(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `147 + x * (23 ±0)` + // Estimated: `3627 + x * (2499 ±0)` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3627) + // Standard Error: 6_834 + .saturating_add(Weight::from_parts(2_879_038, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2499).saturating_mul(x.into())) } /// Storage: `XcmCoreBuyer::RelayXcmWeightConfig` (r:0 w:1) /// Proof: `XcmCoreBuyer::RelayXcmWeightConfig` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -97,8 +152,8 @@ impl pallet_xcm_core_buyer::WeightInfo for SubstrateWei // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_653_000 picoseconds. - Weight::from_parts(3_882_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `XcmCoreBuyer::RelayChain` (r:0 w:1) @@ -107,8 +162,8 @@ impl pallet_xcm_core_buyer::WeightInfo for SubstrateWei // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_786_000 picoseconds. - Weight::from_parts(3_954_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } \ No newline at end of file diff --git a/runtime/dancebox/src/xcm_config.rs b/runtime/dancebox/src/xcm_config.rs index b6a23cad2..65f5d85af 100644 --- a/runtime/dancebox/src/xcm_config.rs +++ b/runtime/dancebox/src/xcm_config.rs @@ -14,13 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Tanssi. If not, see +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_xcm_core_buyer::XCMNotifier; +use staging_xcm_builder::TrailingSetTopicAsId; use { super::{ currency::MICRODANCE, weights::xcm::XcmWeight as XcmGenericWeights, AccountId, - AllPalletsWithSystem, AssetRate, Balance, Balances, CollatorAssignment, ForeignAssets, - ForeignAssetsCreator, MaintenanceMode, MessageQueue, ParachainInfo, ParachainSystem, - PolkadotXcm, Registrar, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent, - RuntimeOrigin, System, TransactionByteFee, WeightToFee, XcmpQueue, + AllPalletsWithSystem, AssetRate, Balance, Balances, BlockNumber, CollatorAssignment, + ForeignAssets, ForeignAssetsCreator, MaintenanceMode, MessageQueue, ParachainInfo, + ParachainSystem, PolkadotXcm, Registrar, Runtime, RuntimeBlockWeights, RuntimeCall, + RuntimeEvent, RuntimeOrigin, System, TransactionByteFee, WeightToFee, XcmpQueue, }, crate::weights, cumulus_primitives_core::{AggregateMessageOrigin, ParaId}, @@ -99,7 +102,7 @@ pub type XcmBarrier = ( // Weight that is paid for may be consumed. TakeWeightCredit, // Expected responses are OK. - AllowKnownQueryResponses, + TrailingSetTopicAsId>, WithComputedOrigin< ( // If the message is one that immediately attemps to pay for execution, then allow it. @@ -477,7 +480,26 @@ parameter_types! { pub const XcmBuyExecutionDotRococo: u128 = XCM_BUY_EXECUTION_COST_ROCOCO; } -pub const XCM_BUY_EXECUTION_COST_ROCOCO: u128 = 50_000_000; +pub const XCM_BUY_EXECUTION_COST_ROCOCO: u128 = 70_000_000 + 1_266_663_99; + +pub struct XCMNotifierImpl; + +impl XCMNotifier for XCMNotifierImpl { + fn new_notify_query( + responder: impl Into, + notify: impl Into, + timeout: BlockNumberFor, + match_querier: impl Into, + ) -> u64 { + pallet_xcm::Pallet::::new_notify_query(responder, notify, timeout, match_querier) + } +} + +parameter_types! { + pub const CoreBuyingXCMQueryTtl: BlockNumber = 100; + pub const AdditionalTtlForInflightOrders: BlockNumber = 5; + pub const PendingBlockTtl: BlockNumber = 10; +} impl pallet_xcm_core_buyer::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -490,10 +512,16 @@ impl pallet_xcm_core_buyer::Config for Runtime { type GetParathreadMaxCorePrice = GetMaxCorePriceFromServicesPayment; type SelfParaId = parachain_info::Pallet; type RelayChain = RelayChain; - type MaxParathreads = ConstU32<100>; type GetParathreadParams = GetParathreadParamsImpl; type GetAssignedCollators = GetAssignedCollatorsImpl; type UnsignedPriority = ParasUnsignedPriority; + type PendingBlocksTtl = PendingBlockTtl; + type CoreBuyingXCMQueryTtl = AdditionalTtlForInflightOrders; + type AdditionalTtlForInflightOrders = AdditionalTtlForInflightOrders; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type XCMNotifier = XCMNotifierImpl; type WeightInfo = weights::pallet_xcm_core_buyer::SubstrateWeight; } diff --git a/runtime/dancebox/tests/common/xcm/core_buyer.rs b/runtime/dancebox/tests/common/xcm/core_buyer.rs index 991f2280c..27e30a9df 100644 --- a/runtime/dancebox/tests/common/xcm/core_buyer.rs +++ b/runtime/dancebox/tests/common/xcm/core_buyer.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Tanssi. If not, see +use crate::assert_expected_events; +use staging_xcm::latest::{MaybeErrorCode, Response}; +use staging_xcm::v3::QueryId; use { crate::common::{ dummy_boot_nodes, empty_genesis_data, run_to_session, start_block, @@ -41,15 +44,19 @@ const PARATHREAD_ID: u32 = 3333; const ROCOCO_ED: u128 = rococo_runtime_constants::currency::EXISTENTIAL_DEPOSIT; const BUY_EXECUTION_COST: u128 = dancebox_runtime::xcm_config::XCM_BUY_EXECUTION_COST_ROCOCO; // Difference between BUY_EXECUTION_COST and the actual cost that depends on the weight of the XCM -// message, gets refunded. -const BUY_EXECUTION_REFUND: u128 = 5115980; +// message, gets refunded on successful execution of core buying extrinsic. +const BUY_EXECUTION_REFUND: u128 = 3334777; +// Difference between BUY_EXECUTION_COST and the actual cost that depends on the weight of the XCM +// message, gets refunded on un-successful execution of core buying extrinsic. +const BUY_EXECUTION_REFUND_ON_FAILURE: u128 = 1001467; + const PLACE_ORDER_WEIGHT_AT_MOST: Weight = Weight::from_parts(1_000_000_000, 100_000); #[test] fn constants() { // If these constants change, some tests may break assert_eq!(ROCOCO_ED, 100_000_000 / 3); - assert_eq!(BUY_EXECUTION_COST, 50_000_000); + assert_eq!(BUY_EXECUTION_COST, 70_000_000 + 1_266_663_99); } /// The tests in this module all use this function to trigger an XCM message to buy a core. @@ -57,7 +64,9 @@ fn constants() { /// Each test has a different value of /// * tank_account_balance: the balance of the parachain tank account in the relay chain /// * spot_price: the price of a core -fn do_test(tank_account_balance: u128, set_max_core_price: Option) { +fn do_test(tank_account_balance: u128, set_max_core_price: Option) -> QueryId { + let mut query_id = QueryId::MAX; + Dancebox::execute_with(|| { // Register parathread let alice_origin = ::RuntimeOrigin::signed(DanceboxSender::get()); @@ -153,13 +162,17 @@ fn do_test(tank_account_balance: u128, set_max_core_price: Option) { Dancebox, vec![ RuntimeEvent::XcmCoreBuyer( - pallet_xcm_core_buyer::Event::BuyCoreXcmSent { para_id } + pallet_xcm_core_buyer::Event::BuyCoreXcmSent { para_id, .. } ) => { para_id: *para_id == ParaId::from(PARATHREAD_ID), }, ] ); + + query_id = find_query_id_for_para_id(ParaId::from(PARATHREAD_ID)); }); + + query_id } fn assert_relay_order_event_not_emitted() { @@ -178,6 +191,106 @@ fn assert_relay_order_event_not_emitted() { } } +fn assert_xcm_notification_event_not_emitted() { + type RuntimeEvent = ::RuntimeEvent; + + let events = ::events(); + for event in events { + match event { + RuntimeEvent::XcmCoreBuyer( + pallet_xcm_core_buyer::Event::ReceivedBuyCoreXCMResult { .. }, + ) => { + panic!("Event should not have been emitted: {:?}", event); + } + _ => (), + } + } +} + +fn find_query_id_for_para_id(para_id: ParaId) -> QueryId { + type RuntimeEvent = ::RuntimeEvent; + + let events = ::events(); + for event in events { + match event { + RuntimeEvent::XcmCoreBuyer(pallet_xcm_core_buyer::Event::BuyCoreXcmSent { + para_id: event_para_id, + transaction_status_query_id, + }) => { + if event_para_id == para_id { + return transaction_status_query_id; + } + } + _ => (), + } + } + + panic!( + "We should be able to find query_id for para_id: {:?}", + para_id + ); +} + +fn assert_query_response_success(para_id: ParaId, query_id: QueryId) { + assert_query_response(para_id, query_id, true, true); +} + +fn assert_query_response_failure(para_id: ParaId, query_id: QueryId) { + assert_query_response(para_id, query_id, true, false); +} + +fn assert_query_response_not_received(para_id: ParaId, query_id: QueryId) { + assert_query_response(para_id, query_id, false, false); +} + +fn assert_query_response( + para_id: ParaId, + query_id: QueryId, + response_received: bool, + is_successful: bool, +) { + if is_successful && !response_received { + panic!("Invalid input: If response is not received it cannot be successful."); + } + + let maybe_query_id = + pallet_xcm_core_buyer::QueryIdToParaId::<::Runtime>::get(query_id); + // Entry should only exists if we have not received response and vice versa. + if maybe_query_id.is_some() == response_received { + panic!( + "There should not be any query_id<->para_id mapping existing for para_id: {:?}", + para_id + ); + } + + let maybe_in_flight_order = + pallet_xcm_core_buyer::InFlightOrders::<::Runtime>::get(para_id); + // Entry should only exists if we have not received response and vice versa. + if maybe_in_flight_order.is_some() == response_received { + panic!( + "There should not be any para_id<->in_flight_order mapping existing for para_id: {:?}", + para_id + ); + } + + // Entry should only exists if we have got successful response and vice versa. + let maybe_pending_blocks_entry = + pallet_xcm_core_buyer::PendingBlocks::<::Runtime>::get(para_id); + if maybe_pending_blocks_entry.is_some() != is_successful { + if is_successful { + panic!( + "There should be a pending block entry for para_id: {:?}", + para_id + ); + } else { + panic!( + "There should not be a pending block entry for para_id: {:?}", + para_id + ); + } + } +} + /// Get parathread tank address in relay chain. This is derived from the Dancebox para id and the /// parathread para id. fn get_parathread_tank_relay_address() -> AccountId32 { @@ -219,7 +332,7 @@ fn xcm_core_buyer_zero_balance() { let balance_before = 0; // Invariant: if balance_before < BUY_EXECUTION_COST, then balance_after == balance_before - do_test(balance_before, None); + let query_id = do_test(balance_before, None); // Receive XCM message in Relay Chain Rococo::execute_with(|| { @@ -237,6 +350,11 @@ fn xcm_core_buyer_zero_balance() { assert_relay_order_event_not_emitted(); assert_eq!(balance_before, balance_after); }); + + Dancebox::execute_with(|| { + assert_xcm_notification_event_not_emitted(); + assert_query_response_not_received(ParaId::from(PARATHREAD_ID), query_id); + }); } #[test] @@ -248,7 +366,7 @@ fn xcm_core_buyer_only_enough_balance_for_buy_execution() { // balance_after <= (balance_before + BUY_EXECUTION_REFUND - BUY_EXECUTION_COST) // In this case the balance_after is 0 because BUY_EXECUTION_REFUND < ROCOCO_ED, // so the account gets the refund but it is immediatelly killed. - do_test(balance_before, None); + let query_id = do_test(balance_before, None); // Receive XCM message in Relay Chain Rococo::execute_with(|| { @@ -281,6 +399,25 @@ fn xcm_core_buyer_only_enough_balance_for_buy_execution() { assert_relay_order_event_not_emitted(); assert_eq!(balance_after, 0); }); + + Dancebox::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + Dancebox, + vec![ + RuntimeEvent::XcmCoreBuyer( + pallet_xcm_core_buyer::Event::ReceivedBuyCoreXCMResult { + para_id, + response, + } + ) => { + para_id: *para_id == ParaId::from(PARATHREAD_ID), + response: *response != Response::DispatchResult(MaybeErrorCode::Success), + }, + ] + ); + assert_query_response_failure(ParaId::from(PARATHREAD_ID), query_id); + }); } #[test] @@ -292,7 +429,7 @@ fn xcm_core_buyer_enough_balance_except_for_existential_deposit() { let spot_price2 = spot_price; let balance_before = BUY_EXECUTION_COST + spot_price; - do_test(balance_before, None); + let query_id = do_test(balance_before, None); // Receive XCM message in Relay Chain Rococo::execute_with(|| { @@ -343,6 +480,25 @@ fn xcm_core_buyer_enough_balance_except_for_existential_deposit() { ); assert_eq!(balance_after, 0); }); + + Dancebox::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + Dancebox, + vec![ + RuntimeEvent::XcmCoreBuyer( + pallet_xcm_core_buyer::Event::ReceivedBuyCoreXCMResult { + para_id, + response, + } + ) => { + para_id: *para_id == ParaId::from(PARATHREAD_ID), + response: *response == Response::DispatchResult(MaybeErrorCode::Success), + }, + ] + ); + assert_query_response_success(ParaId::from(PARATHREAD_ID), query_id); + }); } #[test] @@ -352,7 +508,7 @@ fn xcm_core_buyer_enough_balance() { let spot_price2 = spot_price; let balance_before = ROCOCO_ED + BUY_EXECUTION_COST + spot_price + 1; - do_test(balance_before, None); + let query_id = do_test(balance_before, None); // Receive XCM message in Relay Chain Rococo::execute_with(|| { @@ -404,6 +560,27 @@ fn xcm_core_buyer_enough_balance() { ); assert_eq!(balance_after, ROCOCO_ED + 1 + BUY_EXECUTION_REFUND); }); + + // Receive notification on dancebox + Dancebox::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + Dancebox, + vec![ + RuntimeEvent::XcmCoreBuyer( + pallet_xcm_core_buyer::Event::ReceivedBuyCoreXCMResult { + para_id, + response, + } + ) => { + para_id: *para_id == ParaId::from(PARATHREAD_ID), + response: *response == Response::DispatchResult(MaybeErrorCode::Success), + }, + ] + ); + + assert_query_response_success(ParaId::from(PARATHREAD_ID), query_id); + }); } #[test] @@ -412,7 +589,7 @@ fn xcm_core_buyer_core_too_expensive() { let balance_before = ROCOCO_ED + BUY_EXECUTION_COST + 1; set_on_demand_base_fee(balance_before * 2); - do_test(balance_before, None); + let query_id = do_test(balance_before, None); // Receive XCM message in Relay Chain Rococo::execute_with(|| { @@ -436,7 +613,7 @@ fn xcm_core_buyer_core_too_expensive() { RuntimeEvent::Balances( pallet_balances::Event::Deposit { who, - amount: BUY_EXECUTION_REFUND, + amount: BUY_EXECUTION_REFUND_ON_FAILURE, } ) => { who: *who == parathread_tank_in_relay, @@ -447,8 +624,29 @@ fn xcm_core_buyer_core_too_expensive() { assert_relay_order_event_not_emitted(); assert_eq!( balance_after, - balance_before + BUY_EXECUTION_REFUND - BUY_EXECUTION_COST + balance_before + BUY_EXECUTION_REFUND_ON_FAILURE - BUY_EXECUTION_COST + ); + }); + + // Receive notification on dancebox + Dancebox::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + Dancebox, + vec![ + RuntimeEvent::XcmCoreBuyer( + pallet_xcm_core_buyer::Event::ReceivedBuyCoreXCMResult { + para_id, + response, + } + ) => { + para_id: *para_id == ParaId::from(PARATHREAD_ID), + response: *response != Response::DispatchResult(MaybeErrorCode::Success), + }, + ] ); + + assert_query_response_failure(ParaId::from(PARATHREAD_ID), query_id); }); } @@ -463,7 +661,7 @@ fn xcm_core_buyer_set_max_core_price() { Dancebox::execute_with(|| {}); - do_test(balance_before, Some(max_core_price)); + let query_id = do_test(balance_before, Some(max_core_price)); // Receive XCM message in Relay Chain Rococo::execute_with(|| { @@ -487,7 +685,7 @@ fn xcm_core_buyer_set_max_core_price() { RuntimeEvent::Balances( pallet_balances::Event::Deposit { who, - amount: BUY_EXECUTION_REFUND, + amount: BUY_EXECUTION_REFUND_ON_FAILURE, } ) => { who: *who == parathread_tank_in_relay, @@ -498,7 +696,27 @@ fn xcm_core_buyer_set_max_core_price() { assert_relay_order_event_not_emitted(); assert_eq!( balance_after, - ROCOCO_ED + 1 + BUY_EXECUTION_REFUND + spot_price + ROCOCO_ED + 1 + BUY_EXECUTION_REFUND_ON_FAILURE + spot_price ); }); + + Dancebox::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + Dancebox, + vec![ + RuntimeEvent::XcmCoreBuyer( + pallet_xcm_core_buyer::Event::ReceivedBuyCoreXCMResult { + para_id, + response, + } + ) => { + para_id: *para_id == ParaId::from(PARATHREAD_ID), + response: *response != Response::DispatchResult(MaybeErrorCode::Success), + }, + ] + ); + + assert_query_response_failure(ParaId::from(PARATHREAD_ID), query_id); + }); } diff --git a/runtime/dancebox/tests/common/xcm/delivery_fees.rs b/runtime/dancebox/tests/common/xcm/delivery_fees.rs index 432424ea9..2272e8791 100644 --- a/runtime/dancebox/tests/common/xcm/delivery_fees.rs +++ b/runtime/dancebox/tests/common/xcm/delivery_fees.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxSender, @@ -25,6 +26,7 @@ use { *, }, frame_support::assert_ok, + frame_support::traits::EnsureOrigin, paste::paste, staging_xcm::{latest::prelude::*, VersionedMultiLocation, VersionedXcm}, xcm_emulator::Chain, @@ -96,12 +98,21 @@ macro_rules! assert_delivery_fees_test { let xcm = Xcm(vec![ RefundSurplus, ]); + let versioned_xcm: VersionedXcm<()> = VersionedXcm::V3(xcm.clone()); let sender_account = [<$chain Sender>]::get(); let balance_sender_before = <$chain as [<$chain ParaPallet>]>::Balances::free_balance(sender_account.clone()); let origin = <$chain as Chain>::RuntimeOrigin::signed(sender_account.clone()); + let origin_location = <<$chain as Chain>::Runtime as pallet_xcm::Config>::SendXcmOrigin::ensure_origin(origin.clone()).expect("cannot conver origin into junctions"); + let interior: Junctions = + origin_location.clone().try_into().unwrap(); + + let final_xcm: Xcm<()> = Xcm(vec![ + DescendOrigin(interior), + RefundSurplus, + ]); let dest: VersionedMultiLocation = $dest.into(); assert_ok!(<$chain as [<$chain ParaPallet>]>::PolkadotXcm::send( @@ -109,11 +120,12 @@ macro_rules! assert_delivery_fees_test { bx!(dest), bx!(versioned_xcm) )); - let (_, price) = validate_send::<<<$chain as Chain>::Runtime as pallet_xcm::Config>::XcmRouter>(MultiLocation::parent(), xcm.clone()).unwrap(); + let (_, price) = validate_send::<<<$chain as Chain>::Runtime as pallet_xcm::Config>::XcmRouter>(MultiLocation::parent(), final_xcm.clone()).unwrap(); let balance_sender_after = <$chain as [<$chain ParaPallet>]>::Balances::free_balance(&sender_account); assert!(balance_sender_after < balance_sender_before); // assert there is at least an asset assert!(!price.is_none()); + assert_expected_events!( $chain, vec![ diff --git a/runtime/dancebox/tests/common/xcm/expected_event_checker.rs b/runtime/dancebox/tests/common/xcm/expected_event_checker.rs new file mode 100644 index 000000000..8d387aef7 --- /dev/null +++ b/runtime/dancebox/tests/common/xcm/expected_event_checker.rs @@ -0,0 +1,103 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see + +#[macro_export] +macro_rules! assert_expected_events { + ( $chain:ident, vec![$( $event_pat:pat => { $($attr:ident : $condition:expr, )* }, )*] ) => { + let mut message: Vec = Vec::new(); + let mut events = <$chain as xcm_emulator::Chain>::events(); + + $( + let mut event_received = false; + let mut meet_conditions = true; + let mut index_match = 0; + let mut event_message: Vec = Vec::new(); + + for (index, event) in events.iter().enumerate() { + // Variable to record current event's meet conditions + #[allow(unused_mut)] // To suppress warning in case no conditions are declared + let mut current_event_meet_conditions = true; + match event { + $event_pat => { + event_received = true; + + #[allow(unused_mut)] // To suppress warning in case no conditions are declared + let mut conditions_message: Vec = Vec::new(); + + $( + // We only want to record condition error messages in case it did not happened before + // Only the first partial match is recorded + if !$condition && event_message.is_empty() { + conditions_message.push( + format!( + " - The attribute {:?} = {:?} did not met the condition {:?}\n", + stringify!($attr), + $attr, + stringify!($condition) + ) + ); + } + current_event_meet_conditions &= $condition; + )* + + // Set the variable to latest matched event's condition evaluation result + meet_conditions = current_event_meet_conditions; + + // Set the index where we found a perfect match + if event_received && meet_conditions { + index_match = index; + break; + } else { + event_message.extend(conditions_message); + } + }, + _ => {} + } + } + + if event_received && !meet_conditions { + message.push( + format!( + "\n\n{}::\x1b[31m{}\x1b[0m was received but some of its attributes did not meet the conditions:\n{}", + stringify!($chain), + stringify!($event_pat), + event_message.concat() + ) + ); + } else if !event_received { + message.push( + format!( + "\n\n{}::\x1b[31m{}\x1b[0m was never received. All events:\n{:#?}", + stringify!($chain), + stringify!($event_pat), + <$chain as xcm_emulator::Chain>::events(), + ) + ); + } else { + // If we find a perfect match we remove the event to avoid being potentially assessed multiple times + events.remove(index_match); + } + )* + + if !message.is_empty() { + // Log events as they will not be logged after the panic + <$chain as xcm_emulator::Chain>::events().iter().for_each(|event| { + log::debug!(target: concat!("events::", stringify!($chain)), "{:?}", event); + }); + panic!("{}", message.concat()) + } + } +} diff --git a/runtime/dancebox/tests/common/xcm/foreign_signed_based_sovereign.rs b/runtime/dancebox/tests/common/xcm/foreign_signed_based_sovereign.rs index 52c6c0809..93f29aa99 100644 --- a/runtime/dancebox/tests/common/xcm/foreign_signed_based_sovereign.rs +++ b/runtime/dancebox/tests/common/xcm/foreign_signed_based_sovereign.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxEmptyReceiver, DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxSender, diff --git a/runtime/dancebox/tests/common/xcm/foreign_sovereigns.rs b/runtime/dancebox/tests/common/xcm/foreign_sovereigns.rs index 6cd449d68..d0000b3b1 100644 --- a/runtime/dancebox/tests/common/xcm/foreign_sovereigns.rs +++ b/runtime/dancebox/tests/common/xcm/foreign_sovereigns.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, EthereumEmptyReceiver, EthereumSender, diff --git a/runtime/dancebox/tests/common/xcm/mod.rs b/runtime/dancebox/tests/common/xcm/mod.rs index 1d1e29aaa..eeb5e9aa0 100644 --- a/runtime/dancebox/tests/common/xcm/mod.rs +++ b/runtime/dancebox/tests/common/xcm/mod.rs @@ -30,7 +30,10 @@ mod token_derivative_reception_relay_simple_container; mod transact; mod trap; +#[macro_use] +mod expected_event_checker; + pub use { paste, - xcm_emulator::{assert_expected_events, bx, Parachain as Para, RelayChain as Relay, TestExt}, + xcm_emulator::{bx, Parachain as Para, RelayChain as Relay, TestExt}, }; diff --git a/runtime/dancebox/tests/common/xcm/reserver_transfers_polkadot_xcm.rs b/runtime/dancebox/tests/common/xcm/reserver_transfers_polkadot_xcm.rs index eb7635a1f..ffb945a90 100644 --- a/runtime/dancebox/tests/common/xcm/reserver_transfers_polkadot_xcm.rs +++ b/runtime/dancebox/tests/common/xcm/reserver_transfers_polkadot_xcm.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxSender, diff --git a/runtime/dancebox/tests/common/xcm/token_derivative_reception_container_dancebox.rs b/runtime/dancebox/tests/common/xcm/token_derivative_reception_container_dancebox.rs index 702640a0c..5568869d1 100644 --- a/runtime/dancebox/tests/common/xcm/token_derivative_reception_container_dancebox.rs +++ b/runtime/dancebox/tests/common/xcm/token_derivative_reception_container_dancebox.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxReceiver, diff --git a/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_frontier_container.rs b/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_frontier_container.rs index 1a0c9c5aa..eac81f7ed 100644 --- a/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_frontier_container.rs +++ b/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_frontier_container.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxSender, EthereumReceiver, diff --git a/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_simple_container.rs b/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_simple_container.rs index 7cb303f38..8d4dd06b8 100644 --- a/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_simple_container.rs +++ b/runtime/dancebox/tests/common/xcm/token_derivative_reception_dancebox_simple_container.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxSender, diff --git a/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_dancebox.rs b/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_dancebox.rs index ba72c5bac..6e939af81 100644 --- a/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_dancebox.rs +++ b/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_dancebox.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxReceiver, diff --git a/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_frontier_container.rs b/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_frontier_container.rs index 93845f5b4..cf495c263 100644 --- a/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_frontier_container.rs +++ b/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_frontier_container.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ EthereumReceiver, FrontierTemplatePara as FrontierTemplate, FrontierTemplateParaPallet, diff --git a/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_simple_container.rs b/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_simple_container.rs index e63838815..09374a5a3 100644 --- a/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_simple_container.rs +++ b/runtime/dancebox/tests/common/xcm/token_derivative_reception_relay_simple_container.rs @@ -15,6 +15,7 @@ // along with Tanssi. If not, see use { + crate::assert_expected_events, crate::common::xcm::{ mocknets::{ SimpleTemplatePara as SimpleTemplate, SimpleTemplateParaPallet, SimpleTemplateReceiver, diff --git a/runtime/dancebox/tests/common/xcm/transact.rs b/runtime/dancebox/tests/common/xcm/transact.rs index 000a4af69..0abeaaf2d 100644 --- a/runtime/dancebox/tests/common/xcm/transact.rs +++ b/runtime/dancebox/tests/common/xcm/transact.rs @@ -17,6 +17,7 @@ use crate::common::xcm::*; use { + crate::assert_expected_events, crate::common::xcm::mocknets::{ DanceboxPara as Dancebox, FrontierTemplatePara as FrontierTemplate, FrontierTemplateParaPallet, SimpleTemplatePara as SimpleTemplate, SimpleTemplateParaPallet, diff --git a/runtime/dancebox/tests/common/xcm/trap.rs b/runtime/dancebox/tests/common/xcm/trap.rs index 678763051..11da0ae41 100644 --- a/runtime/dancebox/tests/common/xcm/trap.rs +++ b/runtime/dancebox/tests/common/xcm/trap.rs @@ -17,6 +17,7 @@ use crate::common::xcm::*; use { + crate::assert_expected_events, crate::common::xcm::mocknets::{ DanceboxPara as Dancebox, WestendRelay as Westend, WestendRelayPallet, }, diff --git a/test/suites/dev-tanssi/weights/test_set_latest_author_data_weight.ts b/test/suites/dev-tanssi/weights/test_set_latest_author_data_weight.ts index ff0595389..decf76ac0 100644 --- a/test/suites/dev-tanssi/weights/test_set_latest_author_data_weight.ts +++ b/test/suites/dev-tanssi/weights/test_set_latest_author_data_weight.ts @@ -12,7 +12,7 @@ describeSuite({ id: "E01", title: "Weight should be match expected", test: async function () { - const expectedRefTime = new BN(1_134_178_671); + const expectedRefTime = new BN(1_245_284_212); const expectedProofSize = new BN(15_236); await context.createBlock(); diff --git a/typescript-api/src/dancebox/interfaces/augment-api-consts.ts b/typescript-api/src/dancebox/interfaces/augment-api-consts.ts index eba44924a..983e22c32 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-consts.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-consts.ts @@ -16,6 +16,7 @@ import type { SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, + XcmV3Junctions, } from "@polkadot/types/lookup"; export type __AugmentedConst = AugmentedConst; @@ -372,8 +373,16 @@ declare module "@polkadot/api-base/types/consts" { [key: string]: Codec; }; xcmCoreBuyer: { - /** Limit how many in-flight XCM requests can be sent to the relay chain in one block. */ - maxParathreads: u32 & AugmentedConst; + /** + * Additional ttl for in flight orders (total would be CoreBuyingXCMQueryTtl + AdditionalTtlForInflightOrders) + * after which the in flight orders can be cleaned up by anyone. + */ + additionalTtlForInflightOrders: u32 & AugmentedConst; + /** TTL to be used in xcm's notify query */ + coreBuyingXCMQueryTtl: u32 & AugmentedConst; + /** TTL for pending blocks entry, which prevents anyone to submit another core buying xcm. */ + pendingBlocksTtl: u32 & AugmentedConst; + universalLocation: XcmV3Junctions & AugmentedConst; /** * A configuration for base priority of unsigned transactions. * diff --git a/typescript-api/src/dancebox/interfaces/augment-api-errors.ts b/typescript-api/src/dancebox/interfaces/augment-api-errors.ts index b12c3a318..caaaa9ff8 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-errors.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-errors.ts @@ -543,6 +543,8 @@ declare module "@polkadot/api-base/types/errors" { [key: string]: AugmentedError; }; xcmCoreBuyer: { + /** Block production is pending for para id with successfully placed order */ + BlockProductionPending: AugmentedError; /** This collator is not assigned to this parathread */ CollatorNotAssigned: AugmentedError; ErrorDeliveringXCM: AugmentedError; @@ -550,6 +552,8 @@ declare module "@polkadot/api-base/types/errors" { /** There are too many in-flight orders, buying cores will not work until some of those orders finish. */ InFlightLimitReached: AugmentedError; InvalidProof: AugmentedError; + /** Inverting location from destination point of view failed */ + LocationInversionFailed: AugmentedError; /** There are no collators assigned to this parathread, so no point in buying a core */ NoAssignedCollators: AugmentedError; /** The para id is not a parathread */ @@ -558,6 +562,10 @@ declare module "@polkadot/api-base/types/errors" { OrderAlreadyExists: AugmentedError; /** Converting a multilocation into a relay relative multilocation failed */ ReanchorFailed: AugmentedError; + /** Modifying XCM to report the result of XCM failed */ + ReportNotifyingSetupFailed: AugmentedError; + /** Unexpected XCM response */ + UnexpectedXCMResponse: AugmentedError; /** * The `XcmWeights` storage has not been set. This must have been set by root with the value of the relay chain * xcm call weight and extrinsic weight diff --git a/typescript-api/src/dancebox/interfaces/augment-api-events.ts b/typescript-api/src/dancebox/interfaces/augment-api-events.ts index 1ad2af4ba..f652da67f 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-events.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-events.ts @@ -1303,7 +1303,21 @@ declare module "@polkadot/api-base/types/events" { }; xcmCoreBuyer: { /** An XCM message to buy a core for this parathread has been sent to the relay chain. */ - BuyCoreXcmSent: AugmentedEvent; + BuyCoreXcmSent: AugmentedEvent< + ApiType, + [paraId: u32, transactionStatusQueryId: u64], + { paraId: u32; transactionStatusQueryId: u64 } + >; + /** We cleaned up expired in flight orders entries. */ + CleanedUpExpiredInFlightOrderEntries: AugmentedEvent], { paraIds: Vec }>; + /** We cleaned up expired pending blocks entries. */ + CleanedUpExpiredPendingBlocksEntries: AugmentedEvent], { paraIds: Vec }>; + /** We received response for xcm */ + ReceivedBuyCoreXCMResult: AugmentedEvent< + ApiType, + [paraId: u32, response: XcmV3Response], + { paraId: u32; response: XcmV3Response } + >; /** Generic event */ [key: string]: AugmentedEvent; }; diff --git a/typescript-api/src/dancebox/interfaces/augment-api-query.ts b/typescript-api/src/dancebox/interfaces/augment-api-query.ts index 5934b69f2..28172c474 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-query.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-query.ts @@ -70,6 +70,7 @@ import type { PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletTreasurySpendStatus, + PalletXcmCoreBuyerInFlightCoreBuyingOrder, PalletXcmCoreBuyerRelayXcmWeightConfigInner, PalletXcmQueryStatus, PalletXcmRemoteLockedFungibleRecord, @@ -1276,8 +1277,26 @@ declare module "@polkadot/api-base/types/storage" { * Set of parathreads that have already sent an XCM message to buy a core recently. Used to avoid 2 collators * buying a core at the same time, because it is only possible to buy 1 core in 1 relay block for the same parathread. */ - inFlightOrders: AugmentedQuery Observable>, []> & - QueryableStorageEntry; + inFlightOrders: AugmentedQuery< + ApiType, + (arg: u32 | AnyNumber | Uint8Array) => Observable>, + [u32] + > & + QueryableStorageEntry; + /** Number of pending blocks */ + pendingBlocks: AugmentedQuery< + ApiType, + (arg: u32 | AnyNumber | Uint8Array) => Observable>, + [u32] + > & + QueryableStorageEntry; + /** Mapping of QueryId to ParaId */ + queryIdToParaId: AugmentedQuery< + ApiType, + (arg: u64 | AnyNumber | Uint8Array) => Observable>, + [u64] + > & + QueryableStorageEntry; /** * This must be set by root with the value of the relay chain xcm call weight and extrinsic weight limit. This is * a storage item because relay chain weights can change, so we need to be able to adjust them without doing a diff --git a/typescript-api/src/dancebox/interfaces/augment-api-tx.ts b/typescript-api/src/dancebox/interfaces/augment-api-tx.ts index 82280f77c..b1d285434 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-tx.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-tx.ts @@ -41,6 +41,7 @@ import type { TpAuthorNotingInherentOwnParachainInherentData, TpContainerChainGenesisDataContainerChainGenesisData, TpTraitsSlotFrequency, + XcmV3Response, XcmV3WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, @@ -2188,11 +2189,40 @@ declare module "@polkadot/api-base/types/submittable" { ) => SubmittableExtrinsic, [u32, PalletXcmCoreBuyerBuyCoreCollatorProof] >; + /** See [`Pallet::clean_up_expired_in_flight_orders`]. */ + cleanUpExpiredInFlightOrders: AugmentedSubmittable< + (expiredInFlightOrders: Vec | (u32 | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic, + [Vec] + >; + /** See [`Pallet::clean_up_expired_pending_blocks`]. */ + cleanUpExpiredPendingBlocks: AugmentedSubmittable< + ( + expiredPendingBlocksParaId: Vec | (u32 | AnyNumber | Uint8Array)[] + ) => SubmittableExtrinsic, + [Vec] + >; /** See [`Pallet::force_buy_core`]. */ forceBuyCore: AugmentedSubmittable< (paraId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32] >; + /** See [`Pallet::query_response`]. */ + queryResponse: AugmentedSubmittable< + ( + queryId: u64 | AnyNumber | Uint8Array, + response: + | XcmV3Response + | { Null: any } + | { Assets: any } + | { ExecutionResult: any } + | { Version: any } + | { PalletsInfo: any } + | { DispatchResult: any } + | string + | Uint8Array + ) => SubmittableExtrinsic, + [u64, XcmV3Response] + >; /** See [`Pallet::set_relay_chain`]. */ setRelayChain: AugmentedSubmittable< ( diff --git a/typescript-api/src/dancebox/interfaces/lookup.ts b/typescript-api/src/dancebox/interfaces/lookup.ts index 7f102ee4a..3c583e4ce 100644 --- a/typescript-api/src/dancebox/interfaces/lookup.ts +++ b/typescript-api/src/dancebox/interfaces/lookup.ts @@ -1773,14 +1773,25 @@ export default { _enum: { BuyCoreXcmSent: { paraId: "u32", + transactionStatusQueryId: "u64", + }, + ReceivedBuyCoreXCMResult: { + paraId: "u32", + response: "XcmV3Response", + }, + CleanedUpExpiredPendingBlocksEntries: { + paraIds: "Vec", + }, + CleanedUpExpiredInFlightOrderEntries: { + paraIds: "Vec", }, }, }, - /** Lookup143: pallet_root_testing::pallet::Event */ + /** Lookup144: pallet_root_testing::pallet::Event */ PalletRootTestingEvent: { _enum: ["DefensiveTestCall"], }, - /** Lookup144: frame_system::Phase */ + /** Lookup145: frame_system::Phase */ FrameSystemPhase: { _enum: { ApplyExtrinsic: "u32", @@ -1788,17 +1799,17 @@ export default { Initialization: "Null", }, }, - /** Lookup148: frame_system::LastRuntimeUpgradeInfo */ + /** Lookup149: frame_system::LastRuntimeUpgradeInfo */ FrameSystemLastRuntimeUpgradeInfo: { specVersion: "Compact", specName: "Text", }, - /** Lookup150: frame_system::CodeUpgradeAuthorization */ + /** Lookup151: frame_system::CodeUpgradeAuthorization */ FrameSystemCodeUpgradeAuthorization: { codeHash: "H256", checkVersion: "bool", }, - /** Lookup151: frame_system::pallet::Call */ + /** Lookup152: frame_system::pallet::Call */ FrameSystemCall: { _enum: { remark: { @@ -1841,41 +1852,41 @@ export default { }, }, }, - /** Lookup155: frame_system::limits::BlockWeights */ + /** Lookup156: frame_system::limits::BlockWeights */ FrameSystemLimitsBlockWeights: { baseBlock: "SpWeightsWeightV2Weight", maxBlock: "SpWeightsWeightV2Weight", perClass: "FrameSupportDispatchPerDispatchClassWeightsPerClass", }, - /** Lookup156: frame_support::dispatch::PerDispatchClass */ + /** Lookup157: frame_support::dispatch::PerDispatchClass */ FrameSupportDispatchPerDispatchClassWeightsPerClass: { normal: "FrameSystemLimitsWeightsPerClass", operational: "FrameSystemLimitsWeightsPerClass", mandatory: "FrameSystemLimitsWeightsPerClass", }, - /** Lookup157: frame_system::limits::WeightsPerClass */ + /** Lookup158: frame_system::limits::WeightsPerClass */ FrameSystemLimitsWeightsPerClass: { baseExtrinsic: "SpWeightsWeightV2Weight", maxExtrinsic: "Option", maxTotal: "Option", reserved: "Option", }, - /** Lookup159: frame_system::limits::BlockLength */ + /** Lookup160: frame_system::limits::BlockLength */ FrameSystemLimitsBlockLength: { max: "FrameSupportDispatchPerDispatchClassU32", }, - /** Lookup160: frame_support::dispatch::PerDispatchClass */ + /** Lookup161: frame_support::dispatch::PerDispatchClass */ FrameSupportDispatchPerDispatchClassU32: { normal: "u32", operational: "u32", mandatory: "u32", }, - /** Lookup161: sp_weights::RuntimeDbWeight */ + /** Lookup162: sp_weights::RuntimeDbWeight */ SpWeightsRuntimeDbWeight: { read: "u64", write: "u64", }, - /** Lookup162: sp_version::RuntimeVersion */ + /** Lookup163: sp_version::RuntimeVersion */ SpVersionRuntimeVersion: { specName: "Text", implName: "Text", @@ -1886,7 +1897,7 @@ export default { transactionVersion: "u32", stateVersion: "u8", }, - /** Lookup166: frame_system::pallet::Error */ + /** Lookup167: frame_system::pallet::Error */ FrameSystemError: { _enum: [ "InvalidSpecName", @@ -1899,49 +1910,49 @@ export default { "Unauthorized", ], }, - /** Lookup168: cumulus_pallet_parachain_system::unincluded_segment::Ancestor */ + /** Lookup169: cumulus_pallet_parachain_system::unincluded_segment::Ancestor */ CumulusPalletParachainSystemUnincludedSegmentAncestor: { usedBandwidth: "CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth", paraHeadHash: "Option", consumedGoAheadSignal: "Option", }, - /** Lookup169: cumulus_pallet_parachain_system::unincluded_segment::UsedBandwidth */ + /** Lookup170: cumulus_pallet_parachain_system::unincluded_segment::UsedBandwidth */ CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth: { umpMsgCount: "u32", umpTotalBytes: "u32", hrmpOutgoing: "BTreeMap", }, - /** Lookup171: cumulus_pallet_parachain_system::unincluded_segment::HrmpChannelUpdate */ + /** Lookup172: cumulus_pallet_parachain_system::unincluded_segment::HrmpChannelUpdate */ CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate: { msgCount: "u32", totalBytes: "u32", }, - /** Lookup176: polkadot_primitives::v6::UpgradeGoAhead */ + /** Lookup177: polkadot_primitives::v6::UpgradeGoAhead */ PolkadotPrimitivesV6UpgradeGoAhead: { _enum: ["Abort", "GoAhead"], }, - /** Lookup177: cumulus_pallet_parachain_system::unincluded_segment::SegmentTracker */ + /** Lookup178: cumulus_pallet_parachain_system::unincluded_segment::SegmentTracker */ CumulusPalletParachainSystemUnincludedSegmentSegmentTracker: { usedBandwidth: "CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth", hrmpWatermark: "Option", consumedGoAheadSignal: "Option", }, - /** Lookup178: polkadot_primitives::v6::PersistedValidationData */ + /** Lookup179: polkadot_primitives::v6::PersistedValidationData */ PolkadotPrimitivesV6PersistedValidationData: { parentHead: "Bytes", relayParentNumber: "u32", relayParentStorageRoot: "H256", maxPovSize: "u32", }, - /** Lookup181: polkadot_primitives::v6::UpgradeRestriction */ + /** Lookup182: polkadot_primitives::v6::UpgradeRestriction */ PolkadotPrimitivesV6UpgradeRestriction: { _enum: ["Present"], }, - /** Lookup182: sp_trie::storage_proof::StorageProof */ + /** Lookup183: sp_trie::storage_proof::StorageProof */ SpTrieStorageProof: { trieNodes: "BTreeSet", }, - /** Lookup184: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot */ + /** Lookup185: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot */ CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: { dmqMqcHead: "H256", relayDispatchQueueRemainingCapacity: @@ -1949,12 +1960,12 @@ export default { ingressChannels: "Vec<(u32,PolkadotPrimitivesV6AbridgedHrmpChannel)>", egressChannels: "Vec<(u32,PolkadotPrimitivesV6AbridgedHrmpChannel)>", }, - /** Lookup185: cumulus_pallet_parachain_system::relay_state_snapshot::RelayDispatchQueueRemainingCapacity */ + /** Lookup186: cumulus_pallet_parachain_system::relay_state_snapshot::RelayDispatchQueueRemainingCapacity */ CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity: { remainingCount: "u32", remainingSize: "u32", }, - /** Lookup188: polkadot_primitives::v6::AbridgedHrmpChannel */ + /** Lookup189: polkadot_primitives::v6::AbridgedHrmpChannel */ PolkadotPrimitivesV6AbridgedHrmpChannel: { maxCapacity: "u32", maxTotalSize: "u32", @@ -1963,7 +1974,7 @@ export default { totalSize: "u32", mqcHead: "Option", }, - /** Lookup189: polkadot_primitives::v6::AbridgedHostConfiguration */ + /** Lookup190: polkadot_primitives::v6::AbridgedHostConfiguration */ PolkadotPrimitivesV6AbridgedHostConfiguration: { maxCodeSize: "u32", maxHeadDataSize: "u32", @@ -1976,17 +1987,17 @@ export default { validationUpgradeDelay: "u32", asyncBackingParams: "PolkadotPrimitivesV6AsyncBackingAsyncBackingParams", }, - /** Lookup190: polkadot_primitives::v6::async_backing::AsyncBackingParams */ + /** Lookup191: polkadot_primitives::v6::async_backing::AsyncBackingParams */ PolkadotPrimitivesV6AsyncBackingAsyncBackingParams: { maxCandidateDepth: "u32", allowedAncestryLen: "u32", }, - /** Lookup196: polkadot_core_primitives::OutboundHrmpMessage */ + /** Lookup197: polkadot_core_primitives::OutboundHrmpMessage */ PolkadotCorePrimitivesOutboundHrmpMessage: { recipient: "u32", data: "Bytes", }, - /** Lookup197: cumulus_pallet_parachain_system::pallet::Call */ + /** Lookup198: cumulus_pallet_parachain_system::pallet::Call */ CumulusPalletParachainSystemCall: { _enum: { set_validation_data: { @@ -2004,24 +2015,24 @@ export default { }, }, }, - /** Lookup198: cumulus_primitives_parachain_inherent::ParachainInherentData */ + /** Lookup199: cumulus_primitives_parachain_inherent::ParachainInherentData */ CumulusPrimitivesParachainInherentParachainInherentData: { validationData: "PolkadotPrimitivesV6PersistedValidationData", relayChainState: "SpTrieStorageProof", downwardMessages: "Vec", horizontalMessages: "BTreeMap>", }, - /** Lookup200: polkadot_core_primitives::InboundDownwardMessage */ + /** Lookup201: polkadot_core_primitives::InboundDownwardMessage */ PolkadotCorePrimitivesInboundDownwardMessage: { sentAt: "u32", msg: "Bytes", }, - /** Lookup203: polkadot_core_primitives::InboundHrmpMessage */ + /** Lookup204: polkadot_core_primitives::InboundHrmpMessage */ PolkadotCorePrimitivesInboundHrmpMessage: { sentAt: "u32", data: "Bytes", }, - /** Lookup206: cumulus_pallet_parachain_system::pallet::Error */ + /** Lookup207: cumulus_pallet_parachain_system::pallet::Error */ CumulusPalletParachainSystemError: { _enum: [ "OverlappingUpgrades", @@ -2034,7 +2045,7 @@ export default { "Unauthorized", ], }, - /** Lookup207: pallet_timestamp::pallet::Call */ + /** Lookup208: pallet_timestamp::pallet::Call */ PalletTimestampCall: { _enum: { set: { @@ -2042,9 +2053,9 @@ export default { }, }, }, - /** Lookup208: staging_parachain_info::pallet::Call */ + /** Lookup209: staging_parachain_info::pallet::Call */ StagingParachainInfoCall: "Null", - /** Lookup209: pallet_sudo::pallet::Call */ + /** Lookup210: pallet_sudo::pallet::Call */ PalletSudoCall: { _enum: { sudo: { @@ -2067,7 +2078,7 @@ export default { remove_key: "Null", }, }, - /** Lookup211: pallet_utility::pallet::Call */ + /** Lookup212: pallet_utility::pallet::Call */ PalletUtilityCall: { _enum: { batch: { @@ -2093,7 +2104,7 @@ export default { }, }, }, - /** Lookup213: dancebox_runtime::OriginCaller */ + /** Lookup214: dancebox_runtime::OriginCaller */ DanceboxRuntimeOriginCaller: { _enum: { system: "FrameSupportDispatchRawOrigin", @@ -2152,7 +2163,7 @@ export default { PolkadotXcm: "PalletXcmOrigin", }, }, - /** Lookup214: frame_support::dispatch::RawOrigin */ + /** Lookup215: frame_support::dispatch::RawOrigin */ FrameSupportDispatchRawOrigin: { _enum: { Root: "Null", @@ -2160,23 +2171,23 @@ export default { None: "Null", }, }, - /** Lookup215: cumulus_pallet_xcm::pallet::Origin */ + /** Lookup216: cumulus_pallet_xcm::pallet::Origin */ CumulusPalletXcmOrigin: { _enum: { Relay: "Null", SiblingParachain: "u32", }, }, - /** Lookup216: pallet_xcm::pallet::Origin */ + /** Lookup217: pallet_xcm::pallet::Origin */ PalletXcmOrigin: { _enum: { Xcm: "StagingXcmV3MultiLocation", Response: "StagingXcmV3MultiLocation", }, }, - /** Lookup217: sp_core::Void */ + /** Lookup218: sp_core::Void */ SpCoreVoid: "Null", - /** Lookup218: pallet_proxy::pallet::Call */ + /** Lookup219: pallet_proxy::pallet::Call */ PalletProxyCall: { _enum: { proxy: { @@ -2227,11 +2238,11 @@ export default { }, }, }, - /** Lookup222: pallet_maintenance_mode::pallet::Call */ + /** Lookup223: pallet_maintenance_mode::pallet::Call */ PalletMaintenanceModeCall: { _enum: ["enter_maintenance_mode", "resume_normal_operation"], }, - /** Lookup223: pallet_tx_pause::pallet::Call */ + /** Lookup224: pallet_tx_pause::pallet::Call */ PalletTxPauseCall: { _enum: { pause: { @@ -2242,7 +2253,7 @@ export default { }, }, }, - /** Lookup224: pallet_balances::pallet::Call */ + /** Lookup225: pallet_balances::pallet::Call */ PalletBalancesCall: { _enum: { transfer_allow_death: { @@ -2277,7 +2288,7 @@ export default { }, }, }, - /** Lookup225: pallet_stream_payment::pallet::Call */ + /** Lookup226: pallet_stream_payment::pallet::Call */ PalletStreamPaymentCall: { _enum: { open_stream: { @@ -2312,7 +2323,7 @@ export default { }, }, }, - /** Lookup226: pallet_stream_payment::pallet::ChangeKind