Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvArch preparations #135

Merged
merged 6 commits into from
Nov 12, 2023
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
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,11 @@ run-tinkernet-solo-bob:
cd tinkernet && ./target/release/tinkernet-collator --chain solo-dev --bob --tmp --listen-addr /ip4/0.0.0.0/tcp/54102/ws --rpc-cors=all --discover-local --collator --bootnodes /ip4/127.0.0.1/tcp/53102/ws/p2p/12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2

run-tinkernet-solo: ; printf "run-tinkernet-solo-alice\nrun-tinkernet-solo-bob" | parallel -u make

run-invarch-solo-alice:
cd invarch && ./target/release/invarch-collator --chain solo-dev --alice --tmp --listen-addr /ip4/0.0.0.0/tcp/53102/ws --rpc-cors=all --discover-local --collator --node-key c12b6d18942f5ee8528c8e2baf4e147b5c5c18710926ea492d09cbd9f6c9f82a

run-invarch-solo-bob:
cd invarch && ./target/release/invarch-collator --chain solo-dev --bob --tmp --listen-addr /ip4/0.0.0.0/tcp/54102/ws --rpc-cors=all --discover-local --collator --bootnodes /ip4/127.0.0.1/tcp/53102/ws/p2p/12D3KooWBmAwcd4PJNJvfV89HwE48nwkRmAgo8Vy3uQEyNNHBox2

run-invarch-solo: ; printf "run-invarch-solo-alice\nrun-invarch-solo-bob" | parallel -u make
37 changes: 37 additions & 0 deletions invarch/Cargo.lock

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

67 changes: 67 additions & 0 deletions invarch/pallet-tx-pause/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
[package]
name = "pallet-tx-pause"
version = "4.0.0-dev"
authors = ["Parity Technologies <[email protected]>"]
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.2.2", default-features = false, features = ["derive"] }
scale-info = { version = "2.0.1", default-features = false, features = ["derive"] }

frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.43" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.43" }
pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.43" }
pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.43" }

[dev-dependencies]
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" }
pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" }
pallet-proxy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" }

[features]
default = [ "std" ]
std = [
"codec/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"pallet-balances?/std",
"pallet-proxy?/std",
"pallet-utility?/std",
"scale-info/std",
"sp-core/std",
"sp-io/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-proxy/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-balances?/try-runtime",
"pallet-proxy?/try-runtime",
"pallet-utility?/try-runtime",
"sp-runtime/try-runtime",
]
241 changes: 241 additions & 0 deletions invarch/pallet-tx-pause/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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_attr(not(feature = "std"), no_std)]
#![deny(rustdoc::broken_intra_doc_links)]

pub mod weights;

use frame_support::{
dispatch::GetDispatchInfo,
pallet_prelude::*,
traits::{CallMetadata, Contains, GetCallMetadata, IsSubType, IsType},
DefaultNoBound,
};
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<T> = BoundedVec<u8, <T as Config>::MaxNameLen>;

/// The stringy name of a call (within a pallet) from [`GetCallMetadata`] for
/// [`Config::RuntimeCall`] variants.
pub type PalletCallNameOf<T> = BoundedVec<u8, <T as Config>::MaxNameLen>;

/// A fully specified pallet ([`PalletNameOf`]) and optional call ([`PalletCallNameOf`])
/// to partially or fully specify an item a variant of a [`Config::RuntimeCall`].
pub type RuntimeCallNameOf<T> = (PalletNameOf<T>, PalletCallNameOf<T>);

#[frame_support::pallet]
pub mod pallet {
use super::*;

#[pallet::pallet]
pub struct Pallet<T>(PhantomData<T>);

#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// The overarching call type.
type RuntimeCall: Parameter
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
+ GetDispatchInfo
+ GetCallMetadata
+ From<frame_system::Call<Self>>
+ IsSubType<Call<Self>>
+ IsType<<Self as frame_system::Config>::RuntimeCall>;

/// The only origin that can pause calls.
type PauseOrigin: EnsureOrigin<Self::RuntimeOrigin>;

/// The only origin that can un-pause calls.
type UnpauseOrigin: EnsureOrigin<Self::RuntimeOrigin>;

/// Contains all calls that cannot be paused.
///
/// The `TxMode` pallet cannot pause its own calls, and does not need to be explicitly
/// added here.
type WhitelistedCalls: Contains<RuntimeCallNameOf<Self>>;

/// Maximum length for pallet name and call name SCALE encoded string names.
///
/// TOO LONG NAMES WILL BE TREATED AS PAUSED.
#[pallet::constant]
type MaxNameLen: Get<u32>;

// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}

/// The set of calls that are explicitly paused.
#[pallet::storage]
pub type PausedCalls<T: Config> =
StorageMap<_, Blake2_128Concat, RuntimeCallNameOf<T>, (), OptionQuery>;

#[pallet::error]
pub enum Error<T> {
/// The call is paused.
IsPaused,

/// The call is unpaused.
IsUnpaused,

/// The call is whitelisted and cannot be paused.
Unpausable,

// The pallet or call does not exist in the runtime.
NotFound,
}

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// This pallet, or a specific call is now paused.
CallPaused { full_name: RuntimeCallNameOf<T> },
/// This pallet, or a specific call is now unpaused.
CallUnpaused { full_name: RuntimeCallNameOf<T> },
}

/// Configure the initial state of this pallet in the genesis block.
#[pallet::genesis_config]
#[derive(DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
/// Initially paused calls.
pub paused: Vec<RuntimeCallNameOf<T>>,
}

#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
for call in &self.paused {
Pallet::<T>::ensure_can_pause(call).expect("Genesis data is known good; qed");
PausedCalls::<T>::insert(call, ());
}
}
}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Pause a call.
///
/// Can only be called by [`Config::PauseOrigin`].
/// Emits an [`Event::CallPaused`] event on success.
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::pause())]
pub fn pause(origin: OriginFor<T>, full_name: RuntimeCallNameOf<T>) -> DispatchResult {
T::PauseOrigin::ensure_origin(origin)?;

Self::do_pause(full_name).map_err(Into::into)
}

/// Un-pause a call.
///
/// Can only be called by [`Config::UnpauseOrigin`].
/// Emits an [`Event::CallUnpaused`] event on success.
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::unpause())]
pub fn unpause(origin: OriginFor<T>, ident: RuntimeCallNameOf<T>) -> DispatchResult {
T::UnpauseOrigin::ensure_origin(origin)?;

Self::do_unpause(ident).map_err(Into::into)
}
}
}

impl<T: Config> Pallet<T> {
pub(crate) fn do_pause(ident: RuntimeCallNameOf<T>) -> Result<(), Error<T>> {
Self::ensure_can_pause(&ident)?;
PausedCalls::<T>::insert(&ident, ());
Self::deposit_event(Event::CallPaused { full_name: ident });

Ok(())
}

pub(crate) fn do_unpause(ident: RuntimeCallNameOf<T>) -> Result<(), Error<T>> {
Self::ensure_can_unpause(&ident)?;
PausedCalls::<T>::remove(&ident);
Self::deposit_event(Event::CallUnpaused { full_name: ident });

Ok(())
}

/// Return whether this call is paused.
pub fn is_paused(full_name: &RuntimeCallNameOf<T>) -> bool {
if T::WhitelistedCalls::contains(full_name) {
return false;
}

<PausedCalls<T>>::contains_key(full_name)
}

/// Same as [`Self::is_paused`] but for inputs unbound by max-encoded-len.
pub fn is_paused_unbound(pallet: Vec<u8>, call: Vec<u8>) -> bool {
let pallet = PalletNameOf::<T>::try_from(pallet);
let call = PalletCallNameOf::<T>::try_from(call);

match (pallet, call) {
(Ok(pallet), Ok(call)) => Self::is_paused(&(pallet, call)),
_ => true,
}
}

/// Ensure that this call can be paused.
pub fn ensure_can_pause(full_name: &RuntimeCallNameOf<T>) -> Result<(), Error<T>> {
// SAFETY: The `TxPause` pallet can never pause itself.
if full_name.0.as_ref() == <Self as PalletInfoAccess>::name().as_bytes().to_vec() {
return Err(Error::<T>::Unpausable);
}

if T::WhitelistedCalls::contains(full_name) {
return Err(Error::<T>::Unpausable);
}
if Self::is_paused(full_name) {
return Err(Error::<T>::IsPaused);
}
Ok(())
}

/// Ensure that this call can be un-paused.
pub fn ensure_can_unpause(full_name: &RuntimeCallNameOf<T>) -> Result<(), Error<T>> {
if Self::is_paused(full_name) {
// SAFETY: Everything that is paused, can be un-paused.
Ok(())
} else {
Err(Error::IsUnpaused)
}
}
}

impl<T: pallet::Config> Contains<<T as frame_system::Config>::RuntimeCall> for Pallet<T>
where
<T as frame_system::Config>::RuntimeCall: GetCallMetadata,
{
/// Return whether the call is allowed to be dispatched.
fn contains(call: &<T as frame_system::Config>::RuntimeCall) -> bool {
let CallMetadata {
pallet_name,
function_name,
} = call.get_call_metadata();
!Pallet::<T>::is_paused_unbound(pallet_name.into(), function_name.into())
}
}
Loading
Loading