From 1c9dca4b2f8fcc0e19c2336ee3186fb07886ba1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Rodriguez?= Date: Wed, 2 Oct 2024 12:10:59 -0300 Subject: [PATCH] Add XCM `DryRun` and `LocationToAccount` runtime APIs to all runtimes (#2980) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * point dependencies to moonbeam-polkadot-sdk-stable2407 * bump packages versions to match polkadot-sdk * apply TransactionPov changes * update runtime configs (wip) * update imports * mute hrmp channel moonriver - Litmus (#2914) * Add step to Build workflow to check for WASM runtime sizes (#2888) * add simple wasm size check * only run on pull requests * add Github token to env * fix download dir name * try comparing previous and current runtimes * change master branch with dynamic target branch ref * add comparison to latest release * test with older release * download from release instead of workflow artifact * debug release tag not saved to env * debug some more * use gh cli to get releases instead of git tag * use gh api instead of releases * remove get build id & fix awk parsing * build runtimes with _, releases with - * add comment to PR and format msg * use markdown report & replace comment * cat report & fix comment formatting * add twiggy diff reports as artifacts * use upload v4 & create reports dir * rm: deprecated ::set-output cmd * add log event (#2918) * Extract Storage Read costs for dev tests involved in #2786 (#2915) * add: storage read cost constant * update test-pov * update xcm-v3 tests * update xcm-v4 tests * add storage read gas cost to constants * update test-precompile * load constant in beforeAll * replace gas cost with weight to gas ratio * Fix auto-pause xcm: incoming XCMP messages where dropped when auto-pause (#2913) * chore: rename crate manual-xcm-rpc -> moonbeam-dev-rpc * add RPC method test_skipRelayBlocks * allow Root to resume XCM execution * update moonkit pin * add dev-test that trigger auto-pause of xcm * prettier * dev test auto-pause xcm: remove unused imports & improve test scenario * add pallet-emergency-para-xcm to moonriver * add pallet-emergency-para-xcm to moonbeam * apply review suggestions * Set the block size to 60mln gas for moonbeam (#2921) * set the block size to 60mln gas for moonbeam * update mbip-5 value in test * Add pallet_parameters (moonbase only) (#2923) * add pallet parameters * XcmFeesAccount * add copyrights * add FeesTreasuryProportion --------- Co-authored-by: Rodrigo Quelhas <22591718+RomarQ@users.noreply.github.com> * make moonbeam compile * remove cumulus_pallet_dmp_queue * remove unused import * add proper para_id to MockValidationDataInherentDataProvider * update config for tests * add MockTimestampInherentDataProvider to simulate consistent and sequential relay slots * Revert "apply TransactionPov changes" This reverts commit 43821077a173d3f1ec6106dfc361a7446f2938ba. * update cargo lock pins * remove import of deleted TransacionPoV * Make cargo test compile * Add XcmRecorder to XcmConfig * Add VersionWrapper to hrmp::COnfig * Remove code from deprecated pallet treasury * Remove code from deprecated DmpQueue * Remove code from deprecated XCMV2 * remove deprecated tresury pallet tests, add some for the new functionality * fix tests * fix remaining dev tests * fix licenses * fix lazy loading backend for stable * remove unused patch * fix linters * fix cargo test with benchmarking and tracing enabled * fix lazy loading * fix command for lazy loading * update frontier pin * support new 'stableYYMM' versioning for polkadot * update polkadot sdk pin * fix download-polkadot script * simplify script * Replace thread_local with AtomicU64 (as per review request) * remove deprecated test code * use latest version of nextest * add DryRunApi and LocationToAccountApi * Update precompiles/collective/src/mock.rs Co-authored-by: Rodrigo Quelhas <22591718+RomarQ@users.noreply.github.com> * apply review suggestions * Revert "apply review suggestions" This reverts commit 6daef572fb5feb408dd9205e78ca0ef971ca141b. * apply review suggestions * fix lazy-loading * re add reset_issuance * add missing weights * remove unused var * add TS tests * cleanup * fmt * fix download correct binaries * cargo fmt * make polkadot worker binearies executable * configure XcmRecorder for mocks --------- Co-authored-by: Gonza Montiel Co-authored-by: Éloïs Co-authored-by: pablito テ Co-authored-by: Rodrigo Quelhas <22591718+RomarQ@users.noreply.github.com> Co-authored-by: Andrea Giacobino Co-authored-by: Tarek Mohamed Abdalla Co-authored-by: Rodrigo Quelhas Co-authored-by: Gonza Montiel --- runtime/common/Cargo.toml | 1 + runtime/common/src/apis.rs | 37 ++++ runtime/moonbase/Cargo.toml | 1 + runtime/moonbase/src/lib.rs | 5 +- runtime/moonbeam/Cargo.toml | 1 + runtime/moonbeam/src/lib.rs | 5 +- runtime/moonriver/Cargo.toml | 1 + runtime/moonriver/src/lib.rs | 5 +- .../test-xcm-v4/test-xcm-dry-run-api.ts | 209 ++++++++++++++++++ .../test-xcm-location-to-account-api.ts | 22 ++ 10 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 test/suites/dev/moonbase/test-xcm-v4/test-xcm-dry-run-api.ts create mode 100644 test/suites/dev/moonbase/test-xcm-v4/test-xcm-location-to-account-api.ts diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index cf735f9c32..981cf21e66 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -166,6 +166,7 @@ runtime-benchmarks = [ "pallet-xcm/runtime-benchmarks", "pallet-moonbeam-lazy-migrations/runtime-benchmarks", "moonbeam-xcm-benchmarks/runtime-benchmarks", + "xcm-runtime-apis/runtime-benchmarks", ] try-runtime = [ "cumulus-pallet-parachain-system/try-runtime", diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index f2997e6e6c..144a82f966 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -765,6 +765,43 @@ macro_rules! impl_runtime_apis_plus_common { } } + impl xcm_runtime_apis::dry_run::DryRunApi + for Runtime { + fn dry_run_call( + origin: OriginCaller, + call: RuntimeCall + ) -> Result, XcmDryRunApiError> { + PolkadotXcm::dry_run_call::< + Runtime, + xcm_config::XcmRouter, + OriginCaller, + RuntimeCall>(origin, call) + } + + fn dry_run_xcm( + origin_location: VersionedLocation, + xcm: VersionedXcm + ) -> Result, XcmDryRunApiError> { + PolkadotXcm::dry_run_xcm::< + Runtime, + xcm_config::XcmRouter, + RuntimeCall, + xcm_config::XcmExecutorConfig>(origin_location, xcm) + } + } + + impl xcm_runtime_apis::conversions::LocationToAccountApi for Runtime { + fn convert_location(location: VersionedLocation) -> Result< + AccountId, + xcm_runtime_apis::conversions::Error + > { + xcm_runtime_apis::conversions::LocationToAccountHelper::< + AccountId, + xcm_config::LocationToAccountId, + >::convert_location(location) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { diff --git a/runtime/moonbase/Cargo.toml b/runtime/moonbase/Cargo.toml index 4127271ddb..160d5387f0 100644 --- a/runtime/moonbase/Cargo.toml +++ b/runtime/moonbase/Cargo.toml @@ -395,6 +395,7 @@ runtime-benchmarks = [ "session-keys-primitives/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", + "xcm-runtime-apis/runtime-benchmarks", ] try-runtime = [ diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index 7fdf19deca..e06469486c 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -120,7 +120,10 @@ use sp_std::{ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; -use xcm_runtime_apis::fees::Error as XcmPaymentApiError; +use xcm_runtime_apis::{ + dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, +}; use smallvec::smallvec; use sp_runtime::serde::{Deserialize, Serialize}; diff --git a/runtime/moonbeam/Cargo.toml b/runtime/moonbeam/Cargo.toml index 4a34f57b12..c52ea28aeb 100644 --- a/runtime/moonbeam/Cargo.toml +++ b/runtime/moonbeam/Cargo.toml @@ -379,6 +379,7 @@ runtime-benchmarks = [ "session-keys-primitives/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", + "xcm-runtime-apis/runtime-benchmarks", ] try-runtime = [ diff --git a/runtime/moonbeam/src/lib.rs b/runtime/moonbeam/src/lib.rs index 246b819d8d..e4d2e81796 100644 --- a/runtime/moonbeam/src/lib.rs +++ b/runtime/moonbeam/src/lib.rs @@ -99,7 +99,10 @@ use sp_runtime::{ }; use sp_std::{convert::TryFrom, prelude::*}; use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; -use xcm_runtime_apis::fees::Error as XcmPaymentApiError; +use xcm_runtime_apis::{ + dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, +}; #[cfg(feature = "std")] use sp_version::NativeVersion; diff --git a/runtime/moonriver/Cargo.toml b/runtime/moonriver/Cargo.toml index 8676640689..1347ed8ca9 100644 --- a/runtime/moonriver/Cargo.toml +++ b/runtime/moonriver/Cargo.toml @@ -384,6 +384,7 @@ runtime-benchmarks = [ "session-keys-primitives/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", + "xcm-runtime-apis/runtime-benchmarks", ] try-runtime = [ "cumulus-pallet-parachain-system/try-runtime", diff --git a/runtime/moonriver/src/lib.rs b/runtime/moonriver/src/lib.rs index 83f1f94245..080d1c9bd5 100644 --- a/runtime/moonriver/src/lib.rs +++ b/runtime/moonriver/src/lib.rs @@ -99,7 +99,10 @@ use sp_runtime::{ }; use sp_std::{convert::TryFrom, prelude::*}; use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; -use xcm_runtime_apis::fees::Error as XcmPaymentApiError; +use xcm_runtime_apis::{ + dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects}, + fees::Error as XcmPaymentApiError, +}; use smallvec::smallvec; #[cfg(feature = "std")] diff --git a/test/suites/dev/moonbase/test-xcm-v4/test-xcm-dry-run-api.ts b/test/suites/dev/moonbase/test-xcm-v4/test-xcm-dry-run-api.ts new file mode 100644 index 0000000000..0676a93c51 --- /dev/null +++ b/test/suites/dev/moonbase/test-xcm-v4/test-xcm-dry-run-api.ts @@ -0,0 +1,209 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { alith, generateKeyringPair } from "@moonwall/util"; +import { ApiPromise, WsProvider } from "@polkadot/api"; +import { u8aToHex } from "@polkadot/util"; +import { XcmFragment } from "../../../../helpers"; + +// TODO: remove once the api is present in @polkadot/api +const runtimeApi = { + runtime: { + DryRunApi: [ + { + methods: { + dry_run_call: { + description: "Dry run call", + params: [ + { + name: "origin", + type: "OriginCaller", + }, + { + name: "call", + type: "Call", + }, + ], + type: "Result, XcmDryRunError>", + }, + dry_run_xcm: { + description: "Dry run XCM program", + params: [ + { + name: "origin_location", + type: "XcmVersionedLocation", + }, + { + name: "xcm", + type: "XcmVersionedXcm", + }, + ], + type: "Result", + }, + }, + version: 1, + }, + ], + }, + types: { + CallDryRunEffects: { + ExecutionResult: "DispatchResultWithPostInfo", + EmittedEvents: "Vec", + LocalXcm: "Option", + ForwardedXcms: "Vec<(XcmVersionedLocation, Vec)>", + }, + DispatchErrorWithPostInfoTPostDispatchInfo: { + postInfo: "PostDispatchInfo", + error: "DispatchError", + }, + DispatchResultWithPostInfo: { + _enum: { + Ok: "PostDispatchInfo", + Err: "DispatchErrorWithPostInfoTPostDispatchInfo", + }, + }, + PostDispatchInfo: { + actualWeight: "Option", + paysFee: "Pays", + }, + XcmDryRunEffects: { + ExecutionResult: "StagingXcmV4TraitsOutcome", + EmittedEvents: "Vec", + ForwardedXcms: "Vec<(XcmVersionedLocation, Vec)>", + }, + XcmDryRunError: { + _enum: { + Unimplemented: "Null", + VersionedConversionFailed: "Null", + }, + }, + }, +}; + +describeSuite({ + id: "D014135", + title: "XCM - DryRunApi", + foundationMethods: "dev", + testCases: ({ context, it }) => { + let polkadotJs: ApiPromise; + + beforeAll(async function () { + polkadotJs = await ApiPromise.create({ + provider: new WsProvider(`ws://localhost:${process.env.MOONWALL_RPC_PORT}/`), + ...runtimeApi, + }); + }); + + it({ + id: "T01", + title: "Should succeed calling DryRunApi::dryRunCall", + test: async function () { + const metadata = await context.polkadotJs().rpc.state.getMetadata(); + const balancesPalletIndex = metadata.asLatest.pallets + .find(({ name }) => name.toString() == "Balances")! + .index.toNumber(); + + const randomReceiver = "0x1111111111111111111111111111111111111111111111111111111111111111"; + + // Beneficiary from destination's point of view + const destBeneficiary = { + V3: { + parents: 0, + interior: { + X1: { + AccountId32: { + network: null, + id: randomReceiver, + }, + }, + }, + }, + }; + + const assetsToSend = { + V3: [ + { + id: { + Concrete: { + parents: 0, + interior: { + X1: { PalletInstance: Number(balancesPalletIndex) }, + }, + }, + }, + fun: { + Fungible: 1_000_000_000_000_000n, + }, + }, + ], + }; + const dest = { + V3: { + parents: 1, + interior: { + Here: null, + }, + }, + }; + const polkadotXcmTx = polkadotJs.tx.polkadotXcm.transferAssets( + dest, + destBeneficiary, + assetsToSend, + 0, + "Unlimited" + ); + + const dryRunCall = await polkadotJs.call.dryRunApi.dryRunCall( + { system: { signed: alith.address } }, + polkadotXcmTx + ); + + expect(dryRunCall.isOk).to.be.true; + expect(dryRunCall.asOk.ExecutionResult.isOk).be.true; + }, + }); + + it({ + id: "T02", + title: "Should succeed calling DryRunApi::dryRunXcm", + test: async function () { + const metadata = await context.polkadotJs().rpc.state.getMetadata(); + const balancesPalletIndex = metadata.asLatest.pallets + .find(({ name }) => name.toString() == "Balances")! + .index.toNumber(); + const randomKeyPair = generateKeyringPair(); + + // We will dry run a "ReserveAssetDeposited" coming from the relay + const xcmMessage = new XcmFragment({ + assets: [ + { + multilocation: { + parents: 0, + interior: { + X1: { PalletInstance: Number(balancesPalletIndex) }, + }, + }, + fungible: 1_000_000_000_000_000n, + }, + ], + beneficiary: u8aToHex(randomKeyPair.addressRaw), + }) + .reserve_asset_deposited() + .clear_origin() + .buy_execution() + .deposit_asset_v3() + .as_v3(); + + const dryRunXcm = await polkadotJs.call.dryRunApi.dryRunXcm( + { + V3: { + Concrete: { parent: 1, interior: { Here: null } }, + }, + }, + xcmMessage + ); + + expect(dryRunXcm.isOk).to.be.true; + expect(dryRunXcm.asOk.ExecutionResult.isComplete).be.true; + }, + }); + }, +}); diff --git a/test/suites/dev/moonbase/test-xcm-v4/test-xcm-location-to-account-api.ts b/test/suites/dev/moonbase/test-xcm-v4/test-xcm-location-to-account-api.ts new file mode 100644 index 0000000000..b07ba597c1 --- /dev/null +++ b/test/suites/dev/moonbase/test-xcm-v4/test-xcm-location-to-account-api.ts @@ -0,0 +1,22 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { RELAY_V3_SOURCE_LOCATION } from "../../../../helpers/assets"; + +describeSuite({ + id: "D014136", + title: "XCM - LocationToAccountApi", + foundationMethods: "dev", + testCases: ({ context, it }) => { + it({ + id: "T01", + title: "Should succeed calling LocationToAccountApi::convertLocation", + test: async function () { + const convertLocation = await context + .polkadotJs() + .call.locationToAccountApi.convertLocation(RELAY_V3_SOURCE_LOCATION); + + expect(convertLocation.isOk).to.be.true; + expect(convertLocation.asOk.toHuman()).to.eq("0x506172656E740000000000000000000000000000"); + }, + }); + }, +});