mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Introduce treasury and document (#646)
* Introduce treasury and document * Revert bad changes * More reversions * Add example crate - Remove HasPublicAux - Rename Concrete -> Runtime * Actually commit stuff * Changes * Propagate block number in finalise. * Fix and build example * Fixes. * Fix compilation for treasury. * Fix the treasury test * Tests * Fix. * Fix tests * Fix a few grumbles * Fixes * Fix grumbles
This commit is contained in:
Generated
+36
@@ -2824,6 +2824,24 @@ dependencies = [
|
||||
"substrate-runtime-system 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-example"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-codec-derive 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-balances 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
"substrate-runtime-primitives 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"substrate-runtime-support 0.1.0",
|
||||
"substrate-runtime-system 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-executive"
|
||||
version = "0.1.0"
|
||||
@@ -2996,6 +3014,24 @@ dependencies = [
|
||||
"substrate-runtime-system 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-treasury"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-codec-derive 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-balances 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
"substrate-runtime-primitives 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"substrate-runtime-support 0.1.0",
|
||||
"substrate-runtime-system 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-version"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -24,12 +24,14 @@ members = [
|
||||
"substrate/runtime/contract",
|
||||
"substrate/runtime/council",
|
||||
"substrate/runtime/democracy",
|
||||
"substrate/runtime/example",
|
||||
"substrate/runtime/executive",
|
||||
"substrate/runtime/primitives",
|
||||
"substrate/runtime/session",
|
||||
"substrate/runtime/staking",
|
||||
"substrate/runtime/system",
|
||||
"substrate/runtime/timestamp",
|
||||
"substrate/runtime/treasury",
|
||||
"substrate/runtime/version",
|
||||
"substrate/serializer",
|
||||
"substrate/service",
|
||||
|
||||
@@ -55,7 +55,7 @@ mod tests {
|
||||
use runtime_primitives::{ApplyOutcome, ApplyError, ApplyResult, MaybeUnsigned};
|
||||
use {balances, staking, session, system, consensus};
|
||||
use system::{EventRecord, Phase};
|
||||
use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Concrete, Balances,
|
||||
use demo_runtime::{Header, Block, UncheckedExtrinsic, Extrinsic, Call, Runtime, Balances,
|
||||
BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, BareExtrinsic, System, Event};
|
||||
use ed25519::{Public, Pair};
|
||||
|
||||
@@ -81,7 +81,7 @@ mod tests {
|
||||
let extrinsic = BareExtrinsic {
|
||||
signed: alice(),
|
||||
index: 0,
|
||||
function: Call::Balances(balances::Call::transfer::<Concrete>(bob().into(), 69)),
|
||||
function: Call::Balances(balances::Call::transfer::<Runtime>(bob().into(), 69)),
|
||||
};
|
||||
let signature = MaybeUnsigned(Keyring::from_raw_public(extrinsic.signed.0.clone()).unwrap()
|
||||
.sign(&extrinsic.encode()).into());
|
||||
@@ -104,14 +104,14 @@ mod tests {
|
||||
#[test]
|
||||
fn panic_execution_with_foreign_code_gives_error() {
|
||||
let mut t: TestExternalities<KeccakHasher> = map![
|
||||
twox_128(&<balances::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Concrete>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
twox_128(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, 8, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
@@ -124,14 +124,14 @@ mod tests {
|
||||
#[test]
|
||||
fn bad_extrinsic_with_native_equivalent_code_gives_error() {
|
||||
let mut t: TestExternalities<KeccakHasher> = map![
|
||||
twox_128(&<balances::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Concrete>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
twox_128(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, 8, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
@@ -144,14 +144,14 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
let mut t: TestExternalities<KeccakHasher> = map![
|
||||
twox_128(&<balances::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Concrete>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
twox_128(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, 8, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
@@ -168,14 +168,14 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_with_foreign_code_gives_ok() {
|
||||
let mut t: TestExternalities<KeccakHasher> = map![
|
||||
twox_128(&<balances::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Concrete>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
twox_128(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, 8, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
@@ -401,14 +401,14 @@ mod tests {
|
||||
#[test]
|
||||
fn panic_execution_gives_error() {
|
||||
let mut t: TestExternalities<KeccakHasher> = map![
|
||||
twox_128(&<balances::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Concrete>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
twox_128(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm");
|
||||
@@ -422,14 +422,14 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_gives_ok() {
|
||||
let mut t: TestExternalities<KeccakHasher> = map![
|
||||
twox_128(&<balances::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Concrete>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
twox_128(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<balances::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm");
|
||||
|
||||
@@ -56,7 +56,7 @@ extern crate demo_primitives;
|
||||
use rstd::prelude::*;
|
||||
use demo_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature};
|
||||
use runtime_primitives::generic;
|
||||
use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256};
|
||||
use runtime_primitives::traits::{Convert, BlakeTwo256};
|
||||
use version::RuntimeVersion;
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
@@ -65,8 +65,8 @@ pub use runtime_primitives::BuildStorage;
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
/// Concrete runtime type used to parameterize the various modules.
|
||||
pub struct Concrete;
|
||||
/// Runtime runtime type used to parameterize the various modules.
|
||||
pub struct Runtime;
|
||||
|
||||
/// Runtime version.
|
||||
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
@@ -78,18 +78,14 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
};
|
||||
|
||||
/// Version module for this concrete runtime.
|
||||
pub type Version = version::Module<Concrete>;
|
||||
pub type Version = version::Module<Runtime>;
|
||||
|
||||
impl version::Trait for Concrete {
|
||||
impl version::Trait for Runtime {
|
||||
const VERSION: RuntimeVersion = VERSION;
|
||||
}
|
||||
|
||||
impl HasPublicAux for Concrete {
|
||||
type PublicAux = AccountId;
|
||||
}
|
||||
|
||||
impl system::Trait for Concrete {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
impl system::Trait for Runtime {
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = Index;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
@@ -101,9 +97,9 @@ impl system::Trait for Concrete {
|
||||
}
|
||||
|
||||
/// System module for this concrete runtime.
|
||||
pub type System = system::Module<Concrete>;
|
||||
pub type System = system::Module<Runtime>;
|
||||
|
||||
impl balances::Trait for Concrete {
|
||||
impl balances::Trait for Runtime {
|
||||
type Balance = Balance;
|
||||
type AccountIndex = AccountIndex;
|
||||
type OnFreeBalanceZero = Staking;
|
||||
@@ -112,25 +108,25 @@ impl balances::Trait for Concrete {
|
||||
}
|
||||
|
||||
/// Staking module for this concrete runtime.
|
||||
pub type Balances = balances::Module<Concrete>;
|
||||
pub type Balances = balances::Module<Runtime>;
|
||||
|
||||
impl consensus::Trait for Concrete {
|
||||
impl consensus::Trait for Runtime {
|
||||
const NOTE_OFFLINE_POSITION: u32 = 1;
|
||||
type SessionKey = SessionKey;
|
||||
type OnOfflineValidator = Staking;
|
||||
}
|
||||
|
||||
/// Consensus module for this concrete runtime.
|
||||
pub type Consensus = consensus::Module<Concrete>;
|
||||
pub type Consensus = consensus::Module<Runtime>;
|
||||
|
||||
impl timestamp::Trait for Concrete {
|
||||
impl timestamp::Trait for Runtime {
|
||||
const TIMESTAMP_SET_POSITION: u32 = 0;
|
||||
|
||||
type Moment = u64;
|
||||
}
|
||||
|
||||
/// Timestamp module for this concrete runtime.
|
||||
pub type Timestamp = timestamp::Module<Concrete>;
|
||||
pub type Timestamp = timestamp::Module<Runtime>;
|
||||
|
||||
/// Session key conversion.
|
||||
pub struct SessionKeyConversion;
|
||||
@@ -140,38 +136,39 @@ impl Convert<AccountId, SessionKey> for SessionKeyConversion {
|
||||
}
|
||||
}
|
||||
|
||||
impl session::Trait for Concrete {
|
||||
impl session::Trait for Runtime {
|
||||
type ConvertAccountIdToSessionKey = SessionKeyConversion;
|
||||
type OnSessionChange = Staking;
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
/// Session module for this concrete runtime.
|
||||
pub type Session = session::Module<Concrete>;
|
||||
pub type Session = session::Module<Runtime>;
|
||||
|
||||
impl staking::Trait for Concrete {
|
||||
impl staking::Trait for Runtime {
|
||||
type OnRewardMinted = ();
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
/// Staking module for this concrete runtime.
|
||||
pub type Staking = staking::Module<Concrete>;
|
||||
pub type Staking = staking::Module<Runtime>;
|
||||
|
||||
impl democracy::Trait for Concrete {
|
||||
impl democracy::Trait for Runtime {
|
||||
type Proposal = PrivCall;
|
||||
}
|
||||
|
||||
/// Democracy module for this concrete runtime.
|
||||
pub type Democracy = democracy::Module<Concrete>;
|
||||
pub type Democracy = democracy::Module<Runtime>;
|
||||
|
||||
impl council::Trait for Concrete {}
|
||||
impl council::Trait for Runtime {}
|
||||
|
||||
/// Council module for this concrete runtime.
|
||||
pub type Council = council::Module<Concrete>;
|
||||
pub type Council = council::Module<Runtime>;
|
||||
/// Council voting module for this concrete runtime.
|
||||
pub type CouncilVoting = council::voting::Module<Concrete>;
|
||||
pub type CouncilVoting = council::voting::Module<Runtime>;
|
||||
|
||||
impl_outer_event! {
|
||||
pub enum Event for Concrete {
|
||||
pub enum Event for Runtime {
|
||||
balances, session, staking
|
||||
}
|
||||
}
|
||||
@@ -179,7 +176,7 @@ impl_outer_event! {
|
||||
impl_outer_dispatch! {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
|
||||
pub enum Call where aux: <Runtime as system::Trait>::PublicAux {
|
||||
Consensus = 0,
|
||||
Balances = 1,
|
||||
Session = 2,
|
||||
@@ -204,7 +201,7 @@ impl_outer_dispatch! {
|
||||
}
|
||||
|
||||
/// The address format for describing accounts.
|
||||
pub type Address = balances::Address<Concrete>;
|
||||
pub type Address = balances::Address<Runtime>;
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
|
||||
/// Block type as expected by this runtime.
|
||||
@@ -218,11 +215,11 @@ pub type Extrinsic = generic::Extrinsic<Address, Index, Call>;
|
||||
/// Extrinsic type that is signed.
|
||||
pub type BareExtrinsic = generic::Extrinsic<AccountId, Index, Call>;
|
||||
/// Executive: handles dispatch to the various modules.
|
||||
pub type Executive = executive::Executive<Concrete, Block, Balances, Balances,
|
||||
pub type Executive = executive::Executive<Runtime, Block, Balances, Balances,
|
||||
(((((), Council), Democracy), Staking), Session)>;
|
||||
|
||||
impl_outer_config! {
|
||||
pub struct GenesisConfig for Concrete {
|
||||
pub struct GenesisConfig for Runtime {
|
||||
ConsensusConfig => consensus,
|
||||
SystemConfig => system,
|
||||
BalancesConfig => balances,
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "basic_add"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"polkadot-parachain 0.1.0",
|
||||
"pwasm-libc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wee_alloc 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nan-preserving-float"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nodrop"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "parity-wasm"
|
||||
version = "0.31.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polkadot-parachain"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pwasm-libc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlibc"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "substrate-codec"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasmi"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wee_alloc"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memory_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
|
||||
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
|
||||
"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781"
|
||||
"checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131"
|
||||
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
|
||||
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
||||
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
|
||||
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
|
||||
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
|
||||
"checksum memory_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc"
|
||||
"checksum pwasm-libc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "027307d6d2086ffb7f399227d42593c5341e8869a55ac8dd7c79d7ca04ec00e2"
|
||||
"checksum rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe"
|
||||
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
|
||||
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum wasmi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4a6d379e9332b1b1f52c5a87f2481c85c7c931d8ec411963dfb8f26b1ec1e3"
|
||||
"checksum wee_alloc 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27875be1daf838fa18f3e94fd19fd12638e34615b42f56da2610c8f46be80cc6"
|
||||
"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
@@ -787,7 +787,7 @@ macro_rules! __impl_store_fns {
|
||||
};
|
||||
|
||||
($traitinstance:ident $name:ident get($getfn:ident) : $ty:ty; $($t:tt)*) => {
|
||||
__impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $gettype $ty);
|
||||
__impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $ty);
|
||||
__impl_store_fns!($traitinstance $($t)*);
|
||||
};
|
||||
($traitinstance:ident pub $name:ident get($getfn:ident) : $ty:ty; $($t:tt)*) => {
|
||||
|
||||
@@ -45,7 +45,7 @@ use rstd::{cmp, result};
|
||||
use codec::{Encode, Decode, Codec, Input, Output};
|
||||
use runtime_support::{StorageValue, StorageMap, Parameter};
|
||||
use runtime_support::dispatch::Result;
|
||||
use primitives::traits::{Zero, One, RefInto, SimpleArithmetic, Executable, MakePayment,
|
||||
use primitives::traits::{Zero, One, RefInto, SimpleArithmetic, OnFinalise, MakePayment,
|
||||
As, AuxLookup, Member, CheckedAdd, CheckedSub};
|
||||
use address::Address as RawAddress;
|
||||
|
||||
@@ -91,6 +91,16 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for a hook to get called when some balance has been minted.
|
||||
pub trait OnMinted<Balance> {
|
||||
/// Some balance `b` was minted.
|
||||
fn on_minted(b: Balance);
|
||||
}
|
||||
|
||||
impl<Balance> OnMinted<Balance> for () {
|
||||
fn on_minted(_b: Balance) {}
|
||||
}
|
||||
|
||||
/// Determinator for whether a given account is able to transfer balance.
|
||||
pub trait EnsureAccountLiquid<AccountId> {
|
||||
/// Returns `Ok` iff the account is able to transfer funds normally. `Err(...)`
|
||||
@@ -400,6 +410,17 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created.
|
||||
///
|
||||
/// This is a sensitive function since it circumvents any fees associated with account
|
||||
/// setup. Ensure it is only called by trusted code.
|
||||
///
|
||||
/// NOTE: This assumes that the total stake remains unchanged after this operation. If
|
||||
/// you mean to actually mint value into existence, then use `reward` instead.
|
||||
pub fn increase_free_balance_creating(who: &T::AccountId, value: T::Balance) -> UpdateBalanceOutcome {
|
||||
Self::set_free_balance_creating(who, Self::free_balance(who) + value)
|
||||
}
|
||||
|
||||
/// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the
|
||||
/// free balance. This function cannot fail.
|
||||
///
|
||||
@@ -621,8 +642,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Executable for Module<T> {
|
||||
fn execute() {
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(_n: T::BlockNumber) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::HasPublicAux;
|
||||
use primitives::testing::{Digest, Header};
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use runtime_io;
|
||||
@@ -28,11 +27,8 @@ use {GenesisConfig, Module, Trait, system};
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
//! exsistential deposit) then it reaps the account. That will lead to deletion of the associated
|
||||
//! code and storage of the account.
|
||||
//!
|
||||
//! [`Module::execute`]: struct.Module.html#impl-Executable
|
||||
//! [`Module::execute`]: struct.Module.html#impl-OnFinalise
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
@@ -101,7 +101,7 @@ use account_db::{AccountDb, OverlayAccountDb};
|
||||
use double_map::StorageDoubleMap;
|
||||
|
||||
use codec::Codec;
|
||||
use runtime_primitives::traits::{As, RefInto, SimpleArithmetic, Executable};
|
||||
use runtime_primitives::traits::{As, RefInto, SimpleArithmetic, OnFinalise};
|
||||
use runtime_support::dispatch::Result;
|
||||
use runtime_support::{Parameter, StorageMap, StorageValue};
|
||||
|
||||
@@ -270,8 +270,8 @@ impl<T: Trait> balances::OnFreeBalanceZero<T::AccountId> for Module<T> {
|
||||
}
|
||||
|
||||
/// Finalization hook for the smart-contract module.
|
||||
impl<T: Trait> Executable for Module<T> {
|
||||
fn execute() {
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(_n: T::BlockNumber) {
|
||||
<GasSpent<T>>::kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use double_map::StorageDoubleMap;
|
||||
use runtime_io::with_externalities;
|
||||
use runtime_primitives::testing::{Digest, H256, Header};
|
||||
use runtime_primitives::traits::{BlakeTwo256, HasPublicAux};
|
||||
use runtime_primitives::traits::{BlakeTwo256};
|
||||
use runtime_primitives::BuildStorage;
|
||||
use runtime_support::StorageMap;
|
||||
use substrate_primitives::KeccakHasher;
|
||||
@@ -29,11 +29,8 @@ use {
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
|
||||
@@ -34,6 +34,7 @@ std = [
|
||||
"substrate-runtime-io/std",
|
||||
"substrate-runtime-support/std",
|
||||
"substrate-runtime-primitives/std",
|
||||
"substrate-runtime-consensus/std",
|
||||
"substrate-runtime-balances/std",
|
||||
"substrate-runtime-democracy/std",
|
||||
"substrate-runtime-system/std",
|
||||
|
||||
@@ -618,7 +618,7 @@ mod tests {
|
||||
pub use runtime_io::with_externalities;
|
||||
pub use substrate_primitives::H256;
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{HasPublicAux, BlakeTwo256};
|
||||
use primitives::traits::{BlakeTwo256};
|
||||
use primitives::testing::{Digest, Header};
|
||||
use substrate_primitives::KeccakHasher;
|
||||
|
||||
@@ -633,11 +633,8 @@ mod tests {
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::borrow::Borrow;
|
||||
use primitives::traits::{Executable, RefInto, Hash};
|
||||
use primitives::traits::{OnFinalise, RefInto, Hash};
|
||||
use runtime_io::print;
|
||||
use substrate_runtime_support::dispatch::Result;
|
||||
use substrate_runtime_support::{StorageValue, StorageMap, IsSubType};
|
||||
@@ -200,9 +200,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Executable for Council<T> {
|
||||
fn execute() {
|
||||
let n = <system::Module<T>>::block_number();
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Council<T> {
|
||||
fn on_finalise(n: T::BlockNumber) {
|
||||
if let Err(e) = Self::end_block(n) {
|
||||
print("Guru meditation");
|
||||
print(e);
|
||||
|
||||
@@ -43,7 +43,7 @@ extern crate substrate_runtime_system as system;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::result;
|
||||
use primitives::traits::{Zero, Executable, RefInto, As, MaybeSerializeDebug};
|
||||
use primitives::traits::{Zero, OnFinalise, RefInto, As, MaybeSerializeDebug};
|
||||
use substrate_runtime_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType};
|
||||
use substrate_runtime_support::dispatch::Result;
|
||||
|
||||
@@ -288,9 +288,9 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Executable for Module<T> {
|
||||
fn execute() {
|
||||
if let Err(e) = Self::end_block(<system::Module<T>>::block_number()) {
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(n: T::BlockNumber) {
|
||||
if let Err(e) = Self::end_block(n) {
|
||||
runtime_io::print(e);
|
||||
}
|
||||
}
|
||||
@@ -351,7 +351,7 @@ mod tests {
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{HasPublicAux, BlakeTwo256};
|
||||
use primitives::traits::{BlakeTwo256};
|
||||
use primitives::testing::{Digest, Header};
|
||||
|
||||
impl_outer_dispatch! {
|
||||
@@ -365,11 +365,8 @@ mod tests {
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "substrate-runtime-example"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
|
||||
substrate-runtime-io = { path = "../../runtime-io", default_features = false }
|
||||
substrate-runtime-support = { path = "../../runtime-support", default_features = false }
|
||||
substrate-runtime-primitives = { path = "../primitives", default_features = false }
|
||||
substrate-codec = { path = "../../codec", default_features = false }
|
||||
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
substrate-primitives = { path = "../../primitives", default_features = false }
|
||||
substrate-runtime-system = { path = "../system", default_features = false }
|
||||
substrate-runtime-balances = { path = "../balances", default_features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"substrate-runtime-std/std",
|
||||
"substrate-runtime-io/std",
|
||||
"substrate-runtime-support/std",
|
||||
"substrate-runtime-primitives/std",
|
||||
"substrate-runtime-balances/std",
|
||||
"serde/std",
|
||||
"serde_derive",
|
||||
"substrate-codec/std",
|
||||
"substrate-codec-derive/std",
|
||||
"substrate-primitives/std",
|
||||
"substrate-runtime-system/std",
|
||||
]
|
||||
@@ -0,0 +1,385 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! The Example: A simple example of a runtime module demonstrating
|
||||
//! concepts, APIs and structures common to most runtime modules.
|
||||
|
||||
// Ensure we're `no_std` when compiling for Wasm.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
// Assert macros used in tests.
|
||||
#[cfg_attr(feature = "std", macro_use)]
|
||||
extern crate substrate_runtime_std;
|
||||
|
||||
// Needed for tests (`with_externalities`).
|
||||
#[cfg(test)]
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
|
||||
// Needed for the set of mock primatives used in our tests.
|
||||
#[cfg(test)]
|
||||
extern crate substrate_primitives;
|
||||
|
||||
// Needed for deriving `Serialize` and `Deserialize` for various types.
|
||||
// We only implement the serde traits for std builds - they're unneeded
|
||||
// in the wasm runtime.
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
// Needed for deriving `Encode` and `Decode` for `RawEvent`.
|
||||
#[macro_use]
|
||||
extern crate substrate_codec_derive;
|
||||
extern crate substrate_codec as codec;
|
||||
|
||||
// Needed for type-safe access to storage DB.
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
|
||||
// Needed for various traits. In our case, `OnFinalise`.
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
// `system` module provides us with all sorts of useful stuff and macros
|
||||
// depend on it being around.
|
||||
extern crate substrate_runtime_system as system;
|
||||
// `balances` module is needed for our little example. It's not required in
|
||||
// general (though if you want your module to be able to work with tokens, then you
|
||||
// might find it useful).
|
||||
extern crate substrate_runtime_balances as balances;
|
||||
|
||||
use runtime_primitives::traits::OnFinalise;
|
||||
use runtime_support::{StorageValue, dispatch::Result};
|
||||
|
||||
/// Our module's configuration trait. All our types and consts go in here. If the
|
||||
/// module is dependent on specific other modules, then their configuration traits
|
||||
/// should be added to our implied traits list.
|
||||
///
|
||||
/// `system::Trait` should always be included in our implied traits.
|
||||
pub trait Trait: balances::Trait {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||
}
|
||||
|
||||
// The module declaration. This states the entry points that we handle. The
|
||||
// macro takes care of the marshalling of arguments and dispatch.
|
||||
decl_module! {
|
||||
// Simple declaration of the `Module` type. Lets the macro know what its working on.
|
||||
pub struct Module<T: Trait>;
|
||||
|
||||
// The unpriviledged entry points. Any account can call into these by signing and submitting
|
||||
// an extrinsic. Ensure that calls into each of these execute in a time, memory and
|
||||
// using storage space proportional to any costs paid for by the caller.
|
||||
//
|
||||
// The account that is calling this (i.e. the one that signed the extrinsic) is provided
|
||||
// via the `aux` argument, always first in each function call. As such functions must
|
||||
// always look like:
|
||||
//
|
||||
// `fn foo(aux, bar: Bar, baz: Baz) -> Result = 0;`
|
||||
//
|
||||
// The `Result` is required as part of the syntax (and expands to the conventional dispatch
|
||||
// result of `Result<(), &'static str>`). The index after `=` must be unique within this
|
||||
// enum (the `PrivCall` enum is allowed to reuse indexes).
|
||||
//
|
||||
// When you come to `impl` them later in the module, you must specify the full type for `aux`:
|
||||
//
|
||||
// `fn foo(aux: T::PublicAux, bar: Bar, baz: Baz) { ... }`
|
||||
//
|
||||
// This is your public interface. Be extremely careful.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum Call where aux: T::PublicAux {
|
||||
// This is just a simple example of how to interact with the module from the external
|
||||
// world.
|
||||
fn accumulate_dummy(aux, increase_by: T::Balance) -> Result = 0;
|
||||
}
|
||||
|
||||
// The priviledged entry points. These are provided to allow any governance modules in
|
||||
// the runtime to be able to execute common functions. Unlike for `Call` there is no
|
||||
// auxilliary data to encode the sender (since there is no sender). Though still important
|
||||
// to ensure that these execute in reasonable time and space, they can do what would
|
||||
// otherwise be costly or unsafe operations.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
// A priviledged call; in this case it resets our dummy value to something new.
|
||||
fn set_dummy(new_dummy: T::Balance) -> Result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Exported Event type that's generic over the configuration trait.
|
||||
// NOTE: External macro-fu expects this type to exist and be generic over
|
||||
// the configuration trait.
|
||||
pub type Event<T> = RawEvent<
|
||||
<T as balances::Trait>::Balance,
|
||||
>;
|
||||
|
||||
/// An event in this module. Events are simple means of reporting specific conditions and
|
||||
/// circumstances that have happened that users, Dapps and/or chain explorers would find
|
||||
/// interesting and otherwise difficult to detect.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawEvent<B> {
|
||||
// Just a normal `enum`, here's a dummy event to ensure it compiles.
|
||||
/// Dummy event, just here so there's a generic type that's used.
|
||||
Dummy(B),
|
||||
}
|
||||
|
||||
// By convention we implement any trait for which a "null implemntation" makes sense
|
||||
// for `()`. This is the case for conversion of module `Event` types and hook traits. It
|
||||
// is helpful for test code and production configurations where no eventing is necessary
|
||||
// or the hook is unused.
|
||||
impl<B> From<RawEvent<B>> for () {
|
||||
fn from(_: RawEvent<B>) -> () { () }
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
// A macro for the Storage trait, and its implementation, for this module.
|
||||
// This allows for type-safe usage of the Substrate storage database, so you can
|
||||
// keep things around between blocks.
|
||||
trait Store for Module<T: Trait> as Example {
|
||||
// Any storage declarations of the form:
|
||||
// `pub? Name get(getter_name)? : [required | default]? <type>;`
|
||||
// where `<type>` is either:
|
||||
// - `Type` (a basic value item); or
|
||||
// - `map [ KeyType => ValueType ]` (a map item).
|
||||
//
|
||||
// Note that there are two optional modifiers for the storage type declaration.
|
||||
// - `Foo: u32`:
|
||||
// - `Foo::put(1); Foo::get()` returns `Some(1)`;
|
||||
// - `Foo::kill(); Foo::get()` returns `None`.
|
||||
// - `Foo: required u32`:
|
||||
// - `Foo::put(1); Foo::get()` returns `1`;
|
||||
// - `Foo::kill(); Foo::get()` panics.
|
||||
// - `Foo: default u32`:
|
||||
// - `Foo::put(1); Foo::get()` returns `1`;
|
||||
// - `Foo::kill(); Foo::get()` returns `0` (u32::default()).
|
||||
// e.g. Foo: u32;
|
||||
// e.g. pub Bar get(bar): default map [ T::AccountId => Vec<(T::Balance, u64)> ];
|
||||
//
|
||||
// For basic value items, you'll get a type which implements
|
||||
// `runtime_support::StorageValue`. For map items, you'll get a type which
|
||||
// implements `runtime_support::StorageMap`.
|
||||
//
|
||||
// If they have a getter (`get(getter_name)`), then your module will come
|
||||
// equiped with `fn getter_name() -> Type` for basic value items or
|
||||
// `fn getter_name(key: KeyType) -> ValueType` for map items.
|
||||
Dummy get(dummy): T::Balance;
|
||||
}
|
||||
}
|
||||
|
||||
// The main implementation block for the module. Functions here fall into three broad
|
||||
// categories:
|
||||
// - Implementations of dispatch functions. The dispatch code generated by the module macro
|
||||
// expects each of its functions to be implemented.
|
||||
// - Public interface. These are functions that are `pub` and generally fall into inspector
|
||||
// functions that do not write to storage and operation functions that do.
|
||||
// - Private functions. These are your usual private utilities unavailable to other modules.
|
||||
impl<T: Trait> Module<T> {
|
||||
/// Deposit one of this module's events.
|
||||
// TODO: move into `decl_module` macro.
|
||||
fn deposit_event(event: Event<T>) {
|
||||
<system::Module<T>>::deposit_event(<T as Trait>::Event::from(event).into());
|
||||
}
|
||||
|
||||
// Implement Calls/PrivCalls and add public immutables and private mutables.
|
||||
|
||||
// Implement dispatched function `accumulate_dummy`. This just increases the value
|
||||
// of `Dummy` by `increase_by`.
|
||||
//
|
||||
// Since this is a dispatched function there are two extremely important things to
|
||||
// remember:
|
||||
//
|
||||
// - MUST NOT PANIC: Under no circumstances (save, perhaps, storage getting into an
|
||||
// irreparably damaged state) must this function panic.
|
||||
// - NO SIDE-EFFECTS ON ERROR: This function must either complete totally (and return
|
||||
// `Ok(())` or it must have no side-effects on storage and return `Err('Some reason')`.
|
||||
//
|
||||
// The first is relatively easy to audit for - just ensure all panickers are removed from
|
||||
// logic that executes in production (which you do anyway, right?!). To ensure the second
|
||||
// is followed, you should do all tests for validity at the top of your function. This
|
||||
// is stuff like checking the sender (`aux`) or that state is such that the operation
|
||||
// makes sense.
|
||||
//
|
||||
// Once you've determined that it's all good, then enact the operation and change storage.
|
||||
// If you can't be certain that the operation will succeed without substantial computation
|
||||
// then you have a classic blockchain attack scenario. The normal way of managing this is
|
||||
// to attach a bond to the operation. As the first major alteration of storage, reserve
|
||||
// some value from the sender's account (`Balances` module has a `reserve` function for
|
||||
// exactly this scenario). This amount should be enough to cover any costs of the
|
||||
// substantial execution in case it turns out that you can't proceed with the operation.
|
||||
//
|
||||
// If it eventually transpires that the operation is fine and, therefore, that the
|
||||
// expense of the checks should be borne by the network, then you can refund the reserved
|
||||
// deposit. If, however, the operation turns out to be invalid and the computation is
|
||||
// wasted, then you can burn it or repatriate elsewhere.
|
||||
//
|
||||
// Security bonds ensure that attackers can't game it by ensuring that anyone interacting
|
||||
// with the system either progresses it or pays for the trouble of faffing around with
|
||||
// no progress.
|
||||
//
|
||||
// If you don't respect these rules, it is likely that your chain will be attackable.
|
||||
fn accumulate_dummy(_aux: &T::PublicAux, increase_by: T::Balance) -> Result {
|
||||
// Read the value of dummy from storage.
|
||||
let dummy = Self::dummy();
|
||||
// Will also work using the `::get` on the storage item type iself:
|
||||
// let dummy = <Dummy<T>>::get();
|
||||
|
||||
// Calculate the new value.
|
||||
let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by);
|
||||
|
||||
// Put the new value into storage.
|
||||
<Dummy<T>>::put(new_dummy);
|
||||
// Will also work with a reference:
|
||||
// <Dummy<T>>::put(&new_dummy);
|
||||
|
||||
// Let's deposit an event to let the outside world know this happened.
|
||||
Self::deposit_event(RawEvent::Dummy(increase_by));
|
||||
|
||||
// All good.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Implementation of a priviledged call. This doesn't have an `aux` parameter because
|
||||
// it's not (directly) from an extrinsic, but rather the system as a whole has decided
|
||||
// to execute it. Different runtimes have different reasons for allow priviledged
|
||||
// calls to be executed - we don't need to care why. Because it's priviledged, we can
|
||||
// assume it's a one-off operation and substantial processing/storage/memory can be used
|
||||
// without worrying about gameability or attack scenarios.
|
||||
fn set_dummy(new_value: T::Balance) -> Result {
|
||||
// Put the new value into storage.
|
||||
<Dummy<T>>::put(new_value);
|
||||
|
||||
// All good.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// This trait expresses what should happen when the block is finalised.
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(_: T::BlockNumber) {
|
||||
// Anything that needs to be done at the end of the block.
|
||||
// We just kill our dummy storage item.
|
||||
<Dummy<T>>::kill();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
/// The genesis block configuration type. This is a simple default-capable struct that
|
||||
/// contains any fields with which this module can be configured at genesis time.
|
||||
pub struct GenesisConfig<T: Trait> {
|
||||
/// A value with which to initialise the Dummy storage item.
|
||||
pub dummy: T::Balance,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: Trait> Default for GenesisConfig<T> {
|
||||
fn default() -> Self {
|
||||
GenesisConfig {
|
||||
dummy: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This expresses the specific key/value pairs that must be placed in storage in order
|
||||
// to initialise the module and properly reflect the configuration.
|
||||
//
|
||||
// Ideally this would re-use the `::put` logic in the storage item type for introducing
|
||||
// the values into the `StorageMap` (which is just a `HashMap<Vec<u8>, Vec<u8>>`). That
|
||||
// is not yet in place, though, so for now we do everything "manually", using `hash`,
|
||||
// `::key()` and `.to_vec()` for the key and `.encode()` for the value.
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: Trait> runtime_primitives::BuildStorage for GenesisConfig<T>
|
||||
{
|
||||
fn build_storage(self) -> ::std::result::Result<runtime_primitives::StorageMap, String> {
|
||||
use codec::Encode;
|
||||
Ok(map![
|
||||
Self::hash(<Dummy<T>>::key()).to_vec() => self.dummy.encode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use runtime_primitives::BuildStorage;
|
||||
use runtime_primitives::traits::{BlakeTwo256};
|
||||
|
||||
// The testing primitives are very useful for avoiding having to work with signatures
|
||||
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried.
|
||||
use runtime_primitives::testing::{Digest, Header};
|
||||
|
||||
// For testing the module, we construct most of a mock runtime. This means
|
||||
// first constructing a configuration type (`Test`) which `impl`s each of the
|
||||
// configuration traits of modules we want to use.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type AccountIndex = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type EnsureAccountLiquid = ();
|
||||
type Event = ();
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Event = ();
|
||||
}
|
||||
type Example = Module<Test>;
|
||||
|
||||
// This function basically just builds a genesis storage key/value store according to
|
||||
// our desired mockup.
|
||||
fn new_test_ext() -> runtime_io::TestExternalities<KeccakHasher> {
|
||||
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
// We use default for brevity, but you can configure as desired if needed.
|
||||
t.extend(balances::GenesisConfig::<Test>::default().build_storage().unwrap());
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
dummy: 42,
|
||||
}.build_storage().unwrap());
|
||||
t.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
// Check that GenesisBuilder works properly.
|
||||
assert_eq!(Example::dummy(), Some(42));
|
||||
|
||||
// Check that accumulate works when we have Some value in Dummy already.
|
||||
assert_ok!(Example::accumulate_dummy(&0, 27));
|
||||
assert_eq!(Example::dummy(), Some(69));
|
||||
|
||||
// Check that finalising the block removes Dummy from storage.
|
||||
<Example as OnFinalise<u64>>::on_finalise(1);
|
||||
assert_eq!(Example::dummy(), None);
|
||||
|
||||
// Check that accumulate works when we Dummy has None in it.
|
||||
assert_ok!(Example::accumulate_dummy(&0, 42));
|
||||
assert_eq!(Example::dummy(), Some(42));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ extern crate substrate_runtime_staking as staking;
|
||||
use rstd::prelude::*;
|
||||
use rstd::marker::PhantomData;
|
||||
use rstd::result;
|
||||
use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, Executable,
|
||||
use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise,
|
||||
MakePayment, Hash, AuxLookup};
|
||||
use codec::{Codec, Encode};
|
||||
use system::extrinsics_root;
|
||||
@@ -96,7 +96,7 @@ impl<
|
||||
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
|
||||
Lookup: AuxLookup<Source=Address, Target=System::AccountId>,
|
||||
Payment: MakePayment<System::AccountId>,
|
||||
Finalisation: Executable,
|
||||
Finalisation: OnFinalise<System::BlockNumber>,
|
||||
> Executive<System, Block, Lookup, Payment, Finalisation> where
|
||||
Block::Extrinsic: Checkable<fn(Address) -> Result<System::AccountId, &'static str>> + Codec,
|
||||
<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked: Applyable<Index=System::Index, AccountId=System::AccountId>
|
||||
@@ -135,7 +135,7 @@ impl<
|
||||
|
||||
// post-transactional book-keeping.
|
||||
<system::Module<System>>::note_finished_extrinsics();
|
||||
Finalisation::execute();
|
||||
Finalisation::on_finalise(*header.number());
|
||||
|
||||
// any final checks
|
||||
Self::final_checks(&header);
|
||||
@@ -145,7 +145,7 @@ impl<
|
||||
/// except state-root.
|
||||
pub fn finalise_block() -> System::Header {
|
||||
<system::Module<System>>::note_finished_extrinsics();
|
||||
Finalisation::execute();
|
||||
Finalisation::on_finalise(<system::Module<System>>::block_number());
|
||||
|
||||
// setup extrinsics
|
||||
<system::Module<System>>::derive_extrinsics();
|
||||
@@ -231,7 +231,7 @@ mod tests {
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{HasPublicAux, Identity, Header as HeaderT, BlakeTwo256, AuxLookup};
|
||||
use primitives::traits::{Identity, Header as HeaderT, BlakeTwo256, AuxLookup};
|
||||
use primitives::testing::{Digest, Header, Block};
|
||||
use system;
|
||||
|
||||
@@ -253,9 +253,6 @@ mod tests {
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl consensus::Trait for Test {
|
||||
const NOTE_OFFLINE_POSITION: u32 = 1;
|
||||
type SessionKey = u64;
|
||||
@@ -269,7 +266,7 @@ mod tests {
|
||||
type Event = MetaEvent;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = substrate_primitives::H256;
|
||||
@@ -285,6 +282,7 @@ mod tests {
|
||||
type Event = MetaEvent;
|
||||
}
|
||||
impl staking::Trait for Test {
|
||||
type OnRewardMinted = ();
|
||||
type Event = MetaEvent;
|
||||
}
|
||||
impl timestamp::Trait for Test {
|
||||
|
||||
@@ -118,10 +118,6 @@ impl<T: Default + PartialEq> MaybeEmpty for T {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasPublicAux {
|
||||
type PublicAux: MaybeEmpty;
|
||||
}
|
||||
|
||||
pub trait RefInto<T> {
|
||||
fn ref_into(&self) -> &T;
|
||||
}
|
||||
@@ -184,18 +180,18 @@ impl<T:
|
||||
rstd::ops::BitAnd<Self, Output = Self>
|
||||
> SimpleBitOps for T {}
|
||||
|
||||
/// Something that can be executed.
|
||||
pub trait Executable {
|
||||
fn execute();
|
||||
/// The block finalisation trait. Implementing this lets you express what should happen
|
||||
/// for your module when the block is ending.
|
||||
pub trait OnFinalise<BlockNumber> {
|
||||
/// The block is being finalised. Implement to have something happen.
|
||||
fn on_finalise(_n: BlockNumber) {}
|
||||
}
|
||||
|
||||
impl Executable for () {
|
||||
fn execute() {}
|
||||
}
|
||||
impl<A: Executable, B: Executable> Executable for (A, B) {
|
||||
fn execute() {
|
||||
A::execute();
|
||||
B::execute();
|
||||
impl<N> OnFinalise<N> for () {}
|
||||
impl<N: Copy, A: OnFinalise<N>, B: OnFinalise<N>> OnFinalise<N> for (A, B) {
|
||||
fn on_finalise(n: N) {
|
||||
A::on_finalise(n);
|
||||
B::on_finalise(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ extern crate substrate_runtime_system as system;
|
||||
extern crate substrate_runtime_timestamp as timestamp;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use primitives::traits::{Zero, One, RefInto, Executable, Convert, As};
|
||||
use primitives::traits::{Zero, One, RefInto, OnFinalise, Convert, As};
|
||||
use runtime_support::{StorageValue, StorageMap};
|
||||
use runtime_support::dispatch::Result;
|
||||
|
||||
@@ -114,10 +114,6 @@ decl_storage! {
|
||||
// Timestamp when current session started.
|
||||
pub CurrentStart get(current_start): required T::Moment;
|
||||
|
||||
// Opinions of the current validator set about the activeness of their peers.
|
||||
// Gets cleared when the validator set changes.
|
||||
pub BadValidators get(bad_validators): Vec<T::AccountId>;
|
||||
|
||||
// New session is being forced is this entry exists; in which case, the boolean value is whether
|
||||
// the new session should be considered a normal rotation (rewardable) or exceptional (slashable).
|
||||
pub ForcingNewSession get(forcing_new_session): bool;
|
||||
@@ -175,11 +171,10 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
/// Hook to be called after transaction processing.
|
||||
pub fn check_rotate_session() {
|
||||
pub fn check_rotate_session(block_number: T::BlockNumber) {
|
||||
// do this last, after the staking system has had chance to switch out the authorities for the
|
||||
// new set.
|
||||
// check block number and call next_session if necessary.
|
||||
let block_number = <system::Module<T>>::block_number();
|
||||
let is_final_block = ((block_number - Self::last_length_change()) % Self::length()).is_zero();
|
||||
let (should_end_session, apply_rewards) = <ForcingNewSession<T>>::take()
|
||||
.map_or((is_final_block, is_final_block), |apply_rewards| (true, apply_rewards));
|
||||
@@ -245,9 +240,9 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Executable for Module<T> {
|
||||
fn execute() {
|
||||
Self::check_rotate_session();
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(n: T::BlockNumber) {
|
||||
Self::check_rotate_session(n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,21 +288,18 @@ mod tests {
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
|
||||
use primitives::traits::{Identity, BlakeTwo256};
|
||||
use primitives::testing::{Digest, Header};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl consensus::Trait for Test {
|
||||
const NOTE_OFFLINE_POSITION: u32 = 1;
|
||||
type SessionKey = u64;
|
||||
type OnOfflineValidator = ();
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
@@ -362,28 +354,28 @@ mod tests {
|
||||
System::set_block_number(1);
|
||||
assert_ok!(Session::set_length(10));
|
||||
assert_eq!(Session::blocks_remaining(), 1);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(1);
|
||||
|
||||
System::set_block_number(2);
|
||||
assert_eq!(Session::blocks_remaining(), 0);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(2);
|
||||
assert_eq!(Session::length(), 10);
|
||||
|
||||
System::set_block_number(7);
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
assert_eq!(Session::blocks_remaining(), 5);
|
||||
assert_ok!(Session::force_new_session(false));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(7);
|
||||
|
||||
System::set_block_number(8);
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
assert_eq!(Session::blocks_remaining(), 9);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(8);
|
||||
|
||||
System::set_block_number(17);
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
assert_eq!(Session::blocks_remaining(), 0);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(17);
|
||||
|
||||
System::set_block_number(18);
|
||||
assert_eq!(Session::current_index(), 3);
|
||||
@@ -396,45 +388,45 @@ mod tests {
|
||||
// Block 1: Change to length 3; no visible change.
|
||||
System::set_block_number(1);
|
||||
assert_ok!(Session::set_length(3));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(1);
|
||||
assert_eq!(Session::length(), 2);
|
||||
assert_eq!(Session::current_index(), 0);
|
||||
|
||||
// Block 2: Length now changed to 3. Index incremented.
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Session::set_length(3));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(2);
|
||||
assert_eq!(Session::length(), 3);
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
|
||||
// Block 3: Length now changed to 3. Index incremented.
|
||||
System::set_block_number(3);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(3);
|
||||
assert_eq!(Session::length(), 3);
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
|
||||
// Block 4: Change to length 2; no visible change.
|
||||
System::set_block_number(4);
|
||||
assert_ok!(Session::set_length(2));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(4);
|
||||
assert_eq!(Session::length(), 3);
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
|
||||
// Block 5: Length now changed to 2. Index incremented.
|
||||
System::set_block_number(5);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(5);
|
||||
assert_eq!(Session::length(), 2);
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
|
||||
// Block 6: No change.
|
||||
System::set_block_number(6);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(6);
|
||||
assert_eq!(Session::length(), 2);
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
|
||||
// Block 7: Next index.
|
||||
System::set_block_number(7);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(7);
|
||||
assert_eq!(Session::length(), 2);
|
||||
assert_eq!(Session::current_index(), 3);
|
||||
});
|
||||
@@ -445,12 +437,12 @@ mod tests {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
// Block 1: No change
|
||||
System::set_block_number(1);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(1);
|
||||
assert_eq!(Consensus::authorities(), vec![1, 2, 3]);
|
||||
|
||||
// Block 2: Session rollover, but no change.
|
||||
System::set_block_number(2);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(2);
|
||||
assert_eq!(Consensus::authorities(), vec![1, 2, 3]);
|
||||
|
||||
// Block 3: Set new key for validator 2; no visible change.
|
||||
@@ -458,12 +450,12 @@ mod tests {
|
||||
assert_ok!(Session::set_key(&2, 5));
|
||||
assert_eq!(Consensus::authorities(), vec![1, 2, 3]);
|
||||
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(3);
|
||||
assert_eq!(Consensus::authorities(), vec![1, 2, 3]);
|
||||
|
||||
// Block 4: Session rollover, authority 2 changes.
|
||||
System::set_block_number(4);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(4);
|
||||
assert_eq!(Consensus::authorities(), vec![1, 5, 3]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ use rstd::prelude::*;
|
||||
use runtime_support::{Parameter, StorageValue, StorageMap};
|
||||
use runtime_support::dispatch::Result;
|
||||
use session::OnSessionChange;
|
||||
use primitives::traits::{Zero, One, Bounded, RefInto, Executable,
|
||||
use primitives::traits::{Zero, One, Bounded, RefInto, OnFinalise,
|
||||
As, AuxLookup};
|
||||
use balances::address::Address;
|
||||
use balances::{address::Address, OnMinted};
|
||||
|
||||
mod mock;
|
||||
|
||||
@@ -96,6 +96,9 @@ impl<B: Parameter + Codec + Default> Default for ValidatorPrefs<B> {
|
||||
}
|
||||
*/
|
||||
pub trait Trait: balances::Trait + session::Trait {
|
||||
/// Some tokens minted.
|
||||
type OnRewardMinted: OnMinted<<Self as balances::Trait>::Balance>;
|
||||
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||
}
|
||||
@@ -435,10 +438,12 @@ impl<T: Trait> Module<T> {
|
||||
if should_reward {
|
||||
// apply good session reward
|
||||
let reward = Self::this_session_reward(actual_elapsed);
|
||||
for v in <session::Module<T>>::validators().iter() {
|
||||
let validators = <session::Module<T>>::validators();
|
||||
for v in validators.iter() {
|
||||
Self::reward_validator(v, reward);
|
||||
}
|
||||
Self::deposit_event(RawEvent::Reward(reward));
|
||||
T::OnRewardMinted::on_minted(reward * <T::Balance as As<usize>>::sa(validators.len()));
|
||||
}
|
||||
|
||||
let session_index = <session::Module<T>>::current_index();
|
||||
@@ -507,8 +512,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Executable for Module<T> {
|
||||
fn execute() {
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(_n: T::BlockNumber) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{HasPublicAux, Identity};
|
||||
use primitives::traits::{Identity};
|
||||
use primitives::testing::{Digest, Header};
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use runtime_io;
|
||||
@@ -28,16 +28,13 @@ use {GenesisConfig, Module, Trait, consensus, session, system, timestamp, balanc
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl consensus::Trait for Test {
|
||||
const NOTE_OFFLINE_POSITION: u32 = 1;
|
||||
type SessionKey = u64;
|
||||
type OnOfflineValidator = ();
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = <Self as HasPublicAux>::PublicAux;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
@@ -64,6 +61,7 @@ impl timestamp::Trait for Test {
|
||||
type Moment = u64;
|
||||
}
|
||||
impl Trait for Test {
|
||||
type OnRewardMinted = ();
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
|
||||
@@ -177,19 +177,19 @@ fn rewards_should_work() {
|
||||
|
||||
System::set_block_number(3);
|
||||
Timestamp::set_timestamp(15); // on time.
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 0);
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
assert_eq!(Balances::total_balance(&10), 11);
|
||||
System::set_block_number(6);
|
||||
Timestamp::set_timestamp(31); // a little late
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 0);
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
assert_eq!(Balances::total_balance(&10), 20); // less reward
|
||||
System::set_block_number(9);
|
||||
Timestamp::set_timestamp(50); // very late
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 1);
|
||||
assert_eq!(Session::current_index(), 3);
|
||||
assert_eq!(Balances::total_balance(&10), 27); // much less reward
|
||||
@@ -207,13 +207,13 @@ fn slashing_should_work() {
|
||||
assert_eq!(Balances::total_balance(&10), 1);
|
||||
|
||||
System::set_block_number(3);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 0);
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
assert_eq!(Balances::total_balance(&10), 11);
|
||||
|
||||
System::set_block_number(6);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 0);
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
assert_eq!(Balances::total_balance(&10), 21);
|
||||
@@ -244,13 +244,13 @@ fn staking_should_work() {
|
||||
assert_ok!(Staking::stake(&1));
|
||||
assert_ok!(Staking::stake(&2));
|
||||
assert_ok!(Staking::stake(&4));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 0);
|
||||
assert_eq!(Session::validators(), vec![10, 20]);
|
||||
|
||||
// Block 2: New validator set now.
|
||||
System::set_block_number(2);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 1);
|
||||
assert_eq!(Session::validators(), vec![4, 2]);
|
||||
|
||||
@@ -259,33 +259,33 @@ fn staking_should_work() {
|
||||
assert_ok!(Staking::stake(&3));
|
||||
assert_ok!(Staking::unstake(&4, Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32));
|
||||
assert_eq!(Staking::current_era(), 1);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
|
||||
// Block 4: New era - validators change.
|
||||
System::set_block_number(4);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 2);
|
||||
assert_eq!(Session::validators(), vec![3, 2]);
|
||||
|
||||
// Block 5: Transfer stake from highest to lowest. No change yet.
|
||||
System::set_block_number(5);
|
||||
assert_ok!(Balances::transfer(&4, 1.into(), 40));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
|
||||
// Block 6: Lowest now validator.
|
||||
System::set_block_number(6);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::validators(), vec![1, 3]);
|
||||
|
||||
// Block 7: Unstake three. No change yet.
|
||||
System::set_block_number(7);
|
||||
assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::validators(), vec![1, 3]);
|
||||
|
||||
// Block 8: Back to one and two.
|
||||
System::set_block_number(8);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::validators(), vec![1, 2]);
|
||||
});
|
||||
}
|
||||
@@ -303,7 +303,7 @@ fn nominating_and_rewards_should_work() {
|
||||
assert_ok!(Staking::stake(&2));
|
||||
assert_ok!(Staking::stake(&3));
|
||||
assert_ok!(Staking::nominate(&4, 1.into()));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 1);
|
||||
assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3
|
||||
assert_eq!(Balances::total_balance(&1), 10);
|
||||
@@ -313,7 +313,7 @@ fn nominating_and_rewards_should_work() {
|
||||
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Staking::unnominate(&4, 0));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Staking::current_era(), 2);
|
||||
assert_eq!(Session::validators(), vec![3, 2]);
|
||||
assert_eq!(Balances::total_balance(&1), 12);
|
||||
@@ -325,7 +325,7 @@ fn nominating_and_rewards_should_work() {
|
||||
assert_ok!(Staking::stake(&4));
|
||||
assert_ok!(Staking::unstake(&3, Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32));
|
||||
assert_ok!(Staking::nominate(&3, 1.into()));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::validators(), vec![1, 4]);
|
||||
assert_eq!(Balances::total_balance(&1), 12);
|
||||
assert_eq!(Balances::total_balance(&2), 30);
|
||||
@@ -333,7 +333,7 @@ fn nominating_and_rewards_should_work() {
|
||||
assert_eq!(Balances::total_balance(&4), 48);
|
||||
|
||||
System::set_block_number(4);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Balances::total_balance(&1), 13);
|
||||
assert_eq!(Balances::total_balance(&2), 30);
|
||||
assert_eq!(Balances::total_balance(&3), 58);
|
||||
@@ -372,7 +372,7 @@ fn nominating_slashes_should_work() {
|
||||
assert_eq!(Session::validators(), vec![10, 20]);
|
||||
|
||||
System::set_block_number(2);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
|
||||
Timestamp::set_timestamp(15);
|
||||
System::set_block_number(4);
|
||||
@@ -380,7 +380,7 @@ fn nominating_slashes_should_work() {
|
||||
assert_ok!(Staking::stake(&3));
|
||||
assert_ok!(Staking::nominate(&2, 3.into()));
|
||||
assert_ok!(Staking::nominate(&4, 1.into()));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
|
||||
assert_eq!(Staking::current_era(), 1);
|
||||
assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2
|
||||
@@ -424,7 +424,7 @@ fn staking_eras_work() {
|
||||
|
||||
// Block 1: No change.
|
||||
System::set_block_number(1);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 1);
|
||||
assert_eq!(Staking::sessions_per_era(), 2);
|
||||
assert_eq!(Staking::last_era_length_change(), 0);
|
||||
@@ -432,7 +432,7 @@ fn staking_eras_work() {
|
||||
|
||||
// Block 2: Simple era change.
|
||||
System::set_block_number(2);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 2);
|
||||
assert_eq!(Staking::sessions_per_era(), 2);
|
||||
assert_eq!(Staking::last_era_length_change(), 0);
|
||||
@@ -441,7 +441,7 @@ fn staking_eras_work() {
|
||||
// Block 3: Schedule an era length change; no visible changes.
|
||||
System::set_block_number(3);
|
||||
assert_ok!(Staking::set_sessions_per_era(3));
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 3);
|
||||
assert_eq!(Staking::sessions_per_era(), 2);
|
||||
assert_eq!(Staking::last_era_length_change(), 0);
|
||||
@@ -449,7 +449,7 @@ fn staking_eras_work() {
|
||||
|
||||
// Block 4: Era change kicks in.
|
||||
System::set_block_number(4);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 4);
|
||||
assert_eq!(Staking::sessions_per_era(), 3);
|
||||
assert_eq!(Staking::last_era_length_change(), 4);
|
||||
@@ -457,7 +457,7 @@ fn staking_eras_work() {
|
||||
|
||||
// Block 5: No change.
|
||||
System::set_block_number(5);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 5);
|
||||
assert_eq!(Staking::sessions_per_era(), 3);
|
||||
assert_eq!(Staking::last_era_length_change(), 4);
|
||||
@@ -465,7 +465,7 @@ fn staking_eras_work() {
|
||||
|
||||
// Block 6: No change.
|
||||
System::set_block_number(6);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 6);
|
||||
assert_eq!(Staking::sessions_per_era(), 3);
|
||||
assert_eq!(Staking::last_era_length_change(), 4);
|
||||
@@ -473,7 +473,7 @@ fn staking_eras_work() {
|
||||
|
||||
// Block 7: Era increment.
|
||||
System::set_block_number(7);
|
||||
Session::check_rotate_session();
|
||||
Session::check_rotate_session(System::block_number());
|
||||
assert_eq!(Session::current_index(), 7);
|
||||
assert_eq!(Staking::sessions_per_era(), 3);
|
||||
assert_eq!(Staking::last_era_length_change(), 4);
|
||||
|
||||
@@ -40,7 +40,7 @@ extern crate substrate_codec as codec;
|
||||
|
||||
use runtime_support::{StorageValue, Parameter};
|
||||
use runtime_support::dispatch::Result;
|
||||
use runtime_primitives::traits::{Executable, MaybeEmpty, SimpleArithmetic, As, Zero};
|
||||
use runtime_primitives::traits::{OnFinalise, MaybeEmpty, SimpleArithmetic, As, Zero};
|
||||
|
||||
pub trait Trait: consensus::Trait where
|
||||
<Self as system::Trait>::PublicAux: MaybeEmpty
|
||||
@@ -101,8 +101,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Executable for Module<T> {
|
||||
fn execute() {
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(_n: T::BlockNumber) {
|
||||
assert!(<Self as Store>::DidUpdate::take(), "Timestamp must be updated once in the block");
|
||||
}
|
||||
}
|
||||
@@ -143,16 +143,13 @@ mod tests {
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::H256;
|
||||
use runtime_primitives::BuildStorage;
|
||||
use runtime_primitives::traits::{HasPublicAux, BlakeTwo256};
|
||||
use runtime_primitives::traits::{BlakeTwo256};
|
||||
use runtime_primitives::testing::{Digest, Header};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
impl HasPublicAux for Test {
|
||||
type PublicAux = u64;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = u64;
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "substrate-runtime-treasury"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
|
||||
substrate-runtime-io = { path = "../../runtime-io", default_features = false }
|
||||
substrate-runtime-support = { path = "../../runtime-support", default_features = false }
|
||||
substrate-runtime-primitives = { path = "../primitives", default_features = false }
|
||||
substrate-codec = { path = "../../codec", default_features = false }
|
||||
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
substrate-primitives = { path = "../../primitives", default_features = false }
|
||||
substrate-runtime-system = { path = "../system", default_features = false }
|
||||
substrate-runtime-balances = { path = "../balances", default_features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"substrate-runtime-std/std",
|
||||
"substrate-runtime-io/std",
|
||||
"substrate-runtime-support/std",
|
||||
"substrate-runtime-primitives/std",
|
||||
"substrate-runtime-balances/std",
|
||||
"serde/std",
|
||||
"serde_derive",
|
||||
"substrate-codec/std",
|
||||
"substrate-codec-derive/std",
|
||||
"substrate-primitives/std",
|
||||
"substrate-runtime-system/std",
|
||||
]
|
||||
@@ -0,0 +1,558 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! The Treasury: Keeps account of the taxed cash and handles its deployment.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg_attr(any(feature = "std", test), macro_use)]
|
||||
extern crate substrate_runtime_std as rstd;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_codec_derive;
|
||||
|
||||
extern crate substrate_codec as codec;
|
||||
#[cfg(test)]
|
||||
extern crate substrate_primitives;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate substrate_runtime_system as system;
|
||||
extern crate substrate_runtime_balances as balances;
|
||||
|
||||
use rstd::ops::{Mul, Div};
|
||||
use runtime_support::{StorageValue, StorageMap};
|
||||
use runtime_support::dispatch::Result;
|
||||
use runtime_primitives::traits::{As, OnFinalise, Zero, RefInto};
|
||||
use balances::OnMinted;
|
||||
|
||||
/// Our module's configuration trait. All our types and consts go in here. If the
|
||||
/// module is dependent on specific other modules, then their configuration traits
|
||||
/// should be added to our implied traits list.
|
||||
///
|
||||
/// `system::Trait` should always be included in our implied traits.
|
||||
pub trait Trait: balances::Trait {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||
}
|
||||
|
||||
type ProposalIndex = u32;
|
||||
|
||||
// The module declaration. This states the entry points that we handle. The
|
||||
// macro takes care of the marshalling of arguments and dispatch.
|
||||
decl_module! {
|
||||
// Simple declaration of the `Module` type. Lets the macro know what its working on.
|
||||
pub struct Module<T: Trait>;
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum Call where aux: T::PublicAux {
|
||||
// Put forward a suggestion for spending. A deposit proportional to the value
|
||||
// is reserved and slashed if the proposal is rejected. It is returned once the
|
||||
// proposal is awarded.
|
||||
fn propose_spend(aux, value: T::Balance, beneficiary: T::AccountId) -> Result = 0;
|
||||
}
|
||||
|
||||
// The priviledged entry points. These are provided to allow any governance modules in
|
||||
// the runtime to be able to execute common functions. Unlike for `Call` there is no
|
||||
// auxilliary data to encode the sender (since there is no sender). Though still important
|
||||
// to ensure that these execute in reasonable time and space, they can do what would
|
||||
// otherwise be costly or unsafe operations.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
// Set the balance of funds available to spend.
|
||||
fn set_pot(new_pot: T::Balance) -> Result = 0;
|
||||
|
||||
// (Re-)configure this module.
|
||||
fn configure(proposal_bond: Permill, proposal_bond_minimum: T::Balance, spend_period: T::BlockNumber, burn: Permill) -> Result = 1;
|
||||
|
||||
// Reject a proposed spend. The original deposit will be slashed.
|
||||
fn reject_proposal(proposal_id: ProposalIndex) -> Result = 2;
|
||||
|
||||
// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary
|
||||
// and the original deposit will be returned.
|
||||
fn approve_proposal(proposal_id: ProposalIndex) -> Result = 3;
|
||||
}
|
||||
}
|
||||
|
||||
/// A spending proposal.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
|
||||
pub struct Proposal<AccountId, Balance> {
|
||||
proposer: AccountId,
|
||||
value: Balance,
|
||||
beneficiary: AccountId,
|
||||
bond: Balance,
|
||||
}
|
||||
|
||||
/// Permill is parts-per-million (i.e. after multiplying by this, divide by `PERMILL`).
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Permill(u32);
|
||||
|
||||
// TODO: impl Mul<Permill> for N where N: As<usize>
|
||||
impl Permill {
|
||||
fn times<N: As<usize> + Mul<N, Output=N> + Div<N, Output=N>>(self, b: N) -> N {
|
||||
// TODO: handle overflows
|
||||
b * <N as As<usize>>::sa(self.0 as usize) / <N as As<usize>>::sa(1000000)
|
||||
}
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Treasury {
|
||||
// Config...
|
||||
|
||||
// Proportion of funds that should be bonded in order to place a proposal. An accepted
|
||||
// proposal gets these back. A rejected proposal doesn't.
|
||||
ProposalBond get(proposal_bond): required Permill;
|
||||
|
||||
// Minimum amount of funds that should be placed ina deposit for making a proposal.
|
||||
ProposalBondMinimum get(proposal_bond_minimum): required T::Balance;
|
||||
|
||||
// Period between successive spends.
|
||||
SpendPeriod get(spend_period): required T::BlockNumber;
|
||||
|
||||
// Percentage of spare funds (if any) that are burnt per spend period.
|
||||
Burn get(burn): required Permill;
|
||||
|
||||
// State...
|
||||
|
||||
// Total funds available to this module for spending.
|
||||
Pot get(pot): default T::Balance;
|
||||
|
||||
// Number of proposals that have been made.
|
||||
ProposalCount get(proposal_count): default ProposalIndex;
|
||||
|
||||
// Proposals that have been made.
|
||||
Proposals get(proposals): map [ ProposalIndex => Proposal<T::AccountId, T::Balance> ];
|
||||
|
||||
// Proposal indices that have been approved but not yet awarded.
|
||||
Approvals get(approvals): default Vec<ProposalIndex>;
|
||||
}
|
||||
}
|
||||
|
||||
/// Exported Event type that's generic over the configuration trait.
|
||||
pub type Event<T> = RawEvent<
|
||||
<T as balances::Trait>::Balance,
|
||||
<T as system::Trait>::AccountId,
|
||||
>;
|
||||
|
||||
/// An event in this module.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawEvent<Balance, AccountId> {
|
||||
/// New proposal.
|
||||
Proposed(ProposalIndex),
|
||||
/// We have ended a spend period and will now allocate funds.
|
||||
Spending(Balance),
|
||||
/// Some funds have been allocated.
|
||||
Awarded(ProposalIndex, Balance, AccountId),
|
||||
/// Some of our funds have been burnt.
|
||||
Burnt(Balance),
|
||||
/// Spending has finished; this is the amount that rolls over until next spend.
|
||||
Rollover(Balance),
|
||||
}
|
||||
|
||||
impl<B, A> From<RawEvent<B, A>> for () {
|
||||
fn from(_: RawEvent<B, A>) -> () { () }
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
/// Deposit one of this module's events.
|
||||
fn deposit_event(event: Event<T>) {
|
||||
<system::Module<T>>::deposit_event(<T as Trait>::Event::from(event).into());
|
||||
}
|
||||
|
||||
// Implement Calls/PrivCalls and add public immutables and private mutables.
|
||||
|
||||
fn propose_spend(aux: &T::PublicAux, value: T::Balance, beneficiary: T::AccountId) -> Result {
|
||||
let proposer = aux.ref_into();
|
||||
|
||||
let bond = Self::calculate_bond(value);
|
||||
<balances::Module<T>>::reserve(proposer, bond)
|
||||
.map_err(|_| "Proposer's balance too low")?;
|
||||
|
||||
let c = Self::proposal_count();
|
||||
<ProposalCount<T>>::put(c + 1);
|
||||
<Proposals<T>>::insert(c, Proposal { proposer: proposer.clone(), value, beneficiary, bond });
|
||||
|
||||
Self::deposit_event(RawEvent::Proposed(c));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reject_proposal(proposal_id: ProposalIndex) -> Result {
|
||||
let proposal = <Proposals<T>>::take(proposal_id).ok_or("No proposal at that index")?;
|
||||
|
||||
let value = proposal.bond;
|
||||
let _ = <balances::Module<T>>::slash_reserved(&proposal.proposer, value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn approve_proposal(proposal_id: ProposalIndex) -> Result {
|
||||
ensure!(<Proposals<T>>::exists(proposal_id), "No proposal at that index");
|
||||
|
||||
{
|
||||
let mut v = <Approvals<T>>::get();
|
||||
v.push(proposal_id);
|
||||
<Approvals<T>>::put(v);
|
||||
}
|
||||
//TODO gav: make work:
|
||||
//<Approvals<T>>::mutate(|a| a.push(proposal_id));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_pot(new_pot: T::Balance) -> Result {
|
||||
// Put the new value into storage.
|
||||
<Pot<T>>::put(new_pot);
|
||||
|
||||
// All good.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn configure(
|
||||
proposal_bond: Permill,
|
||||
proposal_bond_minimum: T::Balance,
|
||||
spend_period: T::BlockNumber,
|
||||
burn: Permill
|
||||
) -> Result {
|
||||
<ProposalBond<T>>::put(proposal_bond);
|
||||
<ProposalBondMinimum<T>>::put(proposal_bond_minimum);
|
||||
<SpendPeriod<T>>::put(spend_period);
|
||||
<Burn<T>>::put(burn);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The needed bond for a proposal whose spend is `value`.
|
||||
fn calculate_bond(value: T::Balance) -> T::Balance {
|
||||
Self::proposal_bond_minimum().max(Self::proposal_bond().times(value))
|
||||
}
|
||||
|
||||
// Spend some money!
|
||||
fn spend_funds() {
|
||||
let mut budget_remaining = Self::pot();
|
||||
Self::deposit_event(RawEvent::Spending(budget_remaining));
|
||||
|
||||
let mut missed_any = false;
|
||||
let remaining_approvals: Vec<_> = <Approvals<T>>::get().into_iter().filter(|&index| {
|
||||
// Should always be true, but shouldn't panic if false or we're screwed.
|
||||
if let Some(p) = Self::proposals(index) {
|
||||
if p.value <= budget_remaining {
|
||||
budget_remaining -= p.value;
|
||||
<Proposals<T>>::remove(index);
|
||||
|
||||
// return their deposit.
|
||||
let _ = <balances::Module<T>>::unreserve(&p.proposer, p.bond);
|
||||
|
||||
// provide the allocation.
|
||||
<balances::Module<T>>::increase_free_balance_creating(&p.beneficiary, p.value);
|
||||
|
||||
Self::deposit_event(RawEvent::Awarded(index, p.value, p.beneficiary));
|
||||
false
|
||||
} else {
|
||||
missed_any = true;
|
||||
true
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}).collect();
|
||||
<Approvals<T>>::put(remaining_approvals);
|
||||
|
||||
if !missed_any {
|
||||
// burn some proportion of the remaining budget if we run a surplus.
|
||||
let burn = Self::burn().times(budget_remaining);
|
||||
budget_remaining -= burn;
|
||||
Self::deposit_event(RawEvent::Burnt(burn))
|
||||
}
|
||||
|
||||
Self::deposit_event(RawEvent::Rollover(budget_remaining));
|
||||
|
||||
<Pot<T>>::put(budget_remaining);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnMinted<T::Balance> for Module<T> {
|
||||
fn on_minted(b: T::Balance) {
|
||||
<Pot<T>>::put(Self::pot() + b);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
|
||||
fn on_finalise(n: T::BlockNumber) {
|
||||
// Check to see if we should spend some funds!
|
||||
if (n % Self::spend_period()).is_zero() {
|
||||
Self::spend_funds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
/// The genesis block configuration type. This is a simple default-capable struct that
|
||||
/// contains any fields with which this module can be configured at genesis time.
|
||||
pub struct GenesisConfig<T: Trait> {
|
||||
pub proposal_bond: Permill,
|
||||
pub proposal_bond_minimum: T::Balance,
|
||||
pub spend_period: T::BlockNumber,
|
||||
pub burn: Permill,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl<T: Trait> Default for GenesisConfig<T> {
|
||||
fn default() -> Self {
|
||||
GenesisConfig {
|
||||
proposal_bond: Default::default(),
|
||||
proposal_bond_minimum: Default::default(),
|
||||
spend_period: Default::default(),
|
||||
burn: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl<T: Trait> runtime_primitives::BuildStorage for GenesisConfig<T>
|
||||
{
|
||||
fn build_storage(self) -> ::std::result::Result<runtime_primitives::StorageMap, String> {
|
||||
use codec::Encode;
|
||||
Ok(map![
|
||||
Self::hash(<ProposalBond<T>>::key()).to_vec() => self.proposal_bond.encode(),
|
||||
Self::hash(<ProposalBondMinimum<T>>::key()).to_vec() => self.proposal_bond_minimum.encode(),
|
||||
Self::hash(<SpendPeriod<T>>::key()).to_vec() => self.spend_period.encode(),
|
||||
Self::hash(<Burn<T>>::key()).to_vec() => self.burn.encode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::{H256, KeccakHasher};
|
||||
use runtime_primitives::BuildStorage;
|
||||
use runtime_primitives::traits::{BlakeTwo256};
|
||||
use runtime_primitives::testing::{Digest, Header};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
impl system::Trait for Test {
|
||||
type PublicAux = Self::AccountId;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type AccountIndex = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type EnsureAccountLiquid = ();
|
||||
type Event = ();
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Event = ();
|
||||
}
|
||||
type Balances = balances::Module<Test>;
|
||||
type Treasury = Module<Test>;
|
||||
|
||||
fn new_test_ext() -> runtime_io::TestExternalities<KeccakHasher> {
|
||||
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
t.extend(balances::GenesisConfig::<Test>{
|
||||
balances: vec![(0, 100), (1, 10), (2, 1)],
|
||||
transaction_base_fee: 0,
|
||||
transaction_byte_fee: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
existential_deposit: 0,
|
||||
reclaim_rebate: 0,
|
||||
}.build_storage().unwrap());
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
proposal_bond: Permill(50_000), // 5%
|
||||
proposal_bond_minimum: 1,
|
||||
spend_period: 2,
|
||||
burn: Permill(500_000), // 50%
|
||||
}.build_storage().unwrap());
|
||||
t.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn genesis_config_works() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_eq!(Treasury::proposal_bond(), Permill(50_000));
|
||||
assert_eq!(Treasury::proposal_bond_minimum(), 1);
|
||||
assert_eq!(Treasury::spend_period(), 2);
|
||||
assert_eq!(Treasury::burn(), Permill(500_000));
|
||||
assert_eq!(Treasury::pot(), 0);
|
||||
assert_eq!(Treasury::proposal_count(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minting_works() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
// Check that accumulate works when we have Some value in Dummy already.
|
||||
Treasury::on_minted(100);
|
||||
assert_eq!(Treasury::pot(), 100);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spend_proposal_takes_min_deposit() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_ok!(Treasury::propose_spend(&0, 1, 3));
|
||||
assert_eq!(Balances::free_balance(&0), 99);
|
||||
assert_eq!(Balances::reserved_balance(&0), 1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spend_proposal_takes_proportional_deposit() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_ok!(Treasury::propose_spend(&0, 100, 3));
|
||||
assert_eq!(Balances::free_balance(&0), 95);
|
||||
assert_eq!(Balances::reserved_balance(&0), 5);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spend_proposal_fails_when_proposer_poor() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_noop!(Treasury::propose_spend(&2, 100, 3), "Proposer's balance too low");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepted_spend_proposal_ignored_outside_spend_period() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
assert_ok!(Treasury::propose_spend(&0, 100, 3));
|
||||
assert_ok!(Treasury::approve_proposal(0));
|
||||
|
||||
<Treasury as OnFinalise<u64>>::on_finalise(1);
|
||||
assert_eq!(Balances::free_balance(&3), 0);
|
||||
assert_eq!(Treasury::pot(), 100);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unused_pot_should_diminish() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
<Treasury as OnFinalise<u64>>::on_finalise(2);
|
||||
assert_eq!(Treasury::pot(), 50);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejected_spend_proposal_ignored_on_spend_period() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
assert_ok!(Treasury::propose_spend(&0, 100, 3));
|
||||
assert_ok!(Treasury::reject_proposal(0));
|
||||
|
||||
<Treasury as OnFinalise<u64>>::on_finalise(2);
|
||||
assert_eq!(Balances::free_balance(&3), 0);
|
||||
assert_eq!(Treasury::pot(), 50);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reject_already_rejected_spend_proposal_fails() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
assert_ok!(Treasury::propose_spend(&0, 100, 3));
|
||||
assert_ok!(Treasury::reject_proposal(0));
|
||||
assert_noop!(Treasury::reject_proposal(0), "No proposal at that index");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reject_non_existant_spend_proposal_fails() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_noop!(Treasury::reject_proposal(0), "No proposal at that index");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accept_non_existant_spend_proposal_fails() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_noop!(Treasury::approve_proposal(0), "No proposal at that index");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accept_already_rejected_spend_proposal_fails() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
assert_ok!(Treasury::propose_spend(&0, 100, 3));
|
||||
assert_ok!(Treasury::reject_proposal(0));
|
||||
assert_noop!(Treasury::approve_proposal(0), "No proposal at that index");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepted_spend_proposal_enacted_on_spend_period() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
assert_ok!(Treasury::propose_spend(&0, 100, 3));
|
||||
assert_ok!(Treasury::approve_proposal(0));
|
||||
|
||||
<Treasury as OnFinalise<u64>>::on_finalise(2);
|
||||
assert_eq!(Balances::free_balance(&3), 100);
|
||||
assert_eq!(Treasury::pot(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pot_underflow_should_not_diminish() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
Treasury::on_minted(100);
|
||||
|
||||
assert_ok!(Treasury::propose_spend(&0, 150, 3));
|
||||
assert_ok!(Treasury::approve_proposal(0));
|
||||
|
||||
<Treasury as OnFinalise<u64>>::on_finalise(2);
|
||||
assert_eq!(Treasury::pot(), 100);
|
||||
|
||||
Treasury::on_minted(100);
|
||||
<Treasury as OnFinalise<u64>>::on_finalise(4);
|
||||
assert_eq!(Balances::free_balance(&3), 150);
|
||||
assert_eq!(Treasury::pot(), 25);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user