Skip to content

Commit de957f9

Browse files
authored
add authority module (#200)
1 parent 7184f18 commit de957f9

File tree

9 files changed

+754
-308
lines changed

9 files changed

+754
-308
lines changed

Cargo.dev.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ members = [
1111
"gradually-update",
1212
"schedule-update",
1313
"benchmarking",
14+
"authority",
1415
]

authority/Cargo.toml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[package]
2+
name = "orml-authority"
3+
description = "Auction module that implements `Auction` trait."
4+
repository = "https://github.com/open-web3-stack/open-runtime-module-library/tree/master/auction"
5+
license = "Apache-2.0"
6+
version = "0.1.0"
7+
authors = ["Acala Developers"]
8+
edition = "2018"
9+
10+
[dependencies]
11+
serde = { version = "1.0.101", optional = true }
12+
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false }
13+
sp-runtime = { version = "2.0.0-rc1", default-features = false }
14+
sp-io = { version = "2.0.0-rc1", default-features = false }
15+
sp-std = { version = "2.0.0-rc1", default-features = false }
16+
17+
frame-support = { version = "2.0.0-rc1", default-features = false }
18+
frame-system = { version = "2.0.0-rc1", default-features = false }
19+
20+
orml-traits = { path = "../traits", version = "0.1.0", default-features = false }
21+
22+
[dev-dependencies]
23+
sp-core = { version = "2.0.0-rc1", default-features = false }
24+
clear_on_drop = { version = "0.2.3", features = ["no_cc"] } # https://github.com/paritytech/substrate/issues/4179
25+
26+
[features]
27+
default = ["std"]
28+
std = [
29+
"serde",
30+
"codec/std",
31+
"sp-runtime/std",
32+
"sp-io/std",
33+
"sp-std/std",
34+
"frame-support/std",
35+
"frame-system/std",
36+
"orml-traits/std",
37+
]

authority/src/lib.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#![cfg_attr(not(feature = "std"), no_std)]
2+
// Disable the following two lints since they originate from an external macro (namely decl_storage)
3+
#![allow(clippy::string_lit_as_bytes)]
4+
#![allow(clippy::boxed_local)]
5+
#![allow(clippy::borrowed_box)]
6+
7+
use frame_support::{
8+
decl_error,
9+
decl_module,
10+
dispatch::PostDispatchInfo,
11+
ensure,
12+
traits::{EnsureOrigin, Get},
13+
weights::{FunctionOf, GetDispatchInfo, Pays},
14+
//weights::{GetDispatchInfo},
15+
Parameter,
16+
};
17+
use frame_system::{self as system};
18+
use orml_traits::{DelayedDispatchTime, DispatchId, Scheduler};
19+
use sp_runtime::{
20+
traits::{BadOrigin, CheckedAdd, CheckedSub, Dispatchable},
21+
RuntimeDebug,
22+
};
23+
use sp_std::prelude::*;
24+
25+
mod mock;
26+
mod tests;
27+
28+
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
29+
pub struct DelayedOrigin<BlockNumber, Origin> {
30+
pub delay: BlockNumber,
31+
pub origin: Origin,
32+
}
33+
34+
/// Origin for the authority module.
35+
pub type Origin<T> =
36+
DelayedOrigin<<T as system::Trait>::BlockNumber, system::RawOrigin<<T as system::Trait>::AccountId>>;
37+
38+
pub struct EnsureDelayed<Delay, Inner, BlockNumber>(sp_std::marker::PhantomData<(Delay, Inner, BlockNumber)>);
39+
40+
impl<
41+
O: Into<Result<DelayedOrigin<BlockNumber, O>, O>> + From<DelayedOrigin<BlockNumber, O>>,
42+
Delay: Get<BlockNumber>,
43+
Inner: EnsureOrigin<O>,
44+
BlockNumber: PartialOrd,
45+
> EnsureOrigin<O> for EnsureDelayed<Delay, Inner, BlockNumber>
46+
{
47+
type Success = Inner::Success;
48+
49+
fn try_origin(o: O) -> Result<Self::Success, O> {
50+
o.into().and_then(|delayed_origin| {
51+
if delayed_origin.delay >= Delay::get() {
52+
Inner::try_origin(delayed_origin.origin)
53+
} else {
54+
Err(delayed_origin.origin)
55+
}
56+
})
57+
}
58+
}
59+
60+
pub trait Trait: system::Trait {
61+
type Origin: From<DelayedOrigin<Self::BlockNumber, system::RawOrigin<Self::AccountId>>>
62+
+ From<system::RawOrigin<Self::AccountId>>;
63+
type Call: Parameter
64+
+ Dispatchable<Origin = <Self as system::Trait>::Origin, PostInfo = PostDispatchInfo>
65+
+ GetDispatchInfo;
66+
type RootDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
67+
type DelayedRootDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
68+
type DelayedDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
69+
type VetoOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
70+
type InstantDispatchOrigin: EnsureOrigin<<Self as system::Trait>::Origin>;
71+
type Scheduler: Scheduler<Self::BlockNumber, Origin = <Self as Trait>::Origin, Call = <Self as Trait>::Call>;
72+
type MinimumDelay: Get<Self::BlockNumber>;
73+
}
74+
75+
decl_error! {
76+
/// Error for authority module.
77+
pub enum Error for Module<T: Trait> {
78+
BlockNumberOverflow,
79+
InvalidDelayedDispatchTime,
80+
}
81+
}
82+
83+
type CallOf<T> = <T as Trait>::Call;
84+
85+
decl_module! {
86+
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
87+
type Error = Error<T>;
88+
89+
const MinimumDelay: T::BlockNumber = T::MinimumDelay::get();
90+
91+
#[weight = FunctionOf(
92+
|args: (&Box<CallOf<T>>,)| args.0.get_dispatch_info().weight + 10_000,
93+
|args: (&Box<CallOf<T>>,)| args.0.get_dispatch_info().class,
94+
Pays::Yes,
95+
)]
96+
pub fn dispatch_root(origin, call: Box<CallOf<T>>) {
97+
T::RootDispatchOrigin::try_origin(origin).map_err(|_| BadOrigin)?;
98+
call.dispatch(frame_system::RawOrigin::Root.into()).map(|_| ()).map_err(|e| e.error)?;
99+
}
100+
101+
#[weight = FunctionOf(
102+
|args: (&Box<CallOf<T>>, &DelayedDispatchTime<T::BlockNumber>)| args.0.get_dispatch_info().weight + 10_000,
103+
|args: (&Box<CallOf<T>>, &DelayedDispatchTime<T::BlockNumber>)| args.0.get_dispatch_info().class,
104+
Pays::Yes,
105+
)]
106+
pub fn schedule_dispatch_root(origin, call: Box<CallOf<T>>, when: DelayedDispatchTime<T::BlockNumber>) {
107+
let now = <frame_system::Module<T>>::block_number();
108+
let when_block = match when {
109+
DelayedDispatchTime::At(at_block) => {
110+
ensure!(at_block > now, Error::<T>::InvalidDelayedDispatchTime);
111+
at_block
112+
},
113+
DelayedDispatchTime::After(after_block) => {
114+
now.checked_add(&after_block).ok_or(Error::<T>::BlockNumberOverflow)?
115+
},
116+
};
117+
118+
if when_block >= T::MinimumDelay::get() + now {
119+
T::DelayedRootDispatchOrigin::try_origin(origin).map_err(|_| BadOrigin)?;
120+
} else {
121+
T::InstantDispatchOrigin::try_origin(origin).map_err(|_| BadOrigin)?;
122+
}
123+
124+
// schedule call with Root origin
125+
let _ = T::Scheduler::schedule(frame_system::RawOrigin::Root.into(), *call, when);
126+
}
127+
128+
#[weight = FunctionOf(
129+
|args: (&Box<CallOf<T>>, &DelayedDispatchTime<T::BlockNumber>)| args.0.get_dispatch_info().weight + 10_000,
130+
|args: (&Box<CallOf<T>>, &DelayedDispatchTime<T::BlockNumber>)| args.0.get_dispatch_info().class,
131+
Pays::Yes,
132+
)]
133+
pub fn schedule_dispatch_delayed(origin, call: Box<CallOf<T>>, when: DelayedDispatchTime<T::BlockNumber>) {
134+
T::DelayedDispatchOrigin::try_origin(origin.clone()).map_err(|_| BadOrigin)?;
135+
136+
let now = <frame_system::Module<T>>::block_number();
137+
let delay_block = match when {
138+
DelayedDispatchTime::At(at_block) => {
139+
at_block.checked_sub(&now).ok_or(Error::<T>::InvalidDelayedDispatchTime)?
140+
},
141+
DelayedDispatchTime::After(after_block) => {
142+
ensure!(after_block.checked_add(&now).is_some(), Error::<T>::BlockNumberOverflow);
143+
after_block
144+
},
145+
};
146+
147+
let raw_origin = origin.into().map_err(|_| BadOrigin)?;
148+
let delayed_origin = DelayedOrigin{
149+
delay: delay_block,
150+
origin: raw_origin,
151+
};
152+
153+
// dispatch call with DelayedOrigin
154+
let _ = T::Scheduler::schedule(delayed_origin.into(), *call, when);
155+
}
156+
157+
#[weight = 0]
158+
pub fn veto(origin, dispatch_id: DispatchId) {
159+
T::VetoOrigin::try_origin(origin).map_err(|_| BadOrigin)?;
160+
T::Scheduler::cancel(dispatch_id);
161+
}
162+
}
163+
}

authority/src/mock.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//! Mocks for the authority module.
2+
3+
#![cfg(test)]
4+
5+
use frame_support::{ord_parameter_types, parameter_types};
6+
use frame_system::EnsureSignedBy;
7+
use sp_core::H256;
8+
use sp_runtime::{
9+
testing::Header,
10+
traits::{Block as BlockT, IdentityLookup},
11+
Perbill,
12+
};
13+
14+
use super::*;
15+
use crate as authority;
16+
17+
pub type AccountId = u128;
18+
pub type BlockNumber = u64;
19+
20+
parameter_types! {
21+
pub const BlockHashCount: u64 = 250;
22+
pub const MaximumBlockWeight: u32 = 1024;
23+
pub const MaximumBlockLength: u32 = 2 * 1024;
24+
pub const AvailableBlockRatio: Perbill = Perbill::one();
25+
}
26+
27+
impl frame_system::Trait for Runtime {
28+
type Origin = Origin;
29+
type Index = u64;
30+
type BlockNumber = BlockNumber;
31+
type Call = ();
32+
type Hash = H256;
33+
type Hashing = ::sp_runtime::traits::BlakeTwo256;
34+
type AccountId = AccountId;
35+
type Lookup = IdentityLookup<Self::AccountId>;
36+
type Header = Header;
37+
type Event = ();
38+
type BlockHashCount = BlockHashCount;
39+
type MaximumBlockWeight = MaximumBlockWeight;
40+
type MaximumBlockLength = MaximumBlockLength;
41+
type AvailableBlockRatio = AvailableBlockRatio;
42+
type Version = ();
43+
type ModuleToIndex = ();
44+
type AccountData = ();
45+
type OnNewAccount = ();
46+
type OnKilledAccount = ();
47+
type DbWeight = ();
48+
type BlockExecutionWeight = ();
49+
type ExtrinsicBaseWeight = ();
50+
type MaximumExtrinsicWeight = ();
51+
}
52+
53+
pub struct MockScheduler;
54+
impl Scheduler<BlockNumber> for MockScheduler {
55+
type Origin = Origin;
56+
type Call = Call;
57+
58+
fn schedule(_: Self::Origin, _: Self::Call, _: DelayedDispatchTime<BlockNumber>) -> DispatchId {
59+
Default::default()
60+
}
61+
62+
fn cancel(_: DispatchId) {}
63+
}
64+
65+
ord_parameter_types! {
66+
pub const One: AccountId = 1;
67+
pub const Two: AccountId = 2;
68+
}
69+
70+
parameter_types! {
71+
pub const MinimumDelay: BlockNumber = 10;
72+
}
73+
74+
impl Trait for Runtime {
75+
type Origin = Origin;
76+
type Call = Call;
77+
type RootDispatchOrigin = EnsureSignedBy<One, AccountId>;
78+
type DelayedRootDispatchOrigin = EnsureSignedBy<One, AccountId>;
79+
type DelayedDispatchOrigin = EnsureSignedBy<One, AccountId>;
80+
type VetoOrigin = EnsureSignedBy<One, AccountId>;
81+
type InstantDispatchOrigin = EnsureSignedBy<Two, AccountId>;
82+
type Scheduler = MockScheduler;
83+
type MinimumDelay = MinimumDelay;
84+
}
85+
86+
pub type Block = sp_runtime::generic::Block<Header, UncheckedExtrinsic>;
87+
pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic<u32, u64, Call, ()>;
88+
89+
frame_support::construct_runtime!(
90+
pub enum Runtime where
91+
Block = Block,
92+
NodeBlock = Block,
93+
UncheckedExtrinsic = UncheckedExtrinsic
94+
{
95+
System: frame_system::{Module, Call, Event<T>},
96+
Authority: authority::{Module, Call, Origin<T>},
97+
}
98+
);
99+
100+
pub struct ExtBuilder;
101+
102+
impl Default for ExtBuilder {
103+
fn default() -> Self {
104+
ExtBuilder
105+
}
106+
}
107+
108+
impl ExtBuilder {
109+
pub fn build(self) -> sp_io::TestExternalities {
110+
let t = frame_system::GenesisConfig::default()
111+
.build_storage::<Runtime>()
112+
.unwrap();
113+
114+
t.into()
115+
}
116+
}

0 commit comments

Comments
 (0)