[FRAME Core] New pallets: safe-mode and tx-pause (#12092)

* Add safe-mode

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add to kitchensink-runtime

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Spelling

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename to tx-pause

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add SafeMode pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Automatically disable safe-mode in on_init…

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add permissionless enable+extend

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add repay+slash stake methods

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix stakes storage

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Genesis config for safe-mode pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Genesis config for safe-mode pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename ExtrinsicName to FunctionName

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Origin variable duration

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename FunctionName -> CallName

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename and docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Pallet safe mode tests (#12148)

* Add safe-mode mock runtime
* Add safe-mode tests
* Add ForceEnable- and ForceExtendOrigin
* Start dummy benchmarks
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Tests for `pallet-tx-pause` (#12259)

* mock added
* tests added
* dummy benchmarks started

* rename to active/inactive
tests broken, in progress

* Runtime types, fix tests

* WIP safe mode and tx pause {continued} (#12371)

* test coverage on safe mode and tx pause
* benchmarks & tests
* tests passing, use FullNameOf to check tx-pause unfilterables
* naming updates

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Set block number

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* dummy weights generated, safe mode

* add repay_reservation call with RepaymentDelay per #10033 feature requirements

* make call name optional to allow pausing pallets, handle `Contains` correctly for this throughout, doc comments started

* move to full_name notation for all interfaces, last commit introduced 1 more storage read.

* refactor is_paused

* safe math on safe mode

* Make stuff compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cleanup & renames

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cleanup TxPause pallet

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix benches

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Refactor to fungibles::* and rename stuf

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix node config

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Typos

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove CausalHoldReason

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Refactor benchmarks and runtime configs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add traits

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove old code

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cleanup safe-mode benches

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update frame/safe-mode/Cargo.toml

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/safe-mode/Cargo.toml

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove getters

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update Cargo.lock

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove phantom

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix test

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove phantom

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Apply suggestions from code review

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Use new as Origin benchmarking syntax

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix node

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix tx-pause benches

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Renames

* Remove duplicate test

* Add docs

* docs

* Apply suggestions from code review

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>

* Cleanup tests

* docs

* Cleanup GenesisConfigs

* Doc traits

* Remove PauseTooLongNames

* docs

* Use V2 benchmarking

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Use RuntimeHoldReason

* Fix kitchensink runtime

* Fix CI

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix CI

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Review

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename Stake to Deposit

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add docs

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add Notify and test it

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix kitchensink

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update frame/safe-mode/src/tests.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/safe-mode/src/tests.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/tx_pause.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/tx-pause/src/lib.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/tx-pause/src/lib.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/tx-pause/src/mock.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Simplify code

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Update frame/support/src/traits/safe_mode.rs

Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>

* Fixup merge

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make stuff compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make tx-pause compile again

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix features

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix more features

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_safe_mode

* Update weights

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Dan Shields <35669742+NukeManDan@users.noreply.github.com>
Co-authored-by: Dan Shields <nukemandan@protonmail.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
Co-authored-by: command-bot <>
This commit is contained in:
Oliver Tale-Yazdi
2023-08-25 02:56:00 +02:00
committed by GitHub
parent 46bd466e48
commit 3710edfedc
22 changed files with 3339 additions and 6 deletions
+222
View File
@@ -0,0 +1,222 @@
// 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(RuntimeOrigin::signed(0)));
assert_ok!(TxPause::pause(
RuntimeOrigin::signed(mock::PauseOrigin::get()),
full_name::<Test>(b"Balances", b"transfer")
));
assert_err!(
call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)),
frame_system::Error::<Test>::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::<Test>(b"Utility", b"batch")
),);
assert_err!(
batch_call.clone().dispatch(RuntimeOrigin::signed(0)),
frame_system::Error::<Test>::CallFiltered
);
});
}
#[test]
fn can_unpause_specific_call() {
new_test_ext().execute_with(|| {
assert_ok!(TxPause::pause(
RuntimeOrigin::signed(mock::PauseOrigin::get()),
full_name::<Test>(b"Balances", b"transfer"),
));
assert_err!(
call_transfer(2, 1).dispatch(RuntimeOrigin::signed(2)),
frame_system::Error::<Test>::CallFiltered
);
assert_ok!(TxPause::unpause(
RuntimeOrigin::signed(mock::UnpauseOrigin::get()),
full_name::<Test>(b"Balances", 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::<Test>(b"Balances", 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::<Test>::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::<Test>(b"Balances", 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::<Test>::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::<Test>(b"TxPause", b"pause"),
),
Error::<Test>::Unpausable
);
});
}
#[test]
fn fails_to_pause_unpausable_call_when_other_call_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::<Test>(b"Balances", b"transfer"),
));
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::<Test>::CallFiltered
);
});
}
#[test]
fn fails_to_pause_unpausable_call() {
new_test_ext().execute_with(|| {
assert_noop!(
TxPause::pause(
RuntimeOrigin::signed(mock::PauseOrigin::get()),
full_name::<Test>(b"Balances", b"transfer_keep_alive"),
),
Error::<Test>::Unpausable
);
});
}
#[test]
fn fails_to_pause_already_paused_pallet() {
new_test_ext().execute_with(|| {
assert_ok!(TxPause::pause(
RuntimeOrigin::signed(mock::PauseOrigin::get()),
full_name::<Test>(b"Balances", b"transfer"),
));
assert_noop!(
TxPause::pause(
RuntimeOrigin::signed(mock::PauseOrigin::get()),
full_name::<Test>(b"Balances", b"transfer"),
),
Error::<Test>::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::<Test>(b"Balances", b"transfer_keep_alive"),
),
Error::<Test>::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<T: Config>(pallet_name: &[u8], call_name: &[u8]) -> RuntimeCallNameOf<T> {
<RuntimeCallNameOf<T>>::from((
pallet_name.to_vec().try_into().unwrap(),
call_name.to_vec().try_into().unwrap(),
))
}