Unverified Commit 39181b46 authored by Keith Yeung's avatar Keith Yeung
Browse files

WIP for testing recursion limit in WASM

parent 08379ba5
Pipeline #151276 failed with stages
in 14 minutes and 18 seconds
......@@ -7222,6 +7222,7 @@ dependencies = [
"pallet-transaction-payment",
"pallet-transaction-payment-rpc-runtime-api",
"pallet-vesting",
"pallet-xcm",
"parity-scale-codec",
"polkadot-parachain",
"polkadot-primitives",
......@@ -7250,6 +7251,9 @@ dependencies = [
"sp-version",
"substrate-wasm-builder",
"tiny-keccak",
"xcm",
"xcm-builder",
"xcm-executor",
]
[[package]]
......@@ -12275,14 +12279,23 @@ name = "xcm-executor"
version = "0.9.8"
dependencies = [
"frame-support",
"frame-system",
"futures 0.3.15",
"impl-trait-for-tuples",
"log",
"pallet-xcm",
"parity-scale-codec",
"polkadot-test-client",
"polkadot-test-runtime",
"polkadot-test-service",
"sp-arithmetic",
"sp-consensus",
"sp-core",
"sp-io",
"sp-keyring",
"sp-runtime",
"sp-std",
"sp-tracing",
"xcm",
]
......
......@@ -55,8 +55,12 @@ pallet-vesting = { git = "https://github.com/paritytech/substrate", branch = "ma
runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false }
primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false }
pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false }
polkadot-parachain = { path = "../../parachain", default-features = false }
polkadot-runtime-parachains = { path = "../parachains", default-features = false }
xcm-builder = { path = "../../xcm/xcm-builder", default-features = false }
xcm-executor = { path = "../../xcm/xcm-executor", default-features = false }
xcm = { path = "../../xcm", default-features = false }
[dev-dependencies]
hex-literal = "0.3.1"
......@@ -82,6 +86,10 @@ std = [
"inherents/std",
"sp-core/std",
"polkadot-parachain/std",
"pallet-xcm/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
"sp-api/std",
"tx-pool-api/std",
"block-builder-api/std",
......
......@@ -79,6 +79,7 @@ pub use sp_runtime::BuildStorage;
/// Constant values used within the runtime.
pub mod constants;
pub mod xcm_config;
use constants::{currency::*, fee::*, time::*};
// Make the WASM binary available.
......@@ -486,6 +487,29 @@ impl parachains_ump::Config for Runtime {
type FirstMessageFactorPercent = FirstMessageFactorPercent;
}
parameter_types! {
pub const BaseXcmWeight: frame_support::weights::Weight = 1_000;
pub const AnyNetwork: xcm::v0::NetworkId = xcm::v0::NetworkId::Any;
}
pub type LocalOriginToLocation = xcm_builder::SignedToAccountId32<Origin, AccountId, AnyNetwork>;
impl pallet_xcm::Config for Runtime {
// The config types here are entirely configurable, since the only one that is sorely needed
// is `XcmExecutor`, which will be used in unit tests located in xcm-executor.
type Event = Event;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmRouter = xcm_config::DoNothingRouter;
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type XcmExecuteFilter = ();
type XcmExecutor = xcm_executor::XcmExecutor<xcm_config::XcmConfig>;
type XcmTeleportFilter =
frame_support::traits::All<(xcm::v0::MultiLocation, Vec<xcm::v0::MultiAsset>)>;
type XcmReserveTransferFilter =
frame_support::traits::All<(xcm::v0::MultiLocation, Vec<xcm::v0::MultiAsset>)>;
type Weigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, Call>;
}
impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
......@@ -541,6 +565,7 @@ construct_runtime! {
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event<T>},
Ump: parachains_ump::{Pallet, Call, Storage, Event},
Dmp: parachains_dmp::{Pallet, Call, Storage},
Xcm: pallet_xcm::{Pallet, Call, Event<T>, Origin},
ParasDisputes: parachains_disputes::{Pallet, Storage, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>},
......@@ -852,3 +877,13 @@ sp_api::impl_runtime_apis! {
}
}
}
#[cfg(feature = "std")]
pub fn new_test_ext() -> sp_io::TestExternalities {
let t = frame_system::GenesisConfig::default()
.build_storage::<Runtime>()
.unwrap();
let mut ext: sp_io::TestExternalities = t.into();
ext.execute_with(|| System::set_block_number(1));
ext
}
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
use frame_support::{parameter_types, traits::All};
use xcm::v0::{Error as XcmError, MultiAsset, MultiLocation, Result as XcmResult, SendXcm, Xcm};
use xcm_builder::{
AllowUnpaidExecutionFrom, LocationInverter, FixedWeightBounds, FixedRateOfConcreteFungible,
};
use xcm_executor::{Assets, traits::TransactAsset};
parameter_types! {
pub Ancestry: MultiLocation = MultiLocation::Null;
pub KsmPerSecond: (MultiLocation, u128) = (MultiLocation::Null, 1);
}
pub struct DoNothingRouter;
impl SendXcm for DoNothingRouter {
fn send_xcm(_dest: MultiLocation, _msg: Xcm<()>) -> XcmResult {
Ok(())
}
}
pub type Barrier = AllowUnpaidExecutionFrom<All<MultiLocation>>;
pub struct DummyAssetTransactor;
impl TransactAsset for DummyAssetTransactor {
fn deposit_asset(_what: &MultiAsset, _who: &MultiLocation) -> XcmResult {
Ok(())
}
fn withdraw_asset(_what: &MultiAsset, _who: &MultiLocation) -> Result<Assets, XcmError> {
Ok(Assets::default())
}
}
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type Call = super::Call;
type XcmSender = DoNothingRouter;
type AssetTransactor = DummyAssetTransactor;
type OriginConverter = pallet_xcm::XcmPassthrough<super::Origin>;
type IsReserve = ();
type IsTeleporter = ();
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<super::BaseXcmWeight, super::Call>;
type Trader = FixedRateOfConcreteFungible<KsmPerSecond, ()>;
type ResponseHandler = ();
}
......@@ -17,6 +17,17 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
log = { version = "0.4.14", default-features = false }
[dev-dependencies]
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
futures = "0.3.15"
pallet-xcm = { path = "../pallet-xcm" }
polkadot-test-client = { path = "../../node/test/client" }
polkadot-test-runtime = { path = "../../runtime/test-runtime" }
polkadot-test-service = { path = "../../node/test/service" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
[features]
default = ["std"]
std = [
......
......@@ -356,3 +356,104 @@ impl<Config: config::Config> XcmExecutor<Config> {
Ok(total_surplus)
}
}
#[cfg(test)]
mod tests {
use super::*;
use polkadot_test_client::{
BlockBuilderExt, ClientBlockImportExt, DefaultTestClientBuilderExt, ExecutionStrategy,
InitPolkadotBlockBuilder, TestClientBuilder, TestClientBuilderExt,
};
use polkadot_test_runtime::new_test_ext;
use polkadot_test_service::construct_extrinsic;
#[test]
fn recursion_limit_works() {
use xcm::v0::prelude::*;
sp_tracing::try_init_simple();
new_test_ext().execute_with(|| {
let mut client = TestClientBuilder::new()
.set_execution_strategy(ExecutionStrategy::AlwaysWasm)
.build();
// let mut msg = WithdrawAsset {
// assets: vec![ConcreteFungible { id: X1(Parent), amount: 0 }],
// effects: vec![],
// };
// for _ in 0..MAX_RECURSION_LIMIT {
// // nest `msg` into itself on each iteration.
// msg = WithdrawAsset {
// assets: vec![ConcreteFungible { id: X1(Parent), amount: 0 }],
// effects: vec![BuyExecution {
// fees: All,
// weight: 0,
// debt: 5,
// halt_on_error: true,
// xcm: vec![msg],
// }],
// };
// }
let execute = construct_extrinsic(
&client,
// polkadot_test_runtime::Call::Xcm(
// pallet_xcm::Call::execute(Box::new(msg.clone()), 1_000_000_000),
// ),
polkadot_test_runtime::Call::System(
frame_system::Call::remark_with_event(b"hello".to_vec()),
),
sp_keyring::Sr25519Keyring::Alice,
);
let mut block_builder = client.init_polkadot_block_builder();
block_builder.push_polkadot_extrinsic(execute).expect("pushes extrinsic");
let block = block_builder.build().expect("Finalizes the block").block;
futures::executor::block_on(client.import(sp_consensus::BlockOrigin::Own, block))
.expect("imports the block");
assert!(polkadot_test_runtime::System::events().iter().any(|r| matches!(
dbg!(&r.event),
polkadot_test_runtime::Event::Xcm(pallet_xcm::Event::Attempted(Outcome::Complete(_))),
)));
// msg = WithdrawAsset {
// assets: vec![ConcreteFungible { id: X1(Parent), amount: 0 }],
// effects: vec![BuyExecution {
// fees: All,
// weight: 0,
// debt: 5,
// halt_on_error: true,
// xcm: vec![msg],
// }],
// };
// let execute = construct_extrinsic(
// &client,
// polkadot_test_runtime::Call::Xcm(
// pallet_xcm::Call::execute(Box::new(msg.clone()), 1_000_000_000),
// ),
// sp_keyring::Sr25519Keyring::Alice,
// );
// let mut block_builder = client.init_polkadot_block_builder();
// block_builder.push_polkadot_extrinsic(execute).expect("pushes extrinsic");
// let block = block_builder.build().expect("Finalizes the block").block;
// futures::executor::block_on(client.import(sp_consensus::BlockOrigin::Own, block))
// .expect("imports the block");
// assert!(polkadot_test_runtime::System::events().iter().any(|r| matches!(
// r.event,
// polkadot_test_runtime::Event::Xcm(pallet_xcm::Event::Attempted(
// Outcome::Incomplete(_, XcmError::RecursionLimitReached),
// )),
// )));
});
}
}
......@@ -212,63 +212,4 @@ mod tests {
);
});
}
#[test]
fn recursion_limit_works() {
use parachain::{Event, System};
use xcm_executor::MAX_RECURSION_LIMIT;
MockNet::reset();
ParaA::execute_with(|| {
let mut msg = WithdrawAsset {
assets: vec![ConcreteFungible { id: X1(Parent), amount: 0 }],
effects: vec![],
};
for _ in 0..MAX_RECURSION_LIMIT {
// nest `msg` into itself on each iteration.
msg = WithdrawAsset {
assets: vec![ConcreteFungible { id: X1(Parent), amount: 0 }],
effects: vec![xcm::v0::Order::BuyExecution {
fees: All,
weight: 0,
debt: 5,
halt_on_error: true,
xcm: vec![msg],
}],
};
}
let origin = parachain::Origin::signed(ALICE);
assert_ok!(ParachainPalletXcm::execute(origin, Box::new(msg.clone()), 1_000_000_000));
assert!(System::events().iter().any(|r| matches!(
r.event,
Event::PolkadotXcm(pallet_xcm::Event::Attempted(xcm::v0::Outcome::Complete(_))),
)));
let origin = parachain::Origin::signed(ALICE);
msg = WithdrawAsset {
assets: vec![ConcreteFungible { id: X1(Parent), amount: 0 }],
effects: vec![xcm::v0::Order::BuyExecution {
fees: All,
weight: 0,
debt: 5,
halt_on_error: true,
xcm: vec![msg],
}],
};
assert_ok!(ParachainPalletXcm::execute(origin, Box::new(msg), 1_000_000_000));
assert!(System::events().iter().any(|r| matches!(
r.event,
Event::PolkadotXcm(pallet_xcm::Event::Attempted(xcm::v0::Outcome::Incomplete(
_,
xcm::v0::Error::RecursionLimitReached
))),
)));
});
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment