From b18743979d93161e47bf1e4d753595687af78f8d Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Mon, 16 Jan 2023 19:08:40 +0100 Subject: [PATCH 1/8] feat: tx-pause fork --- crates/tx-pause/Cargo.toml | 61 ++++++ crates/tx-pause/src/benchmarking.rs | 61 ++++++ crates/tx-pause/src/lib.rs | 321 ++++++++++++++++++++++++++++ crates/tx-pause/src/mock.rs | 257 ++++++++++++++++++++++ crates/tx-pause/src/tests.rs | 241 +++++++++++++++++++++ crates/tx-pause/src/weights.rs | 93 ++++++++ 6 files changed, 1034 insertions(+) create mode 100644 crates/tx-pause/Cargo.toml create mode 100644 crates/tx-pause/src/benchmarking.rs create mode 100644 crates/tx-pause/src/lib.rs create mode 100644 crates/tx-pause/src/mock.rs create mode 100644 crates/tx-pause/src/tests.rs create mode 100644 crates/tx-pause/src/weights.rs diff --git a/crates/tx-pause/Cargo.toml b/crates/tx-pause/Cargo.toml new file mode 100644 index 0000000000..0fe99c2035 --- /dev/null +++ b/crates/tx-pause/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "pallet-tx-pause" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME transaction pause pallet" +readme = "README.md" + +[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"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } +pallet-balances = { version = "4.0.0-dev", path = "../balances", default-features = false, optional = true } +pallet-utility = { version = "4.0.0-dev", path = "../utility", default-features = false, optional = true } +pallet-proxy = { version = "4.0.0-dev", path = "../proxy", default-features = false, optional = true } + +[dev-dependencies] +sp-core = { version = "6.0.0", path = "../../primitives/core" } +sp-std = { version = "4.0.0", path = "../../primitives/std" } +sp-io = { version = "6.0.0", path = "../../primitives/io" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } +pallet-utility = { version = "4.0.0-dev", path = "../utility" } +pallet-proxy = { version = "4.0.0-dev", path = "../proxy" } + + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "pallet-balances?/std", + "pallet-utility?/std", + "pallet-proxy?/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/crates/tx-pause/src/benchmarking.rs b/crates/tx-pause/src/benchmarking.rs new file mode 100644 index 0000000000..6fc20a9630 --- /dev/null +++ b/crates/tx-pause/src/benchmarking.rs @@ -0,0 +1,61 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(feature = "runtime-benchmarks")] + +use super::{Pallet as TxPause, *}; + +use frame_benchmarking::benchmarks; + +benchmarks! { + pause { + let full_name: FullNameOf = (name::(b"SomePalletName"), Some(name::(b"SomePalletName"))); + // let pallet_name: PalletNameOf = name::(b"SomePalletName"); + // let maybe_call_name: Option> = Some(name::(b"some_call_name")); + let origin = T::PauseOrigin::successful_origin(); + // let call = Call::::pause { full_name: full_name.clone() }; + // let call = Call::::pause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; + + }: _(origin, full_name.clone()) + verify { + assert!(TxPause::::paused_calls(full_name.clone()).is_some()) + } + + unpause { + let full_name: FullNameOf = (name::(b"SomePalletName"), Some(name::(b"SomePalletName"))); + let pause_origin = T::PauseOrigin::successful_origin(); + + TxPause::::pause( + pause_origin, + full_name.clone(), + )?; + + let unpause_origin = T::UnpauseOrigin::successful_origin(); + // let call = Call::::unpause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; + + }: _(unpause_origin, full_name.clone()) + verify { + assert!(TxPause::::paused_calls(full_name.clone()).is_none()) + + } + + impl_benchmark_test_suite!(TxPause, crate::mock::new_test_ext(), crate::mock::Test); +} + +pub fn name(bytes: &[u8]) -> BoundedVec { + bytes.to_vec().try_into().unwrap() +} diff --git a/crates/tx-pause/src/lib.rs b/crates/tx-pause/src/lib.rs new file mode 100644 index 0000000000..f4a1696634 --- /dev/null +++ b/crates/tx-pause/src/lib.rs @@ -0,0 +1,321 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Transaction Pause Pallet +//! +//! The Transaction Pause pallet provides a dynamic call filter that can be controlled with +//! extrinsics. This pallet may be used to disable dispatch of specific calls within a runtime. +//! +//! - [`Config`] +//! - [`Call`] +//! - [`Pallet`] +//! +//! ## Overview +//! +//! The Transaction Pause pallet provides functions for: +//! +//! - Setting a dynamic list of [`FullNameOf`] items that are matched against to filter these calls. +//! - Setting [`Config::WhitelistCallNames`] that cannot be paused by this pallet. +//! - Repatriating a reserved balance to a beneficiary account that exists. +//! - Transferring a balance between accounts (when not reserved). +//! - Slashing an account balance. +//! - Account creation and removal. +//! - Managing total issuance. +//! - Setting and managing locks. +//! +//! Can also be used as call-filter by the runtime together with the SafeMode +//! +//! TODO expand an link to safe mode in docs. +//! +//! ### Terminology +//! +//! - **Pause**: The ability to dispatch of a specific call becomes disabled. +//! - **Unpause**: The ability to dispatch of a specific call becomes enabled, if it was paused. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! - `pause` - Pause a pallet or optionally a specific call within a pallet. +//! - `unpause` - Unpause a pallet or optionally a specific call within a pallet. +//! +//! ## Usage +//! +//! The following examples show how to use the Transaction Pause pallet in your custom pallet. +//! TODO check doc links +//! ### Example within a runtime's [`pallet-frame-system::BaseCallFilter`] configuration: +//! +//! ```ignore +//! impl frame_system::Config for Runtime { +//! … +//! type BaseCallFilter = InsideBoth>; +//! … +//! } +//! ``` +//! +//! ## Genesis config +//! +//! The Transaction Pause pallet may be configured to pause calls on genesis with it's +//! [`GenesisConfig`]. +//! +//! ## Assumptions +//! +//! * TODO + +#![cfg_attr(not(feature = "std"), no_std)] + +mod benchmarking; +#[cfg(test)] +pub mod mock; +#[cfg(test)] +mod tests; +pub mod weights; + +use frame_support::{ + dispatch::GetDispatchInfo, + pallet_prelude::*, + traits::{CallMetadata, Contains, GetCallMetadata, IsSubType, IsType}, +}; +use frame_system::pallet_prelude::*; +use sp_runtime::{traits::Dispatchable, DispatchResult}; +use sp_std::{convert::TryInto, prelude::*}; + +pub use pallet::*; +pub use weights::*; + +/// The stringy name of a pallet from [`GetCallMetadata`] for [`Config::RuntimeCall`] variants. +pub type PalletNameOf = BoundedVec::MaxNameLen>; +/// The stringy name of a call (within a pallet) from [`GetCallMetadata`] for +/// [`Config::RuntimeCall`] variants. +pub type CallNameOf = BoundedVec::MaxNameLen>; +/// A sully specified pallet ([`PalletNameOf`]) and optional call ([`CallNameOf`]) +/// to partially or fully specify an item a variant of a [`Config::RuntimeCall`]. +pub type FullNameOf = (PalletNameOf, Option>); + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// The overarching call type. + type RuntimeCall: Parameter + + Dispatchable + + GetDispatchInfo + + GetCallMetadata + + From> + + IsSubType> + + IsType<::RuntimeCall>; + + /// The only origin that can pause calls. + type PauseOrigin: EnsureOrigin; + + /// The only origin that can un-pause calls. + type UnpauseOrigin: EnsureOrigin; + + /// Contains all calls that cannot be paused. + /// + /// The `TxMode` pallet cannot pause it's own calls, and does not need to be explicitly + /// added here. + type WhitelistCallNames: Contains>; + + /// Maximum length for pallet and call SCALE encoded string names. + /// + /// Too long names will not be truncated but handled like + /// [`Self::PauseTooLongNames`] specifies. + #[pallet::constant] + type MaxNameLen: Get; + + /// Specifies if functions and pallets with too long names should be treated as paused. + /// + /// Setting this to `true` ensures that all calls that + /// are callable, are also pause-able. + /// Otherwise there could be a situation where a call + /// is callable but not pause-able, which would could be exploited. + #[pallet::constant] + type PauseTooLongNames: Get; + + // Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + /// The call is (already or still) paused. + IsPaused, + + /// The call is (already or still) unpaused. + IsUnpaused, + + /// The call is listed as safe and cannot be paused. + IsUnpausable, + + // The pallet or call does not exist in the runtime. + NotFound, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// This pallet, or a specific call is now paused. \[pallet_name, Option\] + SomethingPaused { full_name: FullNameOf }, + /// This pallet, or a specific call is now unpaused. \[pallet_name, Option\] + SomethingUnpaused { full_name: FullNameOf }, + } + + /// The set of calls that are explicitly paused. + #[pallet::storage] + #[pallet::getter(fn paused_calls)] + pub type PausedCalls = + StorageMap<_, Blake2_128Concat, FullNameOf, (), OptionQuery>; + + /// Configure the initial state of this pallet in the genesis block. + #[pallet::genesis_config] + pub struct GenesisConfig { + /// The initially paused calls. + pub paused: Vec>, + pub _phantom: PhantomData, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + // NOTE: `derive(Default)` does not work together with `#[pallet::genesis_config]`. + // We therefore need to add a trivial default impl. + fn default() -> Self { + Self { paused: Default::default(), _phantom: PhantomData } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + for (pallet_name, maybe_call_name) in &self.paused { + PausedCalls::::insert((pallet_name, maybe_call_name), ()); + } + } + } + + #[pallet::call] + impl Pallet { + /// Pause a call. + /// + /// Can only be called by [`Config::PauseOrigin`]. + /// Emits an [`Event::SomethingPaused`] event on success. + #[pallet::weight(T::WeightInfo::pause())] + pub fn pause(origin: OriginFor, full_name: FullNameOf) -> DispatchResult { + T::PauseOrigin::ensure_origin(origin)?; + + Self::ensure_can_pause(&full_name)?; + PausedCalls::::insert(&full_name, ()); + Self::deposit_event(Event::SomethingPaused { full_name }); + + Ok(()) + } + + /// Un-pause a call. + /// + /// Can only be called by [`Config::UnpauseOrigin`]. + /// Emits an [`Event::SomethingUnpaused`] event on success. + #[pallet::weight(T::WeightInfo::unpause())] + pub fn unpause(origin: OriginFor, full_name: FullNameOf) -> DispatchResult { + T::UnpauseOrigin::ensure_origin(origin)?; + + Self::ensure_can_unpause(&full_name)?; + PausedCalls::::remove(&full_name); + Self::deposit_event(Event::SomethingUnpaused { full_name }); + Ok(()) + } + } +} + +impl Pallet { + /// Return whether this pallet or call is paused. + pub fn is_paused_unbound(pallet_name: Vec, call_name: Vec) -> bool { + let pallet_name = PalletNameOf::::try_from(pallet_name); + let call_name = CallNameOf::::try_from(call_name); + + match (pallet_name, call_name) { + (Ok(pallet_name), Ok(call_name)) => Self::is_paused(&&>::from(( + pallet_name.clone(), + Some(call_name.clone()), + ))), + _ => T::PauseTooLongNames::get(), + } + } + + /// Return whether this pallet or call is paused + pub fn is_paused(full_name: &FullNameOf) -> bool { + let (pallet_name, maybe_call_name) = full_name; + // SAFETY: Everything that is whitelisted cannot be paused, + // including calls within paused pallets. + if T::WhitelistCallNames::contains(&>::from(( + pallet_name.clone(), + maybe_call_name.clone(), + ))) { + return false + }; + // Check is pallet is paused. + if >::contains_key(>::from((pallet_name.clone(), None))) { + return true + }; + // Check if call in a pallet is paused + >::contains_key(full_name) + } + + /// Ensure that this pallet or call can be paused. + pub fn ensure_can_pause(full_name: &FullNameOf) -> Result<(), Error> { + // The `TxPause` pallet can never be paused. + if full_name.0.as_ref() == ::name().as_bytes().to_vec() { + return Err(Error::::IsUnpausable) + } + if Self::is_paused(&full_name) { + return Err(Error::::IsPaused) + } + if T::WhitelistCallNames::contains(&full_name) { + return Err(Error::::IsUnpausable) + } + Ok(()) + } + + /// Ensure that this call can be un-paused. + pub fn ensure_can_unpause(full_name: &FullNameOf) -> Result<(), Error> { + if Self::is_paused(&full_name) { + // SAFETY: Everything that is paused, can be un-paused. + Ok(()) + } else { + Err(Error::IsUnpaused) + } + } +} + +impl Contains<::RuntimeCall> for Pallet +where + ::RuntimeCall: GetCallMetadata, +{ + /// Return whether the call is allowed to be dispatched. + fn contains(call: &::RuntimeCall) -> bool { + let CallMetadata { pallet_name, function_name } = call.get_call_metadata(); + !Pallet::::is_paused_unbound(pallet_name.into(), function_name.into()) + } +} diff --git a/crates/tx-pause/src/mock.rs b/crates/tx-pause/src/mock.rs new file mode 100644 index 0000000000..e54ae3823a --- /dev/null +++ b/crates/tx-pause/src/mock.rs @@ -0,0 +1,257 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test utilities for transaction pause (tx pause) pallet. + +use super::*; +use crate as pallet_tx_pause; + +use frame_support::{ + parameter_types, + traits::{ConstU64, Everything, InsideBoth, InstanceFilter, SortedMembers}, +}; +use frame_system::EnsureSignedBy; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +parameter_types! { + pub const BlockHashCount: u64 = 250; +} +impl frame_system::Config for Test { + type BaseCallFilter = InsideBoth; + type BlockWeights = (); + type BlockLength = (); + type Origin = Origin; + 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 = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const MaxLocks: u32 = 10; +} +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_utility::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, +)] +pub enum ProxyType { + Any, + JustTransfer, + JustUtility, +} +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::JustTransfer => { + matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) + }, + ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), + } + } + fn is_superset(&self, o: &Self) -> bool { + self == &ProxyType::Any || self == o + } +} +impl pallet_proxy::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ConstU64<1>; + type ProxyDepositFactor = ConstU64<1>; + type MaxProxies = ConstU32<4>; + type WeightInfo = (); + type CallHasher = BlakeTwo256; + type MaxPending = ConstU32<2>; + type AnnouncementDepositBase = ConstU64<1>; + type AnnouncementDepositFactor = ConstU64<1>; +} + +parameter_types! { + pub const PauseOrigin: u64 = 1; + pub const UnpauseOrigin: u64 = 2; + pub const MaxNameLen: u32 = 50; + pub const PauseTooLongNames: bool = false; +} + +#[derive(Copy, Clone, Encode, Decode, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo)] +pub struct WhitelistCallNames; + +/// Contains used by `BaseCallFiler` so this impl whitelists `Balances::transfer_keep_alive` +/// and all DummyPallet calls. All others may be paused. +impl Contains> for WhitelistCallNames { + fn contains(full_name: &FullNameOf) -> bool { + let unpausables: Vec> = vec![ + ( + b"Balances".to_vec().try_into().unwrap(), + Some(b"transfer_keep_alive".to_vec().try_into().unwrap()), + ), + (b"DummyPallet".to_vec().try_into().unwrap(), None), + ]; + + for unpausable_call in unpausables { + let (pallet_name, maybe_call_name) = full_name; + if unpausable_call.1.is_none() { + return &unpausable_call.0 == pallet_name + } else { + if &unpausable_call.0 == pallet_name { + return &unpausable_call.1 == maybe_call_name + } + } + } + + false + } +} + +// Required impl to use some ::get() in tests +impl SortedMembers for PauseOrigin { + fn sorted_members() -> Vec { + vec![Self::get()] + } + #[cfg(feature = "runtime-benchmarks")] + fn add(_m: &u64) {} +} +impl SortedMembers for UnpauseOrigin { + fn sorted_members() -> Vec { + vec![Self::get()] + } + #[cfg(feature = "runtime-benchmarks")] + fn add(_m: &u64) {} +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureSignedBy; + type UnpauseOrigin = EnsureSignedBy; + type WhitelistCallNames = WhitelistCallNames; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Utility: pallet_utility, + Proxy: pallet_proxy, + TxPause: pallet_tx_pause, + } +); + +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { + // The 0 account is NOT a special origin. The rest may be: + balances: vec![(0, 1234), (1, 5678), (2, 5678), (3, 5678), (4, 5678)], + } + .assimilate_storage(&mut t) + .unwrap(); + + GenesisBuild::::assimilate_storage( + &pallet_tx_pause::GenesisConfig { paused: vec![], _phantom: Default::default() }, + &mut t, + ) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} + +pub fn next_block() { + TxPause::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + TxPause::on_initialize(System::block_number()); +} + +pub fn run_to(n: u64) { + while System::block_number() < n { + next_block(); + } +} diff --git a/crates/tx-pause/src/tests.rs b/crates/tx-pause/src/tests.rs new file mode 100644 index 0000000000..d490db7b64 --- /dev/null +++ b/crates/tx-pause/src/tests.rs @@ -0,0 +1,241 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg(test)] + +use super::*; +use crate::mock::{RuntimeCall, *}; + +use frame_support::{assert_err, assert_noop, assert_ok, dispatch::Dispatchable}; + +// GENERAL SUCCESS/POSITIVE TESTS --------------------- + +#[test] +fn can_pause_specific_call() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(Origin::signed(0))); + + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")) + )); + + assert_err!( + call_transfer(2, 1).dispatch(Origin::signed(2)), + frame_system::Error::::CallFiltered + ); + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(Origin::signed(3))); + }); +} + +#[test] +fn can_pause_all_calls_in_pallet_except_on_whitelist() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(Origin::signed(0))); + + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); + assert_ok!(batch_call.clone().dispatch(Origin::signed(0))); + + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Utility", None) + ),); + + assert_err!( + batch_call.clone().dispatch(Origin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn can_unpause_specific_call() { + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + assert_err!( + call_transfer(2, 1).dispatch(Origin::signed(2)), + frame_system::Error::::CallFiltered + ); + + assert_ok!(TxPause::unpause( + Origin::signed(mock::UnpauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + assert_ok!(call_transfer(4, 1).dispatch(Origin::signed(0))); + }); +} + +#[test] +fn can_filter_balance_in_batch_when_paused() { + new_test_ext().execute_with(|| { + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); + + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + + assert_ok!(batch_call.clone().dispatch(Origin::signed(0))); + System::assert_last_event( + pallet_utility::Event::BatchInterrupted { + index: 0, + error: frame_system::Error::::CallFiltered.into(), + } + .into(), + ); + }); +} + +#[test] +fn can_filter_balance_in_proxy_when_paused() { + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + + assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::JustTransfer, 0)); + + assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, Box::new(call_transfer(1, 1)))); + System::assert_last_event( + pallet_proxy::Event::ProxyExecuted { + result: DispatchError::from(frame_system::Error::::CallFiltered).into(), + } + .into(), + ); + }); +} + +// GENERAL FAIL/NEGATIVE TESTS --------------------- + +#[test] +fn fails_to_pause_self() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"TxPause", Some(b"pause")), + ), + Error::::IsUnpausable + ); + }); +} + +#[test] +fn fails_to_pause_unpausable_pallet() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"DummyPallet", Some(b"any_call")), + ), + Error::::IsUnpausable + ); + }); +} + +#[test] +fn fails_to_pause_unpausable_call_when_pallet_is_paused() { + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(Origin::signed(0))); + + let batch_call = + RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); + assert_ok!(batch_call.clone().dispatch(Origin::signed(0))); + + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", None), + )); + + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(Origin::signed(3))); + assert_err!( + call_transfer(2, 1).dispatch(Origin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn fails_to_pause_unpausable_call() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer_keep_alive")), + ), + Error::::IsUnpausable + ); + }); +} + +#[test] +fn fails_to_pause_already_paused_pallet() { + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + + assert_noop!( + TxPause::pause( + Origin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + ), + Error::::IsPaused + ); + }); +} + +#[test] +fn fails_to_unpause_not_paused_pallet() { + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::unpause( + Origin::signed(mock::UnpauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer_keep_alive")), + ), + Error::::IsUnpaused + ); + }); +} + +pub fn call_transfer(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(pallet_balances::Call::transfer { dest, value }) +} + +pub fn call_transfer_keep_alive(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { dest, value }) +} + +pub fn full_name( + pallet_name_bytes: &[u8], + maybe_call_name_bytes: Option<&[u8]>, +) -> FullNameOf { + match maybe_call_name_bytes { + Some(call_name_bytes) => >::from(( + pallet_name_bytes.to_vec().try_into().unwrap(), + Some(call_name_bytes.to_vec().try_into().unwrap()), + )), + None => >::from((pallet_name_bytes.to_vec().try_into().unwrap(), None)), + } +} diff --git a/crates/tx-pause/src/weights.rs b/crates/tx-pause/src/weights.rs new file mode 100644 index 0000000000..a4b408eef3 --- /dev/null +++ b/crates/tx-pause/src/weights.rs @@ -0,0 +1,93 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for pallet_tx_pause +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-10-15, STEPS: `1`, REPEAT: 1, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `pop-os`, CPU: `12th Gen Intel(R) Core(TM) i7-12700H` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/substrate +// benchmark +// pallet +// --steps +// 1 +// --repeat +// 1 +// --extrinsic +// * +// --execution +// wasm +// --wasm-execution +// compiled +// --heap-pages +// 4096 +// --pallet +// pallet_tx_pause +// --chain +// dev +// --output +// frame/tx-pause/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_tx_pause. +pub trait WeightInfo { + fn pause() -> Weight; + fn unpause() -> Weight; +} + +/// Weights for pallet_tx_pause using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: TxPause PausedCalls (r:2 w:1) + fn pause() -> Weight { + Weight::from_ref_time(61_745_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: TxPause PausedCalls (r:2 w:1) + fn unpause() -> Weight { + Weight::from_ref_time(55_117_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: TxPause PausedCalls (r:2 w:1) + fn pause() -> Weight { + Weight::from_ref_time(61_745_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: TxPause PausedCalls (r:2 w:1) + fn unpause() -> Weight { + Weight::from_ref_time(55_117_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } +} From 705831c7bbdb74eeff6bcdf5ac8de94686838b82 Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Mon, 16 Jan 2023 19:24:46 +0100 Subject: [PATCH 2/8] fix: get tx-pause to compile --- Cargo.lock | 18 ++++++++++++ crates/tx-pause/Cargo.toml | 33 ++++++++++----------- crates/tx-pause/src/lib.rs | 6 ++-- crates/tx-pause/src/mock.rs | 2 +- crates/tx-pause/src/tests.rs | 56 ++++++++++++++++++------------------ 5 files changed, 67 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45902fed38..d118987e67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13144,6 +13144,24 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "tx-pause" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-proxy", + "pallet-utility", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "typenum" version = "1.16.0" diff --git a/crates/tx-pause/Cargo.toml b/crates/tx-pause/Cargo.toml index 0fe99c2035..a745d77fc6 100644 --- a/crates/tx-pause/Cargo.toml +++ b/crates/tx-pause/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-tx-pause" +name = "tx-pause" version = "4.0.0-dev" authors = ["Parity Technologies "] edition = "2021" @@ -14,23 +14,24 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } -frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } -sp-runtime = { version = "6.0.0", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "4.0.0", default-features = false, path = "../../primitives/std" } -pallet-balances = { version = "4.0.0-dev", path = "../balances", default-features = false, optional = true } -pallet-utility = { version = "4.0.0-dev", path = "../utility", default-features = false, optional = true } -pallet-proxy = { version = "4.0.0-dev", path = "../proxy", default-features = false, optional = true } +scale-info = { version = "2.2.0", default-features = false, features = ["derive"] } + +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false, optional = true } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false, optional = true } +pallet-proxy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false, optional = true } [dev-dependencies] -sp-core = { version = "6.0.0", path = "../../primitives/core" } -sp-std = { version = "4.0.0", path = "../../primitives/std" } -sp-io = { version = "6.0.0", path = "../../primitives/io" } -pallet-balances = { version = "4.0.0-dev", path = "../balances" } -pallet-utility = { version = "4.0.0-dev", path = "../utility" } -pallet-proxy = { version = "4.0.0-dev", path = "../proxy" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +pallet-proxy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } [features] diff --git a/crates/tx-pause/src/lib.rs b/crates/tx-pause/src/lib.rs index f4a1696634..6b97afd7ef 100644 --- a/crates/tx-pause/src/lib.rs +++ b/crates/tx-pause/src/lib.rs @@ -121,7 +121,7 @@ pub mod pallet { /// The overarching call type. type RuntimeCall: Parameter - + Dispatchable + + Dispatchable + GetDispatchInfo + GetCallMetadata + From> @@ -129,10 +129,10 @@ pub mod pallet { + IsType<::RuntimeCall>; /// The only origin that can pause calls. - type PauseOrigin: EnsureOrigin; + type PauseOrigin: EnsureOrigin; /// The only origin that can un-pause calls. - type UnpauseOrigin: EnsureOrigin; + type UnpauseOrigin: EnsureOrigin; /// Contains all calls that cannot be paused. /// diff --git a/crates/tx-pause/src/mock.rs b/crates/tx-pause/src/mock.rs index e54ae3823a..a9294b6ac4 100644 --- a/crates/tx-pause/src/mock.rs +++ b/crates/tx-pause/src/mock.rs @@ -38,7 +38,7 @@ impl frame_system::Config for Test { type BaseCallFilter = InsideBoth; type BlockWeights = (); type BlockLength = (); - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type Index = u64; type BlockNumber = u64; diff --git a/crates/tx-pause/src/tests.rs b/crates/tx-pause/src/tests.rs index d490db7b64..983d5cf504 100644 --- a/crates/tx-pause/src/tests.rs +++ b/crates/tx-pause/src/tests.rs @@ -27,37 +27,37 @@ use frame_support::{assert_err, assert_noop, assert_ok, dispatch::Dispatchable}; #[test] fn can_pause_specific_call() { new_test_ext().execute_with(|| { - assert_ok!(call_transfer(1, 1).dispatch(Origin::signed(0))); + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")) )); assert_err!( - call_transfer(2, 1).dispatch(Origin::signed(2)), + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), frame_system::Error::::CallFiltered ); - assert_ok!(call_transfer_keep_alive(3, 1).dispatch(Origin::signed(3))); + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); }); } #[test] fn can_pause_all_calls_in_pallet_except_on_whitelist() { new_test_ext().execute_with(|| { - assert_ok!(call_transfer(1, 1).dispatch(Origin::signed(0))); + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); let batch_call = RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); - assert_ok!(batch_call.clone().dispatch(Origin::signed(0))); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Utility", None) ),); assert_err!( - batch_call.clone().dispatch(Origin::signed(0)), + batch_call.clone().dispatch(RuntimeOrigin::signed(0)), frame_system::Error::::CallFiltered ); }); @@ -67,19 +67,19 @@ fn can_pause_all_calls_in_pallet_except_on_whitelist() { fn can_unpause_specific_call() { new_test_ext().execute_with(|| { assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")), )); assert_err!( - call_transfer(2, 1).dispatch(Origin::signed(2)), + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), frame_system::Error::::CallFiltered ); assert_ok!(TxPause::unpause( - Origin::signed(mock::UnpauseOrigin::get()), + RuntimeOrigin::signed(mock::UnpauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")), )); - assert_ok!(call_transfer(4, 1).dispatch(Origin::signed(0))); + assert_ok!(call_transfer(4, 1).dispatch(RuntimeOrigin::signed(0))); }); } @@ -90,11 +90,11 @@ fn can_filter_balance_in_batch_when_paused() { RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")), )); - assert_ok!(batch_call.clone().dispatch(Origin::signed(0))); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); System::assert_last_event( pallet_utility::Event::BatchInterrupted { index: 0, @@ -109,13 +109,13 @@ fn can_filter_balance_in_batch_when_paused() { fn can_filter_balance_in_proxy_when_paused() { new_test_ext().execute_with(|| { assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")), )); - assert_ok!(Proxy::add_proxy(Origin::signed(1), 2, ProxyType::JustTransfer, 0)); + assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); - assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, Box::new(call_transfer(1, 1)))); + assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer(1, 1)))); System::assert_last_event( pallet_proxy::Event::ProxyExecuted { result: DispatchError::from(frame_system::Error::::CallFiltered).into(), @@ -132,7 +132,7 @@ fn fails_to_pause_self() { new_test_ext().execute_with(|| { assert_noop!( TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"TxPause", Some(b"pause")), ), Error::::IsUnpausable @@ -145,7 +145,7 @@ fn fails_to_pause_unpausable_pallet() { new_test_ext().execute_with(|| { assert_noop!( TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"DummyPallet", Some(b"any_call")), ), Error::::IsUnpausable @@ -156,20 +156,20 @@ fn fails_to_pause_unpausable_pallet() { #[test] fn fails_to_pause_unpausable_call_when_pallet_is_paused() { new_test_ext().execute_with(|| { - assert_ok!(call_transfer(1, 1).dispatch(Origin::signed(0))); + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); let batch_call = RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); - assert_ok!(batch_call.clone().dispatch(Origin::signed(0))); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", None), )); - assert_ok!(call_transfer_keep_alive(3, 1).dispatch(Origin::signed(3))); + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); assert_err!( - call_transfer(2, 1).dispatch(Origin::signed(0)), + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(0)), frame_system::Error::::CallFiltered ); }); @@ -180,7 +180,7 @@ fn fails_to_pause_unpausable_call() { new_test_ext().execute_with(|| { assert_noop!( TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer_keep_alive")), ), Error::::IsUnpausable @@ -192,13 +192,13 @@ fn fails_to_pause_unpausable_call() { fn fails_to_pause_already_paused_pallet() { new_test_ext().execute_with(|| { assert_ok!(TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")), )); assert_noop!( TxPause::pause( - Origin::signed(mock::PauseOrigin::get()), + RuntimeOrigin::signed(mock::PauseOrigin::get()), full_name::(b"Balances", Some(b"transfer")), ), Error::::IsPaused @@ -211,7 +211,7 @@ fn fails_to_unpause_not_paused_pallet() { new_test_ext().execute_with(|| { assert_noop!( TxPause::unpause( - Origin::signed(mock::UnpauseOrigin::get()), + RuntimeOrigin::signed(mock::UnpauseOrigin::get()), full_name::(b"Balances", Some(b"transfer_keep_alive")), ), Error::::IsUnpaused From db4b2924c9c6365a662a63d0a517d1a938dfe79f Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Mon, 16 Jan 2023 20:49:39 +0100 Subject: [PATCH 3/8] test: integration tests for tx-pause --- Cargo.lock | 1 + standalone/runtime/Cargo.toml | 3 + standalone/runtime/src/lib.rs | 25 +++- standalone/runtime/tests/mock/mod.rs | 3 + standalone/runtime/tests/test_governance.rs | 143 +++++++++++++++++++- 5 files changed, 172 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d118987e67..c516388c54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3887,6 +3887,7 @@ dependencies = [ "substrate-wasm-builder", "supply", "traits", + "tx-pause", "vault-registry", "vault-registry-rpc-runtime-api", "xcm-builder", diff --git a/standalone/runtime/Cargo.toml b/standalone/runtime/Cargo.toml index 287b7bafa6..a2a8d13a85 100644 --- a/standalone/runtime/Cargo.toml +++ b/standalone/runtime/Cargo.toml @@ -80,6 +80,7 @@ clients-info = { path = "../../crates/clients-info", default-features = false } loans = { path = "../../crates/loans", default-features = false } traits = { path = "../../crates/traits", default-features = false } farming = { path = "../../crates/farming", default-features = false } +tx-pause = { path = "../../crates/tx-pause", default-features = false } primitives = { package = "interbtc-primitives", path = "../../primitives", default-features = false } @@ -186,6 +187,7 @@ std = [ "loans/std", "traits/std", "farming/std", + "tx-pause/std", "primitives/std", @@ -233,6 +235,7 @@ runtime-benchmarks = [ "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", "farming/runtime-benchmarks", + "tx-pause/runtime-benchmarks", "orml-asset-registry/runtime-benchmarks", diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index 6eaf408cdf..a5b443f90f 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -42,6 +42,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. +use frame_support::traits::Nothing; pub use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -182,9 +183,12 @@ impl Contains for BaseCallFilter { ) { // always allow core calls true + } else if security::Pallet::::is_parachain_shutdown() { + // disallow all non-core calls if shutdown + false } else { - // disallow everything if shutdown - !security::Pallet::::is_parachain_shutdown() + // normal operation: allow all calls that are not explicitly paused + TxPause::contains(call) } } } @@ -1093,6 +1097,22 @@ impl loans::Config for Runtime { type OnExchangeRateChange = vault_registry::PoolManager; } +parameter_types! { + pub const MaxNameLen: u32 = 128; + pub const PauseTooLongNames: bool = false; +} + +impl tx_pause::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureRoot; + type UnpauseOrigin = EnsureRoot; + type WhitelistCallNames = Nothing; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); +} + construct_runtime! { pub enum Runtime where Block = Block, @@ -1109,6 +1129,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 8, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 9, + TxPause: tx_pause::{Pallet, Call, Storage, Event} = 10, // # Tokens & Balances Currency: currency::{Pallet} = 20, diff --git a/standalone/runtime/tests/mock/mod.rs b/standalone/runtime/tests/mock/mod.rs index 4d11ab5c9d..2d9047ac58 100644 --- a/standalone/runtime/tests/mock/mod.rs +++ b/standalone/runtime/tests/mock/mod.rs @@ -163,6 +163,7 @@ pub type SecurityCall = security::Call; pub type SudoCall = pallet_sudo::Call; pub type SudoError = pallet_sudo::Error; +pub type SystemCall = frame_system::Call; pub type SystemPallet = frame_system::Pallet; pub type SystemError = frame_system::Error; @@ -181,6 +182,8 @@ pub type EscrowPallet = escrow::Pallet; pub type UtilityCall = pallet_utility::Call; +pub type TxPauseCall = tx_pause::Call; + pub type SchedulerCall = pallet_scheduler::Call; pub type SchedulerPallet = pallet_scheduler::Pallet; diff --git a/standalone/runtime/tests/test_governance.rs b/standalone/runtime/tests/test_governance.rs index 9ee282040a..17e1d39e5f 100644 --- a/standalone/runtime/tests/test_governance.rs +++ b/standalone/runtime/tests/test_governance.rs @@ -3,10 +3,14 @@ use crate::assert_eq; use mock::*; use democracy::{PropIndex, ReferendumIndex, ReferendumInfo, ReferendumStatus, Tally, Vote, VoteThreshold}; -use frame_support::traits::{Currency, Hooks}; +use frame_support::{ + assert_err_ignore_postinfo, + traits::{Currency, GetCallMetadata, Hooks}, +}; use orml_vesting::VestingSchedule; use sp_core::{Encode, Hasher}; use sp_runtime::traits::BlakeTwo256; +use tx_pause::FullNameOf; type DemocracyCall = democracy::Call; type DemocracyPallet = democracy::Pallet; @@ -231,6 +235,143 @@ fn can_recover_from_shutdown_using_root() { }); } +fn full_name(pallet_name_bytes: &[u8], maybe_call_name_bytes: Option<&[u8]>) -> FullNameOf { + match maybe_call_name_bytes { + Some(call_name_bytes) => >::from(( + pallet_name_bytes.to_vec().try_into().unwrap(), + Some(call_name_bytes.to_vec().try_into().unwrap()), + )), + None => >::from((pallet_name_bytes.to_vec().try_into().unwrap(), None)), + } +} + +#[test] +fn can_pause_pallets() { + test_with(|| { + let call = RuntimeCall::Tokens(TokensCall::transfer { + dest: account_of(ALICE), + currency_id: DEFAULT_NATIVE_CURRENCY, + amount: 123, + }); + + // sanity check: this call is allowed by default + assert_ok!(call.clone().dispatch(origin_of(account_of(ALICE)))); + + // pause calls to Tokens pallet.. + assert_ok!(RuntimeCall::TxPause(TxPauseCall::pause { + full_name: full_name(b"Tokens", None) + }) + .dispatch(root())); + + assert_noop!(call.dispatch(origin_of(account_of(ALICE))), SystemError::CallFiltered); + }) +} + +#[test] +fn can_pause_functions() { + test_with(|| { + let call = RuntimeCall::Tokens(TokensCall::transfer { + dest: account_of(ALICE), + currency_id: DEFAULT_NATIVE_CURRENCY, + amount: 123, + }); + + // sanity check: this call is allowed by default + assert_ok!(call.clone().dispatch(origin_of(account_of(ALICE)))); + + // pause call.. + assert_ok!(RuntimeCall::TxPause(TxPauseCall::pause { + full_name: full_name(b"Tokens", Some(b"transfer")) + }) + .dispatch(root())); + + assert_noop!(call.dispatch(origin_of(account_of(ALICE))), SystemError::CallFiltered); + + // other functions from the Tokens pallet should continue to function + assert_ok!(RuntimeCall::Tokens(TokensCall::transfer_all { + dest: account_of(ALICE), + currency_id: DEFAULT_NATIVE_CURRENCY, + keep_alive: false, + }) + .dispatch(origin_of(account_of(ALICE)))); + }) +} + +#[test] +fn pause_works_on_calls_in_batch() { + test_with(|| { + let call = RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![RuntimeCall::Tokens(TokensCall::transfer { + dest: account_of(ALICE), + currency_id: DEFAULT_NATIVE_CURRENCY, + amount: 123, + })], + }); + + // sanity check: this call is allowed by default + assert_ok!(call.clone().dispatch(origin_of(account_of(ALICE)))); + + // pause call.. + assert_ok!(RuntimeCall::TxPause(TxPauseCall::pause { + full_name: full_name(b"Tokens", Some(b"transfer")) + }) + .dispatch(root())); + + // we need assert_err_ignore_postinfo since the call does execute, it only bails when the + // nested call inside the batch gets dispatched + assert_err_ignore_postinfo!(call.dispatch(origin_of(account_of(ALICE))), SystemError::CallFiltered); + }) +} + +#[test] +fn can_not_use_txpause_to_brick_parachain() { + test_with(|| { + let call = RuntimeCall::Tokens(TokensCall::transfer { + dest: account_of(ALICE), + currency_id: DEFAULT_NATIVE_CURRENCY, + amount: 123, + }); + + // sanity check: this call is allowed by default + assert_ok!(call.clone().dispatch(origin_of(account_of(ALICE)))); + + // tx-pause pallet itself is unpausable.. + assert_noop!( + RuntimeCall::TxPause(TxPauseCall::pause { + full_name: full_name(b"TxPause", None) + }) + .dispatch(root()), + tx_pause::Error::::IsUnpausable + ); + let pausable_pallets = RuntimeCall::get_module_names() + .into_iter() + .filter(|&&pallet| pallet != "TxPause"); + for pallet in pausable_pallets { + assert_ok!(RuntimeCall::TxPause(TxPauseCall::pause { + full_name: full_name(pallet.as_bytes(), None) + }) + .dispatch(root())); + } + + // sanity check: this call is now paused + assert_noop!( + call.clone().dispatch(origin_of(account_of(ALICE))), + SystemError::CallFiltered + ); + + create_proposal( + RuntimeCall::TxPause(TxPauseCall::unpause { + full_name: full_name(b"Tokens", None), + }) + .encode(), + ); + launch_and_execute_referendum(); + + // verify that call is indeed unpaused + assert_ok!(call.clone().dispatch(origin_of(account_of(ALICE)))); + }) +} + #[test] fn integration_test_governance() { test_with(|| { From f4d8c211cd132e098397f84d361164a816e22afd Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Wed, 18 Jan 2023 13:33:19 +0100 Subject: [PATCH 4/8] feat: add tx-pause to all runtimes --- Cargo.lock | 4 +++ parachain/runtime/interlay/Cargo.toml | 3 +++ parachain/runtime/interlay/src/lib.rs | 25 +++++++++++++++---- parachain/runtime/kintsugi/Cargo.toml | 3 +++ parachain/runtime/kintsugi/src/lib.rs | 24 +++++++++++++++--- parachain/runtime/testnet-interlay/Cargo.toml | 3 +++ parachain/runtime/testnet-interlay/src/lib.rs | 22 +++++++++++++--- parachain/runtime/testnet-kintsugi/Cargo.toml | 3 +++ parachain/runtime/testnet-kintsugi/src/lib.rs | 22 +++++++++++++--- 9 files changed, 94 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c516388c54..b3c47b4904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4034,6 +4034,7 @@ dependencies = [ "substrate-wasm-builder", "supply", "traits", + "tx-pause", "vault-registry", "vault-registry-rpc-runtime-api", "xcm", @@ -4443,6 +4444,7 @@ dependencies = [ "substrate-wasm-builder", "supply", "traits", + "tx-pause", "vault-registry", "vault-registry-rpc-runtime-api", "xcm", @@ -12585,6 +12587,7 @@ dependencies = [ "substrate-wasm-builder", "supply", "traits", + "tx-pause", "vault-registry", "vault-registry-rpc-runtime-api", "xcm", @@ -12691,6 +12694,7 @@ dependencies = [ "substrate-wasm-builder", "supply", "traits", + "tx-pause", "vault-registry", "vault-registry-rpc-runtime-api", "xcm", diff --git a/parachain/runtime/interlay/Cargo.toml b/parachain/runtime/interlay/Cargo.toml index aee2de2c62..67ee77797e 100644 --- a/parachain/runtime/interlay/Cargo.toml +++ b/parachain/runtime/interlay/Cargo.toml @@ -97,6 +97,7 @@ supply = { path = "../../../crates/supply", default-features = false } collator-selection = { path = "../../../crates/collator-selection", default-features = false } clients-info = { path = "../../../crates/clients-info", default-features = false } traits = { path = "../../../crates/traits", default-features = false } +tx-pause = { path = "../../../crates/tx-pause", default-features = false } primitives = { package = "interbtc-primitives", path = "../../../primitives", default-features = false } @@ -213,6 +214,7 @@ std = [ "collator-selection/std", "clients-info/std", "traits/std", + "tx-pause/std", "primitives/std", @@ -256,6 +258,7 @@ runtime-benchmarks = [ "redeem/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", + "tx-pause/runtime-benchmarks", ] disable-runtime-api = [] try-runtime = [ diff --git a/parachain/runtime/interlay/src/lib.rs b/parachain/runtime/interlay/src/lib.rs index 7960c0ca20..0ab60f8986 100644 --- a/parachain/runtime/interlay/src/lib.rs +++ b/parachain/runtime/interlay/src/lib.rs @@ -168,14 +168,11 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) - | RuntimeCall::Authorship(_) - | RuntimeCall::Session(_) | RuntimeCall::Timestamp(_) - | RuntimeCall::ParachainSystem(_) + | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) | RuntimeCall::TechnicalCommittee(_) - | RuntimeCall::Sudo(_) ) { // always allow core calls true @@ -188,7 +185,8 @@ impl Contains for BaseCallFilter { // governance bypasses this call filter). false } else { - true + // normal operation: allow all calls that are not explicitly paused + TxPause::contains(call) } } } @@ -1136,6 +1134,22 @@ impl clients_info::Config for Runtime { type WeightInfo = (); } +parameter_types! { + pub const MaxNameLen: u32 = 128; + pub const PauseTooLongNames: bool = false; +} + +impl tx_pause::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureRoot; + type UnpauseOrigin = EnsureRoot; + type WhitelistCallNames = Nothing; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); +} + construct_runtime! { pub enum Runtime where Block = Block, @@ -1152,6 +1166,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 8, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 9, + TxPause: tx_pause::{Pallet, Call, Storage, Event} = 10, // # Tokens & Balances Currency: currency::{Pallet} = 20, diff --git a/parachain/runtime/kintsugi/Cargo.toml b/parachain/runtime/kintsugi/Cargo.toml index fc5e7cdd69..8aebff0337 100644 --- a/parachain/runtime/kintsugi/Cargo.toml +++ b/parachain/runtime/kintsugi/Cargo.toml @@ -98,6 +98,7 @@ supply = { path = "../../../crates/supply", default-features = false } collator-selection = { path = "../../../crates/collator-selection", default-features = false } clients-info = { path = "../../../crates/clients-info", default-features = false } traits = { path = "../../../crates/traits", default-features = false } +tx-pause = { path = "../../../crates/tx-pause", default-features = false } primitives = { package = "interbtc-primitives", path = "../../../primitives", default-features = false } @@ -219,6 +220,7 @@ std = [ "collator-selection/std", "clients-info/std", "traits/std", + "tx-pause/std", "primitives/std", @@ -262,6 +264,7 @@ runtime-benchmarks = [ "redeem/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", + "tx-pause/runtime-benchmarks", ] disable-runtime-api = [] try-runtime = [ diff --git a/parachain/runtime/kintsugi/src/lib.rs b/parachain/runtime/kintsugi/src/lib.rs index 026a13e528..80629ff074 100644 --- a/parachain/runtime/kintsugi/src/lib.rs +++ b/parachain/runtime/kintsugi/src/lib.rs @@ -166,13 +166,11 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) - | RuntimeCall::Authorship(_) | RuntimeCall::Timestamp(_) - | RuntimeCall::ParachainSystem(_) + | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) | RuntimeCall::TechnicalCommittee(_) - | RuntimeCall::Sudo(_) ) { // always allow core calls true @@ -185,7 +183,8 @@ impl Contains for BaseCallFilter { // governance bypasses this call filter). false } else { - true + // normal operation: allow all calls that are not explicitly paused + TxPause::contains(call) } } } @@ -1134,6 +1133,22 @@ impl clients_info::Config for Runtime { type WeightInfo = (); } +parameter_types! { + pub const MaxNameLen: u32 = 128; + pub const PauseTooLongNames: bool = false; +} + +impl tx_pause::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureRoot; + type UnpauseOrigin = EnsureRoot; + type WhitelistCallNames = Nothing; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); +} + construct_runtime! { pub enum Runtime where Block = Block, @@ -1150,6 +1165,7 @@ construct_runtime! { Identity: pallet_identity::{Pallet, Call, Storage, Event} = 7, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 8, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event} = 9, + TxPause: tx_pause::{Pallet, Call, Storage, Event} = 10, // # Tokens & Balances Currency: currency::{Pallet} = 20, diff --git a/parachain/runtime/testnet-interlay/Cargo.toml b/parachain/runtime/testnet-interlay/Cargo.toml index d827b4188b..45d40a3e47 100644 --- a/parachain/runtime/testnet-interlay/Cargo.toml +++ b/parachain/runtime/testnet-interlay/Cargo.toml @@ -99,6 +99,7 @@ collator-selection = { path = "../../../crates/collator-selection", default-feat clients-info = { path = "../../../crates/clients-info", default-features = false } loans = { path = "../../../crates/loans", default-features = false } traits = { path = "../../../crates/traits", default-features = false } +tx-pause = { path = "../../../crates/tx-pause", default-features = false } primitives = { package = "interbtc-primitives", path = "../../../primitives", default-features = false } @@ -220,6 +221,7 @@ std = [ "clients-info/std", "loans/std", "traits/std", + "tx-pause/std", "primitives/std", @@ -265,6 +267,7 @@ runtime-benchmarks = [ "redeem/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", + "tx-pause/runtime-benchmarks", ] disable-runtime-api = [] dev-interlay = [] diff --git a/parachain/runtime/testnet-interlay/src/lib.rs b/parachain/runtime/testnet-interlay/src/lib.rs index 9718d011b9..8c4726ba36 100644 --- a/parachain/runtime/testnet-interlay/src/lib.rs +++ b/parachain/runtime/testnet-interlay/src/lib.rs @@ -169,9 +169,7 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) - | RuntimeCall::Authorship(_) | RuntimeCall::Timestamp(_) - | RuntimeCall::ParachainSystem(_) | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) @@ -188,7 +186,8 @@ impl Contains for BaseCallFilter { // governance bypasses this call filter). false } else { - true + // normal operation: allow all calls that are not explicitly paused + TxPause::contains(call) } } } @@ -1106,6 +1105,22 @@ impl clients_info::Config for Runtime { type WeightInfo = (); } +parameter_types! { + pub const MaxNameLen: u32 = 128; + pub const PauseTooLongNames: bool = false; +} + +impl tx_pause::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureRoot; + type UnpauseOrigin = EnsureRoot; + type WhitelistCallNames = Nothing; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); +} + impl loans::Config for Runtime { type RuntimeEvent = RuntimeEvent; type PalletId = LoansPalletId; @@ -1135,6 +1150,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 8, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 9, + TxPause: tx_pause::{Pallet, Call, Storage, Event} = 10, // # Tokens & Balances Currency: currency::{Pallet} = 20, diff --git a/parachain/runtime/testnet-kintsugi/Cargo.toml b/parachain/runtime/testnet-kintsugi/Cargo.toml index 9158066d83..400b1e432e 100644 --- a/parachain/runtime/testnet-kintsugi/Cargo.toml +++ b/parachain/runtime/testnet-kintsugi/Cargo.toml @@ -100,6 +100,7 @@ clients-info = { path = "../../../crates/clients-info", default-features = false loans = { path = "../../../crates/loans", default-features = false } traits = { path = "../../../crates/traits", default-features = false } farming = { path = "../../../crates/farming", default-features = false } +tx-pause = { path = "../../../crates/tx-pause", default-features = false } primitives = { package = "interbtc-primitives", path = "../../../primitives", default-features = false } @@ -229,6 +230,7 @@ std = [ "loans/std", "traits/std", "farming/std", + "tx-pause/std", "primitives/std", @@ -281,6 +283,7 @@ runtime-benchmarks = [ "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", "farming/runtime-benchmarks", + "tx-pause/runtime-benchmarks", ] disable-runtime-api = [] dev-interlay = [] diff --git a/parachain/runtime/testnet-kintsugi/src/lib.rs b/parachain/runtime/testnet-kintsugi/src/lib.rs index 55b90ca66e..a9f894ad91 100644 --- a/parachain/runtime/testnet-kintsugi/src/lib.rs +++ b/parachain/runtime/testnet-kintsugi/src/lib.rs @@ -171,9 +171,7 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) - | RuntimeCall::Authorship(_) | RuntimeCall::Timestamp(_) - | RuntimeCall::ParachainSystem(_) | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) @@ -190,7 +188,8 @@ impl Contains for BaseCallFilter { // governance bypasses this call filter). false } else { - true + // normal operation: allow all calls that are not explicitly paused + TxPause::contains(call) } } } @@ -1136,6 +1135,22 @@ impl clients_info::Config for Runtime { type WeightInfo = (); } +parameter_types! { + pub const MaxNameLen: u32 = 128; + pub const PauseTooLongNames: bool = false; +} + +impl tx_pause::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureRoot; + type UnpauseOrigin = EnsureRoot; + type WhitelistCallNames = Nothing; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); +} + impl loans::Config for Runtime { type RuntimeEvent = RuntimeEvent; type PalletId = LoansPalletId; @@ -1165,6 +1180,7 @@ construct_runtime! { Identity: pallet_identity::{Pallet, Call, Storage, Event} = 7, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 8, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event} = 9, + TxPause: tx_pause::{Pallet, Call, Storage, Event} = 10, // # Tokens & Balances Currency: currency::{Pallet} = 20, From d3d7975cbc5259c08dbb6b965feb436d8fd88ef0 Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Wed, 18 Jan 2023 13:33:26 +0100 Subject: [PATCH 5/8] chore: fmt --- crates/tx-pause/src/benchmarking.rs | 52 ++-- crates/tx-pause/src/lib.rs | 411 ++++++++++++++-------------- crates/tx-pause/src/mock.rs | 329 +++++++++++----------- crates/tx-pause/src/tests.rs | 334 +++++++++++----------- 4 files changed, 565 insertions(+), 561 deletions(-) diff --git a/crates/tx-pause/src/benchmarking.rs b/crates/tx-pause/src/benchmarking.rs index 6fc20a9630..a06725d0cd 100644 --- a/crates/tx-pause/src/benchmarking.rs +++ b/crates/tx-pause/src/benchmarking.rs @@ -22,40 +22,40 @@ use super::{Pallet as TxPause, *}; use frame_benchmarking::benchmarks; benchmarks! { - pause { - let full_name: FullNameOf = (name::(b"SomePalletName"), Some(name::(b"SomePalletName"))); - // let pallet_name: PalletNameOf = name::(b"SomePalletName"); - // let maybe_call_name: Option> = Some(name::(b"some_call_name")); - let origin = T::PauseOrigin::successful_origin(); - // let call = Call::::pause { full_name: full_name.clone() }; - // let call = Call::::pause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; - - }: _(origin, full_name.clone()) - verify { - assert!(TxPause::::paused_calls(full_name.clone()).is_some()) - } + pause { + let full_name: FullNameOf = (name::(b"SomePalletName"), Some(name::(b"SomePalletName"))); + // let pallet_name: PalletNameOf = name::(b"SomePalletName"); + // let maybe_call_name: Option> = Some(name::(b"some_call_name")); + let origin = T::PauseOrigin::successful_origin(); + // let call = Call::::pause { full_name: full_name.clone() }; + // let call = Call::::pause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; + + }: _(origin, full_name.clone()) + verify { + assert!(TxPause::::paused_calls(full_name.clone()).is_some()) + } unpause { - let full_name: FullNameOf = (name::(b"SomePalletName"), Some(name::(b"SomePalletName"))); - let pause_origin = T::PauseOrigin::successful_origin(); + let full_name: FullNameOf = (name::(b"SomePalletName"), Some(name::(b"SomePalletName"))); + let pause_origin = T::PauseOrigin::successful_origin(); - TxPause::::pause( - pause_origin, - full_name.clone(), - )?; + TxPause::::pause( + pause_origin, + full_name.clone(), + )?; - let unpause_origin = T::UnpauseOrigin::successful_origin(); - // let call = Call::::unpause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; + let unpause_origin = T::UnpauseOrigin::successful_origin(); + // let call = Call::::unpause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; - }: _(unpause_origin, full_name.clone()) - verify { - assert!(TxPause::::paused_calls(full_name.clone()).is_none()) + }: _(unpause_origin, full_name.clone()) + verify { + assert!(TxPause::::paused_calls(full_name.clone()).is_none()) - } + } - impl_benchmark_test_suite!(TxPause, crate::mock::new_test_ext(), crate::mock::Test); + impl_benchmark_test_suite!(TxPause, crate::mock::new_test_ext(), crate::mock::Test); } pub fn name(bytes: &[u8]) -> BoundedVec { - bytes.to_vec().try_into().unwrap() + bytes.to_vec().try_into().unwrap() } diff --git a/crates/tx-pause/src/lib.rs b/crates/tx-pause/src/lib.rs index 6b97afd7ef..8aa5979ede 100644 --- a/crates/tx-pause/src/lib.rs +++ b/crates/tx-pause/src/lib.rs @@ -86,9 +86,9 @@ mod tests; pub mod weights; use frame_support::{ - dispatch::GetDispatchInfo, - pallet_prelude::*, - traits::{CallMetadata, Contains, GetCallMetadata, IsSubType, IsType}, + dispatch::GetDispatchInfo, + pallet_prelude::*, + traits::{CallMetadata, Contains, GetCallMetadata, IsSubType, IsType}, }; use frame_system::pallet_prelude::*; use sp_runtime::{traits::Dispatchable, DispatchResult}; @@ -108,214 +108,215 @@ pub type FullNameOf = (PalletNameOf, Option>); #[frame_support::pallet] pub mod pallet { - use super::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(PhantomData); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// The overarching call type. - type RuntimeCall: Parameter - + Dispatchable - + GetDispatchInfo - + GetCallMetadata - + From> - + IsSubType> - + IsType<::RuntimeCall>; - - /// The only origin that can pause calls. - type PauseOrigin: EnsureOrigin; - - /// The only origin that can un-pause calls. - type UnpauseOrigin: EnsureOrigin; - - /// Contains all calls that cannot be paused. - /// - /// The `TxMode` pallet cannot pause it's own calls, and does not need to be explicitly - /// added here. - type WhitelistCallNames: Contains>; - - /// Maximum length for pallet and call SCALE encoded string names. - /// - /// Too long names will not be truncated but handled like - /// [`Self::PauseTooLongNames`] specifies. - #[pallet::constant] - type MaxNameLen: Get; - - /// Specifies if functions and pallets with too long names should be treated as paused. - /// - /// Setting this to `true` ensures that all calls that - /// are callable, are also pause-able. - /// Otherwise there could be a situation where a call - /// is callable but not pause-able, which would could be exploited. - #[pallet::constant] - type PauseTooLongNames: Get; - - // Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - } - - #[pallet::error] - pub enum Error { - /// The call is (already or still) paused. - IsPaused, - - /// The call is (already or still) unpaused. - IsUnpaused, - - /// The call is listed as safe and cannot be paused. - IsUnpausable, - - // The pallet or call does not exist in the runtime. - NotFound, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// This pallet, or a specific call is now paused. \[pallet_name, Option\] - SomethingPaused { full_name: FullNameOf }, - /// This pallet, or a specific call is now unpaused. \[pallet_name, Option\] - SomethingUnpaused { full_name: FullNameOf }, - } - - /// The set of calls that are explicitly paused. - #[pallet::storage] - #[pallet::getter(fn paused_calls)] - pub type PausedCalls = - StorageMap<_, Blake2_128Concat, FullNameOf, (), OptionQuery>; - - /// Configure the initial state of this pallet in the genesis block. - #[pallet::genesis_config] - pub struct GenesisConfig { - /// The initially paused calls. - pub paused: Vec>, - pub _phantom: PhantomData, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - // NOTE: `derive(Default)` does not work together with `#[pallet::genesis_config]`. - // We therefore need to add a trivial default impl. - fn default() -> Self { - Self { paused: Default::default(), _phantom: PhantomData } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - for (pallet_name, maybe_call_name) in &self.paused { - PausedCalls::::insert((pallet_name, maybe_call_name), ()); - } - } - } - - #[pallet::call] - impl Pallet { - /// Pause a call. - /// - /// Can only be called by [`Config::PauseOrigin`]. - /// Emits an [`Event::SomethingPaused`] event on success. - #[pallet::weight(T::WeightInfo::pause())] - pub fn pause(origin: OriginFor, full_name: FullNameOf) -> DispatchResult { - T::PauseOrigin::ensure_origin(origin)?; - - Self::ensure_can_pause(&full_name)?; - PausedCalls::::insert(&full_name, ()); - Self::deposit_event(Event::SomethingPaused { full_name }); - - Ok(()) - } - - /// Un-pause a call. - /// - /// Can only be called by [`Config::UnpauseOrigin`]. - /// Emits an [`Event::SomethingUnpaused`] event on success. - #[pallet::weight(T::WeightInfo::unpause())] - pub fn unpause(origin: OriginFor, full_name: FullNameOf) -> DispatchResult { - T::UnpauseOrigin::ensure_origin(origin)?; - - Self::ensure_can_unpause(&full_name)?; - PausedCalls::::remove(&full_name); - Self::deposit_event(Event::SomethingUnpaused { full_name }); - Ok(()) - } - } + use super::*; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// The overarching call type. + type RuntimeCall: Parameter + + Dispatchable + + GetDispatchInfo + + GetCallMetadata + + From> + + IsSubType> + + IsType<::RuntimeCall>; + + /// The only origin that can pause calls. + type PauseOrigin: EnsureOrigin; + + /// The only origin that can un-pause calls. + type UnpauseOrigin: EnsureOrigin; + + /// Contains all calls that cannot be paused. + /// + /// The `TxMode` pallet cannot pause it's own calls, and does not need to be explicitly + /// added here. + type WhitelistCallNames: Contains>; + + /// Maximum length for pallet and call SCALE encoded string names. + /// + /// Too long names will not be truncated but handled like + /// [`Self::PauseTooLongNames`] specifies. + #[pallet::constant] + type MaxNameLen: Get; + + /// Specifies if functions and pallets with too long names should be treated as paused. + /// + /// Setting this to `true` ensures that all calls that + /// are callable, are also pause-able. + /// Otherwise there could be a situation where a call + /// is callable but not pause-able, which would could be exploited. + #[pallet::constant] + type PauseTooLongNames: Get; + + // Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + /// The call is (already or still) paused. + IsPaused, + + /// The call is (already or still) unpaused. + IsUnpaused, + + /// The call is listed as safe and cannot be paused. + IsUnpausable, + + // The pallet or call does not exist in the runtime. + NotFound, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// This pallet, or a specific call is now paused. \[pallet_name, Option\] + SomethingPaused { full_name: FullNameOf }, + /// This pallet, or a specific call is now unpaused. \[pallet_name, Option\] + SomethingUnpaused { full_name: FullNameOf }, + } + + /// The set of calls that are explicitly paused. + #[pallet::storage] + #[pallet::getter(fn paused_calls)] + pub type PausedCalls = StorageMap<_, Blake2_128Concat, FullNameOf, (), OptionQuery>; + + /// Configure the initial state of this pallet in the genesis block. + #[pallet::genesis_config] + pub struct GenesisConfig { + /// The initially paused calls. + pub paused: Vec>, + pub _phantom: PhantomData, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + // NOTE: `derive(Default)` does not work together with `#[pallet::genesis_config]`. + // We therefore need to add a trivial default impl. + fn default() -> Self { + Self { + paused: Default::default(), + _phantom: PhantomData, + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + for (pallet_name, maybe_call_name) in &self.paused { + PausedCalls::::insert((pallet_name, maybe_call_name), ()); + } + } + } + + #[pallet::call] + impl Pallet { + /// Pause a call. + /// + /// Can only be called by [`Config::PauseOrigin`]. + /// Emits an [`Event::SomethingPaused`] event on success. + #[pallet::weight(T::WeightInfo::pause())] + pub fn pause(origin: OriginFor, full_name: FullNameOf) -> DispatchResult { + T::PauseOrigin::ensure_origin(origin)?; + + Self::ensure_can_pause(&full_name)?; + PausedCalls::::insert(&full_name, ()); + Self::deposit_event(Event::SomethingPaused { full_name }); + + Ok(()) + } + + /// Un-pause a call. + /// + /// Can only be called by [`Config::UnpauseOrigin`]. + /// Emits an [`Event::SomethingUnpaused`] event on success. + #[pallet::weight(T::WeightInfo::unpause())] + pub fn unpause(origin: OriginFor, full_name: FullNameOf) -> DispatchResult { + T::UnpauseOrigin::ensure_origin(origin)?; + + Self::ensure_can_unpause(&full_name)?; + PausedCalls::::remove(&full_name); + Self::deposit_event(Event::SomethingUnpaused { full_name }); + Ok(()) + } + } } impl Pallet { - /// Return whether this pallet or call is paused. - pub fn is_paused_unbound(pallet_name: Vec, call_name: Vec) -> bool { - let pallet_name = PalletNameOf::::try_from(pallet_name); - let call_name = CallNameOf::::try_from(call_name); - - match (pallet_name, call_name) { - (Ok(pallet_name), Ok(call_name)) => Self::is_paused(&&>::from(( - pallet_name.clone(), - Some(call_name.clone()), - ))), - _ => T::PauseTooLongNames::get(), - } - } - - /// Return whether this pallet or call is paused - pub fn is_paused(full_name: &FullNameOf) -> bool { - let (pallet_name, maybe_call_name) = full_name; - // SAFETY: Everything that is whitelisted cannot be paused, - // including calls within paused pallets. - if T::WhitelistCallNames::contains(&>::from(( - pallet_name.clone(), - maybe_call_name.clone(), - ))) { - return false - }; - // Check is pallet is paused. - if >::contains_key(>::from((pallet_name.clone(), None))) { - return true - }; - // Check if call in a pallet is paused - >::contains_key(full_name) - } - - /// Ensure that this pallet or call can be paused. - pub fn ensure_can_pause(full_name: &FullNameOf) -> Result<(), Error> { - // The `TxPause` pallet can never be paused. - if full_name.0.as_ref() == ::name().as_bytes().to_vec() { - return Err(Error::::IsUnpausable) - } - if Self::is_paused(&full_name) { - return Err(Error::::IsPaused) - } - if T::WhitelistCallNames::contains(&full_name) { - return Err(Error::::IsUnpausable) - } - Ok(()) - } - - /// Ensure that this call can be un-paused. - pub fn ensure_can_unpause(full_name: &FullNameOf) -> Result<(), Error> { - if Self::is_paused(&full_name) { - // SAFETY: Everything that is paused, can be un-paused. - Ok(()) - } else { - Err(Error::IsUnpaused) - } - } + /// Return whether this pallet or call is paused. + pub fn is_paused_unbound(pallet_name: Vec, call_name: Vec) -> bool { + let pallet_name = PalletNameOf::::try_from(pallet_name); + let call_name = CallNameOf::::try_from(call_name); + + match (pallet_name, call_name) { + (Ok(pallet_name), Ok(call_name)) => { + Self::is_paused(&&>::from((pallet_name.clone(), Some(call_name.clone())))) + } + _ => T::PauseTooLongNames::get(), + } + } + + /// Return whether this pallet or call is paused + pub fn is_paused(full_name: &FullNameOf) -> bool { + let (pallet_name, maybe_call_name) = full_name; + // SAFETY: Everything that is whitelisted cannot be paused, + // including calls within paused pallets. + if T::WhitelistCallNames::contains(&>::from((pallet_name.clone(), maybe_call_name.clone()))) { + return false; + }; + // Check is pallet is paused. + if >::contains_key(>::from((pallet_name.clone(), None))) { + return true; + }; + // Check if call in a pallet is paused + >::contains_key(full_name) + } + + /// Ensure that this pallet or call can be paused. + pub fn ensure_can_pause(full_name: &FullNameOf) -> Result<(), Error> { + // The `TxPause` pallet can never be paused. + if full_name.0.as_ref() == ::name().as_bytes().to_vec() { + return Err(Error::::IsUnpausable); + } + if Self::is_paused(&full_name) { + return Err(Error::::IsPaused); + } + if T::WhitelistCallNames::contains(&full_name) { + return Err(Error::::IsUnpausable); + } + Ok(()) + } + + /// Ensure that this call can be un-paused. + pub fn ensure_can_unpause(full_name: &FullNameOf) -> Result<(), Error> { + if Self::is_paused(&full_name) { + // SAFETY: Everything that is paused, can be un-paused. + Ok(()) + } else { + Err(Error::IsUnpaused) + } + } } impl Contains<::RuntimeCall> for Pallet where - ::RuntimeCall: GetCallMetadata, + ::RuntimeCall: GetCallMetadata, { - /// Return whether the call is allowed to be dispatched. - fn contains(call: &::RuntimeCall) -> bool { - let CallMetadata { pallet_name, function_name } = call.get_call_metadata(); - !Pallet::::is_paused_unbound(pallet_name.into(), function_name.into()) - } + /// Return whether the call is allowed to be dispatched. + fn contains(call: &::RuntimeCall) -> bool { + let CallMetadata { + pallet_name, + function_name, + } = call.get_call_metadata(); + !Pallet::::is_paused_unbound(pallet_name.into(), function_name.into()) + } } diff --git a/crates/tx-pause/src/mock.rs b/crates/tx-pause/src/mock.rs index a9294b6ac4..6775dd6b44 100644 --- a/crates/tx-pause/src/mock.rs +++ b/crates/tx-pause/src/mock.rs @@ -21,124 +21,114 @@ use super::*; use crate as pallet_tx_pause; use frame_support::{ - parameter_types, - traits::{ConstU64, Everything, InsideBoth, InstanceFilter, SortedMembers}, + parameter_types, + traits::{ConstU64, Everything, InsideBoth, InstanceFilter, SortedMembers}, }; use frame_system::EnsureSignedBy; use sp_core::H256; use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, }; parameter_types! { - pub const BlockHashCount: u64 = 250; + pub const BlockHashCount: u64 = 250; } impl frame_system::Config for Test { - type BaseCallFilter = InsideBoth; - type BlockWeights = (); - type BlockLength = (); - 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 = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type BaseCallFilter = InsideBoth; + type BlockWeights = (); + type BlockLength = (); + 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 = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 10; + pub const ExistentialDeposit: u64 = 1; + pub const MaxLocks: u32 = 10; } impl pallet_balances::Config for Test { - type Balance = u64; - type DustRemoval = (); - type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type MaxLocks = MaxLocks; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; } impl pallet_utility::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type PalletsOrigin = OriginCaller; - type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); } #[derive( - Copy, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - Encode, - Decode, - RuntimeDebug, - MaxEncodedLen, - scale_info::TypeInfo, + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo, )] pub enum ProxyType { - Any, - JustTransfer, - JustUtility, + Any, + JustTransfer, + JustUtility, } impl Default for ProxyType { - fn default() -> Self { - Self::Any - } + fn default() -> Self { + Self::Any + } } impl InstanceFilter for ProxyType { - fn filter(&self, c: &RuntimeCall) -> bool { - match self { - ProxyType::Any => true, - ProxyType::JustTransfer => { - matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) - }, - ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), - } - } - fn is_superset(&self, o: &Self) -> bool { - self == &ProxyType::Any || self == o - } + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::JustTransfer => { + matches!(c, RuntimeCall::Balances(pallet_balances::Call::transfer { .. })) + } + ProxyType::JustUtility => matches!(c, RuntimeCall::Utility { .. }), + } + } + fn is_superset(&self, o: &Self) -> bool { + self == &ProxyType::Any || self == o + } } impl pallet_proxy::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type Currency = Balances; - type ProxyType = ProxyType; - type ProxyDepositBase = ConstU64<1>; - type ProxyDepositFactor = ConstU64<1>; - type MaxProxies = ConstU32<4>; - type WeightInfo = (); - type CallHasher = BlakeTwo256; - type MaxPending = ConstU32<2>; - type AnnouncementDepositBase = ConstU64<1>; - type AnnouncementDepositFactor = ConstU64<1>; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ConstU64<1>; + type ProxyDepositFactor = ConstU64<1>; + type MaxProxies = ConstU32<4>; + type WeightInfo = (); + type CallHasher = BlakeTwo256; + type MaxPending = ConstU32<2>; + type AnnouncementDepositBase = ConstU64<1>; + type AnnouncementDepositFactor = ConstU64<1>; } parameter_types! { - pub const PauseOrigin: u64 = 1; - pub const UnpauseOrigin: u64 = 2; + pub const PauseOrigin: u64 = 1; + pub const UnpauseOrigin: u64 = 2; pub const MaxNameLen: u32 = 50; pub const PauseTooLongNames: bool = false; } @@ -149,109 +139,112 @@ pub struct WhitelistCallNames; /// Contains used by `BaseCallFiler` so this impl whitelists `Balances::transfer_keep_alive` /// and all DummyPallet calls. All others may be paused. impl Contains> for WhitelistCallNames { - fn contains(full_name: &FullNameOf) -> bool { - let unpausables: Vec> = vec![ - ( - b"Balances".to_vec().try_into().unwrap(), - Some(b"transfer_keep_alive".to_vec().try_into().unwrap()), - ), - (b"DummyPallet".to_vec().try_into().unwrap(), None), - ]; - - for unpausable_call in unpausables { - let (pallet_name, maybe_call_name) = full_name; - if unpausable_call.1.is_none() { - return &unpausable_call.0 == pallet_name - } else { - if &unpausable_call.0 == pallet_name { - return &unpausable_call.1 == maybe_call_name - } - } - } - - false - } + fn contains(full_name: &FullNameOf) -> bool { + let unpausables: Vec> = vec![ + ( + b"Balances".to_vec().try_into().unwrap(), + Some(b"transfer_keep_alive".to_vec().try_into().unwrap()), + ), + (b"DummyPallet".to_vec().try_into().unwrap(), None), + ]; + + for unpausable_call in unpausables { + let (pallet_name, maybe_call_name) = full_name; + if unpausable_call.1.is_none() { + return &unpausable_call.0 == pallet_name; + } else { + if &unpausable_call.0 == pallet_name { + return &unpausable_call.1 == maybe_call_name; + } + } + } + + false + } } // Required impl to use some ::get() in tests impl SortedMembers for PauseOrigin { - fn sorted_members() -> Vec { - vec![Self::get()] - } - #[cfg(feature = "runtime-benchmarks")] - fn add(_m: &u64) {} + fn sorted_members() -> Vec { + vec![Self::get()] + } + #[cfg(feature = "runtime-benchmarks")] + fn add(_m: &u64) {} } impl SortedMembers for UnpauseOrigin { - fn sorted_members() -> Vec { - vec![Self::get()] - } - #[cfg(feature = "runtime-benchmarks")] - fn add(_m: &u64) {} + fn sorted_members() -> Vec { + vec![Self::get()] + } + #[cfg(feature = "runtime-benchmarks")] + fn add(_m: &u64) {} } impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type PauseOrigin = EnsureSignedBy; - type UnpauseOrigin = EnsureSignedBy; - type WhitelistCallNames = WhitelistCallNames; - type MaxNameLen = MaxNameLen; - type PauseTooLongNames = PauseTooLongNames; - type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PauseOrigin = EnsureSignedBy; + type UnpauseOrigin = EnsureSignedBy; + type WhitelistCallNames = WhitelistCallNames; + type MaxNameLen = MaxNameLen; + type PauseTooLongNames = PauseTooLongNames; + type WeightInfo = (); } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system, - Balances: pallet_balances, - Utility: pallet_utility, - Proxy: pallet_proxy, - TxPause: pallet_tx_pause, - } + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Utility: pallet_utility, + Proxy: pallet_proxy, + TxPause: pallet_tx_pause, + } ); pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - pallet_balances::GenesisConfig:: { - // The 0 account is NOT a special origin. The rest may be: - balances: vec![(0, 1234), (1, 5678), (2, 5678), (3, 5678), (4, 5678)], - } - .assimilate_storage(&mut t) - .unwrap(); - - GenesisBuild::::assimilate_storage( - &pallet_tx_pause::GenesisConfig { paused: vec![], _phantom: Default::default() }, - &mut t, - ) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| { - System::set_block_number(1); - }); - ext + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { + // The 0 account is NOT a special origin. The rest may be: + balances: vec![(0, 1234), (1, 5678), (2, 5678), (3, 5678), (4, 5678)], + } + .assimilate_storage(&mut t) + .unwrap(); + + GenesisBuild::::assimilate_storage( + &pallet_tx_pause::GenesisConfig { + paused: vec![], + _phantom: Default::default(), + }, + &mut t, + ) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext } pub fn next_block() { - TxPause::on_finalize(System::block_number()); - Balances::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - System::on_initialize(System::block_number()); - Balances::on_initialize(System::block_number()); - TxPause::on_initialize(System::block_number()); + TxPause::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + TxPause::on_initialize(System::block_number()); } pub fn run_to(n: u64) { - while System::block_number() < n { - next_block(); - } + while System::block_number() < n { + next_block(); + } } diff --git a/crates/tx-pause/src/tests.rs b/crates/tx-pause/src/tests.rs index 983d5cf504..4ee3ceef47 100644 --- a/crates/tx-pause/src/tests.rs +++ b/crates/tx-pause/src/tests.rs @@ -26,216 +26,226 @@ use frame_support::{assert_err, assert_noop, assert_ok, dispatch::Dispatchable}; #[test] fn can_pause_specific_call() { - new_test_ext().execute_with(|| { - assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); - - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")) - )); - - assert_err!( - call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), - frame_system::Error::::CallFiltered - ); - assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); - }); + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")) + )); + + assert_err!( + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), + frame_system::Error::::CallFiltered + ); + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); + }); } #[test] fn can_pause_all_calls_in_pallet_except_on_whitelist() { - new_test_ext().execute_with(|| { - assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); - - let batch_call = - RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); - assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); - - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Utility", None) - ),); - - assert_err!( - batch_call.clone().dispatch(RuntimeOrigin::signed(0)), - frame_system::Error::::CallFiltered - ); - }); + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); + + let batch_call = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![call_transfer(1, 1)], + }); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Utility", None) + ),); + + assert_err!( + batch_call.clone().dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); } #[test] fn can_unpause_specific_call() { - new_test_ext().execute_with(|| { - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")), - )); - assert_err!( - call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), - frame_system::Error::::CallFiltered - ); - - assert_ok!(TxPause::unpause( - RuntimeOrigin::signed(mock::UnpauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")), - )); - assert_ok!(call_transfer(4, 1).dispatch(RuntimeOrigin::signed(0))); - }); + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + assert_err!( + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)), + frame_system::Error::::CallFiltered + ); + + assert_ok!(TxPause::unpause( + RuntimeOrigin::signed(mock::UnpauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + assert_ok!(call_transfer(4, 1).dispatch(RuntimeOrigin::signed(0))); + }); } #[test] fn can_filter_balance_in_batch_when_paused() { - new_test_ext().execute_with(|| { - let batch_call = - RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); - - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")), - )); - - assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); - System::assert_last_event( - pallet_utility::Event::BatchInterrupted { - index: 0, - error: frame_system::Error::::CallFiltered.into(), - } - .into(), - ); - }); + new_test_ext().execute_with(|| { + let batch_call = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![call_transfer(1, 1)], + }); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + System::assert_last_event( + pallet_utility::Event::BatchInterrupted { + index: 0, + error: frame_system::Error::::CallFiltered.into(), + } + .into(), + ); + }); } #[test] fn can_filter_balance_in_proxy_when_paused() { - new_test_ext().execute_with(|| { - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")), - )); - - assert_ok!(Proxy::add_proxy(RuntimeOrigin::signed(1), 2, ProxyType::JustTransfer, 0)); - - assert_ok!(Proxy::proxy(RuntimeOrigin::signed(2), 1, None, Box::new(call_transfer(1, 1)))); - System::assert_last_event( - pallet_proxy::Event::ProxyExecuted { - result: DispatchError::from(frame_system::Error::::CallFiltered).into(), - } - .into(), - ); - }); + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + + assert_ok!(Proxy::add_proxy( + RuntimeOrigin::signed(1), + 2, + ProxyType::JustTransfer, + 0 + )); + + assert_ok!(Proxy::proxy( + RuntimeOrigin::signed(2), + 1, + None, + Box::new(call_transfer(1, 1)) + )); + System::assert_last_event( + pallet_proxy::Event::ProxyExecuted { + result: DispatchError::from(frame_system::Error::::CallFiltered).into(), + } + .into(), + ); + }); } // GENERAL FAIL/NEGATIVE TESTS --------------------- #[test] fn fails_to_pause_self() { - new_test_ext().execute_with(|| { - assert_noop!( - TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"TxPause", Some(b"pause")), - ), - Error::::IsUnpausable - ); - }); + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"TxPause", Some(b"pause")), + ), + Error::::IsUnpausable + ); + }); } #[test] fn fails_to_pause_unpausable_pallet() { - new_test_ext().execute_with(|| { - assert_noop!( - TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"DummyPallet", Some(b"any_call")), - ), - Error::::IsUnpausable - ); - }); + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"DummyPallet", Some(b"any_call")), + ), + Error::::IsUnpausable + ); + }); } #[test] fn fails_to_pause_unpausable_call_when_pallet_is_paused() { - new_test_ext().execute_with(|| { - assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); - - let batch_call = - RuntimeCall::Utility(pallet_utility::Call::batch { calls: vec![call_transfer(1, 1)] }); - assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); - - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", None), - )); - - assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); - assert_err!( - call_transfer(2, 1).dispatch(RuntimeOrigin::signed(0)), - frame_system::Error::::CallFiltered - ); - }); + new_test_ext().execute_with(|| { + assert_ok!(call_transfer(1, 1).dispatch(RuntimeOrigin::signed(0))); + + let batch_call = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![call_transfer(1, 1)], + }); + assert_ok!(batch_call.clone().dispatch(RuntimeOrigin::signed(0))); + + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", None), + )); + + assert_ok!(call_transfer_keep_alive(3, 1).dispatch(RuntimeOrigin::signed(3))); + assert_err!( + call_transfer(2, 1).dispatch(RuntimeOrigin::signed(0)), + frame_system::Error::::CallFiltered + ); + }); } #[test] fn fails_to_pause_unpausable_call() { - new_test_ext().execute_with(|| { - assert_noop!( - TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer_keep_alive")), - ), - Error::::IsUnpausable - ); - }); + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer_keep_alive")), + ), + Error::::IsUnpausable + ); + }); } #[test] fn fails_to_pause_already_paused_pallet() { - new_test_ext().execute_with(|| { - assert_ok!(TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")), - )); - - assert_noop!( - TxPause::pause( - RuntimeOrigin::signed(mock::PauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer")), - ), - Error::::IsPaused - ); - }); + new_test_ext().execute_with(|| { + assert_ok!(TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + )); + + assert_noop!( + TxPause::pause( + RuntimeOrigin::signed(mock::PauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer")), + ), + Error::::IsPaused + ); + }); } #[test] fn fails_to_unpause_not_paused_pallet() { - new_test_ext().execute_with(|| { - assert_noop!( - TxPause::unpause( - RuntimeOrigin::signed(mock::UnpauseOrigin::get()), - full_name::(b"Balances", Some(b"transfer_keep_alive")), - ), - Error::::IsUnpaused - ); - }); + new_test_ext().execute_with(|| { + assert_noop!( + TxPause::unpause( + RuntimeOrigin::signed(mock::UnpauseOrigin::get()), + full_name::(b"Balances", Some(b"transfer_keep_alive")), + ), + Error::::IsUnpaused + ); + }); } pub fn call_transfer(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(pallet_balances::Call::transfer { dest, value }) + RuntimeCall::Balances(pallet_balances::Call::transfer { dest, value }) } pub fn call_transfer_keep_alive(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { dest, value }) + RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { dest, value }) } -pub fn full_name( - pallet_name_bytes: &[u8], - maybe_call_name_bytes: Option<&[u8]>, -) -> FullNameOf { - match maybe_call_name_bytes { - Some(call_name_bytes) => >::from(( - pallet_name_bytes.to_vec().try_into().unwrap(), - Some(call_name_bytes.to_vec().try_into().unwrap()), - )), - None => >::from((pallet_name_bytes.to_vec().try_into().unwrap(), None)), - } +pub fn full_name(pallet_name_bytes: &[u8], maybe_call_name_bytes: Option<&[u8]>) -> FullNameOf { + match maybe_call_name_bytes { + Some(call_name_bytes) => >::from(( + pallet_name_bytes.to_vec().try_into().unwrap(), + Some(call_name_bytes.to_vec().try_into().unwrap()), + )), + None => >::from((pallet_name_bytes.to_vec().try_into().unwrap(), None)), + } } From 4aded9cf043715f98c198169fb69cb57bfebab27 Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Wed, 18 Jan 2023 15:13:57 +0100 Subject: [PATCH 6/8] refactor: remove StatusCode::Shutdown --- crates/security/src/lib.rs | 5 - crates/security/src/tests.rs | 36 ------- crates/security/src/types.rs | 2 - parachain/runtime/interlay/src/lib.rs | 3 - parachain/runtime/kintsugi/src/lib.rs | 3 - parachain/runtime/testnet-interlay/src/lib.rs | 3 - parachain/runtime/testnet-kintsugi/src/lib.rs | 3 - parachain/src/chain_spec/interlay.rs | 2 +- parachain/src/chain_spec/kintsugi.rs | 2 +- parachain/src/chain_spec/testnet_interlay.rs | 9 +- parachain/src/chain_spec/testnet_kintsugi.rs | 12 +-- standalone/runtime/src/lib.rs | 3 - standalone/runtime/tests/test_btc_relay.rs | 39 -------- standalone/runtime/tests/test_fee_pool.rs | 15 --- standalone/runtime/tests/test_governance.rs | 67 +------------ standalone/runtime/tests/test_issue.rs | 48 --------- standalone/runtime/tests/test_nomination.rs | 1 - standalone/runtime/tests/test_oracle.rs | 12 --- standalone/runtime/tests/test_redeem.rs | 97 +------------------ standalone/runtime/tests/test_replace.rs | 68 ------------- .../runtime/tests/test_vault_registry.rs | 48 --------- standalone/src/chain_spec.rs | 10 +- 22 files changed, 8 insertions(+), 480 deletions(-) diff --git a/crates/security/src/lib.rs b/crates/security/src/lib.rs index b0af617333..33937aaf5a 100644 --- a/crates/security/src/lib.rs +++ b/crates/security/src/lib.rs @@ -195,11 +195,6 @@ impl Pallet { } } - /// Checks if the Parachain has Shutdown - pub fn is_parachain_shutdown() -> bool { - Self::parachain_status() == StatusCode::Shutdown - } - /// Checks if the Parachain has a OracleOffline Error state pub fn is_parachain_error_oracle_offline() -> bool { Self::parachain_status() == StatusCode::Error && >::get().contains(&ErrorCode::OracleOffline) diff --git a/crates/security/src/tests.rs b/crates/security/src/tests.rs index ae3fabd83a..8f7599e747 100644 --- a/crates/security/src/tests.rs +++ b/crates/security/src/tests.rs @@ -18,17 +18,6 @@ macro_rules! assert_emitted { }; } -#[test] -fn test_get_and_set_status() { - run_test(|| { - let status_code = Security::parachain_status(); - assert_eq!(status_code, StatusCode::Running); - Security::set_status(StatusCode::Shutdown); - let status_code = Security::parachain_status(); - assert_eq!(status_code, StatusCode::Shutdown); - }) -} - #[test] fn test_is_ensure_parachain_running_succeeds() { run_test(|| { @@ -45,26 +34,6 @@ fn test_is_ensure_parachain_running_fails() { Security::ensure_parachain_status_running(), TestError::ParachainNotRunning ); - - Security::set_status(StatusCode::Shutdown); - assert_noop!( - Security::ensure_parachain_status_running(), - TestError::ParachainNotRunning - ); - }) -} - -#[test] -fn test_is_parachain_shutdown_succeeds() { - run_test(|| { - Security::set_status(StatusCode::Running); - assert!(!Security::is_parachain_shutdown()); - - Security::set_status(StatusCode::Error); - assert!(!Security::is_parachain_shutdown()); - - Security::set_status(StatusCode::Shutdown); - assert!(Security::is_parachain_shutdown()); }) } @@ -135,11 +104,6 @@ fn test_get_active_block_not_incremented_if_not_running() { Security::set_status(StatusCode::Error); Security::increment_active_block(); assert_eq!(Security::active_block_number(), initial_active_block); - - // not updated if there is shutdown - Security::set_status(StatusCode::Shutdown); - Security::increment_active_block(); - assert_eq!(Security::active_block_number(), initial_active_block); }) } diff --git a/crates/security/src/types.rs b/crates/security/src/types.rs index b166586c5d..88caa61803 100644 --- a/crates/security/src/types.rs +++ b/crates/security/src/types.rs @@ -10,8 +10,6 @@ pub enum StatusCode { Running = 0, /// An error has occurred. See Errors for more details. Error = 1, - /// BTC Parachain operation has been fully suspended. - Shutdown = 2, } impl Default for StatusCode { diff --git a/parachain/runtime/interlay/src/lib.rs b/parachain/runtime/interlay/src/lib.rs index 0ab60f8986..bc5fc65554 100644 --- a/parachain/runtime/interlay/src/lib.rs +++ b/parachain/runtime/interlay/src/lib.rs @@ -176,9 +176,6 @@ impl Contains for BaseCallFilter { ) { // always allow core calls true - } else if security::Pallet::::is_parachain_shutdown() { - // in shutdown mode, all non-core calls are disallowed - false } else if let RuntimeCall::PolkadotXcm(_) = call { // For security reasons, disallow usage of the xcm package by users. Sudo and // governance are still able to call these (sudo is explicitly white-listed, while diff --git a/parachain/runtime/kintsugi/src/lib.rs b/parachain/runtime/kintsugi/src/lib.rs index 80629ff074..e3ef35ade8 100644 --- a/parachain/runtime/kintsugi/src/lib.rs +++ b/parachain/runtime/kintsugi/src/lib.rs @@ -174,9 +174,6 @@ impl Contains for BaseCallFilter { ) { // always allow core calls true - } else if security::Pallet::::is_parachain_shutdown() { - // in shutdown mode, all non-core calls are disallowed - false } else if let RuntimeCall::PolkadotXcm(_) = call { // For security reasons, disallow usage of the xcm package by users. Sudo and // governance are still able to call these (sudo is explicitly white-listed, while diff --git a/parachain/runtime/testnet-interlay/src/lib.rs b/parachain/runtime/testnet-interlay/src/lib.rs index 8c4726ba36..315629d259 100644 --- a/parachain/runtime/testnet-interlay/src/lib.rs +++ b/parachain/runtime/testnet-interlay/src/lib.rs @@ -177,9 +177,6 @@ impl Contains for BaseCallFilter { ) { // always allow core calls true - } else if security::Pallet::::is_parachain_shutdown() { - // in shutdown mode, all non-core calls are disallowed - false } else if let RuntimeCall::PolkadotXcm(_) = call { // For security reasons, disallow usage of the xcm package by users. Sudo and // governance are still able to call these (sudo is explicitly white-listed, while diff --git a/parachain/runtime/testnet-kintsugi/src/lib.rs b/parachain/runtime/testnet-kintsugi/src/lib.rs index a9f894ad91..bb62926318 100644 --- a/parachain/runtime/testnet-kintsugi/src/lib.rs +++ b/parachain/runtime/testnet-kintsugi/src/lib.rs @@ -179,9 +179,6 @@ impl Contains for BaseCallFilter { ) { // always allow core calls true - } else if security::Pallet::::is_parachain_shutdown() { - // in shutdown mode, all non-core calls are disallowed - false } else if let RuntimeCall::PolkadotXcm(_) = call { // For security reasons, disallow usage of the xcm package by users. Sudo and // governance are still able to call these (sudo is explicitly white-listed, while diff --git a/parachain/src/chain_spec/interlay.rs b/parachain/src/chain_spec/interlay.rs index 3974a4c98f..09838568d8 100644 --- a/parachain/src/chain_spec/interlay.rs +++ b/parachain/src/chain_spec/interlay.rs @@ -156,7 +156,7 @@ fn interlay_mainnet_genesis( aura: Default::default(), aura_ext: Default::default(), security: interlay_runtime::SecurityConfig { - initial_status: interlay_runtime::StatusCode::Shutdown, + initial_status: interlay_runtime::StatusCode::Error, }, asset_registry: Default::default(), tokens: Default::default(), diff --git a/parachain/src/chain_spec/kintsugi.rs b/parachain/src/chain_spec/kintsugi.rs index c65895673e..6bd1b56b17 100644 --- a/parachain/src/chain_spec/kintsugi.rs +++ b/parachain/src/chain_spec/kintsugi.rs @@ -160,7 +160,7 @@ fn kintsugi_mainnet_genesis( aura: Default::default(), aura_ext: Default::default(), security: kintsugi_runtime::SecurityConfig { - initial_status: kintsugi_runtime::StatusCode::Shutdown, + initial_status: kintsugi_runtime::StatusCode::Error, }, asset_registry: Default::default(), tokens: Default::default(), diff --git a/parachain/src/chain_spec/testnet_interlay.rs b/parachain/src/chain_spec/testnet_interlay.rs index fef18c88b1..702ea9ce3f 100644 --- a/parachain/src/chain_spec/testnet_interlay.rs +++ b/parachain/src/chain_spec/testnet_interlay.rs @@ -64,7 +64,6 @@ pub fn development_config(id: ParaId) -> InterlayTestnetChainSpec { ], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, Vec::new(), @@ -125,7 +124,6 @@ pub fn staging_testnet_config(id: ParaId) -> InterlayTestnetChainSpec { )], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, Vec::new(), @@ -151,7 +149,6 @@ fn testnet_genesis( authorized_oracles: Vec<(AccountId, Vec)>, id: ParaId, bitcoin_confirmations: u32, - start_shutdown: bool, ) -> testnet_interlay_runtime::GenesisConfig { testnet_interlay_runtime::GenesisConfig { system: testnet_interlay_runtime::SystemConfig { @@ -184,11 +181,7 @@ fn testnet_genesis( aura: Default::default(), aura_ext: Default::default(), security: testnet_interlay_runtime::SecurityConfig { - initial_status: if start_shutdown { - testnet_interlay_runtime::StatusCode::Shutdown - } else { - testnet_interlay_runtime::StatusCode::Error - }, + initial_status: testnet_interlay_runtime::StatusCode::Error, }, sudo: testnet_interlay_runtime::SudoConfig { // Assign network admin rights. diff --git a/parachain/src/chain_spec/testnet_kintsugi.rs b/parachain/src/chain_spec/testnet_kintsugi.rs index 0c8f652b06..5b543465be 100644 --- a/parachain/src/chain_spec/testnet_kintsugi.rs +++ b/parachain/src/chain_spec/testnet_kintsugi.rs @@ -54,7 +54,6 @@ pub fn local_config(id: ParaId) -> KintsugiTestnetChainSpec { )], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, vec![], @@ -108,7 +107,6 @@ pub fn development_config(id: ParaId) -> KintsugiTestnetChainSpec { ], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, Vec::new(), @@ -169,7 +167,6 @@ pub fn staging_testnet_config(id: ParaId) -> KintsugiTestnetChainSpec { )], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, Vec::new(), @@ -230,7 +227,6 @@ pub fn rococo_testnet_config(id: ParaId) -> KintsugiTestnetChainSpec { )], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, Vec::new(), @@ -295,7 +291,6 @@ pub fn westend_testnet_config(id: ParaId) -> KintsugiTestnetChainSpec { )], id, DEFAULT_BITCOIN_CONFIRMATIONS, - false, ) }, Vec::new(), @@ -317,7 +312,6 @@ fn testnet_genesis( authorized_oracles: Vec<(AccountId, Vec)>, id: ParaId, bitcoin_confirmations: u32, - start_shutdown: bool, ) -> testnet_kintsugi_runtime::GenesisConfig { testnet_kintsugi_runtime::GenesisConfig { system: testnet_kintsugi_runtime::SystemConfig { @@ -350,11 +344,7 @@ fn testnet_genesis( aura: Default::default(), aura_ext: Default::default(), security: testnet_kintsugi_runtime::SecurityConfig { - initial_status: if start_shutdown { - testnet_kintsugi_runtime::StatusCode::Shutdown - } else { - testnet_kintsugi_runtime::StatusCode::Error - }, + initial_status: testnet_kintsugi_runtime::StatusCode::Error, }, sudo: testnet_kintsugi_runtime::SudoConfig { // Assign network admin rights. diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index a5b443f90f..b4a854fe18 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -183,9 +183,6 @@ impl Contains for BaseCallFilter { ) { // always allow core calls true - } else if security::Pallet::::is_parachain_shutdown() { - // disallow all non-core calls if shutdown - false } else { // normal operation: allow all calls that are not explicitly paused TxPause::contains(call) diff --git a/standalone/runtime/tests/test_btc_relay.rs b/standalone/runtime/tests/test_btc_relay.rs index 8488dfbbec..284dffb135 100644 --- a/standalone/runtime/tests/test_btc_relay.rs +++ b/standalone/runtime/tests/test_btc_relay.rs @@ -94,45 +94,6 @@ fn integration_test_submit_block_headers_and_verify_transaction_inclusion() { }) } -#[test] -fn integration_test_btc_relay_with_parachain_shutdown_fails() { - ExtBuilder::build().execute_with(|| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::BTCRelay(BTCRelayCall::verify_and_validate_transaction { - raw_merkle_proof: Default::default(), - confirmations: Default::default(), - raw_tx: Default::default(), - expected_btc: Default::default(), - recipient_btc_address: Default::default(), - op_return_id: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - assert_noop!( - RuntimeCall::BTCRelay(BTCRelayCall::verify_transaction_inclusion { - tx_id: Default::default(), - raw_merkle_proof: Default::default(), - confirmations: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - assert_noop!( - RuntimeCall::BTCRelay(BTCRelayCall::validate_transaction { - raw_tx: Default::default(), - expected_btc: Default::default(), - recipient_btc_address: Default::default(), - op_return_id: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - }) -} - #[test] fn integration_test_submit_fork_headers() { ExtBuilder::build().execute_without_relay_init(|| { diff --git a/standalone/runtime/tests/test_fee_pool.rs b/standalone/runtime/tests/test_fee_pool.rs index 85c12146c4..83bb1a2117 100644 --- a/standalone/runtime/tests/test_fee_pool.rs +++ b/standalone/runtime/tests/test_fee_pool.rs @@ -143,21 +143,6 @@ fn integration_test_estimate_vault_reward_rate() { }); } -#[test] -fn integration_test_fee_with_parachain_shutdown_fails() { - test_with(|vault_id_1| { - SecurityPallet::set_status(StatusCode::Shutdown); - assert_noop!( - RuntimeCall::Fee(FeeCall::withdraw_rewards { - vault_id: vault_id_1.clone(), - index: None - }) - .dispatch(origin_of(vault_id_1.account_id)), - SystemError::CallFiltered - ); - }) -} - #[test] fn test_vault_reward_withdrawal() { test_with(|vault_id_1| { diff --git a/standalone/runtime/tests/test_governance.rs b/standalone/runtime/tests/test_governance.rs index 17e1d39e5f..a8cdc69bd4 100644 --- a/standalone/runtime/tests/test_governance.rs +++ b/standalone/runtime/tests/test_governance.rs @@ -172,69 +172,6 @@ fn launch_and_execute_referendum() { SchedulerPallet::on_initialize(act_height); } -#[test] -fn can_recover_from_shutdown_using_governance() { - test_with(|| { - // use sudo to set parachain status - assert_ok!(RuntimeCall::Sudo(SudoCall::sudo { - call: Box::new(RuntimeCall::Security(SecurityCall::set_parachain_status { - status_code: StatusCode::Shutdown, - })), - }) - .dispatch(origin_of(account_of(ALICE)))); - assert!(SecurityPallet::is_parachain_shutdown()); - - create_proposal( - RuntimeCall::Security(SecurityCall::set_parachain_status { - status_code: StatusCode::Running, - }) - .encode(), - ); - launch_and_execute_referendum(); - assert!(!SecurityPallet::is_parachain_shutdown()); - }) -} - -#[test] -fn can_recover_from_shutdown_using_root() { - test_with(|| { - // use sudo to set parachain status - assert_ok!(RuntimeCall::Sudo(SudoCall::sudo { - call: Box::new(RuntimeCall::Security(SecurityCall::set_parachain_status { - status_code: StatusCode::Shutdown, - })), - }) - .dispatch(origin_of(account_of(ALICE)))); - - // verify we cant execute normal calls - assert_noop!( - RuntimeCall::Tokens(TokensCall::transfer { - dest: account_of(ALICE), - currency_id: DEFAULT_NATIVE_CURRENCY, - amount: 123, - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - - // use sudo to set parachain status back to running - assert_ok!(RuntimeCall::Sudo(SudoCall::sudo { - call: Box::new(RuntimeCall::Security(SecurityCall::set_parachain_status { - status_code: StatusCode::Running, - })) - }) - .dispatch(origin_of(account_of(ALICE)))); - - // verify that we can execute normal calls again - assert_ok!(RuntimeCall::Tokens(TokensCall::transfer { - dest: account_of(ALICE), - currency_id: DEFAULT_NATIVE_CURRENCY, - amount: 123, - }) - .dispatch(origin_of(account_of(ALICE)))); - }); -} - fn full_name(pallet_name_bytes: &[u8], maybe_call_name_bytes: Option<&[u8]>) -> FullNameOf { match maybe_call_name_bytes { Some(call_name_bytes) => >::from(( @@ -998,7 +935,7 @@ fn test_sudo_is_disabled_if_key_is_none() { // first a sanity check: sudo works if key is set assert_ok!(RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(RuntimeCall::Security(SecurityCall::set_parachain_status { - status_code: StatusCode::Shutdown, + status_code: StatusCode::Error, })), }) .dispatch(origin_of(account_of(ALICE))),); @@ -1012,7 +949,7 @@ fn test_sudo_is_disabled_if_key_is_none() { assert_noop!( RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(RuntimeCall::Security(SecurityCall::set_parachain_status { - status_code: StatusCode::Shutdown, + status_code: StatusCode::Error, })), }) .dispatch(origin_of(account_of(ALICE))), diff --git a/standalone/runtime/tests/test_issue.rs b/standalone/runtime/tests/test_issue.rs index 6c13992b60..2a346a7498 100644 --- a/standalone/runtime/tests/test_issue.rs +++ b/standalone/runtime/tests/test_issue.rs @@ -149,22 +149,6 @@ mod request_issue_tests { use super::{assert_eq, *}; - /// Request fails if parachain is shutdown - #[test] - fn integration_test_issue_request_precond_not_shutdown() { - test_with(|vault_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - assert_noop!( - RuntimeCall::Issue(IssueCall::request_issue { - amount: 0, - vault_id: vault_id, - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - }); - } - /// Request fails if relay is not initialized #[test] fn integration_test_issue_request_precond_relay_initialized() { @@ -574,23 +558,6 @@ fn integration_test_withdraw_after_request_issue() { mod execute_pending_issue_tests { use super::{assert_eq, *}; - /// Execute fails if parachain is shut down - #[test] - fn integration_test_issue_execute_precond_not_shutdown() { - test_with(|_currency_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::Issue(IssueCall::execute_issue { - issue_id: Default::default(), - merkle_proof: Default::default(), - raw_tx: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - }); - } /// Execute fails if corresponding request doesn't exist #[test] @@ -998,21 +965,6 @@ mod execute_cancelled_issue_tests { mod cancel_issue_tests { use super::{assert_eq, *}; - /// Cancel fails when parachain is shutdown - #[test] - fn integration_test_issue_cancel_precond_not_shutdown() { - test_with(|_currency_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - assert_noop!( - RuntimeCall::Issue(IssueCall::cancel_issue { - issue_id: H256([0; 32]), - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - }); - } - /// Cancel fails if issue request does not exist #[test] fn integration_test_issue_cancel_precond_issue_exists() { diff --git a/standalone/runtime/tests/test_nomination.rs b/standalone/runtime/tests/test_nomination.rs index 6d0b2d862b..314f71b64a 100644 --- a/standalone/runtime/tests/test_nomination.rs +++ b/standalone/runtime/tests/test_nomination.rs @@ -120,7 +120,6 @@ mod spec_based_tests { fn integration_test_nomination_with_parachain_shutdown_status_fails() { // Checked PRECONDITION: The BTC Parachain status in the Security component be `RUNNING:0`. test_with(|_| { - // nomination_with_non_running_status_fails(StatusCode::Shutdown); nomination_with_non_running_status_fails(StatusCode::Error); }); } diff --git a/standalone/runtime/tests/test_oracle.rs b/standalone/runtime/tests/test_oracle.rs index d760d53529..ce83224298 100644 --- a/standalone/runtime/tests/test_oracle.rs +++ b/standalone/runtime/tests/test_oracle.rs @@ -1,14 +1,2 @@ mod mock; use mock::{assert_eq, *}; - -#[test] -fn integration_test_oracle_with_parachain_shutdown_fails() { - ExtBuilder::build().execute_with(|| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::Oracle(OracleCall::feed_values { values: vec![] }).dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - }) -} diff --git a/standalone/runtime/tests/test_redeem.rs b/standalone/runtime/tests/test_redeem.rs index 20257ec4f7..fc6c8f0cbf 100644 --- a/standalone/runtime/tests/test_redeem.rs +++ b/standalone/runtime/tests/test_redeem.rs @@ -72,74 +72,13 @@ mod spec_based_tests { use primitives::VaultCurrencyPair; use super::{assert_eq, *}; - #[test] - fn integration_test_redeem_with_parachain_shutdown_status_fails() { - // PRECONDITION: The BTC Parachain status in the Security component - test_with(|vault_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - assert_noop!( - RuntimeCall::Redeem(RedeemCall::request_redeem { - amount_wrapped: 1500, - btc_address: BtcAddress::random(), - vault_id: vault_id.clone(), - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - - assert_noop!( - RuntimeCall::Redeem(RedeemCall::execute_redeem { - redeem_id: Default::default(), - merkle_proof: Default::default(), - raw_tx: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - - assert_noop!( - RuntimeCall::Redeem(RedeemCall::cancel_redeem { - redeem_id: Default::default(), - reimburse: false - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - assert_noop!( - RuntimeCall::Redeem(RedeemCall::cancel_redeem { - redeem_id: Default::default(), - reimburse: true - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - - assert_noop!( - RuntimeCall::Redeem(RedeemCall::liquidation_redeem { - currencies: vault_id.currencies.clone(), - amount_wrapped: 1000 - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - - assert_noop!( - RuntimeCall::Redeem(RedeemCall::mint_tokens_for_reimbursed_redeem { - currency_pair: vault_id.currencies.clone(), - redeem_id: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - }); - } #[test] fn integration_test_redeem_with_parachain_error_status_fails() { // PRECONDITION: The BTC Parachain status in the Security component test_with(|vault_id| { // `liquidation_redeem` and `execute_redeem` are not tested here - // because they only require the parachain status not to be `Shutdown` + // because they are allowed even in error SecurityPallet::set_status(StatusCode::Error); assert_noop!( @@ -1221,40 +1160,6 @@ mod spec_based_tests { } } -#[test] -fn integration_test_redeem_parachain_status_shutdown_fails() { - test_with(|vault_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::Issue(IssueCall::request_issue { - amount: 0, - vault_id: vault_id.clone(), - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - - assert_noop!( - RuntimeCall::Issue(IssueCall::cancel_issue { - issue_id: H256([0; 32]), - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - - assert_noop!( - RuntimeCall::Issue(IssueCall::execute_issue { - issue_id: H256([0; 32]), - merkle_proof: vec![0u8; 32], - raw_tx: vec![0u8; 32] - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered, - ); - }); -} - mod execute_redeem_payment_limits { use super::{assert_eq, *}; diff --git a/standalone/runtime/tests/test_replace.rs b/standalone/runtime/tests/test_replace.rs index 3fa6771036..c887acacff 100644 --- a/standalone/runtime/tests/test_replace.rs +++ b/standalone/runtime/tests/test_replace.rs @@ -310,27 +310,7 @@ mod accept_replace_tests { } mod request_replace_tests { - use primitives::VaultCurrencyPair; - use super::{assert_eq, *}; - #[test] - fn integration_test_replace_should_fail_if_not_running() { - test_without_initialization(|_currency_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::Replace(ReplaceCall::request_replace { - currency_pair: VaultCurrencyPair { - collateral: Token(DOT), - wrapped: Token(DOT), - }, - amount: 0, - }) - .dispatch(origin_of(account_of(OLD_VAULT))), - SystemError::CallFiltered, - ); - }); - } #[test] fn integration_test_replace_request_replace_at_capacity_succeeds() { @@ -698,54 +678,6 @@ mod execute_replace_payment_limits { } } -#[test] -fn integration_test_replace_with_parachain_shutdown_fails() { - test_with(|old_vault_id, new_vault_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::Replace(ReplaceCall::request_replace { - currency_pair: old_vault_id.currencies.clone(), - amount: old_vault_id.wrapped(0).amount(), - }) - .dispatch(origin_of(old_vault_id.account_id.clone())), - SystemError::CallFiltered, - ); - assert_noop!( - withdraw_replace(&old_vault_id, old_vault_id.wrapped(0)), - SystemError::CallFiltered - ); - assert_noop!( - accept_replace( - &old_vault_id, - &new_vault_id, - old_vault_id.wrapped(0), - griefing(0), - Default::default() - ), - SystemError::CallFiltered - ); - - assert_noop!( - RuntimeCall::Replace(ReplaceCall::execute_replace { - replace_id: Default::default(), - merkle_proof: Default::default(), - raw_tx: Default::default() - }) - .dispatch(origin_of(account_of(OLD_VAULT))), - SystemError::CallFiltered - ); - - assert_noop!( - RuntimeCall::Replace(ReplaceCall::cancel_replace { - replace_id: Default::default() - }) - .dispatch(origin_of(account_of(OLD_VAULT))), - SystemError::CallFiltered - ); - }) -} - #[test] fn integration_test_replace_cancel_replace() { test_with(|old_vault_id, new_vault_id| { diff --git a/standalone/runtime/tests/test_vault_registry.rs b/standalone/runtime/tests/test_vault_registry.rs index d8978afa19..ad8e18f574 100644 --- a/standalone/runtime/tests/test_vault_registry.rs +++ b/standalone/runtime/tests/test_vault_registry.rs @@ -304,54 +304,6 @@ mod withdraw_collateral_test { } } -#[test] -fn integration_test_vault_registry_with_parachain_shutdown_fails() { - test_with(|vault_id| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - RuntimeCall::VaultRegistry(VaultRegistryCall::register_vault { - currency_pair: vault_id.currencies.clone(), - collateral: 0, - }) - .dispatch(origin_of(account_of(VAULT))), - SystemError::CallFiltered - ); - assert_noop!( - RuntimeCall::Nomination(NominationCall::deposit_collateral { - vault_id: vault_id.clone(), - amount: 0 - }) - .dispatch(origin_of(account_of(VAULT))), - SystemError::CallFiltered - ); - assert_noop!( - RuntimeCall::Nomination(NominationCall::withdraw_collateral { - vault_id: vault_id.clone(), - index: None, - amount: 0 - }) - .dispatch(origin_of(account_of(VAULT))), - SystemError::CallFiltered - ); - assert_noop!( - RuntimeCall::VaultRegistry(VaultRegistryCall::register_public_key { - public_key: Default::default() - }) - .dispatch(origin_of(account_of(VAULT))), - SystemError::CallFiltered - ); - assert_noop!( - RuntimeCall::VaultRegistry(VaultRegistryCall::accept_new_issues { - currency_pair: vault_id.currencies.clone(), - accept_new_issues: false - }) - .dispatch(origin_of(account_of(VAULT))), - SystemError::CallFiltered - ); - }); -} - #[test] fn integration_test_vault_registry_undercollateralization_liquidation() { test_with(|vault_id| { diff --git a/standalone/src/chain_spec.rs b/standalone/src/chain_spec.rs index f8bf473fc2..5b68d24cc0 100644 --- a/standalone/src/chain_spec.rs +++ b/standalone/src/chain_spec.rs @@ -91,7 +91,6 @@ pub fn local_config() -> ChainSpec { "Bob".as_bytes().to_vec(), )], 0, - false, ) }, vec![], @@ -150,7 +149,6 @@ pub fn beta_testnet_config() -> ChainSpec { "Interlay".as_bytes().to_vec(), )], 1, - false, ) }, Vec::new(), @@ -200,7 +198,6 @@ pub fn development_config() -> ChainSpec { ), ], 1, - false, ) }, Vec::new(), @@ -240,7 +237,6 @@ fn testnet_genesis( endowed_accounts: Vec, authorized_oracles: Vec<(AccountId, Vec)>, bitcoin_confirmations: u32, - start_shutdown: bool, ) -> GenesisConfig { GenesisConfig { system: SystemConfig { @@ -255,11 +251,7 @@ fn testnet_genesis( authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), }, security: SecurityConfig { - initial_status: if start_shutdown { - StatusCode::Shutdown - } else { - StatusCode::Error - }, + initial_status: StatusCode::Error, }, sudo: SudoConfig { // Assign network admin rights. From 5e61867696cd5d96f5a69c96d7f6b8206981fcfd Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Wed, 18 Jan 2023 15:30:13 +0100 Subject: [PATCH 7/8] chore: add missing try-runtime feature --- crates/tx-pause/src/benchmarking.rs | 4 ++-- parachain/runtime/interlay/Cargo.toml | 1 + parachain/runtime/kintsugi/Cargo.toml | 1 + parachain/runtime/testnet-interlay/Cargo.toml | 1 + parachain/runtime/testnet-kintsugi/Cargo.toml | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/tx-pause/src/benchmarking.rs b/crates/tx-pause/src/benchmarking.rs index a06725d0cd..c7c186d4b4 100644 --- a/crates/tx-pause/src/benchmarking.rs +++ b/crates/tx-pause/src/benchmarking.rs @@ -30,7 +30,7 @@ benchmarks! { // let call = Call::::pause { full_name: full_name.clone() }; // let call = Call::::pause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; - }: _(origin, full_name.clone()) + }: _(origin, full_name.clone()) verify { assert!(TxPause::::paused_calls(full_name.clone()).is_some()) } @@ -47,7 +47,7 @@ benchmarks! { let unpause_origin = T::UnpauseOrigin::successful_origin(); // let call = Call::::unpause { pallet_name: pallet_name.clone(), maybe_call_name: maybe_call_name.clone() }; - }: _(unpause_origin, full_name.clone()) + }: _(unpause_origin, full_name.clone()) verify { assert!(TxPause::::paused_calls(full_name.clone()).is_none()) diff --git a/parachain/runtime/interlay/Cargo.toml b/parachain/runtime/interlay/Cargo.toml index 67ee77797e..b354f0ef39 100644 --- a/parachain/runtime/interlay/Cargo.toml +++ b/parachain/runtime/interlay/Cargo.toml @@ -299,6 +299,7 @@ try-runtime = [ "fee/try-runtime", "nomination/try-runtime", "clients-info/try-runtime", + "tx-pause/try-runtime", "democracy/try-runtime", "pallet-collective/try-runtime", "pallet-membership/try-runtime", diff --git a/parachain/runtime/kintsugi/Cargo.toml b/parachain/runtime/kintsugi/Cargo.toml index 8aebff0337..1e158f6c11 100644 --- a/parachain/runtime/kintsugi/Cargo.toml +++ b/parachain/runtime/kintsugi/Cargo.toml @@ -303,6 +303,7 @@ try-runtime = [ "fee/try-runtime", "nomination/try-runtime", "clients-info/try-runtime", + "tx-pause/try-runtime", "democracy/try-runtime", "pallet-collective/try-runtime", "pallet-membership/try-runtime", diff --git a/parachain/runtime/testnet-interlay/Cargo.toml b/parachain/runtime/testnet-interlay/Cargo.toml index 45d40a3e47..13a89580dd 100644 --- a/parachain/runtime/testnet-interlay/Cargo.toml +++ b/parachain/runtime/testnet-interlay/Cargo.toml @@ -309,6 +309,7 @@ try-runtime = [ "fee/try-runtime", "nomination/try-runtime", "clients-info/try-runtime", + "tx-pause/try-runtime", "loans/try-runtime", "democracy/try-runtime", "pallet-collective/try-runtime", diff --git a/parachain/runtime/testnet-kintsugi/Cargo.toml b/parachain/runtime/testnet-kintsugi/Cargo.toml index 400b1e432e..fd6e2372fc 100644 --- a/parachain/runtime/testnet-kintsugi/Cargo.toml +++ b/parachain/runtime/testnet-kintsugi/Cargo.toml @@ -325,6 +325,7 @@ try-runtime = [ "fee/try-runtime", "nomination/try-runtime", "clients-info/try-runtime", + "tx-pause/try-runtime", "loans/try-runtime", "democracy/try-runtime", "farming/try-runtime", From 80cf335c2863fcf9ab1e076584ad069283665af3 Mon Sep 17 00:00:00 2001 From: Sander Bosma Date: Fri, 20 Jan 2023 11:41:01 +0100 Subject: [PATCH 8/8] fix: restore missing basecallfilter items --- parachain/runtime/interlay/src/lib.rs | 3 +++ parachain/runtime/kintsugi/src/lib.rs | 3 +++ parachain/runtime/testnet-interlay/src/lib.rs | 3 +++ parachain/runtime/testnet-kintsugi/src/lib.rs | 3 +++ 4 files changed, 12 insertions(+) diff --git a/parachain/runtime/interlay/src/lib.rs b/parachain/runtime/interlay/src/lib.rs index bc5fc65554..ec733da7f4 100644 --- a/parachain/runtime/interlay/src/lib.rs +++ b/parachain/runtime/interlay/src/lib.rs @@ -168,7 +168,10 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) + | RuntimeCall::Authorship(_) + | RuntimeCall::Session(_) | RuntimeCall::Timestamp(_) + | RuntimeCall::ParachainSystem(_) | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) diff --git a/parachain/runtime/kintsugi/src/lib.rs b/parachain/runtime/kintsugi/src/lib.rs index e3ef35ade8..b40f958de7 100644 --- a/parachain/runtime/kintsugi/src/lib.rs +++ b/parachain/runtime/kintsugi/src/lib.rs @@ -166,7 +166,10 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) + | RuntimeCall::Authorship(_) + | RuntimeCall::Session(_) | RuntimeCall::Timestamp(_) + | RuntimeCall::ParachainSystem(_) | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) diff --git a/parachain/runtime/testnet-interlay/src/lib.rs b/parachain/runtime/testnet-interlay/src/lib.rs index 315629d259..87ca687fe3 100644 --- a/parachain/runtime/testnet-interlay/src/lib.rs +++ b/parachain/runtime/testnet-interlay/src/lib.rs @@ -169,7 +169,10 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) + | RuntimeCall::Authorship(_) + | RuntimeCall::Session(_) | RuntimeCall::Timestamp(_) + | RuntimeCall::ParachainSystem(_) | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_) diff --git a/parachain/runtime/testnet-kintsugi/src/lib.rs b/parachain/runtime/testnet-kintsugi/src/lib.rs index bb62926318..ea319cb5e0 100644 --- a/parachain/runtime/testnet-kintsugi/src/lib.rs +++ b/parachain/runtime/testnet-kintsugi/src/lib.rs @@ -171,7 +171,10 @@ impl Contains for BaseCallFilter { if matches!( call, RuntimeCall::System(_) + | RuntimeCall::Authorship(_) + | RuntimeCall::Session(_) | RuntimeCall::Timestamp(_) + | RuntimeCall::ParachainSystem(_) | RuntimeCall::Sudo(_) | RuntimeCall::Democracy(_) | RuntimeCall::Escrow(_)