Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
allow specify schedule dispatch origin
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed Jun 18, 2020
1 parent 0c42ced commit 6d11c9d
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 30 deletions.
2 changes: 2 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ parameter_types! {
impl pallet_scheduler::Trait for Runtime {
type Event = Event;
type Origin = Origin;
type PalletsOrigin = OriginCaller;
type Call = Call;
type MaximumWeight = MaximumSchedulerWeight;
}
Expand Down Expand Up @@ -455,6 +456,7 @@ impl pallet_democracy::Trait for Runtime {
type OperationalPreimageOrigin = pallet_collective::EnsureMember<AccountId, CouncilCollective>;
type Slash = Treasury;
type Scheduler = Scheduler;
type PalletsOrigin = OriginCaller;
type MaxVotes = MaxVotes;
}

Expand Down
2 changes: 1 addition & 1 deletion frame/collective/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub trait Trait<I: Instance=DefaultInstance>: frame_system::Trait {
}

/// Origin for the collective module.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode)]
pub enum RawOrigin<AccountId, I> {
/// It has been condoned by a given number of members of the collective from a given total.
Members(MemberCount, MemberCount),
Expand Down
6 changes: 5 additions & 1 deletion frame/democracy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,10 @@ pub trait Trait: frame_system::Trait + Sized {
type Slash: OnUnbalanced<NegativeImbalanceOf<Self>>;

/// The Scheduler.
type Scheduler: ScheduleNamed<Self::BlockNumber, Self::Proposal>;
type Scheduler: ScheduleNamed<Self::BlockNumber, Self::Proposal, Self::PalletsOrigin>;

/// Overarching type of all pallets origins.
type PalletsOrigin: From<system::RawOrigin<Self::AccountId>>;

/// The maximum number of votes for an account.
///
Expand Down Expand Up @@ -1642,6 +1645,7 @@ impl<T: Trait> Module<T> {
when,
None,
63,
system::RawOrigin::Root.into(),
Call::enact_proposal(status.proposal_hash, index).into(),
).is_err() {
frame_support::print("LOGIC ERROR: bake_referendum/schedule_named failed");
Expand Down
66 changes: 50 additions & 16 deletions frame/scheduler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@

mod benchmarking;

use sp_std::prelude::*;
use codec::{Encode, Decode};
use sp_std::{prelude::*, marker::PhantomData};
use codec::{Encode, Decode, Codec};
use sp_runtime::{RuntimeDebug, traits::{Zero, One}};
use frame_support::{
decl_module, decl_storage, decl_event, decl_error,
dispatch::{Dispatchable, DispatchError, DispatchResult, Parameter},
traits::{Get, schedule},
traits::{Get, schedule, OriginTrait},
weights::{GetDispatchInfo, Weight},
};
use frame_system::{self as system, ensure_root};
Expand All @@ -66,7 +66,10 @@ pub trait Trait: system::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;

/// The aggregated origin which the dispatch will take.
type Origin: From<system::RawOrigin<Self::AccountId>>;
type Origin: OriginTrait<PalletsOrigin = Self::PalletsOrigin> + From<Self::PalletsOrigin>;

/// The caller origin, overarching type of all pallets origins.
type PalletsOrigin: From<system::RawOrigin<Self::AccountId>> + Codec + Clone;

/// The aggregated call type.
type Call: Parameter + Dispatchable<Origin=<Self as Trait>::Origin> + GetDispatchInfo + From<system::Call<Self>>;
Expand All @@ -82,8 +85,8 @@ pub type PeriodicIndex = u32;
pub type TaskAddress<BlockNumber> = (BlockNumber, u32);

/// Information regarding an item to be executed in the future.
#[derive(Clone, RuntimeDebug, Encode, Decode)]
pub struct Scheduled<Call, BlockNumber> {
#[derive(Clone, RuntimeDebug, Encode)]
pub struct Scheduled<Call, BlockNumber, PalletsOrigin, AccountId> {
/// The unique identity for this task, if there is one.
maybe_id: Option<Vec<u8>>,
/// This task's priority.
Expand All @@ -92,13 +95,36 @@ pub struct Scheduled<Call, BlockNumber> {
call: Call,
/// If the call is periodic, then this points to the information concerning that.
maybe_periodic: Option<schedule::Period<BlockNumber>>,
/// The origin to dispatch the call.
origin: PalletsOrigin,
_phantom: PhantomData<AccountId>,
}

impl<Call, BlockNumber, PalletsOrigin, AccountId> Decode for Scheduled<Call, BlockNumber, PalletsOrigin, AccountId>
where
Call: Decode,
BlockNumber: Decode,
PalletsOrigin: Decode + From<system::RawOrigin<AccountId>>
{
fn decode<I: codec::Input>(input: &mut I) -> sp_std::result::Result<Self, codec::Error> {
// Implement decode manually to keep backwards compatibility.
// Old version does not have origin field and default to ROOT.
Ok(Scheduled {
maybe_id: Decode::decode(input)?,
priority: Decode::decode(input)?,
call: Decode::decode(input)?,
maybe_periodic: Decode::decode(input)?,
origin: Decode::decode(input).unwrap_or_else(|_| system::RawOrigin::Root.into()),
_phantom: Default::default(),
})
}
}

decl_storage! {
trait Store for Module<T: Trait> as Scheduler {
/// Items to be executed, indexed by the block number that they should be executed on.
pub Agenda: map hasher(twox_64_concat) T::BlockNumber
=> Vec<Option<Scheduled<<T as Trait>::Call, T::BlockNumber>>>;
=> Vec<Option<Scheduled<<T as Trait>::Call, T::BlockNumber, T::PalletsOrigin, T::AccountId>>>;

/// Lookup from identity to the block number and index of the task.
Lookup: map hasher(twox_64_concat) Vec<u8> => Option<TaskAddress<T::BlockNumber>>;
Expand Down Expand Up @@ -145,7 +171,7 @@ decl_module! {
call: Box<<T as Trait>::Call>,
) {
ensure_root(origin)?;
let _ = Self::do_schedule(when, maybe_periodic, priority, *call);
let _ = Self::do_schedule(when, maybe_periodic, priority, system::RawOrigin::Root.into(), *call);
}

/// Cancel an anonymously scheduled task.
Expand Down Expand Up @@ -183,7 +209,7 @@ decl_module! {
call: Box<<T as Trait>::Call>,
) {
ensure_root(origin)?;
Self::do_schedule_named(id, when, maybe_periodic, priority, *call)?;
Self::do_schedule_named(id, when, maybe_periodic, priority, system::RawOrigin::Root.into(), *call)?;
}

/// Cancel a named scheduled task.
Expand Down Expand Up @@ -247,7 +273,7 @@ decl_module! {
// - It does not push the weight past the limit.
// - It is the first item in the schedule
if s.priority <= schedule::HARD_DEADLINE || cumulative_weight <= limit || order == 0 {
let r = s.call.clone().dispatch(system::RawOrigin::Root.into());
let r = s.call.clone().dispatch(s.origin.clone().into());
let maybe_id = s.maybe_id.clone();
if let &Some((period, count)) = &s.maybe_periodic {
if count > 1 {
Expand Down Expand Up @@ -293,14 +319,17 @@ impl<T: Trait> Module<T> {
when: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
origin: T::PalletsOrigin,
call: <T as Trait>::Call
) -> TaskAddress<T::BlockNumber> {
// sanitize maybe_periodic
let maybe_periodic = maybe_periodic
.filter(|p| p.1 > 1 && !p.0.is_zero())
// Remove one from the number of repetitions since we will schedule one now.
.map(|(p, c)| (p, c - 1));
let s = Some(Scheduled { maybe_id: None, priority, call, maybe_periodic });
let s = Some(Scheduled {
maybe_id: None, priority, call, maybe_periodic, origin, _phantom: PhantomData::<T::AccountId>::default(),
});
Agenda::<T>::append(when, s);
let index = Agenda::<T>::decode_len(when).unwrap_or(1) as u32 - 1;
Self::deposit_event(RawEvent::Scheduled(when, index));
Expand All @@ -324,6 +353,7 @@ impl<T: Trait> Module<T> {
when: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
origin: T::PalletsOrigin,
call: <T as Trait>::Call,
) -> Result<TaskAddress<T::BlockNumber>, DispatchError> {
// ensure id it is unique
Expand All @@ -337,7 +367,9 @@ impl<T: Trait> Module<T> {
// Remove one from the number of repetitions since we will schedule one now.
.map(|(p, c)| (p, c - 1));

let s = Scheduled { maybe_id: Some(id.clone()), priority, call, maybe_periodic };
let s = Scheduled {
maybe_id: Some(id.clone()), priority, call, maybe_periodic, origin, _phantom: Default::default()
};
Agenda::<T>::append(when, Some(s));
let index = Agenda::<T>::decode_len(when).unwrap_or(1) as u32 - 1;
let address = (when, index);
Expand All @@ -358,34 +390,36 @@ impl<T: Trait> Module<T> {
}
}

impl<T: Trait> schedule::Anon<T::BlockNumber, <T as Trait>::Call> for Module<T> {
impl<T: Trait> schedule::Anon<T::BlockNumber, <T as Trait>::Call, T::PalletsOrigin> for Module<T> {
type Address = TaskAddress<T::BlockNumber>;

fn schedule(
when: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
origin: T::PalletsOrigin,
call: <T as Trait>::Call
) -> Self::Address {
Self::do_schedule(when, maybe_periodic, priority, call)
Self::do_schedule(when, maybe_periodic, priority, origin, call)
}

fn cancel((when, index): Self::Address) -> Result<(), ()> {
Self::do_cancel((when, index)).map_err(|_| ())
}
}

impl<T: Trait> schedule::Named<T::BlockNumber, <T as Trait>::Call> for Module<T> {
impl<T: Trait> schedule::Named<T::BlockNumber, <T as Trait>::Call, T::PalletsOrigin> for Module<T> {
type Address = TaskAddress<T::BlockNumber>;

fn schedule_named(
id: Vec<u8>,
when: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
origin: T::PalletsOrigin,
call: <T as Trait>::Call,
) -> Result<Self::Address, ()> {
Self::do_schedule_named(id, when, maybe_periodic, priority, call).map_err(|_| ())
Self::do_schedule_named(id, when, maybe_periodic, priority, origin, call).map_err(|_| ())
}

fn cancel_named(id: Vec<u8>) -> Result<(), ()> {
Expand Down
38 changes: 29 additions & 9 deletions frame/support/src/origin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,14 @@ macro_rules! impl_outer_origin {
fn filter_call(&self, call: &Self::Call) -> bool {
(self.filter)(call)
}

fn caller(&self) -> &Self::PalletsOrigin {
&self.caller
}
}

$crate::paste::item! {
#[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)]
#[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug, $crate::codec::Encode, $crate::codec::Decode)]
$(#[$attr])*
#[allow(non_camel_case_types)]
pub enum $caller_name {
Expand All @@ -252,16 +256,29 @@ macro_rules! impl_outer_origin {
}
}

impl From<$system::Origin<$runtime>> for $name {
impl From<$system::Origin<$runtime>> for $caller_name {
fn from(x: $system::Origin<$runtime>) -> Self {
$caller_name::system(x)
}
}

impl From<$caller_name> for $name {
fn from(x: $caller_name) -> Self {
let mut o = $name {
caller: $caller_name::system(x),
caller: x,
filter: $crate::sp_std::rc::Rc::new(Box::new(|_| true)),
};
$crate::traits::OriginTrait::reset_filter(&mut o);
o
}
}

impl From<$system::Origin<$runtime>> for $name {
fn from(x: $system::Origin<$runtime>) -> Self {
let x: $caller_name = x.into();
x.into()
}
}
impl Into<$crate::sp_std::result::Result<$system::Origin<$runtime>, $name>> for $name {
fn into(self) -> $crate::sp_std::result::Result<$system::Origin<$runtime>, Self> {
if let $caller_name::system(l) = self.caller {
Expand All @@ -276,16 +293,19 @@ macro_rules! impl_outer_origin {
<$system::Origin<$runtime>>::from(x).into()
}
}

$(
$crate::paste::item! {
impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $caller_name {
fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self {
$caller_name::[< $module $( _ $generic_instance )? >](x)
}
}

impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name {
fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self {
let mut o = $name {
caller: $caller_name::[< $module $( _ $generic_instance )? >](x),
filter: $crate::sp_std::rc::Rc::new(Box::new(|_| true)),
};
$crate::traits::OriginTrait::reset_filter(&mut o);
o
let x: $caller_name = x.into();
x.into()
}
}
impl Into<
Expand Down
9 changes: 7 additions & 2 deletions frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,7 @@ pub mod schedule {
pub const LOWEST_PRIORITY: Priority = 255;

/// A type that can be used as a scheduler.
pub trait Anon<BlockNumber, Call> {
pub trait Anon<BlockNumber, Call, Origin> {
/// An address which can be used for removing a scheduled task.
type Address: Codec + Clone + Eq + EncodeLike + Debug;

Expand All @@ -1500,6 +1500,7 @@ pub mod schedule {
when: BlockNumber,
maybe_periodic: Option<Period<BlockNumber>>,
priority: Priority,
origin: Origin,
call: Call
) -> Self::Address;

Expand All @@ -1517,7 +1518,7 @@ pub mod schedule {
}

/// A type that can be used as a scheduler.
pub trait Named<BlockNumber, Call> {
pub trait Named<BlockNumber, Call, Origin> {
/// An address which can be used for removing a scheduled task.
type Address: Codec + Clone + Eq + EncodeLike + sp_std::fmt::Debug;

Expand All @@ -1529,6 +1530,7 @@ pub mod schedule {
when: BlockNumber,
maybe_periodic: Option<Period<BlockNumber>>,
priority: Priority,
origin: Origin,
call: Call
) -> Result<Self::Address, ()>;

Expand Down Expand Up @@ -1592,6 +1594,9 @@ pub trait OriginTrait: Sized {

/// Filter the call, if false then call is filtered out.
fn filter_call(&self, call: &Self::Call) -> bool;

/// Get the caller.
fn caller(&self) -> &Self::PalletsOrigin;
}

/// Trait to be used when types are exactly same.
Expand Down
2 changes: 1 addition & 1 deletion frame/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ pub struct EventRecord<E: Parameter + Member, T> {
}

/// Origin for the System module.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode)]
pub enum RawOrigin<AccountId> {
/// The system itself ordained this dispatch to happen: this is the highest privilege level.
Root,
Expand Down

0 comments on commit 6d11c9d

Please sign in to comment.