diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 76f40ae9..db1935c7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -62,8 +62,8 @@ jobs: uses: jlumbroso/free-disk-space@main with: android: true - dotnet: false - haskell: false + dotnet: true + haskell: true large-packages: false swap-storage: false diff --git a/Cargo.lock b/Cargo.lock index da99bd55..7173c1a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6043,6 +6043,39 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-lockdown-mode" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-dmp-queue", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-assets", + "pallet-balances", + "pallet-remark", + "pallet-xcm", + "parachain-info", + "parachains-common", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", + "xcm-builder", + "xcm-executor", + "xcm-primitives", + "xcm-simulator", +] + [[package]] name = "pallet-membership" version = "4.0.0-dev" @@ -6282,6 +6315,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-remark" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.40#98f2e3451c9143278ec53c6718940aeabcd3b68a" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-scheduler" version = "4.0.0-dev" @@ -12378,6 +12426,7 @@ dependencies = [ "pallet-dex-rpc-runtime-api", "pallet-identity", "pallet-insecure-randomness-collective-flip", + "pallet-lockdown-mode", "pallet-multisig", "pallet-preimage", "pallet-scheduler", @@ -12412,12 +12461,29 @@ dependencies = [ "sp-transaction-pool", "sp-version", "substrate-wasm-builder", + "trappist-runtime-benchmarks", "xcm", "xcm-builder", "xcm-executor", "xcm-primitives", ] +[[package]] +name = "trappist-runtime-benchmarks" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "trappist-service" version = "1.0.0" @@ -14005,6 +14071,7 @@ name = "xcm-primitives" version = "0.0.1" dependencies = [ "frame-support", + "sp-runtime", "sp-std", "xcm", "xcm-executor", diff --git a/node/service/src/chain_spec/trappist.rs b/node/service/src/chain_spec/trappist.rs index b2053db4..5d9fa82c 100644 --- a/node/service/src/chain_spec/trappist.rs +++ b/node/service/src/chain_spec/trappist.rs @@ -233,6 +233,7 @@ fn testnet_genesis( phantom: Default::default(), }, treasury: Default::default(), + lockdown_mode: Default::default(), } } @@ -349,5 +350,6 @@ fn trappist_live_genesis( phantom: Default::default(), }, treasury: Default::default(), + lockdown_mode: Default::default(), } } diff --git a/pallets/asset-registry/src/benchmarking.rs b/pallets/asset-registry/src/benchmarking.rs index d5df544a..154111c0 100644 --- a/pallets/asset-registry/src/benchmarking.rs +++ b/pallets/asset-registry/src/benchmarking.rs @@ -5,48 +5,38 @@ use super::*; #[allow(unused)] use crate::Pallet as AssetRegistry; use frame_benchmarking::benchmarks; -use frame_support::{assert_ok, traits::fungibles::Inspect}; +use frame_support::assert_ok; use frame_system::RawOrigin; use xcm::opaque::latest::{ Junction::{GeneralIndex, PalletInstance, Parachain}, Junctions, MultiLocation, }; -pub const LOCAL_ASSET_ID: u32 = 10; - benchmarks! { - where_clause { - where - T::Assets: Inspect<::AccountId, AssetId = u32>, - } - register_reserve_asset { + let asset_id = T::BenchmarkHelper::get_registered_asset(); let asset_multi_location = MultiLocation { parents: 1, interior: Junctions::X3(Parachain(Default::default()), PalletInstance(Default::default()), GeneralIndex(Default::default())) }; - }: _(RawOrigin::Root, LOCAL_ASSET_ID, asset_multi_location.clone()) + }: _(RawOrigin::Root, asset_id, asset_multi_location.clone()) verify { - let read_asset_multi_location = AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID) - .expect("error reading AssetIdMultiLocation"); - assert_eq!(read_asset_multi_location, asset_multi_location); + assert_eq!(AssetIdMultiLocation::::get(asset_id), Some(asset_multi_location)); } unregister_reserve_asset { + let asset_id = T::BenchmarkHelper::get_registered_asset(); let asset_multi_location = MultiLocation { parents: 1, interior: Junctions::X3(Parachain(Default::default()), PalletInstance(Default::default()), GeneralIndex(Default::default())) }; - assert_ok!(AssetRegistry::::register_reserve_asset(RawOrigin::Root.into(), LOCAL_ASSET_ID, asset_multi_location.clone())); - let read_asset_multi_location = AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID) - .expect("error reading AssetIdMultiLocation"); - assert_eq!(read_asset_multi_location, asset_multi_location); - - }: _(RawOrigin::Root, LOCAL_ASSET_ID) + assert_ok!(AssetRegistry::::register_reserve_asset(RawOrigin::Root.into(), asset_id, asset_multi_location.clone())); + assert!(AssetIdMultiLocation::::contains_key(asset_id)); + }: _(RawOrigin::Root, asset_id) verify { - assert_eq!(AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID), None); + assert_eq!(AssetIdMultiLocation::::get(asset_id), None); } impl_benchmark_test_suite!(AssetRegistry, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/pallets/asset-registry/src/lib.rs b/pallets/asset-registry/src/lib.rs index 24ccc330..26eefa42 100644 --- a/pallets/asset-registry/src/lib.rs +++ b/pallets/asset-registry/src/lib.rs @@ -32,21 +32,27 @@ pub mod pallet { type AssetIdOf = <::Assets as Inspect<::AccountId>>::AssetId; + #[cfg(feature = "runtime-benchmarks")] + pub trait BenchmarkHelper { + fn get_registered_asset() -> AssetId; + } + #[pallet::config] pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; type ReserveAssetModifierOrigin: EnsureOrigin; type Assets: Inspect; type WeightInfo: WeightInfo; + /// Helper trait for benchmarks. + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper: BenchmarkHelper>; } #[pallet::storage] - #[pallet::getter(fn asset_id_multilocation)] pub type AssetIdMultiLocation = StorageMap<_, Blake2_128Concat, AssetIdOf, MultiLocation>; #[pallet::storage] - #[pallet::getter(fn asset_multilocation_id)] pub type AssetMultiLocationId = StorageMap<_, Blake2_128Concat, MultiLocation, AssetIdOf>; @@ -81,7 +87,7 @@ pub mod pallet { T::ReserveAssetModifierOrigin::ensure_origin(origin)?; // verify asset exists on pallet-assets - ensure!(Self::asset_exists(asset_id), Error::::AssetDoesNotExist); + ensure!(T::Assets::asset_exists(asset_id), Error::::AssetDoesNotExist); // verify asset is not yet registered ensure!( @@ -90,23 +96,23 @@ pub mod pallet { ); // verify MultiLocation is valid - let parents_multi_location_ok = { asset_multi_location.parents == 1 }; - let junctions_multi_location_ok = matches!( - asset_multi_location.interior, - Junctions::X3(Parachain(_), PalletInstance(_), GeneralIndex(_)) - ); - ensure!( - parents_multi_location_ok && junctions_multi_location_ok, + matches!( + asset_multi_location, + MultiLocation { + parents: 1, + interior: Junctions::X3(Parachain(_), PalletInstance(_), GeneralIndex(_)) + } + ), Error::::WrongMultiLocation ); - // register asset + // register asset_id => asset_multi_location AssetIdMultiLocation::::insert(asset_id, &asset_multi_location); + // register asset_multi_location => asset_id AssetMultiLocationId::::insert(&asset_multi_location, asset_id); Self::deposit_event(Event::ReserveAssetRegistered { asset_id, asset_multi_location }); - Ok(()) } @@ -118,12 +124,11 @@ pub mod pallet { ) -> DispatchResult { T::ReserveAssetModifierOrigin::ensure_origin(origin)?; - // verify asset is registered + // remove asset_id => asset_multi_location, while getting the value let asset_multi_location = - AssetIdMultiLocation::::get(asset_id).ok_or(Error::::AssetIsNotRegistered)?; - - // unregister asset - AssetIdMultiLocation::::remove(asset_id); + AssetIdMultiLocation::::mutate_exists(asset_id, Option::take) + .ok_or(Error::::AssetIsNotRegistered)?; + // remove asset_multi_location => asset_id AssetMultiLocationId::::remove(&asset_multi_location); Self::deposit_event(Event::ReserveAssetUnregistered { asset_id, asset_multi_location }); @@ -136,15 +141,8 @@ pub mod pallet { AssetIdMultiLocation::::get(asset_id) } - fn get_asset_id(asset_type: MultiLocation) -> Option> { + fn get_asset_id(asset_type: &MultiLocation) -> Option> { AssetMultiLocationId::::get(asset_type) } } - - impl Pallet { - // check if the asset exists - fn asset_exists(asset_id: AssetIdOf) -> bool { - T::Assets::asset_exists(asset_id) - } - } } diff --git a/pallets/asset-registry/src/mock.rs b/pallets/asset-registry/src/mock.rs index cdb31dea..ff8295bc 100644 --- a/pallets/asset-registry/src/mock.rs +++ b/pallets/asset-registry/src/mock.rs @@ -57,11 +57,22 @@ impl system::Config for Test { type MaxConsumers = ConstU32<16>; } +#[cfg(feature = "runtime-benchmarks")] +pub struct MockAssetRegistryBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_registry::BenchmarkHelper for MockAssetRegistryBenchmarkHelper { + fn get_registered_asset() -> u32 { + LOCAL_ASSET_ID + } +} + impl pallet_asset_registry::Config for Test { type RuntimeEvent = RuntimeEvent; type ReserveAssetModifierOrigin = frame_system::EnsureRoot; type Assets = Assets; type WeightInfo = pallet_asset_registry::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = MockAssetRegistryBenchmarkHelper; } impl pallet_balances::Config for Test { diff --git a/pallets/asset-registry/src/tests.rs b/pallets/asset-registry/src/tests.rs index 3d08c598..2b5271ff 100644 --- a/pallets/asset-registry/src/tests.rs +++ b/pallets/asset-registry/src/tests.rs @@ -1,42 +1,67 @@ -use crate::{mock::*, Error}; use frame_support::{assert_noop, assert_ok}; use xcm::latest::prelude::*; +use crate::{mock::*, AssetIdMultiLocation, AssetMultiLocationId, Error}; + +const STATEMINE_ASSET_MULTI_LOCATION: MultiLocation = MultiLocation { + parents: 1, + interior: X3( + Parachain(StatemineParaIdInfo::get()), + PalletInstance(StatemineAssetsInstanceInfo::get()), + GeneralIndex(StatemineAssetIdInfo::get()), + ), +}; + #[test] fn register_reserve_asset_works() { new_test_ext().execute_with(|| { - let statemine_para_id = StatemineParaIdInfo::get(); - let statemine_assets_pallet = StatemineAssetsInstanceInfo::get(); - let statemine_asset_id = StatemineAssetIdInfo::get(); + assert_ok!(AssetRegistry::register_reserve_asset( + RuntimeOrigin::root(), + LOCAL_ASSET_ID, + STATEMINE_ASSET_MULTI_LOCATION, + )); - let statemine_asset_multi_location = MultiLocation { - parents: 1, - interior: X3( - Parachain(statemine_para_id), - PalletInstance(statemine_assets_pallet), - GeneralIndex(statemine_asset_id), + assert_eq!( + AssetIdMultiLocation::::get(LOCAL_ASSET_ID), + Some(STATEMINE_ASSET_MULTI_LOCATION) + ); + assert_eq!( + AssetMultiLocationId::::get(STATEMINE_ASSET_MULTI_LOCATION), + Some(LOCAL_ASSET_ID) + ); + }); +} + +#[test] +fn cannot_register_unexisting_asset() { + new_test_ext().execute_with(|| { + let unexisting_asset_id = 9999; + + assert_noop!( + AssetRegistry::register_reserve_asset( + RuntimeOrigin::root(), + unexisting_asset_id, + STATEMINE_ASSET_MULTI_LOCATION, ), - }; + Error::::AssetDoesNotExist + ); + }); +} +#[test] +fn cannot_double_register() { + new_test_ext().execute_with(|| { assert_ok!(AssetRegistry::register_reserve_asset( RuntimeOrigin::root(), LOCAL_ASSET_ID, - statemine_asset_multi_location.clone(), + STATEMINE_ASSET_MULTI_LOCATION, )); - let read_asset_multi_location = AssetRegistry::asset_id_multilocation(LOCAL_ASSET_ID) - .expect("error reading AssetIdMultiLocation"); - assert_eq!(read_asset_multi_location, statemine_asset_multi_location); - - let read_asset_id = AssetRegistry::asset_multilocation_id(&statemine_asset_multi_location) - .expect("error reading AssetMultiLocationId"); - assert_eq!(read_asset_id, LOCAL_ASSET_ID); - assert_noop!( AssetRegistry::register_reserve_asset( RuntimeOrigin::root(), LOCAL_ASSET_ID, - statemine_asset_multi_location, + STATEMINE_ASSET_MULTI_LOCATION, ), Error::::AssetAlreadyRegistered ); @@ -46,30 +71,25 @@ fn register_reserve_asset_works() { #[test] fn unregister_reserve_asset_works() { new_test_ext().execute_with(|| { - let statemine_para_id = StatemineParaIdInfo::get(); - let statemine_assets_pallet = StatemineAssetsInstanceInfo::get(); - let statemine_asset_id = StatemineAssetIdInfo::get(); - - let statemine_asset_multi_location = MultiLocation { - parents: 1, - interior: X3( - Parachain(statemine_para_id), - PalletInstance(statemine_assets_pallet), - GeneralIndex(statemine_asset_id), - ), - }; - assert_ok!(AssetRegistry::register_reserve_asset( RuntimeOrigin::root(), LOCAL_ASSET_ID, - statemine_asset_multi_location.clone(), + STATEMINE_ASSET_MULTI_LOCATION, )); assert_ok!(AssetRegistry::unregister_reserve_asset(RuntimeOrigin::root(), LOCAL_ASSET_ID)); - assert!(AssetRegistry::asset_id_multilocation(LOCAL_ASSET_ID).is_none()); - assert!( - AssetRegistry::asset_multilocation_id(statemine_asset_multi_location.clone()).is_none() + assert!(AssetIdMultiLocation::::get(LOCAL_ASSET_ID).is_none()); + assert!(AssetMultiLocationId::::get(STATEMINE_ASSET_MULTI_LOCATION).is_none()); + }); +} + +#[test] +fn cannot_register_unregistered_asset() { + new_test_ext().execute_with(|| { + assert_noop!( + AssetRegistry::unregister_reserve_asset(RuntimeOrigin::root(), LOCAL_ASSET_ID), + Error::::AssetIsNotRegistered ); }); } diff --git a/pallets/asset-registry/src/weights.rs b/pallets/asset-registry/src/weights.rs index 8074c5b4..36b9cd13 100644 --- a/pallets/asset-registry/src/weights.rs +++ b/pallets/asset-registry/src/weights.rs @@ -2,11 +2,10 @@ //! Autogenerated weights for `pallet_asset_registry` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-04, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bernardo-benchmarking`, CPU: `AMD EPYC 7B13` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// collected on a c2d-highcpu-8 of Google Cloud Platform +//! DATE: 2023-05-18, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `vale`, CPU: `11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // ./target/release/trappist-collator @@ -16,6 +15,8 @@ // dev // --pallet // pallet_asset_registry +// --execution=wasm +// --wasm-execution=compiled // --extrinsic // * // --steps @@ -40,36 +41,66 @@ pub trait WeightInfo { /// Weight functions for `pallet_asset_registry`. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Assets Asset (r:1 w:0) - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + /// Proof: AssetRegistry AssetIdMultiLocation (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) + /// Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Proof: AssetRegistry AssetMultiLocationId (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) fn register_reserve_asset() -> Weight { - Weight::from_parts(18_710_000, 0) + // Proof Size summary in bytes: + // Measured: `123` + // Estimated: `7762` + // Minimum execution time: 21_998_000 picoseconds. + Weight::from_parts(22_970_000, 0) + .saturating_add(Weight::from_parts(0, 7762)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + /// Proof: AssetRegistry AssetIdMultiLocation (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) + /// Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Proof: AssetRegistry AssetMultiLocationId (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) fn unregister_reserve_asset() -> Weight { - Weight::from_parts(16_570_000, 0) + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `4087` + // Minimum execution time: 17_862_000 picoseconds. + Weight::from_parts(18_454_000, 0) + .saturating_add(Weight::from_parts(0, 4087)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } } impl WeightInfo for () { - // Storage: Assets Asset (r:1 w:0) - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + /// Proof: AssetRegistry AssetIdMultiLocation (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) + /// Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Proof: AssetRegistry AssetMultiLocationId (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) fn register_reserve_asset() -> Weight { - Weight::from_parts(18_710_000, 0) + // Proof Size summary in bytes: + // Measured: `123` + // Estimated: `7762` + // Minimum execution time: 21_998_000 picoseconds. + Weight::from_parts(22_970_000, 0) + .saturating_add(Weight::from_parts(0, 7762)) .saturating_add(RocksDbWeight::get().reads(2)) .saturating_add(RocksDbWeight::get().writes(2)) } - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + /// Proof: AssetRegistry AssetIdMultiLocation (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) + /// Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + /// Proof: AssetRegistry AssetMultiLocationId (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) fn unregister_reserve_asset() -> Weight { - Weight::from_parts(16_570_000, 0) + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `4087` + // Minimum execution time: 17_862_000 picoseconds. + Weight::from_parts(18_454_000, 0) + .saturating_add(Weight::from_parts(0, 4087)) .saturating_add(RocksDbWeight::get().reads(1)) .saturating_add(RocksDbWeight::get().writes(2)) } diff --git a/pallets/benchmarks/Cargo.toml b/pallets/benchmarks/Cargo.toml new file mode 100644 index 00000000..37a06362 --- /dev/null +++ b/pallets/benchmarks/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "trappist-runtime-benchmarks" +version = "0.1.0" +edition = "2021" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", ] } +scale-info = { version = "2.3.1", default-features = false, features = ["derive"] } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } + +xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.40" } +xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.40" } + +[dev-dependencies] +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-std/std", + "xcm-executor/std" +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] \ No newline at end of file diff --git a/pallets/benchmarks/src/benchmarking.rs b/pallets/benchmarks/src/benchmarking.rs new file mode 100644 index 00000000..7d6da011 --- /dev/null +++ b/pallets/benchmarks/src/benchmarking.rs @@ -0,0 +1,57 @@ +use frame_benchmarking::benchmarks; +use sp_runtime::SaturatedConversion; +use xcm::prelude::AssetId as XcmAssetId; + +use crate::*; + +benchmarks! { + drop_assets_fungible { + let origin = MultiLocation::default(); + let asset_id = 1; + let location: MultiLocation = Parachain(asset_id).into(); + T::register_asset(asset_id.into(), location.clone()); + let asset = MultiAsset { id: XcmAssetId::Concrete(location), fun: Fungibility::Fungible(100) }; + } : { + T::DropAssets::drop_assets( + &origin, + asset.into(), + &XcmContext { + origin: Some(origin.clone()), + message_hash: [0; 32], + topic: None, + }, + ); + } + + drop_assets_native { + let origin = MultiLocation::default(); + let location = MultiLocation { parents: 0, interior: Here }; + let amount = T::ExistentialDeposit::get().saturated_into(); + let asset = MultiAsset { id: XcmAssetId::Concrete(location), fun: Fungibility::Fungible(amount) }; + } : { + T::DropAssets::drop_assets( + &origin, + asset.into(), + &XcmContext { + origin: Some(origin.clone()), + message_hash: [0; 32], + topic: None, + }, + ); + } + + drop_assets_default { + let origin = MultiLocation::default(); + let asset = MultiAsset { id: XcmAssetId::Abstract(Default::default()), fun: Fungibility::Fungible(0) }; + } : { + T::DropAssets::drop_assets( + &origin, + asset.into(), + &XcmContext { + origin: Some(origin.clone()), + message_hash: [0; 32], + topic: None, + }, + ); + } +} diff --git a/pallets/benchmarks/src/lib.rs b/pallets/benchmarks/src/lib.rs new file mode 100644 index 00000000..34427034 --- /dev/null +++ b/pallets/benchmarks/src/lib.rs @@ -0,0 +1,43 @@ +//! Pallet for benchmarking. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::Codec; +use frame_support::{pallet_prelude::*, traits::tokens::AssetId}; +use sp_runtime::traits::AtLeast32BitUnsigned; +use xcm::prelude::*; +use xcm_executor::traits::DropAssets; + +pub use pallet::*; +pub use weights::*; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; +pub mod weights; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// Identifier for the class of asset. + type AssetId: AssetId + From; + + /// The balance of an account. + type Balance: Parameter + Member + AtLeast32BitUnsigned + Codec + TypeInfo; + + /// The minimum amount required to keep an account open. + #[pallet::constant] + type ExistentialDeposit: Get; + + /// Handler for when some non-empty `Assets` value should be dropped. + type DropAssets: DropAssets; + + /// Handler to register an asset. + fn register_asset(asset_id: Self::AssetId, location: MultiLocation); + } + + #[pallet::pallet] + pub struct Pallet(_); +} diff --git a/pallets/benchmarks/src/weights.rs b/pallets/benchmarks/src/weights.rs new file mode 100644 index 00000000..411eef76 --- /dev/null +++ b/pallets/benchmarks/src/weights.rs @@ -0,0 +1,7 @@ +use frame_support::weights::Weight; + +pub trait WeightInfo { + fn drop_assets_fungible() -> Weight; + fn drop_assets_native() -> Weight; + fn drop_assets_default() -> Weight; +} diff --git a/pallets/lockdown-mode/Cargo.toml b/pallets/lockdown-mode/Cargo.toml new file mode 100644 index 00000000..14746944 --- /dev/null +++ b/pallets/lockdown-mode/Cargo.toml @@ -0,0 +1,77 @@ +[package] +name = "pallet-lockdown-mode" +version = "0.1.0" +description = "Trappist pallet for setting lockdown mode." +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/paritytech/trappist" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive",] } +scale-info = { version = "2.3.1", default-features = false, features = ["derive"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.40", default-features = false } +pallet-assets = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +log = "0.4.17" +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } + +xcm-primitives = { path = "../../primitives/xcm", default-features = false } + +[dev-dependencies] +sp-core = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +sp-io = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +sp-runtime = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } +pallet-remark = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.40" } + + +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +xcm-simulator = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } + +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.40", default-features = false } +parachains-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.40", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.40", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.40", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.40", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-runtime/std", + "sp-std/std", + "pallet-assets/std", + "pallet-balances/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "xcm-primitives/std", + "xcm/std", + "xcm-executor/std", + "xcm-builder/std", + "pallet-xcm/std", + "polkadot-core-primitives/std", + "polkadot-runtime-parachains/std", + "polkadot-parachain/std", + "parachain-info/std", + "parachains-common/std", + "cumulus-pallet-dmp-queue/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] \ No newline at end of file diff --git a/pallets/lockdown-mode/README.md b/pallets/lockdown-mode/README.md new file mode 100644 index 00000000..94e9686c --- /dev/null +++ b/pallets/lockdown-mode/README.md @@ -0,0 +1,41 @@ +# Lockdown Mode Pallet + +The Lockdown Mode Pallet is a Substrate module that provides functionality to lock down the runtime execution in a Substrate-based blockchain system. When the lockdown mode is activated, it filters out incoming calls and messages to ensure that only authorized actions are allowed. + +## Overview + +This pallet the governance of the chain to activate or deactivate a lockdown mode. When the lockdown mode is activated, incoming runtime calls and downward messages are filtered based on a preconfigured filter. Additionally, it suspends the execution of XCM (Cross-Consensus Message) messages in the `on_idle` hook. + +The lockdown mode status is stored in the `LockdownModeStatus` storage item. When the lockdown mode is deactivated, the system resumes normal operations, including the execution of XCM messages in the `on_idle` hook. + +## Configuration + +This pallet supports configurable traits that allow customization according to specific needs. + +### Types + +- `RuntimeEvent`: Specifies the runtime event type. +- `LockdownModeOrigin`: Specifies the origin that is allowed to activate and deactivate the lockdown mode. +- `BlackListedCalls`: Specifies the filter used to filter incoming runtime calls in lockdown mode. +- `LockdownDmpHandler`: Specifies the handler for downward messages in lockdown mode. +- `XcmExecutorManager`: Interface to control the execution of XCMP Queue messages. + + +## Extrinsics + +The pallet provides the following extrinsics: + +- `activate_lockdown_mode`: Activates the lockdown mode. Only the specified `LockdownModeOrigin` can call this extrinsic. It updates the `LockdownModeStatus` storage item to `ACTIVATED` (true) and attempts to suspend the execution of XCM messages in the `on_idle` hook. +- `deactivate_lockdown_mode`: Deactivates the lockdown mode. Only the specified `LockdownModeOrigin` can call this extrinsic. It updates the `LockdownModeStatus` storage item to `DEACTIVATED` (false) and attempts to resume the execution of XCM messages in the `on_idle` hook. + + +#### Errors + +Possible errors returned by the dispatchable calls are: + +- `LockdownModeAlreadyActivated`: The lockdown mode is already activated. +- `LockdownModeAlreadyDeactivated`: The lockdown mode is already deactivated. + +Please note that any failure to suspend or resume XCM execution in the `on_idle` hook is not treated as a fatal error that stops the function execution. Instead, it is recorded as an event `FailedToSuspendIdleXcmExecution` or `FailedToResumeIdleXcmExecution`, respectively, and the function continues its execution. + +The lockdown mode can serve as a crucial tool in system maintenance or in case of emergency, when it's necessary to restrict system operation and ensure the system's security and stability. \ No newline at end of file diff --git a/pallets/lockdown-mode/src/benchmarking.rs b/pallets/lockdown-mode/src/benchmarking.rs new file mode 100644 index 00000000..9f98ead7 --- /dev/null +++ b/pallets/lockdown-mode/src/benchmarking.rs @@ -0,0 +1,25 @@ +use super::*; + +#[allow(unused)] +use crate::Pallet as LockdownMode; +use crate::{ACTIVATED, DEACTIVATED}; +use frame_benchmarking::benchmarks; +use frame_system::RawOrigin; + +benchmarks! { + activate_lockdown_mode { + LockdownModeStatus::::put(DEACTIVATED); + }: activate_lockdown_mode(RawOrigin::Root) + verify { + assert_eq!(LockdownModeStatus::::get(), ACTIVATED); + } + + deactivate_lockdown_mode { + LockdownModeStatus::::put(ACTIVATED); + }: deactivate_lockdown_mode(RawOrigin::Root) + verify { + assert_eq!(LockdownModeStatus::::get(), DEACTIVATED); + } + + impl_benchmark_test_suite!(LockdownMode, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/lockdown-mode/src/lib.rs b/pallets/lockdown-mode/src/lib.rs new file mode 100644 index 00000000..dd035e32 --- /dev/null +++ b/pallets/lockdown-mode/src/lib.rs @@ -0,0 +1,148 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +/// Edit this file to define custom logic or remove it if it is not needed. +/// Learn more about FRAME and the core library of Substrate FRAME pallets: +/// +pub use pallet::*; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod weights; +pub use weights::*; + +pub const ACTIVATED: bool = true; +pub const DEACTIVATED: bool = false; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use cumulus_primitives_core::{ + relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler, + }; + use frame_support::{ + pallet_prelude::{ValueQuery, *}, + traits::Contains, + }; + use frame_system::pallet_prelude::*; + use sp_std::vec::Vec; + use xcm_primitives::PauseXcmExecution; + #[pallet::pallet] + pub struct Pallet(_); + + #[derive(Default)] + #[pallet::genesis_config] + /// Genesis config for lockdown mode pallet + pub struct GenesisConfig {} + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + LockdownModeStatus::::put(ACTIVATED); + } + } + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type LockdownModeOrigin: EnsureOrigin; + type BlackListedCalls: Contains; + type LockdownDmpHandler: DmpMessageHandler; + type XcmExecutorManager: PauseXcmExecution; + type WeightInfo: WeightInfo; + } + + #[pallet::storage] + pub type LockdownModeStatus = StorageValue<_, bool, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + LockdownModeActivated, + LockdownModeDeactivated, + /// The call to suspend on_idle XCM execution failed with inner error + FailedToSuspendIdleXcmExecution { + error: DispatchError, + }, + /// The call to resume on_idle XCM execution failed with inner error + FailedToResumeIdleXcmExecution { + error: DispatchError, + }, + } + + #[pallet::error] + pub enum Error { + /// Lockdown mode was already activated + LockdownModeAlreadyActivated, + /// Lockdown mode was already deactivated + LockdownModeAlreadyDeactivated, + } + + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::activate_lockdown_mode())] + pub fn activate_lockdown_mode(origin: OriginFor) -> DispatchResult { + T::LockdownModeOrigin::ensure_origin(origin)?; + + ensure!(!LockdownModeStatus::::get(), Error::::LockdownModeAlreadyActivated); + + LockdownModeStatus::::put(ACTIVATED); + + if let Err(error) = T::XcmExecutorManager::suspend_xcm_execution() { + log::error!("Failed to suspend idle XCM execution {:?}", error); + Self::deposit_event(Event::FailedToSuspendIdleXcmExecution { error }); + } + + Self::deposit_event(Event::LockdownModeActivated); + + Ok(()) + } + + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::deactivate_lockdown_mode())] + pub fn deactivate_lockdown_mode(origin: OriginFor) -> DispatchResult { + T::LockdownModeOrigin::ensure_origin(origin)?; + ensure!(LockdownModeStatus::::get(), Error::::LockdownModeAlreadyDeactivated); + + LockdownModeStatus::::put(DEACTIVATED); + + if let Err(error) = T::XcmExecutorManager::resume_xcm_execution() { + log::error!("Failed to resume idle XCM execution {:?}", error); + Self::deposit_event(Event::FailedToResumeIdleXcmExecution { error }); + } + + Self::deposit_event(Event::LockdownModeDeactivated); + + Ok(()) + } + } + + impl Contains for Pallet { + fn contains(call: &T::RuntimeCall) -> bool { + if LockdownModeStatus::::get() { + T::BlackListedCalls::contains(call) + } else { + return true + } + } + } + + impl DmpMessageHandler for Pallet { + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + if LockdownModeStatus::::get() { + T::LockdownDmpHandler::handle_dmp_messages(iter, Weight::zero()) + } else { + // Normal path, everything should pass through + T::LockdownDmpHandler::handle_dmp_messages(iter, limit) + } + } + } +} diff --git a/pallets/lockdown-mode/src/mock.rs b/pallets/lockdown-mode/src/mock.rs new file mode 100644 index 00000000..e685a875 --- /dev/null +++ b/pallets/lockdown-mode/src/mock.rs @@ -0,0 +1,126 @@ +use crate as pallet_lockdown_mode; +use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler}; +use frame_support::{ + traits::{ConstU16, ConstU64, Contains}, + weights::Weight, +}; +use frame_system as system; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, ConstU32, IdentityLookup}, + DispatchResult, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::parameter_types! { + pub const StatemineParaIdInfo: u32 = 1000u32; + pub const StatemineAssetsInstanceInfo: u8 = 50u8; + pub const StatemineAssetIdInfo: u128 = 1u128; +} + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + LockdownMode: pallet_lockdown_mode::{Pallet, Call, Storage, Event}, + Balance: pallet_balances::{Pallet, Call, Storage, Event}, + Remark: pallet_remark::{Pallet, Call, Storage, Event}, + } +); + +impl system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; +} + +pub struct RuntimeBlackListedCalls; +impl Contains for RuntimeBlackListedCalls { + fn contains(call: &RuntimeCall) -> bool { + match call { + RuntimeCall::Balance(_) => false, + _ => true, + } + } +} + +pub struct LockdownDmpHandler; +impl DmpMessageHandler for LockdownDmpHandler { + fn handle_dmp_messages( + _iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + limit + } +} + +pub struct XcmExecutionManager {} + +impl xcm_primitives::PauseXcmExecution for XcmExecutionManager { + fn suspend_xcm_execution() -> DispatchResult { + Ok(()) + } + fn resume_xcm_execution() -> DispatchResult { + Ok(()) + } +} + +impl pallet_remark::Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +impl pallet_lockdown_mode::Config for Test { + type RuntimeEvent = RuntimeEvent; + type LockdownModeOrigin = frame_system::EnsureRoot; + type BlackListedCalls = RuntimeBlackListedCalls; + type LockdownDmpHandler = LockdownDmpHandler; + type XcmExecutorManager = XcmExecutionManager; + type WeightInfo = pallet_lockdown_mode::weights::SubstrateWeight; +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + let storage = system::GenesisConfig::default().build_storage::().unwrap(); + storage.into() +} diff --git a/pallets/lockdown-mode/src/tests.rs b/pallets/lockdown-mode/src/tests.rs new file mode 100644 index 00000000..cf466b52 --- /dev/null +++ b/pallets/lockdown-mode/src/tests.rs @@ -0,0 +1,71 @@ +use super::*; +use crate::{mock::*, Error, ACTIVATED, DEACTIVATED}; +use frame_support::{assert_noop, assert_ok, traits::Contains}; +use pallet_balances::{self, Call as BalancesCall}; +use pallet_remark::{self, Call as RemarkCall}; + +#[test] +fn activate_lockdown_mode_works() { + new_test_ext().execute_with(|| { + assert_eq!(LockdownModeStatus::::get(), DEACTIVATED); + assert_ok!(LockdownMode::activate_lockdown_mode(RuntimeOrigin::root())); + + let lockdown_mode = LockdownModeStatus::::get(); + assert_eq!(lockdown_mode, ACTIVATED); + + assert_noop!( + LockdownMode::activate_lockdown_mode(RuntimeOrigin::root(),), + Error::::LockdownModeAlreadyActivated + ); + }); +} + +#[test] +fn deactivate_lockdown_mode_works() { + new_test_ext().execute_with(|| { + // We activate lockdown mode first so we can deactivate it. + assert_ok!(LockdownMode::activate_lockdown_mode(RuntimeOrigin::root())); + + assert_ok!(LockdownMode::deactivate_lockdown_mode(RuntimeOrigin::root())); + + let lockdown_mode = LockdownModeStatus::::get(); + assert_eq!(lockdown_mode, DEACTIVATED); + + assert_noop!( + LockdownMode::deactivate_lockdown_mode(RuntimeOrigin::root(),), + Error::::LockdownModeAlreadyDeactivated + ); + }); +} + +#[test] +fn call_not_filtered_in_lockdown_mode() { + new_test_ext().execute_with(|| { + assert_ok!(LockdownMode::activate_lockdown_mode(RuntimeOrigin::root())); + let remark_call = RuntimeCall::Remark(RemarkCall::store { remark: vec![1, 2, 3] }); + let result: bool = LockdownMode::contains(&remark_call); + assert!(result); + }); +} + +#[test] +fn call_filtered_in_lockdown_mode() { + new_test_ext().execute_with(|| { + assert_ok!(LockdownMode::activate_lockdown_mode(RuntimeOrigin::root())); + let balance_call = RuntimeCall::Balance(BalancesCall::transfer { dest: 1, value: 2 }); + + let result: bool = LockdownMode::contains(&balance_call); + assert!(!result); + }); +} + +#[test] +fn call_not_filtered_in_normal_mode() { + new_test_ext().execute_with(|| { + let lockdown_mode = LockdownModeStatus::::get(); + assert_eq!(lockdown_mode, DEACTIVATED); + let balance_call = RuntimeCall::Balance(BalancesCall::transfer { dest: 1, value: 2 }); + let result: bool = LockdownMode::contains(&balance_call); + assert!(result); + }); +} diff --git a/pallets/lockdown-mode/src/weights.rs b/pallets/lockdown-mode/src/weights.rs new file mode 100644 index 00000000..9339a6b7 --- /dev/null +++ b/pallets/lockdown-mode/src/weights.rs @@ -0,0 +1,72 @@ + +//! Autogenerated weights for `pallet_lockdown_mode` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `vale`, CPU: `11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/trappist-collator +// benchmark +// pallet +// --chain +// dev +// --pallet +// pallet_lockdown_mode +// --execution=wasm +// --wasm-execution=compiled +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --output +// pallets/lockdown-mode/src/weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn activate_lockdown_mode() -> Weight; + fn deactivate_lockdown_mode() -> Weight; +} + +/// Weight functions for `pallet_lockdown_mode`. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: LockdownMode LockdownModeStatus (r:1 w:1) + /// Proof: LockdownMode LockdownModeStatus (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: XcmpQueue QueueSuspended (r:0 w:1) + /// Proof Skipped: XcmpQueue QueueSuspended (max_values: Some(1), max_size: None, mode: Measured) + fn activate_lockdown_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `100` + // Estimated: `1586` + // Minimum execution time: 69_552_000 picoseconds. + Weight::from_parts(75_364_000, 0) + .saturating_add(Weight::from_parts(0, 1586)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: LockdownMode LockdownModeStatus (r:1 w:1) + /// Proof: LockdownMode LockdownModeStatus (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: XcmpQueue QueueSuspended (r:0 w:1) + /// Proof Skipped: XcmpQueue QueueSuspended (max_values: Some(1), max_size: None, mode: Measured) + fn deactivate_lockdown_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `100` + // Estimated: `1586` + // Minimum execution time: 42_162_000 picoseconds. + Weight::from_parts(43_321_000, 0) + .saturating_add(Weight::from_parts(0, 1586)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/primitives/xcm/Cargo.toml b/primitives/xcm/Cargo.toml index cd64530e..391b973a 100644 --- a/primitives/xcm/Cargo.toml +++ b/primitives/xcm/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" } @@ -15,6 +16,7 @@ default = [ "std" ] std = [ "sp-std/std", "frame-support/std", + "sp-runtime/std", "xcm/std", "xcm-executor/std" ] diff --git a/primitives/xcm/src/lib.rs b/primitives/xcm/src/lib.rs index 45a9a0b1..802022fe 100644 --- a/primitives/xcm/src/lib.rs +++ b/primitives/xcm/src/lib.rs @@ -3,12 +3,13 @@ use frame_support::{ sp_runtime::SaturatedConversion, traits::{fungibles::Inspect, Currency}, + weights::Weight, }; -use sp_std::{borrow::Borrow, marker::PhantomData, vec::Vec}; +use sp_runtime::DispatchResult; +use sp_std::{borrow::Borrow, marker::PhantomData}; use xcm::{ latest::{ AssetId::Concrete, Fungibility::Fungible, Junctions::Here, MultiAsset, MultiLocation, - Weight, }, v3::XcmContext, }; @@ -27,7 +28,7 @@ where AssetIdInfoGetter: AssetMultiLocationGetter, { fn convert_ref(asset_multi_location: impl Borrow) -> Result { - AssetIdInfoGetter::get_asset_id(asset_multi_location.borrow().clone()).ok_or(()) + AssetIdInfoGetter::get_asset_id(asset_multi_location.borrow()).ok_or(()) } fn reverse_ref(asset_id: impl Borrow) -> Result { @@ -37,7 +38,7 @@ where pub trait AssetMultiLocationGetter { fn get_asset_multi_location(asset_id: AssetId) -> Option; - fn get_asset_id(asset_multi_location: MultiLocation) -> Option; + fn get_asset_id(asset_multi_location: &MultiLocation) -> Option; } pub struct ConvertedRegisteredAssetId( @@ -63,15 +64,34 @@ impl< } } +pub trait DropAssetsWeigher { + fn fungible() -> Weight; + fn native() -> Weight; + fn default() -> Weight; +} + pub struct TrappistDropAssets< AssetId, AssetIdInfoGetter, AssetsPallet, BalancesPallet, XcmPallet, - AccoundId, ->(PhantomData<(AssetId, AssetIdInfoGetter, AssetsPallet, BalancesPallet, XcmPallet, AccoundId)>); -impl DropAssets + AccountId, + Weigher, +>( + PhantomData<( + AssetId, + AssetIdInfoGetter, + AssetsPallet, + BalancesPallet, + XcmPallet, + AccountId, + Weigher, + )>, +); + +impl + DropAssets for TrappistDropAssets< AssetId, AssetIdInfoGetter, @@ -79,52 +99,68 @@ impl where - AssetId: Clone, AssetIdInfoGetter: AssetMultiLocationGetter, AssetsPallet: Inspect, BalancesPallet: Currency, XcmPallet: DropAssets, + Weigher: DropAssetsWeigher, { // assets are whatever the Holding Register had when XCVM halts - fn drop_assets(origin: &MultiLocation, assets: Assets, context: &XcmContext) -> Weight { - let multi_assets: Vec = assets.into(); - let mut trap: Vec = Vec::new(); + fn drop_assets(origin: &MultiLocation, mut assets: Assets, context: &XcmContext) -> Weight { + const NATIVE_LOCATION: MultiLocation = MultiLocation { parents: 0, interior: Here }; - for asset in multi_assets { - if let MultiAsset { id: Concrete(location), fun: Fungible(amount) } = asset.clone() { - // is location a fungible on AssetRegistry? - if let Some(asset_id) = AssetIdInfoGetter::get_asset_id(location.clone()) { - let min_balance = AssetsPallet::minimum_balance(asset_id); + let mut weight: Weight = { + assets.non_fungible.clear(); + Weigher::default() + }; - // only trap if amount ≥ min_balance - // do nothing otherwise (asset is lost) - if min_balance <= amount.saturated_into::() { - trap.push(asset); - } + assets.fungible.retain(|id, &mut amount| { + if let Concrete(location) = id { + match AssetIdInfoGetter::get_asset_id(location) { + Some(asset_id) => { + weight.saturating_accrue(Weigher::fungible()); - // is location the native token? - } else if location == (MultiLocation { parents: 0, interior: Here }) { - let min_balance = BalancesPallet::minimum_balance(); + // only trap if amount ≥ min_balance + // do nothing otherwise (asset is lost) + amount.saturated_into::() >= + AssetsPallet::minimum_balance(asset_id) + }, + None => { + weight.saturating_accrue(Weigher::native()); - // only trap if amount ≥ min_balance - // do nothing otherwise (asset is lost) - if min_balance <= amount.saturated_into::() { - trap.push(asset); - } + // only trap if native token and amount ≥ min_balance + // do nothing otherwise (asset is lost) + *location == NATIVE_LOCATION && + amount.saturated_into::() >= + BalancesPallet::minimum_balance() + }, } + } else { + weight.saturating_accrue(Weigher::default()); + false } - } - - // TODO: put real weight of execution up until this point here - let mut weight: Weight = Weight::from_parts(0, 0); + }); - if !trap.is_empty() { - // we have filtered out non-compliant assets - // insert valid assets into the asset trap implemented by XcmPallet - weight += XcmPallet::drop_assets(origin, trap.into(), context); - } + // we have filtered out non-compliant assets + // insert valid assets into the asset trap implemented by XcmPallet + weight.saturating_add(XcmPallet::drop_assets(origin, assets, context)) + } +} - weight +/// Pause and resume execution of XCM +#[cfg(not(test))] +pub trait PauseXcmExecution { + fn suspend_xcm_execution() -> DispatchResult; + fn resume_xcm_execution() -> DispatchResult; +} +#[cfg(not(test))] +impl PauseXcmExecution for () { + fn suspend_xcm_execution() -> DispatchResult { + Ok(()) + } + fn resume_xcm_execution() -> DispatchResult { + Ok(()) } } diff --git a/runtime/stout/src/xcm_config.rs b/runtime/stout/src/xcm_config.rs index 01112320..c1fa5ba4 100644 --- a/runtime/stout/src/xcm_config.rs +++ b/runtime/stout/src/xcm_config.rs @@ -19,6 +19,7 @@ use super::{ AccountId, Assets, Balance, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; +use cumulus_pallet_xcmp_queue::weights::SubstrateWeight; use frame_support::{ match_types, parameter_types, traits::{ContainsPair, EitherOfDiverse, Everything, Get, Nothing}, @@ -60,7 +61,6 @@ parameter_types! { pub CheckAccount: (AccountId, MintLocation) = (PolkadotXcm::check_account(), MintLocation::Local); pub CheckingAccount: AccountId = PolkadotXcm::check_account(); pub const ExecutiveBody: BodyId = BodyId::Executive; - pub const MaxAssetsIntoHolding: u32 = 64; pub UniversalLocation: InteriorMultiLocation = ( GlobalConsensus(NetworkId::Rococo), Parachain(ParachainInfo::parachain_id().into()), @@ -149,8 +149,9 @@ pub type XcmOriginToTransactDispatchOrigin = ( parameter_types! { // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. - pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000,0); + pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; } match_types! { @@ -294,7 +295,7 @@ impl pallet_xcm::Config for Runtime { type Currency = Balances; type CurrencyMatcher = (); type MaxLockers = ConstU32<8>; - type SovereignAccountOf = (); + type SovereignAccountOf = LocationToAccountId; type TrustedLockers = (); type UniversalLocation = UniversalLocation; // TODO: pallet-xcm weights @@ -319,7 +320,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { EnsureXcm>, >; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = cumulus_pallet_xcmp_queue::weights::SubstrateWeight; + type WeightInfo = SubstrateWeight; type PriceForSiblingDelivery = (); } diff --git a/runtime/trappist/Cargo.toml b/runtime/trappist/Cargo.toml index fb1a7ecf..53fc95e3 100644 --- a/runtime/trappist/Cargo.toml +++ b/runtime/trappist/Cargo.toml @@ -104,7 +104,9 @@ pallet-dex-rpc-runtime-api = { version = "0.0.1", git = "https://github.com/pari pallet-chess = { git = "https://github.com/SubstrateChess/pallet-chess.git", default-features = false, branch = "polkadot-v0.9.40" } # Trappist Pallets -pallet-asset-registry = { version = "0.0.1", default-features = false, path = "../../pallets/asset-registry" } +pallet-asset-registry = { default-features = false, path = "../../pallets/asset-registry" } +trappist-runtime-benchmarks = { default-features = false, path = "../../pallets/benchmarks" } +pallet-lockdown-mode = { version = "0.1.0", default-features = false, path = "../../pallets/lockdown-mode" } [features] default = ["std"] @@ -143,8 +145,9 @@ std = [ "pallet-dex/std", "pallet-dex-rpc-runtime-api/std", "pallet-identity/std", - "pallet-multisig/std", "pallet-insecure-randomness-collective-flip/std", + "pallet-lockdown-mode/std", + "pallet-multisig/std", "pallet-scheduler/std", "pallet-session/std", "pallet-sudo/std", @@ -183,12 +186,14 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-asset-registry/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "trappist-runtime-benchmarks/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-contracts/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-dex/runtime-benchmarks", "pallet-identity/runtime-benchmarks", + "pallet-lockdown-mode/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", diff --git a/runtime/trappist/src/impls.rs b/runtime/trappist/src/impls.rs index 13391c26..125526bf 100644 --- a/runtime/trappist/src/impls.rs +++ b/runtime/trappist/src/impls.rs @@ -16,8 +16,14 @@ //! Auxiliary struct/enums for parachain runtimes. //! Taken from polkadot/runtime/common (at a21cd64) and adapted for parachains. -use frame_support::traits::{Currency, Imbalance, OnUnbalanced}; - +use super::*; +use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler}; +use frame_support::{ + traits::{Contains, Currency, Imbalance, OnUnbalanced}, + weights::Weight, +}; +pub use log; +use sp_runtime::DispatchResult; use sp_std::marker::PhantomData; /// Type alias to conveniently refer to the `Currency::NegativeImbalance` associated type. @@ -66,6 +72,45 @@ where } } } + +pub struct RuntimeBlackListedCalls; +impl Contains for RuntimeBlackListedCalls { + fn contains(call: &RuntimeCall) -> bool { + match call { + RuntimeCall::Balances(_) => false, + RuntimeCall::Assets(_) => false, + RuntimeCall::Dex(_) => false, + RuntimeCall::PolkadotXcm(_) => false, + RuntimeCall::Treasury(_) => false, + RuntimeCall::Chess(_) => false, + RuntimeCall::Contracts(_) => false, + RuntimeCall::Uniques(_) => false, + RuntimeCall::AssetRegistry(_) => false, + _ => true, + } + } +} + +pub struct LockdownDmpHandler; +impl DmpMessageHandler for LockdownDmpHandler { + fn handle_dmp_messages( + _iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + DmpQueue::handle_dmp_messages(_iter, limit) + } +} + +pub struct XcmExecutionManager {} +impl xcm_primitives::PauseXcmExecution for XcmExecutionManager { + fn suspend_xcm_execution() -> DispatchResult { + XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root()) + } + fn resume_xcm_execution() -> DispatchResult { + XcmpQueue::resume_xcm_execution(RuntimeOrigin::root()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/runtime/trappist/src/lib.rs b/runtime/trappist/src/lib.rs index c76bcbc6..8341bdf8 100644 --- a/runtime/trappist/src/lib.rs +++ b/runtime/trappist/src/lib.rs @@ -17,23 +17,25 @@ #![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "256"] -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; pub mod constants; mod contracts; pub mod impls; +mod weights; pub mod xcm_config; pub use common::AssetIdForTrustBackedAssets; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +use cumulus_primitives_core::BodyId; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, ConstU8, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto}, - transaction_validity::{TransactionSource, TransactionValidity}, + transaction_validity::{InvalidTransaction, TransactionSource, TransactionValidity}, ApplyExtrinsicResult, Perbill, Percent, Permill, }; @@ -48,8 +50,8 @@ use frame_support::{ dispatch::DispatchClass, parameter_types, traits::{ - AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, ConstU64, EitherOfDiverse, - EqualPrivilegeOnly, Everything, + AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, ConstU64, Contains, EitherOfDiverse, + EqualPrivilegeOnly, }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}, @@ -61,7 +63,8 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, EnsureSigned, }; - +// Polkadot imports +use pallet_xcm::{EnsureXcm, IsMajorityOfBody}; pub use parachains_common as common; pub use parachains_common::{ impls::AssetsToBlockAuthor, opaque, AccountId, AuraId, Balance, BlockNumber, Hash, Header, @@ -69,18 +72,19 @@ pub use parachains_common::{ NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; -use impls::DealWithFees; +use impls::{LockdownDmpHandler, RuntimeBlackListedCalls, XcmExecutionManager}; + +use polkadot_runtime_common::{prod_or_fast, BlockHashCount, SlowAdjustingFeeUpdate}; +use impls::DealWithFees; use xcm_config::{CollatorSelectionUpdateOrigin, RelayLocation}; +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; -// Polkadot imports -use pallet_xcm::{EnsureXcm, IsMajorityOfBody}; -use polkadot_runtime_common::{prod_or_fast, BlockHashCount, SlowAdjustingFeeUpdate}; -use xcm::latest::prelude::BodyId; - pub const MICROUNIT: Balance = 1_000_000; /// The address format for describing accounts. @@ -170,7 +174,7 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { - type BaseCallFilter = Everything; + type BaseCallFilter = LockdownMode; type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; type AccountId = AccountId; @@ -281,7 +285,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; - type DmpMessageHandler = DmpQueue; + type DmpMessageHandler = LockdownMode; type ReservedDmpWeight = ReservedDmpWeight; type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; @@ -360,7 +364,7 @@ impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = AssetBalance; type AssetId = AssetIdForTrustBackedAssets; - type AssetIdParameter = codec::Compact; + type AssetIdParameter = codec::Compact; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; @@ -561,6 +565,34 @@ impl pallet_dex::Config for Runtime { type MinDeposit = ConstU128<{ UNITS }>; } +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetRegistryBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_registry::BenchmarkHelper + for AssetRegistryBenchmarkHelper +{ + fn get_registered_asset() -> AssetIdForTrustBackedAssets { + use sp_runtime::traits::StaticLookup; + + let root = frame_system::RawOrigin::Root.into(); + let asset_id = 1; + let caller = frame_benchmarking::whitelisted_caller(); + let caller_lookup = ::Lookup::unlookup(caller); + Assets::force_create(root, asset_id.into(), caller_lookup, true, 1) + .expect("Should have been able to force create asset"); + asset_id + } +} + +impl pallet_asset_registry::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ReserveAssetModifierOrigin = frame_system::EnsureRoot; + type Assets = Assets; + type WeightInfo = pallet_asset_registry::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetRegistryBenchmarkHelper; +} + parameter_types! { pub const ChessPalletId: PalletId = PalletId(*b"subchess"); pub const IncentiveShare: u8 = 10; // janitor gets 10% of the prize @@ -579,13 +611,6 @@ impl pallet_chess::Config for Runtime { type IncentiveShare = IncentiveShare; } -impl pallet_asset_registry::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ReserveAssetModifierOrigin = frame_system::EnsureRoot; - type Assets = Assets; - type WeightInfo = pallet_asset_registry::weights::SubstrateWeight; -} - type TreasuryApproveCancelOrigin = EitherOfDiverse< EnsureRoot, pallet_collective::EnsureProportionAtLeast, @@ -628,6 +653,15 @@ impl pallet_treasury::Config for Runtime { type SpendOrigin = frame_support::traits::NeverEnsureOrigin; } +impl pallet_lockdown_mode::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type LockdownModeOrigin = frame_system::EnsureRoot; + type BlackListedCalls = RuntimeBlackListedCalls; + type LockdownDmpHandler = LockdownDmpHandler; + type XcmExecutorManager = XcmExecutionManager; + type WeightInfo = pallet_lockdown_mode::weights::SubstrateWeight; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime where @@ -669,6 +703,7 @@ construct_runtime!( Uniques: pallet_uniques = 43, Scheduler: pallet_scheduler = 44, Preimage: pallet_preimage = 45, + LockdownMode: pallet_lockdown_mode = 46, // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 50, @@ -691,15 +726,12 @@ construct_runtime!( } ); -#[cfg(feature = "runtime-benchmarks")] -#[macro_use] -extern crate frame_benchmarking; - #[cfg(feature = "runtime-benchmarks")] mod benches { define_benchmarks!( [frame_system, SystemBench::] [pallet_asset_registry, AssetRegistry] + [trappist_runtime_benchmarks, trappist_runtime_benchmarks::Pallet::] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] @@ -707,6 +739,7 @@ mod benches { [pallet_contracts, Contracts] [pallet_collective, Council] [pallet_democracy, Democracy] + [pallet_lockdown_mode, LockdownMode] [pallet_treasury, Treasury] [pallet_assets, Assets] [pallet_dex, Dex] @@ -777,6 +810,9 @@ impl_runtime_apis! { tx: ::Extrinsic, block_hash: ::Hash, ) -> TransactionValidity { + if !::BaseCallFilter::contains(&tx.function) { + return InvalidTransaction::Call.into(); + }; Executive::validate_transaction(source, tx, block_hash) } } @@ -974,6 +1010,21 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use xcm_primitives::TrappistDropAssets; + use xcm::prelude::MultiLocation; + use crate::weights::TrappistDropAssetsWeigher; + impl trappist_runtime_benchmarks::Config for Runtime { + type AssetId = AssetIdForTrustBackedAssets; + type Balance = Balance; + type ExistentialDeposit = ConstU128; + type DropAssets = TrappistDropAssets; + + fn register_asset(asset_id: Self::AssetId, location: MultiLocation) { + pallet_asset_registry::AssetMultiLocationId::::insert(&location, asset_id); + pallet_asset_registry::AssetIdMultiLocation::::insert(asset_id, location); + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), diff --git a/runtime/trappist/src/weights/mod.rs b/runtime/trappist/src/weights/mod.rs new file mode 100644 index 00000000..8230a735 --- /dev/null +++ b/runtime/trappist/src/weights/mod.rs @@ -0,0 +1,21 @@ +use ::trappist_runtime_benchmarks::WeightInfo; +use xcm_primitives::DropAssetsWeigher; + +use crate::{Runtime, Weight}; + +mod trappist_runtime_benchmarks; + +pub struct TrappistDropAssetsWeigher(); +impl DropAssetsWeigher for TrappistDropAssetsWeigher { + fn fungible() -> Weight { + trappist_runtime_benchmarks::WeightInfo::::drop_assets_fungible() + } + + fn native() -> Weight { + trappist_runtime_benchmarks::WeightInfo::::drop_assets_native() + } + + fn default() -> Weight { + trappist_runtime_benchmarks::WeightInfo::::drop_assets_default() + } +} diff --git a/runtime/trappist/src/weights/trappist_runtime_benchmarks.rs b/runtime/trappist/src/weights/trappist_runtime_benchmarks.rs new file mode 100644 index 00000000..a830dfb1 --- /dev/null +++ b/runtime/trappist/src/weights/trappist_runtime_benchmarks.rs @@ -0,0 +1,71 @@ + +//! Autogenerated weights for `trappist_runtime_benchmarks` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-18, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `vale`, CPU: `11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/trappist-collator +// benchmark +// pallet +// --chain +// dev +// --pallet +// trappist_runtime_benchmarks +// --execution=wasm +// --wasm-execution=compiled +// --extrinsic +// * +// --steps +// 20 +// --repeat +// 10 +// --output +// runtime/trappist/src/weights/trappist_runtime_benchmarks.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `trappist_runtime_benchmarks`. +pub struct WeightInfo(PhantomData); +impl trappist_runtime_benchmarks::WeightInfo for WeightInfo { + /// Storage: AssetRegistry AssetMultiLocationId (r:1 w:0) + /// Proof: AssetRegistry AssetMultiLocationId (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + fn drop_assets_fungible() -> Weight { + // Proof Size summary in bytes: + // Measured: `131` + // Estimated: `7762` + // Minimum execution time: 9_674_000 picoseconds. + Weight::from_parts(9_953_000, 0) + .saturating_add(Weight::from_parts(0, 7762)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: AssetRegistry AssetMultiLocationId (r:1 w:0) + /// Proof: AssetRegistry AssetMultiLocationId (max_values: None, max_size: Some(622), added: 3097, mode: MaxEncodedLen) + fn drop_assets_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `4087` + // Minimum execution time: 5_313_000 picoseconds. + Weight::from_parts(5_537_000, 0) + .saturating_add(Weight::from_parts(0, 4087)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn drop_assets_default() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_539_000 picoseconds. + Weight::from_parts(1_632_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } +} diff --git a/runtime/trappist/src/xcm_config.rs b/runtime/trappist/src/xcm_config.rs index 7ef445fb..ca0883b1 100644 --- a/runtime/trappist/src/xcm_config.rs +++ b/runtime/trappist/src/xcm_config.rs @@ -13,7 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{constants::fee::default_fee_per_second, impls::ToAuthor, AllPalletsWithSystem}; +use crate::{ + constants::fee::default_fee_per_second, impls::ToAuthor, weights::TrappistDropAssetsWeigher, + AllPalletsWithSystem, +}; use super::{ AccountId, AssetRegistry, Assets, Balance, Balances, ParachainInfo, ParachainSystem, @@ -62,7 +65,6 @@ parameter_types! { pub CheckAccount: (AccountId, MintLocation) = (PolkadotXcm::check_account(), MintLocation::Local); pub CheckingAccount: AccountId = PolkadotXcm::check_account(); pub const ExecutiveBody: BodyId = BodyId::Executive; - pub const MaxAssetsIntoHolding: u32 = 64; pub UniversalLocation: InteriorMultiLocation = ( GlobalConsensus(NetworkId::Rococo), Parachain(ParachainInfo::parachain_id().into()), @@ -175,8 +177,9 @@ pub type XcmOriginToTransactDispatchOrigin = ( parameter_types! { // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. - pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000u64, 0); + pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000u64, 64 * 1024); pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; } match_types! { @@ -276,6 +279,7 @@ impl xcm_executor::Config for XcmConfig { Balances, PolkadotXcm, AccountId, + TrappistDropAssetsWeigher, >; type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; diff --git a/xcm-playground.toml b/xcm-playground.toml index 8da6cd97..d2f26c16 100644 --- a/xcm-playground.toml +++ b/xcm-playground.toml @@ -21,6 +21,11 @@ default_command = "./bin/polkadot" validator = true extra_args = [ "-lparachain=debug" ] + [[relaychain.nodes]] + name = "dave" + validator = true + extra_args = [ "-lparachain=debug" ] + [[parachains]] id = 1000 add_to_genesis = true