Skip to content
Snippets Groups Projects
Unverified Commit 0bcbfd58 authored by wangjj9219's avatar wangjj9219 Committed by GitHub
Browse files

update orml-authority (#225)

* add AsOrigin

* make authority instantiatable

* use ensure_origin
parent d804a141
No related branches found
No related tags found
No related merge requests found
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Disable the following two lints since they originate from an external macro (namely decl_storage) // Disable the following three lints since they originate from an external macro
#![allow(clippy::string_lit_as_bytes)] #![allow(clippy::string_lit_as_bytes)]
#![allow(clippy::boxed_local)] #![allow(clippy::boxed_local)]
#![allow(clippy::borrowed_box)] #![allow(clippy::borrowed_box)]
use frame_support::{ use frame_support::{
decl_error, decl_module, decl_error, decl_module, decl_storage,
dispatch::PostDispatchInfo, dispatch::PostDispatchInfo,
ensure, ensure,
traits::{EnsureOrigin, Get}, traits::{EnsureOrigin, Get},
...@@ -15,7 +15,7 @@ use frame_support::{ ...@@ -15,7 +15,7 @@ use frame_support::{
use frame_system::{self as system}; use frame_system::{self as system};
use orml_traits::{DelayedDispatchTime, DispatchId, Scheduler}; use orml_traits::{DelayedDispatchTime, DispatchId, Scheduler};
use sp_runtime::{ use sp_runtime::{
traits::{BadOrigin, CheckedAdd, CheckedSub, Dispatchable}, traits::{CheckedAdd, CheckedSub, Dispatchable},
RuntimeDebug, RuntimeDebug,
}; };
use sp_std::prelude::*; use sp_std::prelude::*;
...@@ -24,23 +24,20 @@ mod mock; ...@@ -24,23 +24,20 @@ mod mock;
mod tests; mod tests;
#[derive(PartialEq, Eq, Clone, RuntimeDebug)] #[derive(PartialEq, Eq, Clone, RuntimeDebug)]
pub struct DelayedOrigin<BlockNumber, Origin> { pub struct DelayedOrigin<BlockNumber, Origin, I> {
pub delay: BlockNumber, pub delay: BlockNumber,
pub origin: Origin, pub origin: Origin,
_phantom: sp_std::marker::PhantomData<I>,
} }
/// Origin for the authority module. pub struct EnsureDelayed<Delay, Inner, BlockNumber, I>(sp_std::marker::PhantomData<(Delay, Inner, BlockNumber, I)>);
pub type Origin<T> =
DelayedOrigin<<T as system::Trait>::BlockNumber, system::RawOrigin<<T as system::Trait>::AccountId>>;
pub struct EnsureDelayed<Delay, Inner, BlockNumber>(sp_std::marker::PhantomData<(Delay, Inner, BlockNumber)>);
impl< impl<
O: Into<Result<DelayedOrigin<BlockNumber, O>, O>> + From<DelayedOrigin<BlockNumber, O>>, O: Into<Result<DelayedOrigin<BlockNumber, O, I>, O>> + From<DelayedOrigin<BlockNumber, O, I>>,
Delay: Get<BlockNumber>, Delay: Get<BlockNumber>,
Inner: EnsureOrigin<O>, Inner: EnsureOrigin<O>,
BlockNumber: PartialOrd, BlockNumber: PartialOrd,
> EnsureOrigin<O> for EnsureDelayed<Delay, Inner, BlockNumber> I,
> EnsureOrigin<O> for EnsureDelayed<Delay, Inner, BlockNumber, I>
{ {
type Success = Inner::Success; type Success = Inner::Success;
...@@ -55,8 +52,13 @@ impl< ...@@ -55,8 +52,13 @@ impl<
} }
} }
pub trait Trait: system::Trait { /// Origin for the authority module.
type Origin: From<DelayedOrigin<Self::BlockNumber, system::RawOrigin<Self::AccountId>>> pub type Origin<T, I = DefaultInstance> =
DelayedOrigin<<T as system::Trait>::BlockNumber, system::RawOrigin<<T as system::Trait>::AccountId>, I>;
type CallOf<T, I = DefaultInstance> = <T as Trait<I>>::Call;
pub trait Trait<I: Instance = DefaultInstance>: system::Trait {
type Origin: From<DelayedOrigin<Self::BlockNumber, system::RawOrigin<Self::AccountId>, I>>
+ From<system::RawOrigin<Self::AccountId>>; + From<system::RawOrigin<Self::AccountId>>;
type Call: Parameter type Call: Parameter
+ Dispatchable<Origin = <Self as system::Trait>::Origin, PostInfo = PostDispatchInfo> + Dispatchable<Origin = <Self as system::Trait>::Origin, PostInfo = PostDispatchInfo>
...@@ -66,74 +68,81 @@ pub trait Trait: system::Trait { ...@@ -66,74 +68,81 @@ pub trait Trait: system::Trait {
type DelayedDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>; type DelayedDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
type VetoOrigin: EnsureOrigin<<Self as system::Trait>::Origin>; type VetoOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
type InstantDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>; type InstantDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
type Scheduler: Scheduler<Self::BlockNumber, Origin = <Self as Trait>::Origin, Call = <Self as Trait>::Call>; type Scheduler: Scheduler<Self::BlockNumber, Origin = <Self as Trait<I>>::Origin, Call = <Self as Trait<I>>::Call>;
type MinimumDelay: Get<Self::BlockNumber>; type MinimumDelay: Get<Self::BlockNumber>;
type AsOrigin: Get<<Self as system::Trait>::Origin>;
} }
decl_error! { decl_error! {
/// Error for authority module. /// Error for authority module.
pub enum Error for Module<T: Trait> { pub enum Error for Module<T: Trait<I>, I: Instance> {
BlockNumberOverflow, BlockNumberOverflow,
InvalidDelayedDispatchTime, InvalidDelayedDispatchTime,
OriginConvertFailed,
} }
} }
type CallOf<T> = <T as Trait>::Call; decl_storage! {
trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Authority {}
}
decl_module! { decl_module! {
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin { pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: <T as system::Trait>::Origin {
type Error = Error<T>; type Error = Error<T, I>;
const MinimumDelay: T::BlockNumber = T::MinimumDelay::get(); const MinimumDelay: T::BlockNumber = T::MinimumDelay::get();
#[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)] #[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)]
pub fn dispatch_root(origin, call: Box<CallOf<T>>) { pub fn dispatch(origin, call: Box<CallOf<T, I>>) {
T::RootDispatchOrigin::try_origin(origin).map_err(|_| BadOrigin)?; T::RootDispatchOrigin::ensure_origin(origin)?;
call.dispatch(frame_system::RawOrigin::Root.into()).map(|_| ()).map_err(|e| e.error)?; call.dispatch(T::AsOrigin::get()).map(|_| ()).map_err(|e| e.error)?;
} }
#[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)] #[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)]
pub fn schedule_dispatch_root(origin, call: Box<CallOf<T>>, when: DelayedDispatchTime<T::BlockNumber>) { pub fn schedule_dispatch(origin, call: Box<CallOf<T, I>>, when: DelayedDispatchTime<T::BlockNumber>) {
let now = <frame_system::Module<T>>::block_number(); let now = <frame_system::Module<T>>::block_number();
let when_block = match when { let when_block = match when {
DelayedDispatchTime::At(at_block) => { DelayedDispatchTime::At(at_block) => {
ensure!(at_block > now, Error::<T>::InvalidDelayedDispatchTime); ensure!(at_block > now, Error::<T, I>::InvalidDelayedDispatchTime);
at_block at_block
}, },
DelayedDispatchTime::After(after_block) => { DelayedDispatchTime::After(after_block) => {
now.checked_add(&after_block).ok_or(Error::<T>::BlockNumberOverflow)? now.checked_add(&after_block).ok_or(Error::<T, I>::BlockNumberOverflow)?
}, },
}; };
if when_block >= T::MinimumDelay::get() + now { if when_block >= T::MinimumDelay::get() + now {
T::DelayedRootDispatchOrigin::try_origin(origin).map_err(|_| BadOrigin)?; T::DelayedRootDispatchOrigin::ensure_origin(origin)?;
} else { } else {
T::InstantDispatchOrigin::try_origin(origin).map_err(|_| BadOrigin)?; T::InstantDispatchOrigin::ensure_origin(origin)?;
} }
// schedule call with Root origin let raw_origin: system::RawOrigin<T::AccountId> = T::AsOrigin::get().into().map_err(|_| Error::<T, I>::OriginConvertFailed)?;
let _ = T::Scheduler::schedule(frame_system::RawOrigin::Root.into(), *call, when);
// schedule call with as origin
let _ = T::Scheduler::schedule(raw_origin.into(), *call, when);
} }
#[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)] #[weight = (call.get_dispatch_info().weight + 10_000, call.get_dispatch_info().class)]
pub fn schedule_dispatch_delayed(origin, call: Box<CallOf<T>>, when: DelayedDispatchTime<T::BlockNumber>) { pub fn schedule_dispatch_delayed(origin, call: Box<CallOf<T, I>>, when: DelayedDispatchTime<T::BlockNumber>) {
T::DelayedDispatchOrigin::try_origin(origin.clone()).map_err(|_| BadOrigin)?; T::DelayedDispatchOrigin::ensure_origin(origin.clone())?;
let now = <frame_system::Module<T>>::block_number(); let now = <frame_system::Module<T>>::block_number();
let delay_block = match when { let delay_block = match when {
DelayedDispatchTime::At(at_block) => { DelayedDispatchTime::At(at_block) => {
at_block.checked_sub(&now).ok_or(Error::<T>::InvalidDelayedDispatchTime)? at_block.checked_sub(&now).ok_or(Error::<T, I>::InvalidDelayedDispatchTime)?
}, },
DelayedDispatchTime::After(after_block) => { DelayedDispatchTime::After(after_block) => {
ensure!(after_block.checked_add(&now).is_some(), Error::<T>::BlockNumberOverflow); ensure!(after_block.checked_add(&now).is_some(), Error::<T, I>::BlockNumberOverflow);
after_block after_block
}, },
}; };
let raw_origin = origin.into().map_err(|_| BadOrigin)?; let raw_origin = origin.into().map_err(|_| Error::<T, I>::OriginConvertFailed)?;
let delayed_origin = DelayedOrigin{ let delayed_origin = DelayedOrigin{
delay: delay_block, delay: delay_block,
origin: raw_origin, origin: raw_origin,
_phantom: sp_std::marker::PhantomData,
}; };
// dispatch call with DelayedOrigin // dispatch call with DelayedOrigin
...@@ -142,7 +151,7 @@ decl_module! { ...@@ -142,7 +151,7 @@ decl_module! {
#[weight = 0] #[weight = 0]
pub fn veto(origin, dispatch_id: DispatchId) { pub fn veto(origin, dispatch_id: DispatchId) {
T::VetoOrigin::try_origin(origin).map_err(|_| BadOrigin)?; T::VetoOrigin::ensure_origin(origin)?;
T::Scheduler::cancel(dispatch_id); T::Scheduler::cancel(dispatch_id);
} }
} }
......
...@@ -66,10 +66,14 @@ impl Scheduler<BlockNumber> for MockScheduler { ...@@ -66,10 +66,14 @@ impl Scheduler<BlockNumber> for MockScheduler {
ord_parameter_types! { ord_parameter_types! {
pub const One: AccountId = 1; pub const One: AccountId = 1;
pub const Two: AccountId = 2; pub const Two: AccountId = 2;
pub const Three: AccountId = 3;
} }
parameter_types! { parameter_types! {
pub const MinimumDelay: BlockNumber = 10; pub const MinimumDelay: BlockNumber = 10;
pub const MinimumDelayForInstance1: BlockNumber = 20;
pub AsOrigin: Origin = Origin::root();
pub AsOriginForInstance1: Origin = system::RawOrigin::Signed(Three::get()).into();
} }
impl Trait for Runtime { impl Trait for Runtime {
...@@ -82,6 +86,20 @@ impl Trait for Runtime { ...@@ -82,6 +86,20 @@ impl Trait for Runtime {
type InstantDispatchOrigin = EnsureSignedBy<Two, AccountId>; type InstantDispatchOrigin = EnsureSignedBy<Two, AccountId>;
type Scheduler = MockScheduler; type Scheduler = MockScheduler;
type MinimumDelay = MinimumDelay; type MinimumDelay = MinimumDelay;
type AsOrigin = AsOrigin;
}
impl Trait<Instance1> for Runtime {
type Origin = Origin;
type Call = Call;
type RootDispatchOrigin = EnsureSignedBy<One, AccountId>;
type DelayedRootDispatchOrigin = EnsureSignedBy<One, AccountId>;
type DelayedDispatchOrigin = EnsureSignedBy<One, AccountId>;
type VetoOrigin = EnsureSignedBy<One, AccountId>;
type InstantDispatchOrigin = EnsureSignedBy<Two, AccountId>;
type Scheduler = MockScheduler;
type MinimumDelay = MinimumDelayForInstance1;
type AsOrigin = AsOriginForInstance1;
} }
pub type Block = sp_runtime::generic::Block<Header, UncheckedExtrinsic>; pub type Block = sp_runtime::generic::Block<Header, UncheckedExtrinsic>;
...@@ -95,6 +113,7 @@ frame_support::construct_runtime!( ...@@ -95,6 +113,7 @@ frame_support::construct_runtime!(
{ {
System: frame_system::{Module, Call, Event<T>}, System: frame_system::{Module, Call, Event<T>},
Authority: authority::{Module, Call, Origin<T>}, Authority: authority::{Module, Call, Origin<T>},
AuthorityInstance1: authority::<Instance1>::{Module, Call, Origin<T>},
} }
); );
......
...@@ -4,55 +4,86 @@ ...@@ -4,55 +4,86 @@
use super::*; use super::*;
use frame_support::{assert_noop, assert_ok}; use frame_support::{assert_noop, assert_ok};
use mock::{Authority, Call, ExtBuilder, Origin, Runtime, System}; use mock::{Authority, AuthorityInstance1, Call, ExtBuilder, Origin, Runtime, System};
use sp_runtime::{traits::Bounded, Perbill}; use sp_runtime::{
traits::{BadOrigin, Bounded},
Perbill,
};
#[test] #[test]
fn dispatch_root_work() { fn dispatch_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let call = Call::System(frame_system::Call::fill_block(Perbill::one())); let ensure_root_call = Call::System(frame_system::Call::fill_block(Perbill::one()));
assert_ok!(Authority::dispatch_root(Origin::signed(1), Box::new(call.clone()))); let ensure_signed_call = Call::System(frame_system::Call::remark(vec![]));
assert_noop!(Authority::dispatch_root(Origin::signed(2), Box::new(call)), BadOrigin); assert_ok!(Authority::dispatch(
Origin::signed(1),
Box::new(ensure_root_call.clone())
));
assert_noop!(
Authority::dispatch(Origin::signed(2), Box::new(ensure_root_call.clone())),
BadOrigin
);
assert_noop!(
Authority::dispatch(Origin::signed(1), Box::new(ensure_signed_call.clone())),
BadOrigin
);
assert_noop!(
AuthorityInstance1::dispatch(Origin::signed(1), Box::new(ensure_root_call)),
BadOrigin
);
assert_ok!(AuthorityInstance1::dispatch(
Origin::signed(1),
Box::new(ensure_signed_call)
));
}); });
} }
#[test] #[test]
fn schedule_dispatch_root_work() { fn schedule_dispatch_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
System::set_block_number(10); System::set_block_number(10);
let call = Call::System(frame_system::Call::fill_block(Perbill::one())); let ensure_root_call = Call::System(frame_system::Call::fill_block(Perbill::one()));
assert_noop!( assert_noop!(
Authority::schedule_dispatch_root(Origin::signed(1), Box::new(call.clone()), DelayedDispatchTime::At(10)), Authority::schedule_dispatch(
Error::<Runtime>::InvalidDelayedDispatchTime, Origin::signed(1),
Box::new(ensure_root_call.clone()),
DelayedDispatchTime::At(10)
),
Error::<Runtime, DefaultInstance>::InvalidDelayedDispatchTime,
); );
assert_noop!( assert_noop!(
Authority::schedule_dispatch_root( Authority::schedule_dispatch(
Origin::signed(1), Origin::signed(1),
Box::new(call.clone()), Box::new(ensure_root_call.clone()),
DelayedDispatchTime::After(Bounded::max_value()) DelayedDispatchTime::After(Bounded::max_value())
), ),
Error::<Runtime>::BlockNumberOverflow, Error::<Runtime, DefaultInstance>::BlockNumberOverflow,
); );
assert_noop!( assert_noop!(
Authority::schedule_dispatch_root(Origin::signed(2), Box::new(call.clone()), DelayedDispatchTime::At(20)), Authority::schedule_dispatch(
Origin::signed(2),
Box::new(ensure_root_call.clone()),
DelayedDispatchTime::At(20)
),
BadOrigin, BadOrigin,
); );
assert_ok!(Authority::schedule_dispatch_root( assert_ok!(Authority::schedule_dispatch(
Origin::signed(1), Origin::signed(1),
Box::new(call.clone()), Box::new(ensure_root_call.clone()),
DelayedDispatchTime::At(20) DelayedDispatchTime::At(20)
)); ));
assert_noop!( assert_noop!(
Authority::schedule_dispatch_root(Origin::signed(1), Box::new(call.clone()), DelayedDispatchTime::At(19)), Authority::schedule_dispatch(
Origin::signed(1),
Box::new(ensure_root_call.clone()),
DelayedDispatchTime::At(19)
),
BadOrigin, BadOrigin,
); );
assert_ok!(Authority::schedule_dispatch_root( assert_ok!(Authority::schedule_dispatch(
Origin::signed(2), Origin::signed(2),
Box::new(call.clone()), Box::new(ensure_root_call),
DelayedDispatchTime::At(19) DelayedDispatchTime::At(19)
)); ));
}); });
...@@ -75,7 +106,7 @@ fn schedule_dispatch_delayed_work() { ...@@ -75,7 +106,7 @@ fn schedule_dispatch_delayed_work() {
assert_noop!( assert_noop!(
Authority::schedule_dispatch_delayed(Origin::signed(1), Box::new(call.clone()), DelayedDispatchTime::At(9)), Authority::schedule_dispatch_delayed(Origin::signed(1), Box::new(call.clone()), DelayedDispatchTime::At(9)),
Error::<Runtime>::InvalidDelayedDispatchTime, Error::<Runtime, DefaultInstance>::InvalidDelayedDispatchTime,
); );
assert_noop!( assert_noop!(
...@@ -84,7 +115,7 @@ fn schedule_dispatch_delayed_work() { ...@@ -84,7 +115,7 @@ fn schedule_dispatch_delayed_work() {
Box::new(call.clone()), Box::new(call.clone()),
DelayedDispatchTime::After(Bounded::max_value()) DelayedDispatchTime::After(Bounded::max_value())
), ),
Error::<Runtime>::BlockNumberOverflow, Error::<Runtime, DefaultInstance>::BlockNumberOverflow,
); );
assert_ok!(Authority::schedule_dispatch_delayed( assert_ok!(Authority::schedule_dispatch_delayed(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment