Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions substrate/frame/safe-mode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] }
docify = "0.2.6"
frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true}
frame-support = { path = "../support", default-features = false}
frame-system = { path = "../system", default-features = false}
Expand Down
56 changes: 56 additions & 0 deletions substrate/frame/safe-mode/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,62 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Safe Mode
//!
//! Trigger for stopping all extrinsics outside of a specific whitelist.
//!
//! ## WARNING
//!
//! NOT YET AUDITED. DO NOT USE IN PRODUCTION.
//!
//! ## Pallet API
//!
//! See the [`pallet`] module for more information about the interfaces this pallet exposes,
//! including its configuration trait, dispatchables, storage items, events, and errors.
//!
//! ## Overview
//!
//! Safe mode is entered via two paths (deposit or forced) until a set block number.
//! The mode is exited when the block number is reached or a call to one of the exit extrinsics is
//! made. A `WhitelistedCalls` configuration item contains all calls that can be executed while in
//! safe mode.
//!
//! ### Primary Features
//!
//! - Entering safe mode can be via privileged origin or anyone who places a deposit.
//! - Origin configuration items are separated for privileged entering and exiting safe mode.
//! - A configurable duration sets the number of blocks after which the system will exit safe mode.
//! - Safe mode may be extended beyond the configured exit by additional calls.
//!
//! ### Example
//!
//! Configuration of call filters:
//!
//! ```ignore
//! impl frame_system::Config for Runtime {
//! // …
//! type BaseCallFilter = InsideBoth<DefaultFilter, SafeMode>;
//! // …
//! }
//! ```
//!
//! Entering safe mode with deposit:
#![doc = docify::embed!("src/tests.rs", can_activate)]
//!
//! Entering safe mode via privileged origin:
#![doc = docify::embed!("src/tests.rs", can_force_activate_with_config_origin)]
//!
//! Exiting safe mode via privileged origin:
#![doc = docify::embed!("src/tests.rs", can_force_deactivate_with_config_origin)]
//!
//! ## Low Level / Implementation Details
//!
//! ### Use Cost
//!
//! A storage value (`EnteredUntil`) is used to store the block safe mode will be exited on.
//! Using the call filter will require a db read of that storage on the first extrinsic.
//! The storage will be added to the overlay and incur low cost for all additional calls.

#![cfg_attr(not(feature = "std"), no_std)]
#![deny(rustdoc::broken_intra_doc_links)]

Expand Down
3 changes: 3 additions & 0 deletions substrate/frame/safe-mode/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ fn can_filter_balance_in_proxy_when_activated() {
});
}

#[docify::export]
#[test]
fn can_activate() {
new_test_ext().execute_with(|| {
Expand Down Expand Up @@ -271,6 +272,7 @@ fn fails_force_deactivate_if_not_activated() {
});
}

#[docify::export]
#[test]
fn can_force_activate_with_config_origin() {
new_test_ext().execute_with(|| {
Expand All @@ -288,6 +290,7 @@ fn can_force_activate_with_config_origin() {
});
}

#[docify::export]
#[test]
fn can_force_deactivate_with_config_origin() {
new_test_ext().execute_with(|| {
Expand Down
1 change: 1 addition & 0 deletions substrate/frame/tx-pause/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] }
docify = "0.2.6"
frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true}
frame-support = { path = "../support", default-features = false}
frame-system = { path = "../system", default-features = false}
Expand Down
56 changes: 56 additions & 0 deletions substrate/frame/tx-pause/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,62 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Transaction Pause
//!
//! Allows dynamic, chain-state-based pausing and unpausing of specific extrinsics via call filters.
//!
//! ## WARNING
//!
//! NOT YET AUDITED. DO NOT USE IN PRODUCTION.
//!
//! ## Pallet API
//!
//! See the [`pallet`] module for more information about the interfaces this pallet exposes,
//! including its configuration trait, dispatchables, storage items, events, and errors.
//!
//! ## Overview
//!
//! A dynamic call filter that can be controlled with extrinsics.
//!
//! Pausing an extrinsic means that the extrinsic CANNOT be called again until it is unpaused.
//! The exception is calls that use `dispatch_bypass_filter`, typically only with the root origin.
//!
//! ### Primary Features
//!
//! - Calls that should never be paused can be added to a whitelist.
//! - Separate origins are configurable for pausing and pausing.
//! - Pausing is triggered using the string representation of the call.
//! - Pauses can target a single extrinsic or an entire pallet.
//! - Pauses can target future extrinsics or pallets.
//!
//! ### Example
//!
//! Configuration of call filters:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also another simple example of how to use it, possibly by docify embedding a test 🙏

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried setting this up. Does this look useful/correct to you?
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea this looks good. Maybe some more comments in the tests, but i think it works for a first version 👍

//!
//! ```ignore
//! impl frame_system::Config for Runtime {
//! // …
//! type BaseCallFilter = InsideBoth<DefaultFilter, TxPause>;
//! // …
//! }
//! ```
//!
//! Pause specific all:
#![doc = docify::embed!("src/tests.rs", can_pause_specific_call)]
//!
//! Unpause specific all:
#![doc = docify::embed!("src/tests.rs", can_unpause_specific_call)]
//!
//! Pause all calls in a pallet:
#![doc = docify::embed!("src/tests.rs", can_pause_all_calls_in_pallet_except_on_whitelist)]
//!
//! ## Low Level / Implementation Details
//!
//! ### Use Cost
//!
//! A storage map (`PausedCalls`) is used to store currently paused calls.
//! Using the call filter will require a db read of that storage on each extrinsic.

#![cfg_attr(not(feature = "std"), no_std)]
#![deny(rustdoc::broken_intra_doc_links)]

Expand Down
3 changes: 3 additions & 0 deletions substrate/frame/tx-pause/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use sp_runtime::DispatchError;

// GENERAL SUCCESS/POSITIVE TESTS ---------------------

#[docify::export]
#[test]
fn can_pause_specific_call() {
new_test_ext().execute_with(|| {
Expand All @@ -43,6 +44,7 @@ fn can_pause_specific_call() {
});
}

#[docify::export]
#[test]
fn can_pause_all_calls_in_pallet_except_on_whitelist() {
new_test_ext().execute_with(|| {
Expand All @@ -64,6 +66,7 @@ fn can_pause_all_calls_in_pallet_except_on_whitelist() {
});
}

#[docify::export]
#[test]
fn can_unpause_specific_call() {
new_test_ext().execute_with(|| {
Expand Down