mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 08:51:09 +00:00
New sessions, kill consensus module (#2802)
* Draft of new sessions * Reintroduce tuple impls * Move staking module to new session API * More work on staking and grandpa. * Use iterator to avoid cloning and tuple macro * Make runtime build again * Polish the OpaqueKeys devex * Move consensus logic into system & aura. * Fix up system module * Get build mostly going. Stuck at service.rs * Building again * Update srml/staking/src/lib.rs Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> * Refactoring out Consensus module, AuthorityIdOf, &c. * Refactored out DigestItem::AuthoritiesChanged. Building. * Remove tentative code * Remove invalid comment * Make Seal opaque and introduce nice methods for handling opaque items. * Start to use proper digest for Aura authorities tracking. * Fix up grandpa, remove system::Raw/Log * Refactor Grandpa to use new logging infrastructure. Also make authorityid/sessionkey static. Switch over to storing authorities in a straight Vec. * Building again * Tidy up some AuthorityIds * Expunge most of the rest of the AuthorityKey confusion. Also, de-generify Babe and re-generify Aura. * Remove cruft * Untangle last of the `AuthorityId`s. * Sort out finality_tracker * Refactor median getting * Apply suggestions from code review Co-Authored-By: Robert Habermeier <rphmeier@gmail.com> * Session tests works * Update core/sr-primitives/src/generic/digest.rs Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> * Session tests works * Fix for staking from @dvc94ch * log an error * fix test runtime build * Some test fixes * Staking mock update to new session api. * Fix build. * Move OpaqueKeys to primitives. * Use on_initialize instead of check_rotate_session. * Update tests to new staking api. * fixup mock * Fix bond_extra_and_withdraw_unbonded_works. * Fix bond_with_little_staked_value_bounded_by_slot_stake. * Fix bond_with_no_staked_value. * Fix change_controller_works. * Fix less_than_needed_candidates_works. * Fix multi_era_reward_should_work. * Fix nominating_and_rewards_should_work. * Fix nominators_also_get_slashed. * Fix phragmen_large_scale_test. * Fix phragmen_poc_works. * Fix phragmen_score_should_be_accurate_on_large_stakes. * Fix phragmen_should_not_overflow. * Fix reward_destination_works. * Fix rewards_should_work. * Fix sessions_and_eras_should_work. * Fix slot_stake_is_least_staked_validator. * Fix too_many_unbond_calls_should_not_work. * Fix wrong_vote_is_null. * Fix runtime. * Fix wasm runtime build. * Update Cargo.lock * Fix warnings. * Fix grandpa tests. * Fix test-runtime build. * Fix template node build. * Fix stuff. * Update Cargo.lock to fix CI * Re-add missing AuRa logs Runtimes are required to know about every digest they receive ― they panic otherwise. This re-adds support for AuRa pre-runtime digests. * Update core/consensus/babe/src/digest.rs Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> * Kill log trait and all that jazz. * Refactor staking tests. * Fix ci runtime wasm check. * Line length 120. * Make tests build again * Remove trailing commas in function declarations The `extern_functions!` macro doesn’t like them, perhaps due to a bug in rustc. * Fix type error * Fix compilation errors * Fix a test * Another couple of fixes * Fix another test * More test fixes * Another test fix * Bump runtime. * Wrap long line * Fix build, remove redundant code. * Issue to track TODO * Leave the benchmark code alone. * Fix missing `std::time::{Instant, Duration}` * Indentation * Aura ConsensusLog as enum
This commit is contained in:
@@ -109,7 +109,7 @@ cargo-check-subkey:
|
||||
- cd ./subkey
|
||||
- time cargo check --release # makes sense to save artifacts for building it
|
||||
- sccache -s
|
||||
|
||||
|
||||
|
||||
test-linux-stable: &test-linux
|
||||
stage: test
|
||||
@@ -135,7 +135,7 @@ test-linux-stable-int:
|
||||
- $DEPLOY_TAG
|
||||
script:
|
||||
- ./scripts/build.sh --locked
|
||||
- time RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace
|
||||
- time RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace
|
||||
cargo test -p node-cli --release --verbose --locked -- --ignored --test-threads=1
|
||||
- sccache -s
|
||||
allow_failure: true
|
||||
|
||||
Generated
+7
-44
@@ -2152,6 +2152,7 @@ dependencies = [
|
||||
"substrate-cli 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-common 2.0.0",
|
||||
"substrate-finality-grandpa 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
@@ -2177,7 +2178,6 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-contract 2.0.0",
|
||||
"srml-grandpa 2.0.0",
|
||||
"srml-indices 2.0.0",
|
||||
@@ -2238,7 +2238,6 @@ dependencies = [
|
||||
"sr-version 2.0.0",
|
||||
"srml-aura 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-contract 2.0.0",
|
||||
"srml-council 2.0.0",
|
||||
"srml-democracy 2.0.0",
|
||||
@@ -2255,7 +2254,6 @@ dependencies = [
|
||||
"srml-treasury 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-keyring 2.0.0",
|
||||
"substrate-offchain-primitives 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
@@ -2302,7 +2300,6 @@ dependencies = [
|
||||
"sr-version 2.0.0",
|
||||
"srml-aura 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-executive 2.0.0",
|
||||
"srml-indices 2.0.0",
|
||||
"srml-sudo 2.0.0",
|
||||
@@ -2311,7 +2308,6 @@ dependencies = [
|
||||
"srml-timestamp 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-offchain-primitives 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
@@ -3444,12 +3440,12 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-staking 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
@@ -3466,9 +3462,7 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-staking 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
@@ -3493,21 +3487,6 @@ dependencies = [
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srml-consensus"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srml-contract"
|
||||
version = "2.0.0"
|
||||
@@ -3524,7 +3503,6 @@ dependencies = [
|
||||
"sr-sandbox 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
@@ -3624,7 +3602,6 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-finality-tracker 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
@@ -3671,7 +3648,6 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
@@ -3690,7 +3666,6 @@ dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
@@ -4052,11 +4027,9 @@ dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-aura 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-consensus-common 2.0.0",
|
||||
"substrate-consensus-slots 2.0.0",
|
||||
"substrate-executor 2.0.0",
|
||||
@@ -4074,21 +4047,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "substrate-consensus-aura-primitives"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-consensus-authorities"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
@@ -4110,10 +4072,8 @@ dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-babe 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-consensus-babe-primitives 2.0.0",
|
||||
"substrate-consensus-common 2.0.0",
|
||||
"substrate-consensus-slots 2.0.0",
|
||||
@@ -4135,8 +4095,10 @@ version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-slots 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4173,7 +4135,6 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
@@ -4259,6 +4220,7 @@ name = "substrate-finality-grandpa-primitives"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
@@ -4331,6 +4293,8 @@ dependencies = [
|
||||
"substrate-keyring 2.0.0",
|
||||
"substrate-peerset 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
"substrate-test-client 2.0.0",
|
||||
"substrate-test-runtime 2.0.0",
|
||||
"substrate-test-runtime-client 2.0.0",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -4610,7 +4574,6 @@ dependencies = [
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-consensus-babe-primitives 2.0.0",
|
||||
"substrate-executor 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
|
||||
@@ -64,7 +64,6 @@ members = [
|
||||
"srml/assets",
|
||||
"srml/aura",
|
||||
"srml/balances",
|
||||
"srml/consensus",
|
||||
"srml/contract",
|
||||
"srml/council",
|
||||
"srml/democracy",
|
||||
|
||||
@@ -31,7 +31,7 @@ use consensus_common::{self, evaluation};
|
||||
use primitives::{H256, Blake2Hasher, ExecutionContext};
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi,
|
||||
AuthorityIdFor, DigestFor,
|
||||
DigestFor,
|
||||
};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::ApplyError;
|
||||
@@ -134,7 +134,6 @@ impl<C, A> consensus_common::Environment<<C as AuthoringApi>::Block> for Propose
|
||||
fn init(
|
||||
&self,
|
||||
parent_header: &<<C as AuthoringApi>::Block as BlockT>::Header,
|
||||
_: &[AuthorityIdFor<<C as AuthoringApi>::Block>],
|
||||
) -> Result<Self::Proposer, error::Error> {
|
||||
let parent_hash = parent_header.hash();
|
||||
|
||||
@@ -320,7 +319,6 @@ mod tests {
|
||||
|
||||
let mut proposer = proposer_factory.init(
|
||||
&client.header(&BlockId::number(0)).unwrap().unwrap(),
|
||||
&[]
|
||||
).unwrap();
|
||||
|
||||
// when
|
||||
|
||||
@@ -46,12 +46,13 @@ use trie::{MemoryDB, PrefixedMemoryDB, prefixed_key};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash};
|
||||
use primitives::storage::well_known_keys;
|
||||
use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay};
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, Digest, DigestItem,
|
||||
SaturatedConversion
|
||||
use runtime_primitives::{
|
||||
generic::{BlockId, DigestItem}, Justification, StorageOverlay, ChildrenStorageOverlay,
|
||||
BuildStorage
|
||||
};
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion
|
||||
};
|
||||
use runtime_primitives::BuildStorage;
|
||||
use state_machine::backend::Backend as StateBackend;
|
||||
use executor::RuntimeInfo;
|
||||
use state_machine::{CodeExecutor, DBValue};
|
||||
@@ -428,7 +429,11 @@ where Block: BlockT<Hash=H256>,
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> Result<H256, client::error::Error> {
|
||||
fn reset_storage(
|
||||
&mut self,
|
||||
top: StorageOverlay,
|
||||
children: ChildrenStorageOverlay
|
||||
) -> Result<H256, client::error::Error> {
|
||||
|
||||
if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
|
||||
return Err(client::error::Error::GenesisInvalid.into());
|
||||
@@ -542,7 +547,13 @@ impl<Block: BlockT<Hash=H256>> DbChangesTrieStorage<Block> {
|
||||
}
|
||||
|
||||
/// Prune obsolete changes tries.
|
||||
pub fn prune(&self, config: &ChangesTrieConfiguration, tx: &mut DBTransaction, block_hash: Block::Hash, block_num: NumberFor<Block>) {
|
||||
pub fn prune(
|
||||
&self,
|
||||
config: &ChangesTrieConfiguration,
|
||||
tx: &mut DBTransaction,
|
||||
block_hash: Block::Hash,
|
||||
block_num: NumberFor<Block>,
|
||||
) {
|
||||
// never prune on archive nodes
|
||||
let min_blocks_to_keep = match self.min_blocks_to_keep {
|
||||
Some(min_blocks_to_keep) => min_blocks_to_keep,
|
||||
@@ -1429,7 +1440,6 @@ mod tests {
|
||||
changes: Vec<(Vec<u8>, Vec<u8>)>,
|
||||
extrinsics_root: H256,
|
||||
) -> H256 {
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use runtime_primitives::testing::Digest;
|
||||
|
||||
let (changes_root, changes_trie_update) = prepare_changes(changes);
|
||||
|
||||
@@ -31,11 +31,8 @@ use client::error::{Error as ClientError, Result as ClientResult};
|
||||
use client::light::blockchain::Storage as LightBlockchainStorage;
|
||||
use parity_codec::{Decode, Encode};
|
||||
use primitives::Blake2Hasher;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Header as HeaderT,
|
||||
Zero, One, NumberFor, Digest, DigestItem,
|
||||
};
|
||||
use runtime_primitives::generic::{DigestItem, BlockId};
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor};
|
||||
use consensus_common::well_known_cache_keys;
|
||||
use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType};
|
||||
use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta};
|
||||
@@ -574,11 +571,10 @@ pub(crate) mod tests {
|
||||
use client::cht;
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use runtime_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper};
|
||||
use runtime_primitives::traits::AuthorityIdFor;
|
||||
use super::*;
|
||||
|
||||
type Block = RawBlock<ExtrinsicWrapper<u32>>;
|
||||
type AuthorityId = AuthorityIdFor<Block>;
|
||||
type AuthorityId = primitives::ed25519::Public;
|
||||
|
||||
pub fn default_header(parent: &Hash, number: u64) -> Header {
|
||||
Header {
|
||||
@@ -871,7 +867,7 @@ pub(crate) mod tests {
|
||||
fn authorities_are_cached() {
|
||||
let db = LightStorage::new_test();
|
||||
|
||||
fn run_checks(db: &LightStorage<Block>, max: u64, checks: &[(u64, Option<Vec<AuthorityIdFor<Block>>>)]) {
|
||||
fn run_checks(db: &LightStorage<Block>, max: u64, checks: &[(u64, Option<Vec<AuthorityId>>)]) {
|
||||
for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) {
|
||||
let actual = get_authorities(db.cache(), BlockId::Number(*at));
|
||||
assert_eq!(*expected, actual);
|
||||
|
||||
@@ -36,9 +36,10 @@ use consensus::{
|
||||
};
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Header as HeaderT, Zero, NumberFor, CurrentHeight,
|
||||
BlockNumberToHash, ApiRef, ProvideRuntimeApi, Digest, DigestItem,
|
||||
BlockNumberToHash, ApiRef, ProvideRuntimeApi,
|
||||
SaturatedConversion, One, DigestFor,
|
||||
};
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use runtime_primitives::BuildStorage;
|
||||
use crate::runtime_api::{
|
||||
CallRuntimeAt, ConstructRuntimeApi, Core as CoreApi, ProofRecorder,
|
||||
@@ -1760,8 +1761,7 @@ pub(crate) mod tests {
|
||||
use std::collections::HashMap;
|
||||
use super::*;
|
||||
use primitives::blake2_256;
|
||||
use runtime_primitives::traits::DigestItem as DigestItemT;
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use runtime_primitives::DigestItem;
|
||||
use consensus::{BlockOrigin, SelectChain};
|
||||
use test_client::{
|
||||
prelude::*,
|
||||
|
||||
@@ -20,11 +20,8 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use parking_lot::{RwLock, Mutex};
|
||||
use primitives::{ChangesTrieConfiguration, storage::well_known_keys};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{
|
||||
Block as BlockT, Header as HeaderT, Zero,
|
||||
NumberFor, Digest, DigestItem
|
||||
};
|
||||
use runtime_primitives::generic::{BlockId, DigestItem};
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor};
|
||||
use runtime_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay};
|
||||
use state_machine::backend::{Backend as StateBackend, InMemory};
|
||||
use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId};
|
||||
@@ -631,10 +628,9 @@ where
|
||||
|
||||
self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone()));
|
||||
|
||||
let changes_trie_root = header.digest().log(DigestItem::as_changes_trie_root).cloned();
|
||||
if let Some(changes_trie_root) = changes_trie_root {
|
||||
let maybe_changes_trie_root = header.digest().log(DigestItem::as_changes_trie_root).cloned();
|
||||
if let Some(changes_trie_root) = maybe_changes_trie_root {
|
||||
if let Some(changes_trie_update) = operation.changes_trie_update {
|
||||
let changes_trie_root: H::Out = changes_trie_root.into();
|
||||
self.changes_trie_storage.0.insert(
|
||||
*header.number(),
|
||||
changes_trie_root,
|
||||
|
||||
@@ -552,7 +552,25 @@ mod tests {
|
||||
let local_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![1])));
|
||||
let remote_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![2])));
|
||||
let remote_or_local = RemoteOrLocalCallExecutor::new(backend, remote_executor, local_executor);
|
||||
assert_eq!(remote_or_local.call(&BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new()).unwrap(), vec![1]);
|
||||
assert_eq!(remote_or_local.call(&BlockId::Number(1), "test_method", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new()).unwrap(), vec![2]);
|
||||
assert_eq!(
|
||||
remote_or_local.call(
|
||||
&BlockId::Number(0),
|
||||
"test_method",
|
||||
&[],
|
||||
ExecutionStrategy::NativeElseWasm,
|
||||
NeverOffchainExt::new(),
|
||||
).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
assert_eq!(
|
||||
remote_or_local.call(
|
||||
&BlockId::Number(1),
|
||||
"test_method",
|
||||
&[],
|
||||
ExecutionStrategy::NativeElseWasm,
|
||||
NeverOffchainExt::new(),
|
||||
).unwrap(),
|
||||
vec![2],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +501,7 @@ pub mod tests {
|
||||
RemoteCallRequest, RemoteHeaderRequest};
|
||||
use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain};
|
||||
use primitives::{blake2_256, Blake2Hasher, H256};
|
||||
use primitives::storage::{StorageKey, well_known_keys};
|
||||
use primitives::storage::{well_known_keys, StorageKey};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use state_machine::Backend;
|
||||
use super::*;
|
||||
@@ -564,10 +564,10 @@ pub mod tests {
|
||||
remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap().storage_root(::std::iter::empty()).0.into();
|
||||
|
||||
// 'fetch' read proof from remote node
|
||||
let authorities_len = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::AUTHORITY_COUNT.to_vec()))
|
||||
let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec()))
|
||||
.unwrap()
|
||||
.and_then(|v| Decode::decode(&mut &v.0[..])).unwrap();
|
||||
let remote_read_proof = remote_client.read_proof(&remote_block_id, well_known_keys::AUTHORITY_COUNT).unwrap();
|
||||
let remote_read_proof = remote_client.read_proof(&remote_block_id, well_known_keys::HEAP_PAGES).unwrap();
|
||||
|
||||
// check remote read proof locally
|
||||
let local_storage = InMemoryBlockchain::<Block>::new();
|
||||
@@ -580,7 +580,7 @@ pub mod tests {
|
||||
).unwrap();
|
||||
let local_executor = test_client::LocalExecutor::new(None);
|
||||
let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor);
|
||||
(local_checker, remote_block_header, remote_read_proof, authorities_len)
|
||||
(local_checker, remote_block_header, remote_read_proof, heap_pages)
|
||||
}
|
||||
|
||||
fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, Vec<Vec<u8>>) {
|
||||
@@ -619,13 +619,13 @@ pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn storage_read_proof_is_generated_and_checked() {
|
||||
let (local_checker, remote_block_header, remote_read_proof, authorities_len) = prepare_for_read_proof_check();
|
||||
let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check();
|
||||
assert_eq!((&local_checker as &dyn FetchChecker<Block>).check_read_proof(&RemoteReadRequest::<Header> {
|
||||
block: remote_block_header.hash(),
|
||||
header: remote_block_header,
|
||||
key: well_known_keys::AUTHORITY_COUNT.to_vec(),
|
||||
key: well_known_keys::HEAP_PAGES.to_vec(),
|
||||
retry_count: None,
|
||||
}, remote_read_proof).unwrap().unwrap()[0], authorities_len as u8);
|
||||
}, remote_read_proof).unwrap().unwrap()[0], heap_pages as u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -25,7 +25,7 @@ pub use primitives::NativeOrEncoded;
|
||||
#[doc(hidden)]
|
||||
pub use runtime_primitives::{
|
||||
traits::{
|
||||
AuthorityIdFor, Block as BlockT, GetNodeBlockType, GetRuntimeBlockType,
|
||||
Block as BlockT, GetNodeBlockType, GetRuntimeBlockType,
|
||||
Header as HeaderT, ApiRef, RuntimeApiInfo, Hash as HashT,
|
||||
},
|
||||
generic::BlockId, transaction_validity::TransactionValidity,
|
||||
|
||||
@@ -14,12 +14,10 @@ runtime_io = { package = "sr-io", path = "../../sr-io" }
|
||||
slots = { package = "substrate-consensus-slots", path = "../slots" }
|
||||
aura_primitives = { package = "substrate-consensus-aura-primitives", path = "primitives" }
|
||||
inherents = { package = "substrate-inherents", path = "../../inherents" }
|
||||
srml-consensus = { path = "../../../srml/consensus" }
|
||||
srml-aura = { path = "../../../srml/aura" }
|
||||
client = { package = "substrate-client", path = "../../client" }
|
||||
substrate-telemetry = { path = "../../telemetry" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../common" }
|
||||
authorities = { package = "substrate-consensus-authorities", path = "../authorities" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" }
|
||||
futures = "0.1.17"
|
||||
tokio-timer = "0.2.11"
|
||||
|
||||
@@ -6,12 +6,18 @@ description = "Primitives for Aura consensus"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
parity-codec = { version = "3.5", default-features = false }
|
||||
substrate-client = { path = "../../../client", default-features = false }
|
||||
substrate-primitives = { path = "../../../primitives", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../../sr-std", default-features = false }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"rstd/std",
|
||||
"parity-codec/std",
|
||||
"runtime_primitives/std",
|
||||
"substrate-client/std",
|
||||
"substrate-primitives/std",
|
||||
]
|
||||
|
||||
@@ -18,20 +18,32 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use parity_codec::{Encode, Decode, Codec};
|
||||
use substrate_client::decl_runtime_apis;
|
||||
use rstd::vec::Vec;
|
||||
use runtime_primitives::ConsensusEngineId;
|
||||
|
||||
/// The `ConsensusEngineId` of AuRa.
|
||||
pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a'];
|
||||
|
||||
/// An consensus log item for Aura.
|
||||
#[derive(Decode, Encode)]
|
||||
pub enum ConsensusLog<AuthorityId: Codec> {
|
||||
/// The authorities have changed.
|
||||
AuthoritiesChange(Vec<AuthorityId>),
|
||||
}
|
||||
|
||||
decl_runtime_apis! {
|
||||
/// API necessary for block authorship with aura.
|
||||
pub trait AuraApi {
|
||||
pub trait AuraApi<AuthorityId: Codec> {
|
||||
/// Return the slot duration in seconds for Aura.
|
||||
/// Currently, only the value provided by this type at genesis
|
||||
/// will be used.
|
||||
///
|
||||
/// Dynamic slot duration may be supported in the future.
|
||||
fn slot_duration() -> u64;
|
||||
|
||||
// Return the current set of authorities.
|
||||
fn authorities() -> Vec<AuthorityId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,22 @@
|
||||
//!
|
||||
//! This implements the digests for AuRa, to allow the private
|
||||
//! `CompatibleDigestItem` trait to appear in public interfaces.
|
||||
|
||||
use primitives::Pair;
|
||||
use aura_primitives::AURA_ENGINE_ID;
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use runtime_primitives::generic::{DigestItem, OpaqueDigestItemId};
|
||||
use parity_codec::{Encode, Codec};
|
||||
use std::fmt::Debug;
|
||||
|
||||
type Signature<P> = <P as Pair>::Signature;
|
||||
|
||||
/// A digest item which is usable with aura consensus.
|
||||
pub trait CompatibleDigestItem<T: Pair>: Sized {
|
||||
pub trait CompatibleDigestItem<P: Pair>: Sized {
|
||||
/// Construct a digest item which contains a signature on the hash.
|
||||
fn aura_seal(signature: Signature<T>) -> Self;
|
||||
fn aura_seal(signature: Signature<P>) -> Self;
|
||||
|
||||
/// If this item is an Aura seal, return the signature.
|
||||
fn as_aura_seal(&self) -> Option<&Signature<T>>;
|
||||
fn as_aura_seal(&self) -> Option<Signature<P>>;
|
||||
|
||||
/// Construct a digest item which contains the slot number
|
||||
fn aura_pre_digest(slot_num: u64) -> Self;
|
||||
@@ -40,18 +42,17 @@ pub trait CompatibleDigestItem<T: Pair>: Sized {
|
||||
fn as_aura_pre_digest(&self) -> Option<u64>;
|
||||
}
|
||||
|
||||
impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash, P::Public, P::Signature>
|
||||
where P: Pair, P::Signature: Clone + Encode + Decode,
|
||||
impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash> where
|
||||
P: Pair,
|
||||
Signature<P>: Codec,
|
||||
Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static
|
||||
{
|
||||
fn aura_seal(signature: Signature<P>) -> Self {
|
||||
DigestItem::Seal(AURA_ENGINE_ID, signature)
|
||||
DigestItem::Seal(AURA_ENGINE_ID, signature.encode())
|
||||
}
|
||||
|
||||
fn as_aura_seal(&self) -> Option<&Signature<P>> {
|
||||
match self {
|
||||
DigestItem::Seal(AURA_ENGINE_ID, ref sig) => Some(sig),
|
||||
_ => None,
|
||||
}
|
||||
fn as_aura_seal(&self) -> Option<Signature<P>> {
|
||||
self.try_to(OpaqueDigestItemId::Seal(&AURA_ENGINE_ID))
|
||||
}
|
||||
|
||||
fn aura_pre_digest(slot_num: u64) -> Self {
|
||||
@@ -59,9 +60,6 @@ impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash, P::Public, P::Signatu
|
||||
}
|
||||
|
||||
fn as_aura_pre_digest(&self) -> Option<u64> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(AURA_ENGINE_ID, ref buffer) => Decode::decode(&mut &buffer[..]),
|
||||
_ => None,
|
||||
}
|
||||
self.try_to(OpaqueDigestItemId::PreRuntime(&AURA_ENGINE_ID))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,15 @@
|
||||
//!
|
||||
//! Blocks from future steps will be either deferred or rejected depending on how
|
||||
//! far in the future they are.
|
||||
//!
|
||||
//! NOTE: Aura itself is designed to be generic over the crypto used.
|
||||
#![forbid(missing_docs, unsafe_code)]
|
||||
use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug};
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use consensus_common::{self, Authorities, BlockImport, Environment, Proposer,
|
||||
use parity_codec::{Encode, Decode, Codec};
|
||||
use consensus_common::{self, BlockImport, Environment, Proposer,
|
||||
ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError,
|
||||
SelectChain, well_known_cache_keys
|
||||
SelectChain, well_known_cache_keys::{self, Id as CacheKeyId}
|
||||
};
|
||||
use consensus_common::import_queue::{
|
||||
Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport, SharedFinalityProofImport,
|
||||
@@ -45,15 +47,11 @@ use client::{
|
||||
backend::AuxStore,
|
||||
};
|
||||
|
||||
use runtime_primitives::{generic::{self, BlockId}, Justification};
|
||||
use runtime_primitives::traits::{
|
||||
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor,
|
||||
Zero, Member,
|
||||
};
|
||||
use runtime_primitives::{generic::{self, BlockId, OpaqueDigestItemId}, Justification};
|
||||
use runtime_primitives::traits::{Block, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member};
|
||||
|
||||
use primitives::Pair;
|
||||
use inherents::{InherentDataProviders, InherentData};
|
||||
use authorities::AuthoritiesApi;
|
||||
|
||||
use futures::{Future, IntoFuture, future};
|
||||
use tokio_timer::Timeout;
|
||||
@@ -82,9 +80,12 @@ pub struct SlotDuration(slots::SlotDuration<u64>);
|
||||
impl SlotDuration {
|
||||
/// Either fetch the slot duration from disk or compute it from the genesis
|
||||
/// state.
|
||||
pub fn get_or_compute<B: Block, C>(client: &C) -> CResult<Self>
|
||||
pub fn get_or_compute<A, B, C>(client: &C) -> CResult<Self>
|
||||
where
|
||||
C: AuxStore, C: ProvideRuntimeApi, C::Api: AuraApi<B>,
|
||||
A: Codec,
|
||||
B: Block,
|
||||
C: AuxStore + ProvideRuntimeApi,
|
||||
C::Api: AuraApi<B, A>,
|
||||
{
|
||||
slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self)
|
||||
}
|
||||
@@ -138,19 +139,14 @@ pub fn start_aura<B, C, SC, E, I, P, SO, Error, H>(
|
||||
) -> Result<impl Future<Item=(), Error=()>, consensus_common::Error> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + AuxStore + Send + Sync,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, AuthorityId<P>>,
|
||||
SC: SelectChain<B>,
|
||||
generic::DigestItem<B::Hash, P::Public, P::Signature>: DigestItem<Hash=B::Hash>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Hash + Member + Encode + Decode,
|
||||
P::Signature: Hash + Member + Encode + Decode,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, P::Public, P::Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
E: Environment<B, Error=Error>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
@@ -189,20 +185,16 @@ struct AuraWorker<C, E, I, P, SO> {
|
||||
impl<H, B, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B> + Sync,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, AuthorityId<P>>,
|
||||
E: Environment<B, Error=Error>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, P::Public, P::Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Member + Encode + Decode + Hash,
|
||||
P::Signature: Member + Encode + Decode + Hash + Debug,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>, Hash=B::Hash>,
|
||||
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
{
|
||||
type OnSlot = Box<dyn Future<Item=(), Error=consensus_common::Error> + Send>;
|
||||
@@ -257,7 +249,7 @@ impl<H, B, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, P, SO> w
|
||||
);
|
||||
|
||||
// we are the slot author. make a block and sign it.
|
||||
let proposer = match env.init(&chain_head, &authorities) {
|
||||
let proposer = match env.init(&chain_head) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
warn!("Unable to author block in slot {:?}: {:?}", slot_num, e);
|
||||
@@ -506,13 +498,12 @@ impl<C, P> AuraVerifier<C, P>
|
||||
|
||||
#[forbid(deprecated)]
|
||||
impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore,
|
||||
C::Api: BlockBuilderApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore + ProvideCache<B>,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + AsRef<P::Public> + 'static,
|
||||
P::Signature: Encode + Decode,
|
||||
Self: Authorities<B>,
|
||||
{
|
||||
fn verify(
|
||||
&self,
|
||||
@@ -520,13 +511,13 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
mut body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityId<P>>>), String> {
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?;
|
||||
let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data)
|
||||
.map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?;
|
||||
let hash = header.hash();
|
||||
let parent_hash = *header.parent_hash();
|
||||
let authorities = self.authorities(&BlockId::Hash(parent_hash))
|
||||
let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash))
|
||||
.map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?;
|
||||
|
||||
// we add one to allow for some small drift.
|
||||
@@ -569,9 +560,14 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
trace!(target: "aura", "Checked {:?}; importing.", pre_header);
|
||||
telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header);
|
||||
|
||||
let new_authorities = pre_header.digest()
|
||||
.log(DigestItem::as_authorities_change)
|
||||
.map(|digest| digest.to_vec());
|
||||
// `Consensus` is the Aura-specific authorities change log.
|
||||
let maybe_keys = pre_header.digest()
|
||||
.convert_first(|l| l.try_to::<ConsensusLog<AuthorityId<P>>>(
|
||||
OpaqueDigestItemId::Consensus(&AURA_ENGINE_ID)
|
||||
))
|
||||
.map(|ConsensusLog::AuthoritiesChange(a)|
|
||||
vec![(well_known_cache_keys::AUTHORITIES, a.encode())]
|
||||
);
|
||||
|
||||
let import_block = ImportBlock {
|
||||
origin,
|
||||
@@ -584,7 +580,7 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
fork_choice: ForkChoiceStrategy::LongestChain,
|
||||
};
|
||||
|
||||
Ok((import_block, new_authorities))
|
||||
Ok((import_block, maybe_keys))
|
||||
}
|
||||
CheckedHeader::Deferred(a, b) => {
|
||||
debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
|
||||
@@ -597,22 +593,11 @@ impl<B: Block, C, P> Verifier<B> for AuraVerifier<C, P> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, C, P> Authorities<B> for AuraVerifier<C, P> where
|
||||
fn initialize_authorities_cache<A, B, C>(client: &C) -> Result<(), ConsensusError> where
|
||||
A: Codec,
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
{
|
||||
type Error = ConsensusError;
|
||||
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, Self::Error> {
|
||||
authorities(self.client.as_ref(), at)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, A>,
|
||||
{
|
||||
// no cache => no initialization
|
||||
let cache = match client.cache() {
|
||||
@@ -622,7 +607,7 @@ fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError>
|
||||
|
||||
// check if we already have initialized the cache
|
||||
let genesis_id = BlockId::Number(Zero::zero());
|
||||
let genesis_authorities: Option<Vec<AuthorityIdFor<B>>> = cache
|
||||
let genesis_authorities: Option<Vec<A>> = cache
|
||||
.get_at(&well_known_cache_keys::AUTHORITIES, &genesis_id)
|
||||
.and_then(|v| Decode::decode(&mut &v[..]));
|
||||
if genesis_authorities.is_some() {
|
||||
@@ -642,10 +627,11 @@ fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError>
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, ConsensusError> where
|
||||
fn authorities<A, B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<A>, ConsensusError> where
|
||||
A: Codec,
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: AuraApi<B, A>,
|
||||
{
|
||||
client
|
||||
.cache()
|
||||
@@ -653,7 +639,7 @@ fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B
|
||||
.get_at(&well_known_cache_keys::AUTHORITIES, at)
|
||||
.and_then(|v| Decode::decode(&mut &v[..]))
|
||||
)
|
||||
.or_else(|| AuthoritiesApi::authorities(&*client.runtime_api(), at).ok())
|
||||
.or_else(|| AuraApi::authorities(&*client.runtime_api(), at).ok())
|
||||
.ok_or_else(|| consensus_common::Error::InvalidAuthoritiesSet.into())
|
||||
}
|
||||
|
||||
@@ -687,8 +673,8 @@ pub fn import_queue<B, C, P>(
|
||||
) -> Result<AuraImportQueue<B>, consensus_common::Error> where
|
||||
B: Block,
|
||||
C: 'static + ProvideRuntimeApi + ProvideCache<B> + Send + Sync + AuxStore,
|
||||
C::Api: BlockBuilderApi<B> + AuthoritiesApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P> + DigestItem<AuthorityId=AuthorityId<P>>,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef<P::Public>,
|
||||
P::Signature: Encode + Decode,
|
||||
@@ -730,7 +716,12 @@ mod tests {
|
||||
|
||||
type Error = client::error::Error;
|
||||
|
||||
type TestClient = client::Client<test_client::Backend, test_client::Executor, TestBlock, test_client::runtime::RuntimeApi>;
|
||||
type TestClient = client::Client<
|
||||
test_client::Backend,
|
||||
test_client::Executor,
|
||||
TestBlock,
|
||||
test_client::runtime::RuntimeApi
|
||||
>;
|
||||
|
||||
struct DummyFactory(Arc<TestClient>);
|
||||
struct DummyProposer(u64, Arc<TestClient>);
|
||||
@@ -739,7 +730,7 @@ mod tests {
|
||||
type Proposer = DummyProposer;
|
||||
type Error = Error;
|
||||
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[AuthorityId<sr25519::Pair>])
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header)
|
||||
-> Result<DummyProposer, Error>
|
||||
{
|
||||
Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "substrate-consensus-authorities"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Primitives for Aura consensus"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
parity-codec = { version = "3.3", default-features = false }
|
||||
substrate-client = { path = "../../client", default-features = false }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives", default-features = false }
|
||||
runtime_support = { package = "srml-support", path = "../../../srml/support", default-features = false }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false }
|
||||
sr-version = { path = "../../sr-version", default-features = false }
|
||||
runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../sr-std", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"parity-codec/std",
|
||||
"substrate-client/std",
|
||||
"primitives/std",
|
||||
"runtime_support/std",
|
||||
"runtime_primitives/std",
|
||||
"sr-version/std",
|
||||
"runtime_io/std",
|
||||
"rstd/std"
|
||||
]
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2019 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/>.
|
||||
|
||||
//! Authorities API.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use substrate_client::decl_runtime_apis;
|
||||
use runtime_primitives::traits::AuthorityIdFor;
|
||||
use rstd::vec::Vec;
|
||||
|
||||
decl_runtime_apis! {
|
||||
/// Authorities API.
|
||||
pub trait AuthoritiesApi {
|
||||
/// Returns the authorities at the given block.
|
||||
fn authorities() -> Vec<AuthorityIdFor<Block>>;
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,10 @@ runtime_support = { package = "srml-support", path = "../../../srml/support" }
|
||||
runtime_version = { package = "sr-version", path = "../../sr-version" }
|
||||
runtime_io = { package = "sr-io", path = "../../sr-io" }
|
||||
inherents = { package = "substrate-inherents", path = "../../inherents" }
|
||||
srml-consensus = { path = "../../../srml/consensus" }
|
||||
substrate-telemetry = { path = "../../telemetry" }
|
||||
srml-babe = { path = "../../../srml/babe" }
|
||||
client = { package = "substrate-client", path = "../../client" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../common" }
|
||||
authorities = { package = "substrate-consensus-authorities", path = "../authorities" }
|
||||
slots = { package = "substrate-consensus-slots", path = "../slots" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" }
|
||||
futures = "0.1.26"
|
||||
|
||||
@@ -7,13 +7,16 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
substrate-client = { path = "../../../client", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../../sr-std", default-features = false }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false }
|
||||
substrate-primitives = { path = "../../../primitives", default-features = false }
|
||||
slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true }
|
||||
parity-codec = { version = "3.5.1", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"rstd/std",
|
||||
"runtime_primitives/std",
|
||||
"substrate-client/std",
|
||||
"parity-codec/std",
|
||||
|
||||
@@ -18,13 +18,18 @@
|
||||
#![deny(warnings, unsafe_code, missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use rstd::vec::Vec;
|
||||
use runtime_primitives::ConsensusEngineId;
|
||||
use substrate_primitives::sr25519::Public;
|
||||
use substrate_client::decl_runtime_apis;
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in
|
||||
/// the main Babe module. If that ever changes, then this must, too.
|
||||
pub type AuthorityId = Public;
|
||||
|
||||
/// The `ConsensusEngineId` of BABE.
|
||||
pub const BABE_ENGINE_ID: ConsensusEngineId = [b'b', b'a', b'b', b'e'];
|
||||
pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE";
|
||||
|
||||
/// Configuration data used by the BABE consensus engine.
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Encode, Decode)]
|
||||
@@ -69,5 +74,8 @@ decl_runtime_apis! {
|
||||
///
|
||||
/// Dynamic configuration may be supported in the future.
|
||||
fn startup_data() -> BabeConfiguration;
|
||||
|
||||
/// Get the current authorites for Babe.
|
||||
fn authorities() -> Vec<AuthorityId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Private mplementation details of BABE digests.
|
||||
|
||||
use primitives::sr25519::{Public, Signature};
|
||||
use babe_primitives::BABE_ENGINE_ID;
|
||||
use runtime_primitives::generic::DigestItem;
|
||||
use runtime_primitives::{DigestItem, generic::OpaqueDigestItemId};
|
||||
use std::fmt::Debug;
|
||||
use parity_codec::{Decode, Encode, Input};
|
||||
use log::info;
|
||||
use parity_codec::{Decode, Encode, Codec, Input};
|
||||
use schnorrkel::{
|
||||
vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH},
|
||||
PUBLIC_KEY_LENGTH,
|
||||
@@ -89,26 +89,15 @@ pub trait CompatibleDigestItem: Sized {
|
||||
fn as_babe_seal(&self) -> Option<Signature>;
|
||||
}
|
||||
|
||||
impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Vec<u8>>
|
||||
impl<Hash> CompatibleDigestItem for DigestItem<Hash> where
|
||||
Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static
|
||||
{
|
||||
fn babe_pre_digest(digest: BabePreDigest) -> Self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
|
||||
}
|
||||
|
||||
fn as_babe_pre_digest(&self) -> Option<BabePreDigest> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => {
|
||||
let decoded = Decode::decode(&mut &seal[..]);
|
||||
if decoded.is_none() {
|
||||
info!(target: "babe", "Failed to decode {:?}", seal)
|
||||
}
|
||||
decoded
|
||||
}
|
||||
_ => {
|
||||
info!(target: "babe", "Invalid consensus: {:?}!", self);
|
||||
None
|
||||
}
|
||||
}
|
||||
self.try_to(OpaqueDigestItemId::PreRuntime(&BABE_ENGINE_ID))
|
||||
}
|
||||
|
||||
fn babe_seal(signature: Signature) -> Self {
|
||||
@@ -116,34 +105,6 @@ impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Vec<u8>>
|
||||
}
|
||||
|
||||
fn as_babe_seal(&self) -> Option<Signature> {
|
||||
match self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature) => Decode::decode(&mut &signature[..]),
|
||||
_ => None,
|
||||
}
|
||||
self.try_to(OpaqueDigestItemId::Seal(&BABE_ENGINE_ID))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Hash: Debug> CompatibleDigestItem for DigestItem<Hash, Public, Signature>
|
||||
{
|
||||
fn babe_pre_digest(digest: BabePreDigest) -> Self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode())
|
||||
}
|
||||
|
||||
fn as_babe_pre_digest(&self) -> Option<BabePreDigest> {
|
||||
match self {
|
||||
DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => Decode::decode(&mut &seal[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn babe_seal(signature: Signature) -> Self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature)
|
||||
}
|
||||
|
||||
fn as_babe_seal(&self) -> Option<Signature> {
|
||||
match self {
|
||||
DigestItem::Seal(BABE_ENGINE_ID, signature) => Some(signature.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,18 +31,16 @@ use digest::CompatibleDigestItem;
|
||||
pub use digest::{BabePreDigest, BABE_VRF_PREFIX};
|
||||
pub use babe_primitives::*;
|
||||
pub use consensus_common::SyncOracle;
|
||||
use runtime_primitives::{generic, generic::BlockId, Justification};
|
||||
use consensus_common::well_known_cache_keys::Id as CacheKeyId;
|
||||
use runtime_primitives::{generic, generic::{BlockId, OpaqueDigestItemId}, Justification};
|
||||
use runtime_primitives::traits::{
|
||||
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor,
|
||||
Block, Header, DigestItemFor, ProvideRuntimeApi,
|
||||
SimpleBitOps,
|
||||
};
|
||||
use std::{sync::Arc, u64, fmt::{Debug, Display}};
|
||||
use runtime_support::serde::{Serialize, Deserialize};
|
||||
use parity_codec::{Decode, Encode};
|
||||
use primitives::{
|
||||
crypto::Pair,
|
||||
sr25519::{Public, Signature, self},
|
||||
};
|
||||
use primitives::{crypto::Pair, sr25519};
|
||||
use merlin::Transcript;
|
||||
use inherents::{InherentDataProviders, InherentData};
|
||||
use substrate_telemetry::{
|
||||
@@ -58,9 +56,8 @@ use schnorrkel::{
|
||||
VRFProof, VRFProofBatchable, VRFInOut,
|
||||
},
|
||||
};
|
||||
use authorities::AuthoritiesApi;
|
||||
use consensus_common::{
|
||||
self, Authorities, BlockImport, Environment, Proposer,
|
||||
self, BlockImport, Environment, Proposer,
|
||||
ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError,
|
||||
};
|
||||
use srml_babe::{
|
||||
@@ -83,6 +80,7 @@ use log::{error, warn, debug, info, trace};
|
||||
|
||||
use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible, slot_now};
|
||||
|
||||
pub use babe_primitives::AuthorityId;
|
||||
|
||||
/// A slot duration. Create with `get_or_compute`.
|
||||
// FIXME: Once Rust has higher-kinded types, the duplication between this
|
||||
@@ -181,16 +179,11 @@ pub fn start_babe<B, C, SC, E, I, SO, Error, H>(BabeParams {
|
||||
> where
|
||||
B: Block<Header=H>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
SC: SelectChain<B>,
|
||||
generic::DigestItem<B::Hash, Public, Signature>: DigestItem<Hash=B::Hash>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, Public, Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
E: Environment<B, Error=Error>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
Error: std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
@@ -228,17 +221,14 @@ struct BabeWorker<C, E, I, SO> {
|
||||
impl<Hash, H, B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> where
|
||||
B: Block<Header=H, Hash=Hash>,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
E: Environment<B, Error=Error>,
|
||||
E::Proposer: Proposer<B, Error=Error>,
|
||||
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
|
||||
Hash: Debug + Eq + Copy + SimpleBitOps + Encode + Decode + Serialize +
|
||||
for<'de> Deserialize<'de> + Debug + Default + AsRef<[u8]> + AsMut<[u8]> +
|
||||
std::hash::Hash + Display + Send + Sync + 'static,
|
||||
H: Header<
|
||||
Digest=generic::Digest<generic::DigestItem<B::Hash, Public, Signature>>,
|
||||
Hash=B::Hash,
|
||||
>,
|
||||
H: Header<Hash=B::Hash>,
|
||||
I: BlockImport<B> + Send + Sync + 'static,
|
||||
SO: SyncOracle + Send + Clone,
|
||||
Error: std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
|
||||
@@ -304,7 +294,7 @@ impl<Hash, H, B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<C, E, I, SO> w
|
||||
);
|
||||
|
||||
// we are the slot author. make a block and sign it.
|
||||
let proposer = match env.init(&chain_head, &authorities) {
|
||||
let proposer = match env.init(&chain_head) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
warn!(target: "babe", "Unable to author block in slot {:?}: {:?}", slot_num, e);
|
||||
@@ -450,7 +440,7 @@ fn check_header<B: Block + Sized, C: AuxStore>(
|
||||
slot_now: u64,
|
||||
mut header: B::Header,
|
||||
hash: B::Hash,
|
||||
authorities: &[Public],
|
||||
authorities: &[AuthorityId],
|
||||
threshold: u64,
|
||||
) -> Result<CheckedHeader<B::Header, (DigestItemFor<B>, DigestItemFor<B>)>, String>
|
||||
where DigestItemFor<B>: CompatibleDigestItem,
|
||||
@@ -553,10 +543,9 @@ impl<C> BabeVerifier<C> {
|
||||
}
|
||||
|
||||
impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
C: ProvideRuntimeApi + Send + Sync + AuxStore,
|
||||
C::Api: BlockBuilderApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
|
||||
Self: Authorities<B>,
|
||||
C: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache<B>,
|
||||
C::Api: BlockBuilderApi<B> + BabeApi<B>,
|
||||
DigestItemFor<B>: CompatibleDigestItem,
|
||||
{
|
||||
fn verify(
|
||||
&self,
|
||||
@@ -564,7 +553,7 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
mut body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<Public>>), String> {
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
trace!(
|
||||
target: "babe",
|
||||
"Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}",
|
||||
@@ -583,7 +572,7 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
.map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?;
|
||||
let hash = header.hash();
|
||||
let parent_hash = *header.parent_hash();
|
||||
let authorities = self.authorities(&BlockId::Hash(parent_hash))
|
||||
let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash))
|
||||
.map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?;
|
||||
|
||||
// we add one to allow for some small drift.
|
||||
@@ -625,9 +614,12 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
"babe.checked_and_importing";
|
||||
"pre_header" => ?pre_header);
|
||||
|
||||
let new_authorities = pre_header.digest()
|
||||
.log(DigestItem::as_authorities_change)
|
||||
.map(|digest| digest.to_vec());
|
||||
// `Consensus` is the Babe-specific authorities change log.
|
||||
// It's an encoded `Vec<AuthorityId>`, the same format as is stored in the cache,
|
||||
// so no need to decode/re-encode.
|
||||
let maybe_keys = pre_header.digest()
|
||||
.log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)))
|
||||
.map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]);
|
||||
|
||||
let import_block = ImportBlock {
|
||||
origin,
|
||||
@@ -641,7 +633,7 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
};
|
||||
|
||||
// FIXME #1019 extract authorities
|
||||
Ok((import_block, new_authorities))
|
||||
Ok((import_block, maybe_keys))
|
||||
}
|
||||
CheckedHeader::Deferred(a, b) => {
|
||||
debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
|
||||
@@ -654,33 +646,21 @@ impl<B: Block, C> Verifier<B> for BabeVerifier<C> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, C> Authorities<B> for BabeVerifier<C> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
{
|
||||
type Error = ConsensusError;
|
||||
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, Self::Error> {
|
||||
authorities(self.client.as_ref(), at)
|
||||
}
|
||||
}
|
||||
|
||||
fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<
|
||||
Vec<AuthorityIdFor<B>>,
|
||||
Vec<AuthorityId>,
|
||||
ConsensusError,
|
||||
> where
|
||||
B: Block,
|
||||
C: ProvideRuntimeApi + ProvideCache<B>,
|
||||
C::Api: AuthoritiesApi<B>,
|
||||
C::Api: BabeApi<B>,
|
||||
{
|
||||
client
|
||||
.cache()
|
||||
.and_then(|cache| cache.get_at(&well_known_cache_keys::AUTHORITIES, at)
|
||||
.and_then(|v| Decode::decode(&mut &v[..])))
|
||||
.or_else(|| {
|
||||
if client.runtime_api().has_api::<dyn AuthoritiesApi<B>>(at).unwrap_or(false) {
|
||||
AuthoritiesApi::authorities(&*client.runtime_api(), at).ok()
|
||||
if client.runtime_api().has_api::<dyn BabeApi<B>>(at).unwrap_or(false) {
|
||||
BabeApi::authorities(&*client.runtime_api(), at).ok()
|
||||
} else {
|
||||
panic!("We don’t support deprecated code with new consensus algorithms, \
|
||||
therefore this is unreachable; qed")
|
||||
@@ -740,7 +720,7 @@ fn claim_slot(
|
||||
slot_number: u64,
|
||||
genesis_hash: &[u8],
|
||||
epoch: u64,
|
||||
authorities: &[sr25519::Public],
|
||||
authorities: &[AuthorityId],
|
||||
key: &sr25519::Pair,
|
||||
threshold: u64,
|
||||
) -> Option<(VRFInOut, VRFProof, VRFProofBatchable)> {
|
||||
@@ -784,7 +764,7 @@ mod tests {
|
||||
use futures::stream::Stream;
|
||||
use log::debug;
|
||||
use std::time::Duration;
|
||||
type Item = generic::DigestItem<Hash, Public, Signature>;
|
||||
type Item = generic::DigestItem<Hash>;
|
||||
use test_client::AuthorityKeyring;
|
||||
|
||||
type Error = client::error::Error;
|
||||
@@ -803,7 +783,7 @@ mod tests {
|
||||
type Proposer = DummyProposer;
|
||||
type Error = Error;
|
||||
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header, _authorities: &[Public])
|
||||
fn init(&self, parent_header: &<TestBlock as BlockT>::Header)
|
||||
-> Result<DummyProposer, Error>
|
||||
{
|
||||
Ok(DummyProposer(parent_header.number + 1, self.0.clone()))
|
||||
@@ -977,7 +957,7 @@ mod tests {
|
||||
fn wrong_consensus_engine_id_rejected() {
|
||||
drop(env_logger::try_init());
|
||||
let sig = sr25519::Pair::generate().0.sign(b"");
|
||||
let bad_seal: Item = DigestItem::Seal([0; 4], sig);
|
||||
let bad_seal: Item = DigestItem::Seal([0; 4], sig.0.to_vec());
|
||||
assert!(bad_seal.as_babe_pre_digest().is_none());
|
||||
assert!(bad_seal.as_babe_seal().is_none())
|
||||
}
|
||||
@@ -985,7 +965,7 @@ mod tests {
|
||||
#[test]
|
||||
fn malformed_pre_digest_rejected() {
|
||||
drop(env_logger::try_init());
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, Signature([0; 64]));
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, [0; 64].to_vec());
|
||||
assert!(bad_seal.as_babe_pre_digest().is_none());
|
||||
}
|
||||
|
||||
@@ -993,7 +973,7 @@ mod tests {
|
||||
fn sig_is_not_pre_digest() {
|
||||
drop(env_logger::try_init());
|
||||
let sig = sr25519::Pair::generate().0.sign(b"");
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig);
|
||||
let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig.0.to_vec());
|
||||
assert!(bad_seal.as_babe_pre_digest().is_none());
|
||||
assert!(bad_seal.as_babe_seal().is_some())
|
||||
}
|
||||
|
||||
@@ -154,8 +154,6 @@ impl<Block: BlockT> ImportBlock<Block> {
|
||||
|
||||
/// Get a handle to full header (with post-digests applied).
|
||||
pub fn post_header(&self) -> Cow<Block::Header> {
|
||||
use runtime_primitives::traits::Digest;
|
||||
|
||||
if self.post_digests.is_empty() {
|
||||
Cow::Borrowed(&self.header)
|
||||
} else {
|
||||
|
||||
@@ -25,24 +25,16 @@
|
||||
//! instantiated. The `BasicQueue` and `BasicVerifier` traits allow serial
|
||||
//! queues to be instantiated simply.
|
||||
|
||||
use crate::block_import::{
|
||||
use std::{sync::Arc, thread, collections::HashMap};
|
||||
use crossbeam_channel::{self as channel, Receiver, Sender};
|
||||
use parking_lot::Mutex;
|
||||
use runtime_primitives::{Justification, traits::{
|
||||
Block as BlockT, Header as HeaderT, NumberFor,
|
||||
}};
|
||||
use crate::{error::Error as ConsensusError, well_known_cache_keys::Id as CacheKeyId, block_import::{
|
||||
BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport,
|
||||
FinalityProofImport, FinalityProofRequestBuilder,
|
||||
};
|
||||
use crossbeam_channel::{self as channel, Receiver, Sender};
|
||||
use parity_codec::Encode;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use runtime_primitives::traits::{
|
||||
AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor, Digest,
|
||||
};
|
||||
use runtime_primitives::Justification;
|
||||
|
||||
use crate::error::Error as ConsensusError;
|
||||
use parity_codec::alloc::collections::hash_map::HashMap;
|
||||
}};
|
||||
|
||||
/// Reputation change for peers which send us a block with an incomplete header.
|
||||
const INCOMPLETE_HEADER_REPUTATION_CHANGE: i32 = -(1 << 20);
|
||||
@@ -94,7 +86,7 @@ pub trait Verifier<B: BlockT>: Send + Sync {
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityIdFor<B>>>), String>;
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String>;
|
||||
}
|
||||
|
||||
/// Blocks import queue API.
|
||||
@@ -906,7 +898,7 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
|
||||
r => return Ok(r), // Any other successful result means that the block is already imported.
|
||||
}
|
||||
|
||||
let (import_block, new_authorities) = verifier.verify(block_origin, header, justification, block.body)
|
||||
let (import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body)
|
||||
.map_err(|msg| {
|
||||
if let Some(ref peer) = peer {
|
||||
trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg);
|
||||
@@ -917,8 +909,8 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
|
||||
})?;
|
||||
|
||||
let mut cache = HashMap::new();
|
||||
if let Some(authorities) = new_authorities {
|
||||
cache.insert(crate::well_known_cache_keys::AUTHORITIES, authorities.encode());
|
||||
if let Some(keys) = maybe_keys {
|
||||
cache.extend(keys.into_iter());
|
||||
}
|
||||
|
||||
import_error(import_handle.import_block(import_block, cache))
|
||||
@@ -979,7 +971,7 @@ mod tests {
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
body: Option<Vec<B::Extrinsic>>,
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityIdFor<B>>>), String> {
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
Ok((ImportBlock {
|
||||
origin,
|
||||
header,
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{AuthorityIdFor, Block, DigestFor};
|
||||
use runtime_primitives::traits::{Block, DigestFor};
|
||||
use futures::prelude::*;
|
||||
pub use inherents::InherentData;
|
||||
|
||||
@@ -54,14 +53,6 @@ pub use block_import::{
|
||||
};
|
||||
pub use select_chain::SelectChain;
|
||||
|
||||
/// Trait for getting the authorities at a given block.
|
||||
pub trait Authorities<B: Block> {
|
||||
type Error: std::error::Error + Send + 'static;
|
||||
|
||||
/// Get the authorities at the given block.
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, Self::Error>;
|
||||
}
|
||||
|
||||
/// Environment producer for a Consensus instance. Creates proposer instance and communication streams.
|
||||
pub trait Environment<B: Block> {
|
||||
/// The proposer type this creates.
|
||||
@@ -71,7 +62,7 @@ pub trait Environment<B: Block> {
|
||||
|
||||
/// Initialize the proposal logic on top of a specific header. Provide
|
||||
/// the authorities at that header.
|
||||
fn init(&self, parent_header: &B::Header, authorities: &[AuthorityIdFor<B>])
|
||||
fn init(&self, parent_header: &B::Header)
|
||||
-> Result<Self::Proposer, Self::Error>;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,25 +112,24 @@ impl<AuthorityId: Eq + Clone + std::hash::Hash> OfflineTracker<AuthorityId> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use primitives::ed25519::Public as AuthorityId;
|
||||
|
||||
#[test]
|
||||
fn validator_offline() {
|
||||
let mut tracker = OfflineTracker::<AuthorityId>::new();
|
||||
let v = AuthorityId::from_raw([0; 32]);
|
||||
let v2 = AuthorityId::from_raw([1; 32]);
|
||||
let v3 = AuthorityId::from_raw([2; 32]);
|
||||
tracker.note_round_end(v.clone(), true);
|
||||
tracker.note_round_end(v2.clone(), true);
|
||||
tracker.note_round_end(v3.clone(), true);
|
||||
let mut tracker = OfflineTracker::<u64>::new();
|
||||
let v1 = 1;
|
||||
let v2 = 2;
|
||||
let v3 = 3;
|
||||
tracker.note_round_end(v1, true);
|
||||
tracker.note_round_end(v2, true);
|
||||
tracker.note_round_end(v3, true);
|
||||
|
||||
let slash_time = REPORT_TIME + Duration::from_secs(5);
|
||||
tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time;
|
||||
tracker.observed.get_mut(&v1).unwrap().offline_since -= slash_time;
|
||||
tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time;
|
||||
|
||||
assert_eq!(tracker.reports(&[v.clone(), v2.clone(), v3.clone()]), vec![0, 1]);
|
||||
assert_eq!(tracker.reports(&[v1, v2, v3]), vec![0, 1]);
|
||||
|
||||
tracker.note_new_block(&[v.clone(), v3.clone()]);
|
||||
assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]);
|
||||
tracker.note_new_block(&[v1, v3]);
|
||||
assert_eq!(tracker.reports(&[v1, v2, v3]), vec![0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ client = { package = "substrate-client", path = "../../client" }
|
||||
transaction_pool = { package = "substrate-transaction-pool", path = "../../transaction-pool" }
|
||||
runtime_support = { package = "srml-support", path = "../../../srml/support" }
|
||||
srml-system = { path = "../../../srml/system" }
|
||||
srml-consensus = { path = "../../../srml/consensus" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" }
|
||||
runtime_version = { package = "sr-version", path = "../../sr-version" }
|
||||
runtime_io = { package = "sr-io", path = "../../sr-io" }
|
||||
|
||||
@@ -112,7 +112,9 @@ trait ReadPrimitive<T: Sized> {
|
||||
impl ReadPrimitive<u32> for MemoryInstance {
|
||||
fn read_primitive(&self, offset: u32) -> ::std::result::Result<u32, UserError> {
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
Ok(LittleEndian::read_u32(&self.get(offset, 4).map_err(|_| UserError("Invalid attempt to read_primitive"))?))
|
||||
let result = self.get(offset, 4)
|
||||
.map_err(|_| UserError("Invalid attempt to read_primitive"))?;
|
||||
Ok(LittleEndian::read_u32(&result))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,20 +166,44 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_storage"))?;
|
||||
let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine key in ext_set_storage"))?;
|
||||
let value = this.memory.get(value_data, value_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine value in ext_set_storage"))?;
|
||||
if let Some(_preimage) = this.hash_lookup.get(&key) {
|
||||
debug_trace!(target: "wasm-trace", "*** Setting storage: %{} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&_preimage), HexDisplay::from(&value), HexDisplay::from(&key));
|
||||
debug_trace!(
|
||||
target: "wasm-trace",
|
||||
"*** Setting storage: %{} -> {} [k={}]",
|
||||
::primitives::hexdisplay::ascii_format(&_preimage),
|
||||
HexDisplay::from(&value),
|
||||
HexDisplay::from(&key),
|
||||
);
|
||||
} else {
|
||||
debug_trace!(target: "wasm-trace", "*** Setting storage: {} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&key), HexDisplay::from(&value), HexDisplay::from(&key));
|
||||
debug_trace!(
|
||||
target: "wasm-trace",
|
||||
"*** Setting storage: {} -> {} [k={}]",
|
||||
::primitives::hexdisplay::ascii_format(&key),
|
||||
HexDisplay::from(&value),
|
||||
HexDisplay::from(&key),
|
||||
);
|
||||
}
|
||||
this.ext.set_storage(key, value);
|
||||
Ok(())
|
||||
},
|
||||
ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => {
|
||||
let storage_key = this.memory.get(storage_key_data, storage_key_len as usize).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_set_child_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_child_storage"))?;
|
||||
let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_child_storage"))?;
|
||||
ext_set_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
value_data: *const u8,
|
||||
value_len: u32
|
||||
) => {
|
||||
let storage_key = this.memory.get(storage_key_data, storage_key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine storage_key in ext_set_child_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine key in ext_set_child_storage"))?;
|
||||
let value = this.memory.get(value_data, value_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine value in ext_set_child_storage"))?;
|
||||
if let Some(_preimage) = this.hash_lookup.get(&key) {
|
||||
debug_trace!(
|
||||
target: "wasm-trace", "*** Setting child storage: {} -> %{} -> {} [k={}]",
|
||||
@@ -202,12 +228,18 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
this.ext.set_child_storage(storage_key, key, value);
|
||||
Ok(())
|
||||
},
|
||||
ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) => {
|
||||
ext_clear_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32
|
||||
) => {
|
||||
let storage_key = this.memory.get(
|
||||
storage_key_data,
|
||||
storage_key_len as usize
|
||||
).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_clear_child_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_child_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine key in ext_clear_child_storage"))?;
|
||||
debug_trace!(target: "wasm-trace", "*** Clearing child storage: {} -> {} [k={}]",
|
||||
::primitives::hexdisplay::ascii_format(&storage_key),
|
||||
if let Some(_preimage) = this.hash_lookup.get(&key) {
|
||||
@@ -224,7 +256,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_clear_storage(key_data: *const u8, key_len: u32) => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?;
|
||||
debug_trace!(target: "wasm-trace", "*** Clearing storage: {} [k={}]",
|
||||
if let Some(_preimage) = this.hash_lookup.get(&key) {
|
||||
format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage))
|
||||
@@ -235,15 +268,22 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine key in ext_exists_storage"))?;
|
||||
Ok(if this.ext.exists_storage(&key) { 1 } else { 0 })
|
||||
},
|
||||
ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32 => {
|
||||
ext_exists_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32
|
||||
) -> u32 => {
|
||||
let storage_key = this.memory.get(
|
||||
storage_key_data,
|
||||
storage_key_len as usize
|
||||
).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_exists_child_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_child_storage"))?;
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine key in ext_exists_child_storage"))?;
|
||||
let storage_key = ChildStorageKey::from_vec(storage_key)
|
||||
.ok_or_else(||
|
||||
UserError("ext_exists_child_storage: child storage key is not valid")
|
||||
@@ -251,7 +291,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(if this.ext.exists_child_storage(storage_key, &key) { 1 } else { 0 })
|
||||
},
|
||||
ext_clear_prefix(prefix_data: *const u8, prefix_len: u32) => {
|
||||
let prefix = this.memory.get(prefix_data, prefix_len as usize).map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?;
|
||||
let prefix = this.memory.get(prefix_data, prefix_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?;
|
||||
this.ext.clear_prefix(&prefix);
|
||||
Ok(())
|
||||
},
|
||||
@@ -291,7 +332,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
|
||||
if let Some(value) = maybe_value {
|
||||
let offset = this.heap.allocate(value.len() as u32)? as u32;
|
||||
this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?;
|
||||
this.memory.set(offset, &value)
|
||||
.map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?;
|
||||
this.memory.write_primitive(written_out, value.len() as u32)
|
||||
.map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_storage"))?;
|
||||
Ok(offset)
|
||||
@@ -302,7 +344,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
}
|
||||
},
|
||||
// return 0 and place u32::max_value() into written_out if no value exists for the key.
|
||||
ext_get_allocated_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => {
|
||||
ext_get_allocated_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
written_out: *mut u32
|
||||
) -> *mut u8 => {
|
||||
let storage_key = this.memory.get(
|
||||
storage_key_data,
|
||||
storage_key_len as usize
|
||||
@@ -337,7 +385,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
|
||||
if let Some(value) = maybe_value {
|
||||
let offset = this.heap.allocate(value.len() as u32)? as u32;
|
||||
this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_child_storage"))?;
|
||||
this.memory.set(offset, &value)
|
||||
.map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_child_storage"))?;
|
||||
this.memory.write_primitive(written_out, value.len() as u32)
|
||||
.map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_child_storage"))?;
|
||||
Ok(offset)
|
||||
@@ -348,8 +397,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
}
|
||||
},
|
||||
// return u32::max_value() if no value exists for the key.
|
||||
ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?;
|
||||
ext_get_storage_into(
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
value_data: *mut u8,
|
||||
value_len: u32,
|
||||
value_offset: u32
|
||||
) -> u32 => {
|
||||
let key = this.memory.get(key_data, key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?;
|
||||
let maybe_value = this.ext.storage(&key);
|
||||
debug_trace!(target: "wasm-trace", "*** Getting storage: {} == {} [k={}]",
|
||||
if let Some(_preimage) = this.hash_lookup.get(&key) {
|
||||
@@ -368,14 +424,23 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
if let Some(value) = maybe_value {
|
||||
let value = &value[value_offset as usize..];
|
||||
let written = ::std::cmp::min(value_len as usize, value.len());
|
||||
this.memory.set(value_data, &value[..written]).map_err(|_| UserError("Invalid attempt to set value in ext_get_storage_into"))?;
|
||||
this.memory.set(value_data, &value[..written])
|
||||
.map_err(|_| UserError("Invalid attempt to set value in ext_get_storage_into"))?;
|
||||
Ok(written as u32)
|
||||
} else {
|
||||
Ok(u32::max_value())
|
||||
}
|
||||
},
|
||||
// return u32::max_value() if no value exists for the key.
|
||||
ext_get_child_storage_into(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => {
|
||||
ext_get_child_storage_into(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
value_data: *mut u8,
|
||||
value_len: u32,
|
||||
value_offset: u32
|
||||
) -> u32 => {
|
||||
let storage_key = this.memory.get(
|
||||
storage_key_data,
|
||||
storage_key_len as usize
|
||||
@@ -410,7 +475,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
if let Some(value) = maybe_value {
|
||||
let value = &value[value_offset as usize..];
|
||||
let written = ::std::cmp::min(value_len as usize, value.len());
|
||||
this.memory.set(value_data, &value[..written]).map_err(|_| UserError("Invalid attempt to set value in ext_get_child_storage_into"))?;
|
||||
this.memory.set(value_data, &value[..written])
|
||||
.map_err(|_| UserError("Invalid attempt to set value in ext_get_child_storage_into"))?;
|
||||
Ok(written as u32)
|
||||
} else {
|
||||
Ok(u32::max_value())
|
||||
@@ -418,11 +484,17 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
},
|
||||
ext_storage_root(result: *mut u8) => {
|
||||
let r = this.ext.storage_root();
|
||||
this.memory.set(result, r.as_ref()).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?;
|
||||
this.memory.set(result, r.as_ref())
|
||||
.map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8 => {
|
||||
let storage_key = this.memory.get(storage_key_data, storage_key_len as usize).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_child_storage_root"))?;
|
||||
ext_child_storage_root(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
written_out: *mut u32
|
||||
) -> *mut u8 => {
|
||||
let storage_key = this.memory.get(storage_key_data, storage_key_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to determine storage_key in ext_child_storage_root"))?;
|
||||
let storage_key = ChildStorageKey::from_slice(&*storage_key)
|
||||
.ok_or_else(||
|
||||
UserError("ext_child_storage_root: child storage key is not valid")
|
||||
@@ -430,7 +502,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
let value = this.ext.child_storage_root(storage_key);
|
||||
|
||||
let offset = this.heap.allocate(value.len() as u32)? as u32;
|
||||
this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?;
|
||||
this.memory.set(offset, &value)
|
||||
.map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?;
|
||||
this.memory.write_primitive(written_out, value.len() as u32)
|
||||
.map_err(|_| UserError("Invalid attempt to write written_out in ext_child_storage_root"))?;
|
||||
Ok(offset)
|
||||
@@ -446,13 +519,19 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
let r = this.ext.storage_changes_root(parent_hash)
|
||||
.map_err(|_| UserError("Invaid parent_hash passed to ext_storage_changes_root"))?;
|
||||
if let Some(r) = r {
|
||||
this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?;
|
||||
this.memory.set(result, &r[..])
|
||||
.map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?;
|
||||
Ok(1)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
},
|
||||
ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => {
|
||||
ext_blake2_256_enumerated_trie_root(
|
||||
values_data: *const u8,
|
||||
lens_data: *const u32,
|
||||
lens_len: u32,
|
||||
result: *mut u8
|
||||
) => {
|
||||
let values = (0..lens_len)
|
||||
.map(|i| this.memory.read_primitive(lens_data + i * 4))
|
||||
.collect::<::std::result::Result<Vec<u32>, UserError>>()?
|
||||
@@ -464,7 +543,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
)
|
||||
.collect::<::std::result::Result<Vec<_>, UserError>>()?;
|
||||
let r = ordered_trie_root::<Blake2Hasher, _, _>(values.into_iter());
|
||||
this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root"))?;
|
||||
this.memory.set(result, &r[..])
|
||||
.map_err(|_| UserError("Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_chain_id() -> u64 => {
|
||||
@@ -477,7 +557,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
this.hash_lookup.insert(hashed.to_vec(), vec![]);
|
||||
hashed
|
||||
} else {
|
||||
let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_64"))?;
|
||||
let key = this.memory.get(data, len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get key in ext_twox_64"))?;
|
||||
let hashed_key = twox_64(&key);
|
||||
debug_trace!(target: "xxhash", "XXhash: {} -> {}",
|
||||
if let Ok(_skey) = str::from_utf8(&key) {
|
||||
@@ -491,7 +572,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
hashed_key
|
||||
};
|
||||
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_64"))?;
|
||||
this.memory.set(out, &result)
|
||||
.map_err(|_| UserError("Invalid attempt to set result in ext_twox_64"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_twox_128(data: *const u8, len: u32, out: *mut u8) => {
|
||||
@@ -501,7 +583,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
this.hash_lookup.insert(hashed.to_vec(), vec![]);
|
||||
hashed
|
||||
} else {
|
||||
let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?;
|
||||
let key = this.memory.get(data, len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?;
|
||||
let hashed_key = twox_128(&key);
|
||||
debug_trace!(target: "xxhash", "XXhash: {} -> {}",
|
||||
&if let Ok(_skey) = str::from_utf8(&key) {
|
||||
@@ -515,16 +598,20 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
hashed_key
|
||||
};
|
||||
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_128"))?;
|
||||
this.memory.set(out, &result)
|
||||
.map_err(|_| UserError("Invalid attempt to set result in ext_twox_128"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_twox_256(data: *const u8, len: u32, out: *mut u8) => {
|
||||
let result: [u8; 32] = if len == 0 {
|
||||
twox_256(&[0u8; 0])
|
||||
} else {
|
||||
twox_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?)
|
||||
let mem = this.memory.get(data, len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?;
|
||||
twox_256(&mem)
|
||||
};
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_256"))?;
|
||||
this.memory.set(out, &result)
|
||||
.map_err(|_| UserError("Invalid attempt to set result in ext_twox_256"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_blake2_128(data: *const u8, len: u32, out: *mut u8) => {
|
||||
@@ -533,39 +620,50 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
this.hash_lookup.insert(hashed.to_vec(), vec![]);
|
||||
hashed
|
||||
} else {
|
||||
let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_blake2_128"))?;
|
||||
let key = this.memory.get(data, len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get key in ext_blake2_128"))?;
|
||||
let hashed_key = blake2_128(&key);
|
||||
this.hash_lookup.insert(hashed_key.to_vec(), key);
|
||||
hashed_key
|
||||
};
|
||||
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_128"))?;
|
||||
this.memory.set(out, &result)
|
||||
.map_err(|_| UserError("Invalid attempt to set result in ext_blake2_128"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => {
|
||||
let result: [u8; 32] = if len == 0 {
|
||||
blake2_256(&[0u8; 0])
|
||||
} else {
|
||||
blake2_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?)
|
||||
let mem = this.memory.get(data, len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?;
|
||||
blake2_256(&mem)
|
||||
};
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?;
|
||||
this.memory.set(out, &result)
|
||||
.map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_keccak_256(data: *const u8, len: u32, out: *mut u8) => {
|
||||
let result: [u8; 32] = if len == 0 {
|
||||
tiny_keccak::keccak256(&[0u8; 0])
|
||||
} else {
|
||||
tiny_keccak::keccak256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_keccak_256"))?)
|
||||
let mem = this.memory.get(data, len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get data in ext_keccak_256"))?;
|
||||
tiny_keccak::keccak256(&mem)
|
||||
};
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_keccak_256"))?;
|
||||
this.memory.set(out, &result)
|
||||
.map_err(|_| UserError("Invalid attempt to set result in ext_keccak_256"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => {
|
||||
let mut sig = [0u8; 64];
|
||||
this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?;
|
||||
this.memory.get_into(sig_data, &mut sig[..])
|
||||
.map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?;
|
||||
let mut pubkey = [0u8; 32];
|
||||
this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?;
|
||||
let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?;
|
||||
this.memory.get_into(pubkey_data, &mut pubkey[..])
|
||||
.map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?;
|
||||
let msg = this.memory.get(msg_data, msg_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?;
|
||||
|
||||
Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) {
|
||||
0
|
||||
@@ -575,10 +673,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
},
|
||||
ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => {
|
||||
let mut sig = [0u8; 64];
|
||||
this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_sr25519_verify"))?;
|
||||
this.memory.get_into(sig_data, &mut sig[..])
|
||||
.map_err(|_| UserError("Invalid attempt to get signature in ext_sr25519_verify"))?;
|
||||
let mut pubkey = [0u8; 32];
|
||||
this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?;
|
||||
let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?;
|
||||
this.memory.get_into(pubkey_data, &mut pubkey[..])
|
||||
.map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?;
|
||||
let msg = this.memory.get(msg_data, msg_len as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?;
|
||||
|
||||
Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) {
|
||||
0
|
||||
@@ -588,7 +689,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
},
|
||||
ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32 => {
|
||||
let mut sig = [0u8; 65];
|
||||
this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_secp256k1_ecdsa_recover"))?;
|
||||
this.memory.get_into(sig_data, &mut sig[..])
|
||||
.map_err(|_| UserError("Invalid attempt to get signature in ext_secp256k1_ecdsa_recover"))?;
|
||||
let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) {
|
||||
Ok(rs) => rs,
|
||||
_ => return Ok(1),
|
||||
@@ -600,14 +702,16 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
|
||||
|
||||
let mut msg = [0u8; 32];
|
||||
this.memory.get_into(msg_data, &mut msg[..]).map_err(|_| UserError("Invalid attempt to get message in ext_secp256k1_ecdsa_recover"))?;
|
||||
this.memory.get_into(msg_data, &mut msg[..])
|
||||
.map_err(|_| UserError("Invalid attempt to get message in ext_secp256k1_ecdsa_recover"))?;
|
||||
|
||||
let pubkey = match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) {
|
||||
Ok(pk) => pk,
|
||||
_ => return Ok(3),
|
||||
};
|
||||
|
||||
this.memory.set(pubkey_data, &pubkey.serialize()[1..65]).map_err(|_| UserError("Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover"))?;
|
||||
this.memory.set(pubkey_data, &pubkey.serialize()[1..65])
|
||||
.map_err(|_| UserError("Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover"))?;
|
||||
|
||||
Ok(0)
|
||||
},
|
||||
@@ -986,7 +1090,16 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
this.sandbox_store.instance_teardown(instance_idx)?;
|
||||
Ok(())
|
||||
},
|
||||
ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, args_ptr: *const u8, args_len: usize, return_val_ptr: *const u8, return_val_len: usize, state: usize) -> u32 => {
|
||||
ext_sandbox_invoke(
|
||||
instance_idx: u32,
|
||||
export_ptr: *const u8,
|
||||
export_len: usize,
|
||||
args_ptr: *const u8,
|
||||
args_len: usize,
|
||||
return_val_ptr: *const u8,
|
||||
return_val_len: usize,
|
||||
state: usize
|
||||
) -> u32 => {
|
||||
use parity_codec::{Decode, Encode};
|
||||
|
||||
trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_idx);
|
||||
|
||||
@@ -91,7 +91,13 @@ impl_stubs!(
|
||||
[sr25519_verify(&sig, &msg[..], &pubkey) as u8].to_vec()
|
||||
},
|
||||
test_enumerated_trie_root => |_| {
|
||||
enumerated_trie_root::<substrate_primitives::Blake2Hasher>(&[&b"zero"[..], &b"one"[..], &b"two"[..]]).as_ref().to_vec()
|
||||
enumerated_trie_root::<substrate_primitives::Blake2Hasher>(
|
||||
&[
|
||||
&b"zero"[..],
|
||||
&b"one"[..],
|
||||
&b"two"[..],
|
||||
]
|
||||
).as_ref().to_vec()
|
||||
},
|
||||
test_sandbox => |code: &[u8]| {
|
||||
let ok = execute_sandboxed(code, &[]).is_ok();
|
||||
@@ -108,13 +114,15 @@ impl_stubs!(
|
||||
[ok as u8].to_vec()
|
||||
},
|
||||
test_sandbox_return_val => |code: &[u8]| {
|
||||
let result = execute_sandboxed(
|
||||
let ok = match execute_sandboxed(
|
||||
code,
|
||||
&[
|
||||
sandbox::TypedValue::I32(0x1336),
|
||||
]
|
||||
);
|
||||
let ok = if let Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) = result { true } else { false };
|
||||
) {
|
||||
Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) => true,
|
||||
_ => false,
|
||||
};
|
||||
[ok as u8].to_vec()
|
||||
},
|
||||
test_sandbox_instantiate => |code: &[u8]| {
|
||||
|
||||
@@ -10,6 +10,7 @@ substrate-primitives = { path = "../../primitives", default-features = false }
|
||||
parity-codec = { version = "3.3", default-features = false, features = ["derive"] }
|
||||
sr-primitives = { path = "../../sr-primitives", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../sr-std", default-features = false }
|
||||
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -19,4 +20,5 @@ std = [
|
||||
"parity-codec/std",
|
||||
"sr-primitives/std",
|
||||
"rstd/std",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -21,17 +21,32 @@
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use serde::Serialize;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use substrate_primitives::ed25519;
|
||||
use sr_primitives::traits::{DigestFor, NumberFor};
|
||||
use sr_primitives::{ConsensusEngineId, traits::{DigestFor, NumberFor}};
|
||||
use client::decl_runtime_apis;
|
||||
use rstd::vec::Vec;
|
||||
|
||||
use ed25519::Public as AuthorityId;
|
||||
/// The grandpa crypto scheme defined via the keypair type.
|
||||
#[cfg(feature = "std")]
|
||||
pub type AuthorityPair = substrate_primitives::ed25519::Pair;
|
||||
|
||||
/// Identity of a Grandpa authority.
|
||||
pub type AuthorityId = substrate_primitives::ed25519::Public;
|
||||
|
||||
/// Signature for a Grandpa authority.
|
||||
pub type AuthoritySignature = substrate_primitives::ed25519::Signature;
|
||||
|
||||
/// The `ConsensusEngineId` of GRANDPA.
|
||||
pub const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK";
|
||||
|
||||
/// The weight of an authority.
|
||||
pub type AuthorityWeight = u64;
|
||||
|
||||
/// A scheduled change of authority set.
|
||||
#[cfg_attr(feature = "std", derive(Debug, PartialEq))]
|
||||
#[derive(Clone, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode)]
|
||||
pub struct ScheduledChange<N> {
|
||||
/// The new authorities after the change, along with their respective weights.
|
||||
pub next_authorities: Vec<(AuthorityId, u64)>,
|
||||
@@ -44,14 +59,6 @@ pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change";
|
||||
/// WASM function call to get current GRANDPA authorities.
|
||||
pub const AUTHORITIES_CALL: &str = "grandpa_authorities";
|
||||
|
||||
/// Well-known storage keys for GRANDPA.
|
||||
pub mod well_known_keys {
|
||||
/// The key for the authorities and weights vector in storage.
|
||||
pub const AUTHORITY_PREFIX: &[u8] = b":grandpa:auth:";
|
||||
/// The key for the authorities count.
|
||||
pub const AUTHORITY_COUNT: &[u8] = b":grandpa:auth:len";
|
||||
}
|
||||
|
||||
decl_runtime_apis! {
|
||||
/// APIs for integrating the GRANDPA finality gadget into runtimes.
|
||||
/// This should be implemented on the runtime side.
|
||||
@@ -107,6 +114,6 @@ decl_runtime_apis! {
|
||||
/// When called at block B, it will return the set of authorities that should be
|
||||
/// used to finalize descendants of this block (B+1, B+2, ...). The block B itself
|
||||
/// is finalized by the authorities from block B-1.
|
||||
fn grandpa_authorities() -> Vec<(AuthorityId, u64)>;
|
||||
fn grandpa_authorities() -> Vec<(AuthorityId, AuthorityWeight)>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +18,17 @@
|
||||
|
||||
use fork_tree::ForkTree;
|
||||
use parking_lot::RwLock;
|
||||
use substrate_primitives::ed25519;
|
||||
use grandpa::voter_set::VoterSet;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use log::{debug, info};
|
||||
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
use std::cmp::Ord;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Add;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ed25519::Public as AuthorityId;
|
||||
|
||||
/// A shared authority set.
|
||||
pub(crate) struct SharedAuthoritySet<H, N> {
|
||||
inner: Arc<RwLock<AuthoritySet<H, N>>>,
|
||||
@@ -522,8 +520,8 @@ mod tests {
|
||||
pending_forced_changes: Vec::new(),
|
||||
};
|
||||
|
||||
let set_a = vec![(AuthorityId([1; 32]), 5)];
|
||||
let set_b = vec![(AuthorityId([2; 32]), 5)];
|
||||
let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)];
|
||||
let set_b = vec![(AuthorityId::from_raw([2; 32]), 5)];
|
||||
|
||||
// two competing changes at the same height on different forks
|
||||
let change_a = PendingChange {
|
||||
@@ -587,8 +585,8 @@ mod tests {
|
||||
pending_forced_changes: Vec::new(),
|
||||
};
|
||||
|
||||
let set_a = vec![(AuthorityId([1; 32]), 5)];
|
||||
let set_c = vec![(AuthorityId([2; 32]), 5)];
|
||||
let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)];
|
||||
let set_c = vec![(AuthorityId::from_raw([2; 32]), 5)];
|
||||
|
||||
// two competing changes at the same height on different forks
|
||||
let change_a = PendingChange {
|
||||
@@ -653,7 +651,7 @@ mod tests {
|
||||
pending_forced_changes: Vec::new(),
|
||||
};
|
||||
|
||||
let set_a = vec![(AuthorityId([1; 32]), 5)];
|
||||
let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)];
|
||||
|
||||
let change_a = PendingChange {
|
||||
next_authorities: set_a.clone(),
|
||||
@@ -719,8 +717,8 @@ mod tests {
|
||||
pending_forced_changes: Vec::new(),
|
||||
};
|
||||
|
||||
let set_a = vec![(AuthorityId([1; 32]), 5)];
|
||||
let set_b = vec![(AuthorityId([2; 32]), 5)];
|
||||
let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)];
|
||||
let set_b = vec![(AuthorityId::from_raw([2; 32]), 5)];
|
||||
|
||||
let change_a = PendingChange {
|
||||
next_authorities: set_a.clone(),
|
||||
|
||||
@@ -26,14 +26,13 @@ use grandpa::round::State as RoundState;
|
||||
use runtime_primitives::traits::{Block as BlockT, NumberFor};
|
||||
use log::{info, warn};
|
||||
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind};
|
||||
use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges};
|
||||
use crate::environment::{CompletedRound, CompletedRounds, HasVoted, SharedVoterSetState, VoterSetState};
|
||||
use crate::NewAuthoritySet;
|
||||
|
||||
use substrate_primitives::ed25519::Public as AuthorityId;
|
||||
|
||||
const VERSION_KEY: &[u8] = b"grandpa_schema_version";
|
||||
const SET_STATE_KEY: &[u8] = b"grandpa_completed_round";
|
||||
const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
|
||||
|
||||
@@ -37,7 +37,6 @@ use log::{debug, trace};
|
||||
use parity_codec::{Encode, Decode};
|
||||
use substrate_primitives::{ed25519, Pair};
|
||||
use substrate_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO};
|
||||
use runtime_primitives::ConsensusEngineId;
|
||||
use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
|
||||
use network::{consensus_gossip as network_gossip, NetworkService};
|
||||
use network_gossip::ConsensusMessage;
|
||||
@@ -55,8 +54,7 @@ mod periodic;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// The consensus engine ID of GRANDPA.
|
||||
pub const GRANDPA_ENGINE_ID: ConsensusEngineId = [b'a', b'f', b'g', b'1'];
|
||||
pub use fg_primitives::GRANDPA_ENGINE_ID;
|
||||
|
||||
// cost scalars for reporting peers.
|
||||
mod cost {
|
||||
|
||||
@@ -50,8 +50,7 @@ use crate::authorities::{AuthoritySet, SharedAuthoritySet};
|
||||
use crate::consensus_changes::SharedConsensusChanges;
|
||||
use crate::justification::GrandpaJustification;
|
||||
use crate::until_imported::UntilVoteTargetImported;
|
||||
|
||||
use ed25519::Public as AuthorityId;
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
/// Data about a completed round.
|
||||
#[derive(Debug, Clone, Decode, Encode, PartialEq)]
|
||||
|
||||
@@ -49,9 +49,9 @@ use runtime_primitives::{Justification, generic::BlockId};
|
||||
use runtime_primitives::traits::{
|
||||
NumberFor, Block as BlockT, Header as HeaderT, One,
|
||||
};
|
||||
use substrate_primitives::{ed25519, H256, Blake2Hasher};
|
||||
use ed25519::Public as AuthorityId;
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
use crate::justification::GrandpaJustification;
|
||||
|
||||
|
||||
@@ -25,13 +25,12 @@ use grandpa::voter_set::VoterSet;
|
||||
use grandpa::{Error as GrandpaError};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{NumberFor, Block as BlockT, Header as HeaderT};
|
||||
use substrate_primitives::{H256, ed25519, Blake2Hasher};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
use crate::{Commit, Error};
|
||||
use crate::communication;
|
||||
|
||||
use ed25519::Public as AuthorityId;
|
||||
|
||||
/// A GRANDPA justification for block finality, it includes a commit message and
|
||||
/// an ancestry proof including all headers routing all precommit target blocks
|
||||
/// to the commit target block. Due to the current voting strategy the precommit
|
||||
|
||||
@@ -82,8 +82,6 @@ use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
pub use fg_primitives::ScheduledChange;
|
||||
|
||||
mod authorities;
|
||||
mod aux_schema;
|
||||
mod communication;
|
||||
@@ -111,8 +109,10 @@ use import::GrandpaBlockImport;
|
||||
use until_imported::UntilCommitBlocksImported;
|
||||
use communication::NetworkBridge;
|
||||
use service::TelemetryOnConnect;
|
||||
use fg_primitives::AuthoritySignature;
|
||||
|
||||
use ed25519::{Public as AuthorityId, Signature as AuthoritySignature};
|
||||
// Re-export these two because it's just so damn convenient.
|
||||
pub use fg_primitives::{AuthorityId, ScheduledChange};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -35,9 +35,9 @@ use runtime_primitives::Justification;
|
||||
use runtime_primitives::traits::{
|
||||
NumberFor, Block as BlockT, Header as HeaderT, ProvideRuntimeApi, DigestFor,
|
||||
};
|
||||
use fg_primitives::GrandpaApi;
|
||||
use fg_primitives::{GrandpaApi, AuthorityId};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use substrate_primitives::{H256, Blake2Hasher, ed25519::Public as AuthorityId};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
|
||||
use crate::aux_schema::load_decode;
|
||||
use crate::consensus_changes::ConsensusChanges;
|
||||
@@ -610,7 +610,7 @@ pub mod tests {
|
||||
let client = test_client::new_light();
|
||||
let mut import_data = LightImportData {
|
||||
last_finalized: Default::default(),
|
||||
authority_set: LightAuthoritySet::genesis(vec![(AuthorityId([1; 32]), 1)]),
|
||||
authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_raw([1; 32]), 1)]),
|
||||
consensus_changes: ConsensusChanges::empty(),
|
||||
};
|
||||
let block = ImportBlock {
|
||||
@@ -661,7 +661,7 @@ pub mod tests {
|
||||
#[test]
|
||||
fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() {
|
||||
let mut cache = HashMap::new();
|
||||
cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId([2; 32])].encode());
|
||||
cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_raw([2; 32])].encode());
|
||||
assert_eq!(import_block(cache, None), ImportResult::Imported(ImportedAux {
|
||||
clear_justification_requests: false,
|
||||
needs_justification: false,
|
||||
@@ -674,7 +674,7 @@ pub mod tests {
|
||||
fn finality_proof_required_when_consensus_data_changes_and_incorrect_justification_provided() {
|
||||
let justification = TestJustification(false, Vec::new()).encode();
|
||||
let mut cache = HashMap::new();
|
||||
cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId([2; 32])].encode());
|
||||
cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_raw([2; 32])].encode());
|
||||
assert_eq!(
|
||||
import_block(cache, Some(justification)),
|
||||
ImportResult::Imported(ImportedAux {
|
||||
@@ -690,7 +690,7 @@ pub mod tests {
|
||||
#[test]
|
||||
fn aux_data_updated_on_start() {
|
||||
let aux_store = InMemoryAuxStore::<Block>::new();
|
||||
let api = Arc::new(TestApi::new(vec![(AuthorityId([1; 32]), 1)]));
|
||||
let api = Arc::new(TestApi::new(vec![(AuthorityId::from_raw([1; 32]), 1)]));
|
||||
|
||||
// when aux store is empty initially
|
||||
assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none());
|
||||
@@ -705,7 +705,7 @@ pub mod tests {
|
||||
#[test]
|
||||
fn aux_data_loaded_on_restart() {
|
||||
let aux_store = InMemoryAuxStore::<Block>::new();
|
||||
let api = Arc::new(TestApi::new(vec![(AuthorityId([1; 32]), 1)]));
|
||||
let api = Arc::new(TestApi::new(vec![(AuthorityId::from_raw([1; 32]), 1)]));
|
||||
|
||||
// when aux store is non-empty initially
|
||||
let mut consensus_changes = ConsensusChanges::<H256, u64>::empty();
|
||||
@@ -714,7 +714,7 @@ pub mod tests {
|
||||
&[
|
||||
(
|
||||
LIGHT_AUTHORITY_SET_KEY,
|
||||
LightAuthoritySet::genesis(vec![(AuthorityId([42; 32]), 2)]).encode().as_slice(),
|
||||
LightAuthoritySet::genesis(vec![(AuthorityId::from_raw([42; 32]), 2)]).encode().as_slice(),
|
||||
),
|
||||
(
|
||||
LIGHT_CONSENSUS_CHANGES_KEY,
|
||||
@@ -726,7 +726,7 @@ pub mod tests {
|
||||
|
||||
// importer uses it on start
|
||||
let data = load_aux_import_data(Default::default(), &aux_store, api).unwrap();
|
||||
assert_eq!(data.authority_set.authorities(), vec![(AuthorityId([42; 32]), 2)]);
|
||||
assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_raw([42; 32]), 2)]);
|
||||
assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ use log::{debug, info, warn};
|
||||
use consensus_common::SelectChain;
|
||||
use client::{CallExecutor, Client, backend::Backend};
|
||||
use runtime_primitives::traits::{NumberFor, Block as BlockT};
|
||||
use substrate_primitives::{ed25519::Public as AuthorityId, H256, Blake2Hasher};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
|
||||
use crate::{
|
||||
AuthoritySignature, global_communication, CommandOrError, Config, environment,
|
||||
@@ -37,6 +37,7 @@ use crate::authorities::SharedAuthoritySet;
|
||||
use crate::communication::NetworkBridge;
|
||||
use crate::consensus_changes::SharedConsensusChanges;
|
||||
use crate::environment::{CompletedRound, CompletedRounds, HasVoted};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
struct ObserverChain<'a, Block: BlockT, B, E, RA>(&'a Client<B, E, Block, RA>);
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ use std::result;
|
||||
use parity_codec::Decode;
|
||||
use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use substrate_primitives::{NativeOrEncoded, ExecutionContext, ed25519::Public as AuthorityId};
|
||||
use substrate_primitives::{NativeOrEncoded, ExecutionContext};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
use authorities::AuthoritySet;
|
||||
use finality_proof::{FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker};
|
||||
@@ -443,7 +444,7 @@ const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
|
||||
|
||||
fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(substrate_primitives::ed25519::Public, u64)> {
|
||||
keys.iter()
|
||||
.map(|key| AuthorityId(key.to_raw_public()))
|
||||
.map(|key| AuthorityId::from_raw(key.to_raw_public()))
|
||||
.map(|id| (id, 1))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ use futures::prelude::*;
|
||||
use futures::stream::Fuse;
|
||||
use parking_lot::Mutex;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
use substrate_primitives::ed25519::Public as AuthorityId;
|
||||
use tokio::timer::Interval;
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::{atomic::{AtomicUsize, Ordering}, Arc};
|
||||
use std::time::{Duration, Instant};
|
||||
use fg_primitives::AuthorityId;
|
||||
|
||||
const LOG_PENDING_INTERVAL: Duration = Duration::from_secs(15);
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ tokio-timer = "0.2.11"
|
||||
tokio = { version = "0.1.11", optional = true }
|
||||
unsigned-varint = { version = "0.2.1", features = ["codec"] }
|
||||
keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true }
|
||||
test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true }
|
||||
test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client", optional = true }
|
||||
erased-serde = "0.3.9"
|
||||
void = "1.0"
|
||||
@@ -46,6 +47,7 @@ zeroize = "0.6.0"
|
||||
env_logger = { version = "0.6" }
|
||||
keyring = { package = "substrate-keyring", path = "../../core/keyring" }
|
||||
test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" }
|
||||
test_runtime = { package = "substrate-test-runtime", path = "../../core/test-runtime" }
|
||||
consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common", features = ["test-helpers"] }
|
||||
tempdir = "0.3"
|
||||
tokio = "0.1.11"
|
||||
|
||||
@@ -37,17 +37,17 @@ use consensus::import_queue::{
|
||||
Link, SharedBlockImport, SharedJustificationImport, Verifier, SharedFinalityProofImport,
|
||||
SharedFinalityProofRequestBuilder,
|
||||
};
|
||||
use consensus::{Error as ConsensusError};
|
||||
use consensus::{Error as ConsensusError, well_known_cache_keys::{self, Id as CacheKeyId}};
|
||||
use consensus::{BlockOrigin, ForkChoiceStrategy, ImportBlock, JustificationImport};
|
||||
use crate::consensus_gossip::{ConsensusGossip, MessageRecipient as GossipMessageRecipient, TopicNotification};
|
||||
use futures::{prelude::*, sync::{mpsc, oneshot}};
|
||||
use crate::message::Message;
|
||||
use libp2p::PeerId;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use primitives::{H256, sr25519::Public as AuthorityId, Blake2Hasher};
|
||||
use primitives::{H256, Blake2Hasher};
|
||||
use crate::protocol::{Context, Protocol, ProtocolConfig, ProtocolStatus, CustomMessageOutcome, NetworkOut};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor};
|
||||
use runtime_primitives::generic::{BlockId, OpaqueDigestItemId};
|
||||
use runtime_primitives::traits::{Block as BlockT, Header, NumberFor};
|
||||
use runtime_primitives::{Justification, ConsensusEngineId};
|
||||
use crate::service::{NetworkLink, NetworkMsg, ProtocolMsg, TransactionPool};
|
||||
use crate::specialization::NetworkSpecialization;
|
||||
@@ -56,6 +56,8 @@ use test_client::{self, AccountKeyring};
|
||||
pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer};
|
||||
pub use test_client::TestClient;
|
||||
|
||||
type AuthorityId = primitives::sr25519::Public;
|
||||
|
||||
#[cfg(any(test, feature = "test-helpers"))]
|
||||
/// A Verifier that accepts all blocks and passes them on with the configured
|
||||
/// finality to be imported.
|
||||
@@ -70,9 +72,12 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier {
|
||||
header: B::Header,
|
||||
justification: Option<Justification>,
|
||||
body: Option<Vec<B::Extrinsic>>
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<AuthorityIdFor<B>>>), String> {
|
||||
let new_authorities = header.digest().log(DigestItem::as_authorities_change)
|
||||
.map(|auth| auth.iter().cloned().collect());
|
||||
) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
let maybe_keys = header.digest()
|
||||
.log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(b"aura"))
|
||||
.or_else(|| l.try_as_raw(OpaqueDigestItemId::Consensus(b"babe")))
|
||||
)
|
||||
.map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]);
|
||||
|
||||
Ok((ImportBlock {
|
||||
origin,
|
||||
@@ -83,7 +88,7 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier {
|
||||
post_digests: vec![],
|
||||
auxiliary: Vec::new(),
|
||||
fork_choice: ForkChoiceStrategy::LongestChain,
|
||||
}, new_authorities))
|
||||
}, maybe_keys))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ fn bench_ed25519(c: &mut Criterion) {
|
||||
let msg = (0..msg_size)
|
||||
.map(|_| rand::random::<u8>())
|
||||
.collect::<Vec<_>>();
|
||||
let key = substrate_primitives::ed25519::Pair::generate();
|
||||
let key = substrate_primitives::ed25519::Pair::generate().0;
|
||||
b.iter(|| key.sign(&msg))
|
||||
}, vec![32, 1024, 1024 * 1024]);
|
||||
|
||||
@@ -79,7 +79,7 @@ fn bench_ed25519(c: &mut Criterion) {
|
||||
let msg = (0..msg_size)
|
||||
.map(|_| rand::random::<u8>())
|
||||
.collect::<Vec<_>>();
|
||||
let key = substrate_primitives::ed25519::Pair::generate();
|
||||
let key = substrate_primitives::ed25519::Pair::generate().0;
|
||||
let sig = key.sign(&msg);
|
||||
let public = key.public();
|
||||
b.iter(|| substrate_primitives::ed25519::Pair::verify(&sig, &msg, &public))
|
||||
|
||||
@@ -58,18 +58,6 @@ pub mod well_known_keys {
|
||||
/// The type of this value is encoded `u64`.
|
||||
pub const HEAP_PAGES: &'static [u8] = b":heappages";
|
||||
|
||||
/// Number of authorities.
|
||||
///
|
||||
/// The type of this value is encoded `u32`. Required by substrate.
|
||||
pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len";
|
||||
|
||||
/// Prefix under which authorities are storied.
|
||||
///
|
||||
/// The full key for N-th authority is generated as:
|
||||
///
|
||||
/// `(n as u32).to_keyed_vec(AUTHORITY_PREFIX)`.
|
||||
pub const AUTHORITY_PREFIX: &'static [u8] = b":auth:";
|
||||
|
||||
/// Current extrinsic index (u32) is stored under this key.
|
||||
pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index";
|
||||
|
||||
|
||||
@@ -254,9 +254,14 @@ fn should_return_runtime_version() {
|
||||
let client = Arc::new(test_client::new());
|
||||
let api = State::new(client.clone(), Subscriptions::new(core.executor()));
|
||||
|
||||
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
|
||||
\"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\
|
||||
[\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",3],\
|
||||
[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\
|
||||
[\"0xf78b278be53f454c\",1]]}";
|
||||
assert_eq!(
|
||||
serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(),
|
||||
r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",2],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",3],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1],["0xcbca25e39f142387",1],["0xf78b278be53f454c",1],["0x7801759919ee83e5",1]]}"#
|
||||
result,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -281,4 +286,3 @@ fn should_notify_on_runtime_version_initially() {
|
||||
// no more notifications on this channel
|
||||
assert_eq!(core.block_on(next.into_future()).unwrap().0, None);
|
||||
}
|
||||
|
||||
|
||||
@@ -629,12 +629,12 @@ impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<
|
||||
/// # use client::{self, LongestChain};
|
||||
/// # use primitives::{Pair as PairT, ed25519};
|
||||
/// # use consensus_common::import_queue::{BasicQueue, Verifier};
|
||||
/// # use consensus_common::{BlockOrigin, ImportBlock};
|
||||
/// # use consensus_common::{BlockOrigin, ImportBlock, well_known_cache_keys::Id as CacheKeyId};
|
||||
/// # use node_runtime::{GenesisConfig, RuntimeApi};
|
||||
/// # use std::sync::Arc;
|
||||
/// # use node_primitives::Block;
|
||||
/// # use runtime_primitives::Justification;
|
||||
/// # use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT};
|
||||
/// # use runtime_primitives::traits::Block as BlockT;
|
||||
/// # use grandpa;
|
||||
/// # construct_simple_protocol! {
|
||||
/// # pub struct NodeProtocol where Block = Block { }
|
||||
@@ -647,7 +647,7 @@ impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<
|
||||
/// # header: B::Header,
|
||||
/// # justification: Option<Justification>,
|
||||
/// # body: Option<Vec<B::Extrinsic>>,
|
||||
/// # ) -> Result<(ImportBlock<B>, Option<Vec<AuthorityIdFor<B>>>), String> {
|
||||
/// # ) -> Result<(ImportBlock<B>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
|
||||
/// # unimplemented!();
|
||||
/// # }
|
||||
/// # }
|
||||
|
||||
@@ -216,9 +216,12 @@ impl CryptoApi for () {
|
||||
}
|
||||
|
||||
fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> {
|
||||
let rs = secp256k1::Signature::parse_slice(&sig[0..64]).map_err(|_| EcdsaVerifyError::BadRS)?;
|
||||
let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8).map_err(|_| EcdsaVerifyError::BadV)?;
|
||||
let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v).map_err(|_| EcdsaVerifyError::BadSignature)?;
|
||||
let rs = secp256k1::Signature::parse_slice(&sig[0..64])
|
||||
.map_err(|_| EcdsaVerifyError::BadRS)?;
|
||||
let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8)
|
||||
.map_err(|_| EcdsaVerifyError::BadV)?;
|
||||
let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v)
|
||||
.map_err(|_| EcdsaVerifyError::BadSignature)?;
|
||||
let mut res = [0u8; 64];
|
||||
res.copy_from_slice(&pubkey.serialize()[1..65]);
|
||||
Ok(res)
|
||||
|
||||
@@ -232,7 +232,13 @@ pub mod ext {
|
||||
/// - `u32::max_value()` if the value does not exists.
|
||||
///
|
||||
/// - Otherwise, the number of bytes written for value.
|
||||
fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32;
|
||||
fn ext_get_storage_into(
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
value_data: *mut u8,
|
||||
value_len: u32,
|
||||
value_offset: u32
|
||||
) -> u32;
|
||||
/// Gets the trie root of the storage.
|
||||
fn ext_storage_root(result: *mut u8);
|
||||
/// Get the change trie root of the current storage overlay at a block with given parent.
|
||||
@@ -241,26 +247,44 @@ pub mod ext {
|
||||
///
|
||||
/// - `1` if the change trie root was found.
|
||||
/// - `0` if the change trie root was not found.
|
||||
fn ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32;
|
||||
fn ext_storage_changes_root(
|
||||
parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32;
|
||||
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_set_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32);
|
||||
fn ext_set_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
value_data: *const u8,
|
||||
value_len: u32
|
||||
);
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_clear_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32);
|
||||
fn ext_clear_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32
|
||||
);
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_exists_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32;
|
||||
fn ext_exists_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32
|
||||
) -> u32;
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_kill_storage`] for details.
|
||||
@@ -300,13 +324,22 @@ pub mod ext {
|
||||
/// # Returns
|
||||
///
|
||||
/// - The pointer to the result vector and `written_out` contains its length.
|
||||
fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8;
|
||||
fn ext_child_storage_root(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
written_out: *mut u32
|
||||
) -> *mut u8;
|
||||
|
||||
/// The current relay chain identifier.
|
||||
fn ext_chain_id() -> u64;
|
||||
|
||||
/// Calculate a blake2_256 merkle trie root.
|
||||
fn ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8);
|
||||
fn ext_blake2_256_enumerated_trie_root(
|
||||
values_data: *const u8,
|
||||
lens_data: *const u32,
|
||||
lens_len: u32,
|
||||
result: *mut u8
|
||||
);
|
||||
/// BLAKE2_128 hash
|
||||
fn ext_blake2_128(data: *const u8, len: u32, out: *mut u8);
|
||||
/// BLAKE2_256 hash
|
||||
@@ -320,11 +353,25 @@ pub mod ext {
|
||||
/// Keccak256 hash
|
||||
fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8);
|
||||
/// Note: ext_ed25519_verify returns 0 if the signature is correct, nonzero otherwise.
|
||||
fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32;
|
||||
fn ext_ed25519_verify(
|
||||
msg_data: *const u8,
|
||||
msg_len: u32,
|
||||
sig_data: *const u8,
|
||||
pubkey_data: *const u8
|
||||
) -> u32;
|
||||
/// Note: ext_sr25519_verify returns 0 if the signature is correct, nonzero otherwise.
|
||||
fn ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32;
|
||||
fn ext_sr25519_verify(
|
||||
msg_data: *const u8,
|
||||
msg_len: u32,
|
||||
sig_data: *const u8,
|
||||
pubkey_data: *const u8
|
||||
) -> u32;
|
||||
/// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise.
|
||||
fn ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32;
|
||||
fn ext_secp256k1_ecdsa_recover(
|
||||
msg_data: *const u8,
|
||||
sig_data: *const u8,
|
||||
pubkey_data: *mut u8
|
||||
) -> u32;
|
||||
|
||||
//================================
|
||||
// Offchain-worker Context
|
||||
|
||||
@@ -22,191 +22,87 @@ use serde::Serialize;
|
||||
use rstd::prelude::*;
|
||||
|
||||
use crate::ConsensusEngineId;
|
||||
use crate::codec::{Decode, Encode, Codec, Input};
|
||||
use crate::traits::{self, Member, DigestItem as DigestItemT, MaybeHash};
|
||||
use crate::codec::{Decode, Encode, Input};
|
||||
|
||||
/// Generic header digest.
|
||||
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
pub struct Digest<Item> {
|
||||
pub struct Digest<Hash: Encode + Decode> {
|
||||
/// A list of logs in the digest.
|
||||
pub logs: Vec<Item>,
|
||||
pub logs: Vec<DigestItem<Hash>>,
|
||||
}
|
||||
|
||||
impl<Item> Default for Digest<Item> {
|
||||
impl<Item: Encode + Decode> Default for Digest<Item> {
|
||||
fn default() -> Self {
|
||||
Digest { logs: Vec::new(), }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Item> traits::Digest for Digest<Item> where
|
||||
Item: DigestItemT + Codec
|
||||
{
|
||||
type Hash = Item::Hash;
|
||||
type Item = Item;
|
||||
|
||||
fn logs(&self) -> &[Self::Item] {
|
||||
impl<Hash: Encode + Decode> Digest<Hash> {
|
||||
/// Get reference to all digest items.
|
||||
pub fn logs(&self) -> &[DigestItem<Hash>] {
|
||||
&self.logs
|
||||
}
|
||||
|
||||
fn push(&mut self, item: Self::Item) {
|
||||
/// Push new digest item.
|
||||
pub fn push(&mut self, item: DigestItem<Hash>) {
|
||||
self.logs.push(item);
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<Self::Item> {
|
||||
/// Pop a digest item.
|
||||
pub fn pop(&mut self) -> Option<DigestItem<Hash>> {
|
||||
self.logs.pop()
|
||||
}
|
||||
|
||||
/// Get reference to the first digest item that matches the passed predicate.
|
||||
pub fn log<T: ?Sized, F: Fn(&DigestItem<Hash>) -> Option<&T>>(&self, predicate: F) -> Option<&T> {
|
||||
self.logs().iter()
|
||||
.filter_map(predicate)
|
||||
.next()
|
||||
}
|
||||
|
||||
/// Get a conversion of the first digest item that successfully converts using the function.
|
||||
pub fn convert_first<T, F: Fn(&DigestItem<Hash>) -> Option<T>>(&self, predicate: F) -> Option<T> {
|
||||
self.logs().iter()
|
||||
.filter_map(predicate)
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
||||
// Macro black magic.
|
||||
macro_rules! gen_digest_type {
|
||||
(
|
||||
$( #[doc = $main_docs:tt] )*
|
||||
pub enum $main:ident $(<$($main_params: tt),+>)? { }
|
||||
$(
|
||||
$( #[doc = $doc_attr:tt] )*
|
||||
pub enum $n:ident $(<$($t: tt),+>)? {
|
||||
$(
|
||||
$( #[doc = $variant_doc:tt] )*
|
||||
$variant:ident(($($interior: ty),*), $q: tt),
|
||||
)*
|
||||
}
|
||||
)+
|
||||
) => {
|
||||
$( #[doc = $main_docs] )*
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum $main $(<$($main_params),+>)? {
|
||||
$(
|
||||
$(
|
||||
$( #[doc = $variant_doc] )*
|
||||
$variant($($interior),*),
|
||||
)*
|
||||
)*
|
||||
}
|
||||
|
||||
gen_digest_type! {
|
||||
@internal
|
||||
$main : $main $(<$($main_params),+>)? => $(
|
||||
$( #[doc = $doc_attr] )*
|
||||
pub enum $n $(<$($t),+>)? {
|
||||
$(
|
||||
$( #[doc = $variant_doc] )*
|
||||
$variant(($($interior),*), $q),
|
||||
)*
|
||||
}
|
||||
)+
|
||||
}
|
||||
};
|
||||
(
|
||||
@internal
|
||||
$main_id:tt : $main:ty => $(
|
||||
$( #[doc = $doc_attr:tt] )*
|
||||
pub enum $n:ident $(<$($t: tt),+>)? {
|
||||
$(
|
||||
$( #[doc = $variant_doc:tt] )*
|
||||
$variant:ident(($($interior: ty),*), $q: tt),
|
||||
)*
|
||||
}
|
||||
)+
|
||||
) => {
|
||||
$(
|
||||
$( #[doc = $doc_attr] )*
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum $n $(<$($t),+>)? {
|
||||
$(
|
||||
$( #[doc = $variant_doc] )*
|
||||
$variant($($interior),*),
|
||||
)*
|
||||
}
|
||||
/// Digest item that is able to encode/decode 'system' digest items and
|
||||
/// provide opaque access to other items.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum DigestItem<Hash> {
|
||||
/// System digest item that contains the root of changes trie at given
|
||||
/// block. It is created for every block iff runtime supports changes
|
||||
/// trie creation.
|
||||
ChangesTrieRoot(Hash),
|
||||
|
||||
impl<Hash, AuthorityId, SealSignature> From<$n $(<$($t),*>)?>
|
||||
for $main {
|
||||
fn from(digest: $n $(<$($t),+>)?) -> Self {
|
||||
match digest {
|
||||
$(
|
||||
$n::$variant $q => $main_id::$variant $q,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
gen_digest_type! {
|
||||
/// Digest item that is able to encode/decode 'system' digest items and
|
||||
/// provide opaque access to other items.
|
||||
/// A pre-runtime digest.
|
||||
///
|
||||
/// For all variants that include a `ConsensusEngineId`, consensus engine
|
||||
/// implementations **MUST** ignore digests that have a `ConsensusEngineId`
|
||||
/// that is not theirs. Node implementations **MUST** reject digests that
|
||||
/// have a `ConsensusEngineId` that corresponds to a consensus engine not in
|
||||
/// use. Node implementations **MUST** reject blocks as malformed if they
|
||||
/// reject any of the block’s digest. If the runtime supports this, the
|
||||
/// node that issued the block **SHOULD** be reported as having committed
|
||||
/// severe misbehavior and punished accordingly. The invalid block, or its
|
||||
/// hash, **SHOULD** constitute adequate proof of such misbehavior.
|
||||
pub enum DigestItem<Hash, AuthorityId, SealSignature> {}
|
||||
/// These are messages from the consensus engine to the runtime, although
|
||||
/// the consensus engine can (and should) read them itself to avoid
|
||||
/// code and state duplication. It is erroneous for a runtime to produce
|
||||
/// these, but this is not (yet) checked.
|
||||
PreRuntime(ConsensusEngineId, Vec<u8>),
|
||||
|
||||
/// A digest item that can be produced by consensus engines. Consensus
|
||||
/// engine implementations **MUST NOT** push digests not in this variant.
|
||||
/// This **SHOULD** be detected at compile time. If it is not, the behavior
|
||||
/// of the blockchain is undefined.
|
||||
pub enum ConsensusDigest<SealSignature> {
|
||||
/// Put a Seal on it. This **MUST** come after all other `DigestItem`
|
||||
/// variants. There **MUST** be exactly one `Seal` per consensus engine,
|
||||
/// and its `ConsensusEngineId` **MUST** be that of the consensus engine
|
||||
/// that produced it. Runtimes will not see this variant.
|
||||
Seal((ConsensusEngineId, SealSignature), (a, b)),
|
||||
/// An inherent digest.
|
||||
///
|
||||
/// These are messages from the consensus engine to the runtime,
|
||||
/// although the consensus engine can (and should) read them itself to
|
||||
/// avoid code and state duplication. It is erroneous for a runtime to
|
||||
/// produce these, but this is checked at compile time. Runtimes can
|
||||
/// (and should) trust these, as with any other inherent. Consensus
|
||||
/// engines MUST verify them.
|
||||
PreRuntime((ConsensusEngineId, Vec<u8>), (a, b)),
|
||||
}
|
||||
/// A message from the runtime to the consensus engine. This should *never*
|
||||
/// be generated by the native code of any consensus engine, but this is not
|
||||
/// checked (yet).
|
||||
Consensus(ConsensusEngineId, Vec<u8>),
|
||||
|
||||
/// A digest item that can be produced by runtimes. Runtime mplementations
|
||||
/// **MUST NOT** push digests not in this variant. This **SHOULD** be
|
||||
/// detected at compile time. If it is not, the behavior of the blockchain
|
||||
/// is undefined.
|
||||
pub enum RuntimeDigest {
|
||||
/// A message from the runtime to the consensus engine. This MUST NOT be
|
||||
/// generated by the native code of any consensus engine, but this is
|
||||
/// caught at compile time. The `ConsensusEngineId` is that of the
|
||||
/// consensus engine for which this digest is intended. Consensus
|
||||
/// engines MUST ignore digests with `ConsensusEngineId`s other than
|
||||
/// their own.
|
||||
Consensus((ConsensusEngineId, Vec<u8>), (a, b)),
|
||||
/// Any 'non-system' digest item, opaque to the native code. Runtimes
|
||||
/// MUST verify these, and reject any they did not produce. These MUST
|
||||
/// NOT be produced by native code.
|
||||
Other((Vec<u8>), (a)),
|
||||
}
|
||||
/// Put a Seal on it. This is only used by native code, and is never seen
|
||||
/// by runtimes.
|
||||
Seal(ConsensusEngineId, Vec<u8>),
|
||||
|
||||
/// A digest item that is reserved for the SRML. Only the SRML is allowed to
|
||||
/// push these digests. Consensus engines and third-party runtime code
|
||||
/// **MUST NOT** push digests in this variant. This **SHOULD** be detected
|
||||
/// at compile time. If it is not, the behavior of the blockchain is
|
||||
/// undefined.
|
||||
pub enum SystemDigest<Hash, AuthorityId> {
|
||||
/// System digest item announcing that authorities set has been changed
|
||||
/// in the block. Contains the new set of authorities.
|
||||
AuthoritiesChange((Vec<AuthorityId>), (a)),
|
||||
/// System digest item that contains the root of changes trie at given
|
||||
/// block. It is created for every block iff runtime supports changes
|
||||
/// trie creation.
|
||||
ChangesTrieRoot((Hash), (a)),
|
||||
}
|
||||
/// Some other thing. Unsupported and experimental.
|
||||
Other(Vec<u8>),
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<Hash: Encode, AuthorityId: Encode, SealSignature: Encode> ::serde::Serialize for DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
impl<Hash: Encode> ::serde::Serialize for DigestItem<Hash> {
|
||||
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer {
|
||||
self.using_encoded(|bytes| {
|
||||
::substrate_primitives::bytes::serialize(bytes, seq)
|
||||
@@ -214,23 +110,13 @@ impl<Hash: Encode, AuthorityId: Encode, SealSignature: Encode> ::serde::Serializ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A 'referencing view' for digest item. Does not own its contents. Used by
|
||||
/// final runtime implementations for encoding/decoding its log items.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> {
|
||||
/// Reference to `DigestItem::AuthoritiesChange`.
|
||||
AuthoritiesChange(&'a [AuthorityId]),
|
||||
pub enum DigestItemRef<'a, Hash: 'a> {
|
||||
/// Reference to `DigestItem::ChangesTrieRoot`.
|
||||
ChangesTrieRoot(&'a Hash),
|
||||
/// A message from the runtime to the consensus engine. This should *never*
|
||||
/// be generated by the native code of any consensus engine, but this is not
|
||||
/// checked (yet).
|
||||
Consensus(&'a ConsensusEngineId, &'a Vec<u8>),
|
||||
/// Put a Seal on it. This is only used by native code, and is never seen
|
||||
/// by runtimes.
|
||||
Seal(&'a ConsensusEngineId, &'a SealSignature),
|
||||
/// A pre-runtime digest.
|
||||
///
|
||||
/// These are messages from the consensus engine to the runtime, although
|
||||
@@ -238,6 +124,13 @@ pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> {
|
||||
/// code and state duplication. It is erroneous for a runtime to produce
|
||||
/// these, but this is not (yet) checked.
|
||||
PreRuntime(&'a ConsensusEngineId, &'a Vec<u8>),
|
||||
/// A message from the runtime to the consensus engine. This should *never*
|
||||
/// be generated by the native code of any consensus engine, but this is not
|
||||
/// checked (yet).
|
||||
Consensus(&'a ConsensusEngineId, &'a Vec<u8>),
|
||||
/// Put a Seal on it. This is only used by native code, and is never seen
|
||||
/// by runtimes.
|
||||
Seal(&'a ConsensusEngineId, &'a Vec<u8>),
|
||||
/// Any 'non-system' digest item, opaque to the native code.
|
||||
Other(&'a Vec<u8>),
|
||||
}
|
||||
@@ -248,86 +141,105 @@ pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> {
|
||||
/// trait for `DigestItemRef`.
|
||||
#[repr(u32)]
|
||||
#[derive(Encode, Decode)]
|
||||
enum DigestItemType {
|
||||
Other = 0,
|
||||
AuthoritiesChange = 1,
|
||||
pub enum DigestItemType {
|
||||
ChangesTrieRoot = 2,
|
||||
PreRuntime = 6,
|
||||
Consensus = 4,
|
||||
Seal = 5,
|
||||
PreRuntime = 6,
|
||||
Other = 0,
|
||||
}
|
||||
|
||||
impl<Hash, AuthorityId, SealSignature> DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
/// Returns Some if `self` is a `DigestItem::Other`.
|
||||
pub fn as_other(&self) -> Option<&Vec<u8>> {
|
||||
/// Type of a digest item that contains raw data; this also names the consensus engine ID where
|
||||
/// applicable. Used to identify one or more digest items of interest.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum OpaqueDigestItemId<'a> {
|
||||
/// Type corresponding to DigestItem::PreRuntime.
|
||||
PreRuntime(&'a ConsensusEngineId),
|
||||
/// Type corresponding to DigestItem::Consensus.
|
||||
Consensus(&'a ConsensusEngineId),
|
||||
/// Type corresponding to DigestItem::Seal.
|
||||
Seal(&'a ConsensusEngineId),
|
||||
/// Some other (non-prescribed) type.
|
||||
Other,
|
||||
}
|
||||
|
||||
impl<Hash> DigestItem<Hash> {
|
||||
/// Returns a 'referencing view' for this digest item.
|
||||
pub fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash> {
|
||||
match *self {
|
||||
DigestItem::Other(ref v) => Some(v),
|
||||
DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v),
|
||||
DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s),
|
||||
DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s),
|
||||
DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s),
|
||||
DigestItem::Other(ref v) => DigestItemRef::Other(v),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Some` if the entry is the `ChangesTrieRoot` entry.
|
||||
pub fn as_changes_trie_root(&self) -> Option<&Hash> {
|
||||
self.dref().as_changes_trie_root()
|
||||
}
|
||||
|
||||
/// Returns `Some` if this entry is the `PreRuntime` entry.
|
||||
pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> {
|
||||
self.dref().as_pre_runtime()
|
||||
}
|
||||
|
||||
/// Returns `Some` if this entry is the `Consensus` entry.
|
||||
pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &[u8])> {
|
||||
self.dref().as_consensus()
|
||||
}
|
||||
|
||||
/// Returns `Some` if this entry is the `Seal` entry.
|
||||
pub fn as_seal(&self) -> Option<(ConsensusEngineId, &[u8])> {
|
||||
self.dref().as_seal()
|
||||
}
|
||||
|
||||
/// Returns Some if `self` is a `DigestItem::Other`.
|
||||
pub fn as_other(&self) -> Option<&[u8]> {
|
||||
match *self {
|
||||
DigestItem::Other(ref v) => Some(&v[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a 'referencing view' for this digest item.
|
||||
fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId, SealSignature> {
|
||||
match *self {
|
||||
DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v),
|
||||
DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v),
|
||||
DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s),
|
||||
DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s),
|
||||
DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s),
|
||||
DigestItem::Other(ref v) => DigestItemRef::Other(v),
|
||||
}
|
||||
/// Returns the opaque data contained in the item if `Some` if this entry has the id given.
|
||||
pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&[u8]> {
|
||||
self.dref().try_as_raw(id)
|
||||
}
|
||||
|
||||
/// Returns the data contained in the item if `Some` if this entry has the id given, decoded
|
||||
/// to the type provided `T`.
|
||||
pub fn try_to<T: Decode>(&self, id: OpaqueDigestItemId) -> Option<T> {
|
||||
self.dref().try_to::<T>(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Hash: Codec + Member,
|
||||
AuthorityId: Codec + Member + MaybeHash,
|
||||
SealSignature: Codec + Member,
|
||||
> traits::DigestItem for DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
type Hash = Hash;
|
||||
type AuthorityId = AuthorityId;
|
||||
|
||||
fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> {
|
||||
self.dref().as_authorities_change()
|
||||
}
|
||||
|
||||
fn as_changes_trie_root(&self) -> Option<&Self::Hash> {
|
||||
self.dref().as_changes_trie_root()
|
||||
}
|
||||
|
||||
fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> {
|
||||
self.dref().as_pre_runtime()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
impl<Hash: Encode> Encode for DigestItem<Hash> {
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
self.dref().encode()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Hash: Decode, AuthorityId: Decode, SealSignature: Decode> Decode for DigestItem<Hash, AuthorityId, SealSignature> {
|
||||
impl<Hash: Decode> Decode for DigestItem<Hash> {
|
||||
#[allow(deprecated)]
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
let item_type: DigestItemType = Decode::decode(input)?;
|
||||
match item_type {
|
||||
DigestItemType::AuthoritiesChange => Some(DigestItem::AuthoritiesChange(
|
||||
Decode::decode(input)?,
|
||||
)),
|
||||
DigestItemType::ChangesTrieRoot => Some(DigestItem::ChangesTrieRoot(
|
||||
Decode::decode(input)?,
|
||||
)),
|
||||
DigestItemType::PreRuntime => {
|
||||
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
|
||||
Some(DigestItem::PreRuntime(vals.0, vals.1))
|
||||
},
|
||||
DigestItemType::Consensus => {
|
||||
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
|
||||
Some(DigestItem::Consensus(vals.0, vals.1))
|
||||
}
|
||||
DigestItemType::Seal => {
|
||||
let vals: (ConsensusEngineId, SealSignature) = Decode::decode(input)?;
|
||||
Some(DigestItem::Seal(vals.0, vals.1))
|
||||
},
|
||||
DigestItemType::PreRuntime => {
|
||||
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
|
||||
Some(DigestItem::PreRuntime(vals.0, vals.1))
|
||||
Some(DigestItem::Seal(vals.0, vals.1))
|
||||
},
|
||||
DigestItemType::Other => Some(DigestItem::Other(
|
||||
Decode::decode(input)?,
|
||||
@@ -336,15 +248,7 @@ impl<Hash: Decode, AuthorityId: Decode, SealSignature: Decode> Decode for Digest
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec + Member> DigestItemRef<'a, Hash, AuthorityId, SealSignature> {
|
||||
/// Cast this digest item into `AuthoritiesChange`.
|
||||
pub fn as_authorities_change(&self) -> Option<&'a [AuthorityId]> {
|
||||
match *self {
|
||||
DigestItemRef::AuthoritiesChange(ref authorities) => Some(authorities),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Hash> DigestItemRef<'a, Hash> {
|
||||
/// Cast this digest item into `ChangesTrieRoot`.
|
||||
pub fn as_changes_trie_root(&self) -> Option<&'a Hash> {
|
||||
match *self {
|
||||
@@ -360,17 +264,56 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast this digest item into `Consensus`
|
||||
pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &'a [u8])> {
|
||||
match *self {
|
||||
DigestItemRef::Consensus(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast this digest item into `Seal`
|
||||
pub fn as_seal(&self) -> Option<(ConsensusEngineId, &'a [u8])> {
|
||||
match *self {
|
||||
DigestItemRef::Seal(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast this digest item into `PreRuntime`
|
||||
pub fn as_other(&self) -> Option<&'a [u8]> {
|
||||
match *self {
|
||||
DigestItemRef::Other(ref data) => Some(data),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to match this digest item to the given opaque item identifier; if it matches, then
|
||||
/// return the opaque data it contains.
|
||||
pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&'a [u8]> {
|
||||
match (id, self) {
|
||||
(OpaqueDigestItemId::Consensus(w), &DigestItemRef::Consensus(v, s)) |
|
||||
(OpaqueDigestItemId::Seal(w), &DigestItemRef::Seal(v, s)) |
|
||||
(OpaqueDigestItemId::PreRuntime(w), &DigestItemRef::PreRuntime(v, s))
|
||||
if v == w => Some(&s[..]),
|
||||
(OpaqueDigestItemId::Other, &DigestItemRef::Other(s)) => Some(&s[..]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to match this digest item to the given opaque item identifier; if it matches, then
|
||||
/// try to cast to the given datatype; if that works, return it.
|
||||
pub fn try_to<T: Decode>(&self, id: OpaqueDigestItemId) -> Option<T> {
|
||||
self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId, SealSignature> {
|
||||
impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
|
||||
match *self {
|
||||
DigestItemRef::AuthoritiesChange(authorities) => {
|
||||
DigestItemType::AuthoritiesChange.encode_to(&mut v);
|
||||
authorities.encode_to(&mut v);
|
||||
},
|
||||
DigestItemRef::ChangesTrieRoot(changes_trie_root) => {
|
||||
DigestItemType::ChangesTrieRoot.encode_to(&mut v);
|
||||
changes_trie_root.encode_to(&mut v);
|
||||
@@ -400,22 +343,20 @@ impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for Di
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_primitives::hash::H512 as Signature;
|
||||
|
||||
#[test]
|
||||
fn should_serialize_digest() {
|
||||
let digest = Digest {
|
||||
logs: vec![
|
||||
DigestItem::AuthoritiesChange(vec![1]),
|
||||
DigestItem::ChangesTrieRoot(4),
|
||||
DigestItem::Other(vec![1, 2, 3]),
|
||||
DigestItem::Seal(Default::default(), Signature::default())
|
||||
DigestItem::Seal(*b"test", vec![1, 2, 3])
|
||||
],
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
::serde_json::to_string(&digest).unwrap(),
|
||||
"{\"logs\":[\"0x010401000000\",\"0x0204000000\",\"0x000c010203\",\"0x050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"]}",
|
||||
r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,10 @@ use serde::Serialize;
|
||||
#[cfg(feature = "std")]
|
||||
use log::debug;
|
||||
use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef};
|
||||
use crate::traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay,
|
||||
Hash as HashT, DigestItem as DigestItemT, MaybeSerializeDebug,
|
||||
MaybeSerializeDebugButNotDeserialize};
|
||||
use crate::traits::{
|
||||
self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug,
|
||||
MaybeSerializeDebugButNotDeserialize
|
||||
};
|
||||
use crate::generic::Digest;
|
||||
|
||||
/// Abstraction over a block header for a substrate chain.
|
||||
@@ -31,7 +32,7 @@ use crate::generic::Digest;
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
||||
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
|
||||
pub struct Header<Number: Copy + Into<u128>, Hash: HashT, DigestItem> {
|
||||
pub struct Header<Number: Copy + Into<u128>, Hash: HashT> {
|
||||
/// The parent hash.
|
||||
pub parent_hash: <Hash as HashT>::Output,
|
||||
/// The block number.
|
||||
@@ -42,7 +43,7 @@ pub struct Header<Number: Copy + Into<u128>, Hash: HashT, DigestItem> {
|
||||
/// The merkle root of the extrinsics.
|
||||
pub extrinsics_root: <Hash as HashT>::Output,
|
||||
/// A chain-specific digest of data useful for light clients or referencing auxiliary data.
|
||||
pub digest: Digest<DigestItem>,
|
||||
pub digest: Digest<<Hash as HashT>::Output>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@@ -54,11 +55,10 @@ pub fn serialize_number<S, T: Copy + Into<u128>>(val: &T, s: S) -> Result<S::Ok,
|
||||
::serde::Serialize::serialize(&(upper + lower), s)
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem> Decode for Header<Number, Hash, DigestItem> where
|
||||
impl<Number, Hash> Decode for Header<Number, Hash> where
|
||||
Number: HasCompact + Copy + Into<u128>,
|
||||
Hash: HashT,
|
||||
Hash::Output: Decode,
|
||||
DigestItem: DigestItemT + Decode,
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Header {
|
||||
@@ -71,11 +71,10 @@ impl<Number, Hash, DigestItem> Decode for Header<Number, Hash, DigestItem> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem> Encode for Header<Number, Hash, DigestItem> where
|
||||
impl<Number, Hash> Encode for Header<Number, Hash> where
|
||||
Number: HasCompact + Copy + Into<u128>,
|
||||
Hash: HashT,
|
||||
Hash::Output: Encode,
|
||||
DigestItem: DigestItemT + Encode,
|
||||
{
|
||||
fn encode_to<T: Output>(&self, dest: &mut T) {
|
||||
dest.push(&self.parent_hash);
|
||||
@@ -86,16 +85,14 @@ impl<Number, Hash, DigestItem> Encode for Header<Number, Hash, DigestItem> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestItem> where
|
||||
impl<Number, Hash> traits::Header for Header<Number, Hash> where
|
||||
Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + MaybeDisplay + SimpleArithmetic + Codec + Copy + Into<u128>,
|
||||
Hash: HashT,
|
||||
DigestItem: DigestItemT<Hash = Hash::Output> + Codec,
|
||||
Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeSerializeDebugButNotDeserialize + MaybeDisplay + SimpleBitOps + Codec,
|
||||
{
|
||||
type Number = Number;
|
||||
type Hash = <Hash as HashT>::Output;
|
||||
type Hashing = Hash;
|
||||
type Digest = Digest<DigestItem>;
|
||||
|
||||
fn number(&self) -> &Self::Number { &self.number }
|
||||
fn set_number(&mut self, num: Self::Number) { self.number = num }
|
||||
@@ -109,23 +106,23 @@ impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestIte
|
||||
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
|
||||
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
|
||||
|
||||
fn digest(&self) -> &Self::Digest { &self.digest }
|
||||
fn digest(&self) -> &Digest<Self::Hash> { &self.digest }
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn digest_mut(&mut self) -> &mut Self::Digest {
|
||||
fn digest_mut(&mut self) -> &mut Digest<Self::Hash> {
|
||||
debug!(target: "header", "Retrieving mutable reference to digest");
|
||||
&mut self.digest
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest }
|
||||
fn digest_mut(&mut self) -> &mut Digest<Self::Hash> { &mut self.digest }
|
||||
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest,
|
||||
digest: Digest<Self::Hash>,
|
||||
) -> Self {
|
||||
Header {
|
||||
number,
|
||||
@@ -137,10 +134,9 @@ impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestIte
|
||||
}
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem> Header<Number, Hash, DigestItem> where
|
||||
impl<Number, Hash> Header<Number, Hash> where
|
||||
Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into<u128>,
|
||||
Hash: HashT,
|
||||
DigestItem: DigestItemT + Codec,
|
||||
Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec,
|
||||
{
|
||||
/// Convenience helper for computing the hash of the header without having
|
||||
|
||||
@@ -37,7 +37,7 @@ pub use self::checked_extrinsic::CheckedExtrinsic;
|
||||
pub use self::header::Header;
|
||||
pub use self::block::{Block, SignedBlock, BlockId};
|
||||
pub use self::digest::{
|
||||
Digest, DigestItem, DigestItemRef, ConsensusDigest, RuntimeDigest, SystemDigest,
|
||||
Digest, DigestItem, DigestItemRef, OpaqueDigestItemId
|
||||
};
|
||||
|
||||
use crate::codec::Encode;
|
||||
|
||||
@@ -17,31 +17,34 @@
|
||||
//! Tests for the generic implementations of Extrinsic/Header/Block.
|
||||
|
||||
use crate::codec::{Decode, Encode};
|
||||
use substrate_primitives::{H256, H512};
|
||||
use substrate_primitives::H256;
|
||||
use super::DigestItem;
|
||||
|
||||
#[test]
|
||||
fn system_digest_item_encoding() {
|
||||
let item = DigestItem::AuthoritiesChange::<H256, u32, H512>(vec![10, 20, 30]);
|
||||
let item = DigestItem::ChangesTrieRoot::<H256>(H256::default());
|
||||
let encoded = item.encode();
|
||||
assert_eq!(encoded, vec![
|
||||
// type = DigestItemType::AuthoritiesChange
|
||||
1,
|
||||
// number of items in authorities set
|
||||
12,
|
||||
// authorities
|
||||
10, 0, 0, 0,
|
||||
20, 0, 0, 0,
|
||||
30, 0, 0, 0,
|
||||
// type = DigestItemType::ChangesTrieRoot
|
||||
2,
|
||||
// trie root
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
]);
|
||||
|
||||
let decoded: DigestItem<H256, u32, H512> = Decode::decode(&mut &encoded[..]).unwrap();
|
||||
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
|
||||
assert_eq!(item, decoded);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_system_digest_item_encoding() {
|
||||
let item = DigestItem::Other::<H256, u32, H512>(vec![10, 20, 30]);
|
||||
let item = DigestItem::Other::<H256>(vec![10, 20, 30]);
|
||||
let encoded = item.encode();
|
||||
assert_eq!(encoded, vec![
|
||||
// type = DigestItemType::Other
|
||||
@@ -52,6 +55,6 @@ fn non_system_digest_item_encoding() {
|
||||
10, 20, 30,
|
||||
]);
|
||||
|
||||
let decoded: DigestItem<H256, u32, H512> = Decode::decode(&mut &encoded[..]).unwrap();
|
||||
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
|
||||
assert_eq!(item, decoded);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ use traits::{SaturatedConversion, UniqueSaturatedInto};
|
||||
pub mod generic;
|
||||
pub mod transaction_validity;
|
||||
|
||||
/// Re-export these since they're only "kind of" generic.
|
||||
pub use generic::{DigestItem, Digest};
|
||||
|
||||
/// A message indicating an invalid signature in extrinsic.
|
||||
pub const BAD_SIGNATURE: &str = "bad signature in extrinsic";
|
||||
|
||||
@@ -614,216 +617,6 @@ macro_rules! impl_outer_config {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE [`PreRuntime` and `Consensus` are special]
|
||||
//
|
||||
// We MUST treat `PreRuntime` and `Consensus` variants specially, as they:
|
||||
//
|
||||
// * have more parameters (both in `generic::DigestItem` and in runtimes)
|
||||
// * have a `PhantomData` parameter in the runtime, but not in `generic::DigestItem`
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __parse_pattern_2 {
|
||||
(PreRuntime $module:ident $internal:ident $v1:ident $v2:ident) => {
|
||||
$internal::$module($module::RawLog::PreRuntime(ref $v1, ref $v2, $crate::rstd::marker::PhantomData))
|
||||
};
|
||||
(Consensus $module:ident $internal:ident $v1:ident $v2:ident) => {
|
||||
$internal::$module($module::RawLog::Consensus(ref $v1, ref $v2, $crate::rstd::marker::PhantomData))
|
||||
};
|
||||
($name:ident $module:ident $internal:ident $v1:ident $v2:ident) => {
|
||||
$internal::$module($module::RawLog::$name(ref $v1))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __parse_pattern {
|
||||
(PreRuntime $engine_id:pat, $binder:pat) => {
|
||||
$crate::generic::DigestItem::PreRuntime($engine_id, $binder)
|
||||
};
|
||||
(Consensus $engine_id:pat, $binder:pat) => {
|
||||
$crate::generic::DigestItem::Consensus($engine_id, $binder)
|
||||
};
|
||||
($name:ident $engine_id:pat, $binder:pat) => {
|
||||
$crate::generic::DigestItem::$name($binder)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __parse_expr {
|
||||
(PreRuntime $engine_id:expr, $module:ident $internal:ident $binder:expr) => {
|
||||
$internal::$module($module::RawLog::PreRuntime($engine_id, $binder, Default::default()))
|
||||
};
|
||||
(Consensus $engine_id:expr, $module:ident $internal:ident $binder:expr) => {
|
||||
$internal::$module($module::RawLog::Consensus($engine_id, $binder, Default::default()))
|
||||
};
|
||||
($name:ident $engine_id:expr, $module:ident $internal:ident $binder:expr) => {
|
||||
$internal::$module($module::RawLog::$name($binder))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __parse_expr_2 {
|
||||
(PreRuntime $module:ident $internal:ident $v1:ident $v2:ident) => {
|
||||
$crate::generic::DigestItemRef::PreRuntime($v1, $v2)
|
||||
};
|
||||
(Consensus $module:ident $internal:ident $v1:ident $v2:ident) => {
|
||||
$crate::generic::DigestItemRef::Consensus($v1, $v2)
|
||||
};
|
||||
($name:ident $module:ident $internal:ident $v1:ident $v2:ident) => {
|
||||
$crate::generic::DigestItemRef::$name($v1)
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates enum that contains all possible log entries for the runtime.
|
||||
/// Every individual module of the runtime that is mentioned, must
|
||||
/// expose a `Log` and `RawLog` enums.
|
||||
///
|
||||
/// Generated enum is binary-compatible with and could be interpreted
|
||||
/// as `generic::DigestItem`.
|
||||
///
|
||||
/// Runtime requirements:
|
||||
/// 1) binary representation of all supported 'system' log items should stay
|
||||
/// the same. Otherwise, the native code will be unable to read log items
|
||||
/// generated by previous runtime versions
|
||||
/// 2) the support of 'system' log items should never be dropped by runtime.
|
||||
/// Otherwise, native code will lost its ability to read items of this type
|
||||
/// even if they were generated by the versions which have supported these
|
||||
/// items.
|
||||
#[macro_export]
|
||||
macro_rules! impl_outer_log {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $name:ident ($internal:ident: DigestItem<$( $genarg:ty ),*>) for $trait:ident {
|
||||
$( $module:ident $(<$instance:path>)? ( $( $sitem:tt ),* ) ),*
|
||||
}
|
||||
) => {
|
||||
/// Wrapper for all possible log entries for the `$trait` runtime. Provides binary-compatible
|
||||
/// `Encode`/`Decode` implementations with the corresponding `generic::DigestItem`.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, $crate::serde::Serialize))]
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct $name($internal);
|
||||
|
||||
/// All possible log entries for the `$trait` runtime. `Encode`/`Decode` implementations
|
||||
/// are auto-generated => it is not binary-compatible with `generic::DigestItem`.
|
||||
#[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, $crate::serde::Serialize))]
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum InternalLog {
|
||||
$(
|
||||
$module($module::Log <$trait $(, $instance)?>),
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
/// Try to convert `$name` into `generic::DigestItemRef`. Returns Some when
|
||||
/// `self` is a 'system' log && it has been marked as 'system' in macro call.
|
||||
/// Otherwise, None is returned.
|
||||
#[allow(unreachable_patterns)]
|
||||
fn dref<'a>(&'a self) -> Option<$crate::generic::DigestItemRef<'a, $($genarg),*>> {
|
||||
match self.0 {
|
||||
$($(
|
||||
$crate::__parse_pattern_2!($sitem $module $internal a b) =>
|
||||
Some($crate::__parse_expr_2!($sitem $module $internal a b)),
|
||||
)*)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::traits::DigestItem for $name {
|
||||
type Hash = <$crate::generic::DigestItem<$($genarg),*> as $crate::traits::DigestItem>::Hash;
|
||||
type AuthorityId = <$crate::generic::DigestItem<$($genarg),*> as $crate::traits::DigestItem>::AuthorityId;
|
||||
|
||||
fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> {
|
||||
self.dref().and_then(|dref| dref.as_authorities_change())
|
||||
}
|
||||
|
||||
fn as_changes_trie_root(&self) -> Option<&Self::Hash> {
|
||||
self.dref().and_then(|dref| dref.as_changes_trie_root())
|
||||
}
|
||||
|
||||
fn as_pre_runtime(&self) -> Option<($crate::ConsensusEngineId, &[u8])> {
|
||||
self.dref().and_then(|dref| dref.as_pre_runtime())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$crate::generic::DigestItem<$($genarg),*>> for $name {
|
||||
/// Converts `generic::DigestItem` into `$name`. If
|
||||
/// `generic::DigestItem` represents a system item which is
|
||||
/// supported by the runtime, it is returned. Otherwise we expect a
|
||||
/// `Other`, `PreDigest`, or `Consensus` log item. Trying to convert
|
||||
/// from anything else will lead to panic at runtime, since the
|
||||
/// runtime does not supports this 'system' log item.
|
||||
#[allow(unreachable_patterns)]
|
||||
fn from(gen: $crate::generic::DigestItem<$($genarg),*>) -> Self {
|
||||
match gen {
|
||||
$($(
|
||||
$crate::__parse_pattern!($sitem b, a) =>
|
||||
$name($crate::__parse_expr!($sitem b, $module $internal a)),
|
||||
)*)*
|
||||
_ => {
|
||||
if let Some(s) = gen.as_other()
|
||||
.and_then(|value| $crate::codec::Decode::decode(&mut &value[..]))
|
||||
.map($name)
|
||||
{
|
||||
s
|
||||
} else {
|
||||
panic!("we only reach here if the runtime did not handle a digest; \
|
||||
runtimes are required to handle all digests they receive; qed"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::codec::Decode for $name {
|
||||
/// `generic::DigestItem` binary compatible decode.
|
||||
fn decode<I: $crate::codec::Input>(input: &mut I) -> Option<Self> {
|
||||
let gen: $crate::generic::DigestItem<$($genarg),*> =
|
||||
$crate::codec::Decode::decode(input)?;
|
||||
Some($name::from(gen))
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::codec::Encode for $name {
|
||||
/// `generic::DigestItem` binary compatible encode.
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
match self.dref() {
|
||||
Some(dref) => dref.encode(),
|
||||
None => {
|
||||
let gen: $crate::generic::DigestItem<$($genarg),*> =
|
||||
$crate::generic::DigestItem::Other(self.0.encode());
|
||||
gen.encode()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl From<$module::Log<$trait $(, $instance)?>> for $name {
|
||||
/// Converts single module log item into `$name`.
|
||||
fn from(x: $module::Log<$trait $(, $instance)? >) -> Self {
|
||||
$name(x.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$module::Log<$trait $(, $instance)?>> for InternalLog {
|
||||
/// Converts single module log item into `$internal`.
|
||||
fn from(x: $module::Log<$trait $(, $instance)?>) -> Self {
|
||||
InternalLog::$module(x)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized
|
||||
/// correctly.
|
||||
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
|
||||
@@ -851,45 +644,7 @@ impl traits::Extrinsic for OpaqueExtrinsic {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use substrate_primitives::hash::{H256, H512};
|
||||
use crate::codec::{Encode, Decode};
|
||||
use crate::traits::DigestItem;
|
||||
|
||||
pub trait RuntimeT {
|
||||
type AuthorityId;
|
||||
}
|
||||
|
||||
pub struct Runtime;
|
||||
|
||||
impl RuntimeT for Runtime {
|
||||
type AuthorityId = u64;
|
||||
}
|
||||
|
||||
mod a {
|
||||
use super::RuntimeT;
|
||||
use crate::codec::{Encode, Decode};
|
||||
use serde::Serialize;
|
||||
pub type Log<R> = RawLog<<R as RuntimeT>::AuthorityId>;
|
||||
|
||||
#[derive(Serialize, Debug, Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<AuthorityId> { A1(AuthorityId), AuthoritiesChange(Vec<AuthorityId>), A3(AuthorityId) }
|
||||
}
|
||||
|
||||
mod b {
|
||||
use super::RuntimeT;
|
||||
use crate::codec::{Encode, Decode};
|
||||
use serde::Serialize;
|
||||
pub type Log<R> = RawLog<<R as RuntimeT>::AuthorityId>;
|
||||
|
||||
#[derive(Serialize, Debug, Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<AuthorityId> { B1(AuthorityId), B2(AuthorityId) }
|
||||
}
|
||||
|
||||
impl_outer_log! {
|
||||
pub enum Log(InternalLog: DigestItem<H256, u64, H512>) for Runtime {
|
||||
a(AuthoritiesChange), b()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! per_thing_mul_upper_test {
|
||||
($num_type:tt, $per:tt) => {
|
||||
@@ -909,41 +664,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_outer_log_works() {
|
||||
// encode/decode regular item
|
||||
let b1: Log = b::RawLog::B1::<u64>(777).into();
|
||||
let encoded_b1 = b1.encode();
|
||||
let decoded_b1: Log = Decode::decode(&mut &encoded_b1[..]).unwrap();
|
||||
assert_eq!(b1, decoded_b1);
|
||||
|
||||
// encode/decode system item
|
||||
let auth_change: Log = a::RawLog::AuthoritiesChange::<u64>(vec![100, 200, 300]).into();
|
||||
let encoded_auth_change = auth_change.encode();
|
||||
let decoded_auth_change: Log = Decode::decode(&mut &encoded_auth_change[..]).unwrap();
|
||||
assert_eq!(auth_change, decoded_auth_change);
|
||||
|
||||
// interpret regular item using `generic::DigestItem`
|
||||
let generic_b1: super::generic::DigestItem<H256, u64, H512> = Decode::decode(&mut &encoded_b1[..]).unwrap();
|
||||
match generic_b1 {
|
||||
super::generic::DigestItem::Other(_) => (),
|
||||
_ => panic!("unexpected generic_b1: {:?}", generic_b1),
|
||||
}
|
||||
|
||||
// interpret system item using `generic::DigestItem`
|
||||
let generic_auth_change: super::generic::DigestItem<H256, u64, H512> = Decode::decode(&mut &encoded_auth_change[..]).unwrap();
|
||||
match generic_auth_change {
|
||||
super::generic::DigestItem::AuthoritiesChange::<H256, u64, H512>(authorities) => assert_eq!(authorities, vec![100, 200, 300]),
|
||||
_ => panic!("unexpected generic_auth_change: {:?}", generic_auth_change),
|
||||
}
|
||||
|
||||
// check that as-style methods are working with system items
|
||||
assert!(auth_change.as_authorities_change().is_some());
|
||||
|
||||
// check that as-style methods are not working with regular items
|
||||
assert!(b1.as_authorities_change().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opaque_extrinsic_serialization() {
|
||||
let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer};
|
||||
use std::{fmt::Debug, ops::Deref, fmt};
|
||||
use crate::codec::{Codec, Encode, Decode};
|
||||
use crate::traits::{self, Checkable, Applyable, BlakeTwo256, Convert};
|
||||
use crate::traits::{self, Checkable, Applyable, BlakeTwo256, OpaqueKeys};
|
||||
use crate::generic;
|
||||
use crate::weights::{Weighable, Weight};
|
||||
use crate::generic::DigestItem as GenDigestItem;
|
||||
pub use substrate_primitives::H256;
|
||||
use substrate_primitives::U256;
|
||||
use substrate_primitives::sr25519::{Public as AuthorityId, Signature as AuthoritySignature};
|
||||
use substrate_primitives::ed25519::{Public as AuthorityId};
|
||||
|
||||
/// Authority Id
|
||||
#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)]
|
||||
@@ -37,39 +37,19 @@ impl Into<AuthorityId> for UintAuthorityId {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converter between u64 and the AuthorityId wrapper type.
|
||||
pub struct ConvertUintAuthorityId;
|
||||
impl Convert<u64, Option<UintAuthorityId>> for ConvertUintAuthorityId {
|
||||
fn convert(a: u64) -> Option<UintAuthorityId> {
|
||||
Some(UintAuthorityId(a))
|
||||
}
|
||||
impl OpaqueKeys for UintAuthorityId {
|
||||
fn count() -> usize { 1 }
|
||||
// Unsafe, i know, but it's test code and it's just there because it's really convenient to
|
||||
// keep `UintAuthorityId` as a u64 under the hood.
|
||||
fn get_raw(&self, _: usize) -> &[u8] { unsafe { &std::mem::transmute::<_, &[u8; 8]>(&self.0)[..] } }
|
||||
fn get<T: Decode>(&self, _: usize) -> Option<T> { self.0.using_encoded(|mut x| T::decode(&mut x)) }
|
||||
}
|
||||
|
||||
/// Digest item
|
||||
pub type DigestItem = GenDigestItem<H256, AuthorityId, AuthoritySignature>;
|
||||
pub type DigestItem = generic::DigestItem<H256>;
|
||||
|
||||
/// Header Digest
|
||||
#[derive(Default, PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)]
|
||||
pub struct Digest {
|
||||
/// Generated logs
|
||||
pub logs: Vec<DigestItem>,
|
||||
}
|
||||
|
||||
impl traits::Digest for Digest {
|
||||
type Hash = H256;
|
||||
type Item = DigestItem;
|
||||
|
||||
fn logs(&self) -> &[Self::Item] {
|
||||
&self.logs
|
||||
}
|
||||
|
||||
fn push(&mut self, item: Self::Item) {
|
||||
self.logs.push(item);
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<Self::Item> {
|
||||
self.logs.pop()
|
||||
}
|
||||
}
|
||||
pub type Digest = generic::Digest<H256>;
|
||||
|
||||
/// Block Header
|
||||
#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)]
|
||||
@@ -92,7 +72,6 @@ impl traits::Header for Header {
|
||||
type Number = u64;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Hash = H256;
|
||||
type Digest = Digest;
|
||||
|
||||
fn number(&self) -> &Self::Number { &self.number }
|
||||
fn set_number(&mut self, num: Self::Number) { self.number = num }
|
||||
@@ -106,15 +85,15 @@ impl traits::Header for Header {
|
||||
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
|
||||
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
|
||||
|
||||
fn digest(&self) -> &Self::Digest { &self.digest }
|
||||
fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest }
|
||||
fn digest(&self) -> &Digest { &self.digest }
|
||||
fn digest_mut(&mut self) -> &mut Digest { &mut self.digest }
|
||||
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest,
|
||||
digest: Digest,
|
||||
) -> Self {
|
||||
Header {
|
||||
number,
|
||||
|
||||
@@ -22,8 +22,9 @@ use runtime_io;
|
||||
#[cfg(feature = "std")] use std::fmt::{Debug, Display};
|
||||
#[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned};
|
||||
use substrate_primitives::{self, Hasher, Blake2Hasher};
|
||||
use crate::codec::{Codec, Encode, HasCompact};
|
||||
use crate::codec::{Codec, Encode, Decode, HasCompact};
|
||||
use crate::transaction_validity::TransactionValidity;
|
||||
use crate::generic::{Digest, DigestItem};
|
||||
pub use integer_sqrt::IntegerSquareRoot;
|
||||
pub use num_traits::{
|
||||
Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
|
||||
@@ -406,7 +407,8 @@ tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W,
|
||||
pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived
|
||||
// traits must be fulfilled by all type parameters.
|
||||
/// The hash type produced.
|
||||
type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + Default;
|
||||
type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy
|
||||
+ Default + Encode + Decode;
|
||||
|
||||
/// The associated hash_db Hasher type.
|
||||
type Hasher: Hasher<Out=Self::Output>;
|
||||
@@ -502,7 +504,7 @@ impl CheckEqual for substrate_primitives::H256 {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> CheckEqual for I where I: DigestItem {
|
||||
impl<H: PartialEq + Eq + MaybeDebug> CheckEqual for super::generic::DigestItem<H> where H: Encode {
|
||||
#[cfg(feature = "std")]
|
||||
fn check_equal(&self, other: &Self) {
|
||||
if self != other {
|
||||
@@ -609,8 +611,6 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe
|
||||
type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>;
|
||||
/// Hashing algorithm
|
||||
type Hashing: Hash<Output = Self::Hash>;
|
||||
/// Digest type
|
||||
type Digest: Digest<Hash = Self::Hash> + Codec;
|
||||
|
||||
/// Creates new header.
|
||||
fn new(
|
||||
@@ -618,7 +618,7 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest
|
||||
digest: Digest<Self::Hash>,
|
||||
) -> Self;
|
||||
|
||||
/// Returns a reference to the header number.
|
||||
@@ -642,9 +642,9 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe
|
||||
fn set_parent_hash(&mut self, hash: Self::Hash);
|
||||
|
||||
/// Returns a reference to the digest.
|
||||
fn digest(&self) -> &Self::Digest;
|
||||
fn digest(&self) -> &Digest<Self::Hash>;
|
||||
/// Get a mutable reference to the digest.
|
||||
fn digest_mut(&mut self) -> &mut Self::Digest;
|
||||
fn digest_mut(&mut self) -> &mut Digest<Self::Hash>;
|
||||
|
||||
/// Returns the hash of the header.
|
||||
fn hash(&self) -> Self::Hash {
|
||||
@@ -690,11 +690,9 @@ pub type HashFor<B> = <<B as Block>::Header as Header>::Hashing;
|
||||
/// Extract the number type for a block.
|
||||
pub type NumberFor<B> = <<B as Block>::Header as Header>::Number;
|
||||
/// Extract the digest type for a block.
|
||||
pub type DigestFor<B> = <<B as Block>::Header as Header>::Digest;
|
||||
pub type DigestFor<B> = Digest<<<B as Block>::Header as Header>::Hash>;
|
||||
/// Extract the digest item type for a block.
|
||||
pub type DigestItemFor<B> = <DigestFor<B> as Digest>::Item;
|
||||
/// Extract the authority ID type for a block.
|
||||
pub type AuthorityIdFor<B> = <DigestItemFor<B> as DigestItem>::AuthorityId;
|
||||
pub type DigestItemFor<B> = DigestItem<<<B as Block>::Header as Header>::Hash>;
|
||||
|
||||
/// A "checkable" piece of information, used by the standard Substrate Executive in order to
|
||||
/// check the validity of a piece of extrinsic information, usually by verifying the signature.
|
||||
@@ -749,49 +747,6 @@ pub trait Applyable: Sized + Send + Sync {
|
||||
fn deconstruct(self) -> (Self::Call, Option<Self::AccountId>);
|
||||
}
|
||||
|
||||
/// Something that acts like a `Digest` - it can have `Log`s `push`ed onto it and these `Log`s are
|
||||
/// each `Codec`.
|
||||
pub trait Digest: Member + MaybeSerializeDebugButNotDeserialize + Default {
|
||||
/// Hash of the items.
|
||||
type Hash: Member;
|
||||
/// Digest item type.
|
||||
type Item: DigestItem<Hash = Self::Hash>;
|
||||
|
||||
/// Get reference to all digest items.
|
||||
fn logs(&self) -> &[Self::Item];
|
||||
/// Push new digest item.
|
||||
fn push(&mut self, item: Self::Item);
|
||||
/// Pop a digest item.
|
||||
fn pop(&mut self) -> Option<Self::Item>;
|
||||
|
||||
/// Get reference to the first digest item that matches the passed predicate.
|
||||
fn log<T: ?Sized, F: Fn(&Self::Item) -> Option<&T>>(&self, predicate: F) -> Option<&T> {
|
||||
self.logs().iter()
|
||||
.filter_map(predicate)
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
||||
/// Single digest item. Could be any type that implements `Member` and provides methods
|
||||
/// for casting member to 'system' log items, known to substrate.
|
||||
///
|
||||
/// If the runtime does not supports some 'system' items, use `()` as a stub.
|
||||
pub trait DigestItem: Codec + Member + MaybeSerializeDebugButNotDeserialize {
|
||||
/// `ChangesTrieRoot` payload.
|
||||
type Hash: Member;
|
||||
/// `AuthorityChange` payload.
|
||||
type AuthorityId: Member + MaybeHash + crate::codec::Encode + crate::codec::Decode;
|
||||
|
||||
/// Returns `Some` if the entry is the `AuthoritiesChange` entry.
|
||||
fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]>;
|
||||
|
||||
/// Returns `Some` if the entry is the `ChangesTrieRoot` entry.
|
||||
fn as_changes_trie_root(&self) -> Option<&Self::Hash>;
|
||||
|
||||
/// Returns `Some` if this entry is the `PreRuntime` entry.
|
||||
fn as_pre_runtime(&self) -> Option<(super::ConsensusEngineId, &[u8])>;
|
||||
}
|
||||
|
||||
/// Auxiliary wrapper that holds an api instance and binds it to the given lifetime.
|
||||
pub struct ApiRef<'a, T>(T, rstd::marker::PhantomData<&'a ()>);
|
||||
|
||||
@@ -861,3 +816,75 @@ pub trait ValidateUnsigned {
|
||||
/// Changes made to storage should be discarded by caller.
|
||||
fn validate_unsigned(call: &Self::Call) -> TransactionValidity;
|
||||
}
|
||||
|
||||
/// Opaque datatype that may be destructured into a series of raw byte slices (which represent
|
||||
/// individual keys).
|
||||
pub trait OpaqueKeys {
|
||||
/// Return the number of encoded keys.
|
||||
fn count() -> usize { 0 }
|
||||
/// Get the raw bytes of key with index `i`.
|
||||
fn get_raw(&self, i: usize) -> &[u8];
|
||||
/// Get the decoded key with index `i`.
|
||||
fn get<T: Decode>(&self, i: usize) -> Option<T> { T::decode(&mut self.get_raw(i)) }
|
||||
/// Verify a proof of ownership for the keys.
|
||||
fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool { true }
|
||||
}
|
||||
|
||||
/// Calls a given macro a number of times with a set of fixed params and an incrementing numeral.
|
||||
/// e.g.
|
||||
/// ```nocompile
|
||||
/// count!(println ("{}",) foo, bar, baz);
|
||||
/// // Will result in three `println!`s: "0", "1" and "2".
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! count {
|
||||
($f:ident ($($x:tt)*) ) => ();
|
||||
($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); };
|
||||
($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); };
|
||||
($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); };
|
||||
($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => {
|
||||
$f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3);
|
||||
};
|
||||
($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => {
|
||||
$f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Just implement `OpaqueKeys` for a given tuple-struct.
|
||||
/// Would be much nicer for this to be converted to `derive` code.
|
||||
macro_rules! impl_opaque_keys {
|
||||
(
|
||||
pub struct $name:ident ( $( $t:ty ),* $(,)* );
|
||||
) => {
|
||||
impl_opaque_keys! {
|
||||
pub struct $name ( $( $t ,)* );
|
||||
impl OpaqueKeys for _ {}
|
||||
}
|
||||
};
|
||||
(
|
||||
pub struct $name:ident ( $( $t:ty ),* $(,)* );
|
||||
impl OpaqueKeys for _ {
|
||||
$($rest:tt)*
|
||||
}
|
||||
) => {
|
||||
#[derive(Default, Clone, PartialEq, Eq, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub struct $name($( pub $t ,)*);
|
||||
impl $crate::traits::OpaqueKeys for $name {
|
||||
fn count() -> usize {
|
||||
let mut c = 0;
|
||||
$( let _: $t; c += 1; )*
|
||||
c
|
||||
}
|
||||
fn get_raw(&self, i: usize) -> &[u8] {
|
||||
$crate::count!(impl_opaque_keys (!! self i) $($t),*);
|
||||
&[]
|
||||
}
|
||||
$($rest)*
|
||||
}
|
||||
};
|
||||
( !! $self:ident $param_i:ident $i:tt) => {
|
||||
if $param_i == $i { return $self.$i.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,9 @@ mod tests {
|
||||
use primitives::{Blake2Hasher};
|
||||
use crate::ChildStorageKey;
|
||||
|
||||
fn test_proving<'a>(trie_backend: &'a TrieBackend<PrefixedMemoryDB<Blake2Hasher>, Blake2Hasher>) -> ProvingBackend<'a, PrefixedMemoryDB<Blake2Hasher>, Blake2Hasher> {
|
||||
fn test_proving<'a>(
|
||||
trie_backend: &'a TrieBackend<PrefixedMemoryDB<Blake2Hasher>,Blake2Hasher>,
|
||||
) -> ProvingBackend<'a, PrefixedMemoryDB<Blake2Hasher>, Blake2Hasher> {
|
||||
ProvingBackend::new(trie_backend)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use log::{debug, warn};
|
||||
use hash_db::{self, Hasher};
|
||||
use trie::{TrieDB, Trie, MemoryDB, PrefixedMemoryDB, DBValue, TrieError, default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie};
|
||||
use trie::{
|
||||
TrieDB, Trie, MemoryDB, PrefixedMemoryDB, DBValue, TrieError,
|
||||
default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie,
|
||||
};
|
||||
use crate::backend::Consolidate;
|
||||
|
||||
/// Patricia trie-based storage trait.
|
||||
|
||||
@@ -16,4 +16,3 @@ parity-codec = "3.5.1"
|
||||
primitives = { package = "substrate-primitives", path = "../primitives" }
|
||||
runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" }
|
||||
state_machine = { package = "substrate-state-machine", path = "../state-machine" }
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ memory-db = { version = "0.12", default-features = false }
|
||||
offchain-primitives = { package = "substrate-offchain-primitives", path = "../offchain/primitives", default-features = false}
|
||||
executive = { package = "srml-executive", path = "../../srml/executive", default-features = false }
|
||||
cfg-if = "0.1.6"
|
||||
consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
substrate-executor = { path = "../executor" }
|
||||
@@ -57,7 +56,6 @@ std = [
|
||||
"memory-db/std",
|
||||
"offchain-primitives/std",
|
||||
"executive/std",
|
||||
"consensus_authorities/std",
|
||||
]
|
||||
# If enabled, the WASM blob is added to the `GenesisConfig`.
|
||||
include-wasm-blob = []
|
||||
|
||||
@@ -18,11 +18,10 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
use runtime_io::{blake2_256, twox_128};
|
||||
use super::AccountId;
|
||||
use super::{AuthorityId, AccountId};
|
||||
use parity_codec::{Encode, KeyedVec, Joiner};
|
||||
use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys};
|
||||
use runtime_primitives::traits::Block;
|
||||
use primitives::sr25519::Public as AuthorityId;
|
||||
|
||||
/// Configuration of a general Substrate test genesis block.
|
||||
pub struct GenesisConfig {
|
||||
@@ -58,16 +57,12 @@ impl GenesisConfig {
|
||||
#[cfg(feature = "include-wasm-blob")]
|
||||
(well_known_keys::CODE.into(), wasm_runtime),
|
||||
(well_known_keys::HEAP_PAGES.into(), vec![].and(&(16 as u64))),
|
||||
(well_known_keys::AUTHORITY_COUNT.into(), vec![].and(&(self.authorities.len() as u32))),
|
||||
].into_iter())
|
||||
.chain(self.authorities.iter()
|
||||
.enumerate()
|
||||
.map(|(i, account)| ((i as u32).to_keyed_vec(well_known_keys::AUTHORITY_PREFIX), vec![].and(account)))
|
||||
)
|
||||
.collect();
|
||||
if let Some(ref changes_trie_config) = self.changes_trie_config {
|
||||
map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode());
|
||||
}
|
||||
map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode());
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ use runtime_primitives::{
|
||||
transaction_validity::TransactionValidity,
|
||||
traits::{
|
||||
BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT,
|
||||
GetNodeBlockType, GetRuntimeBlockType, AuthorityIdFor, Verify,
|
||||
GetNodeBlockType, GetRuntimeBlockType, Verify
|
||||
},
|
||||
};
|
||||
use runtime_version::RuntimeVersion;
|
||||
@@ -49,6 +49,12 @@ use primitives::{sr25519, OpaqueMetadata};
|
||||
use runtime_version::NativeVersion;
|
||||
use inherents::{CheckInherentsResult, InherentData};
|
||||
use cfg_if::cfg_if;
|
||||
pub use consensus_babe::AuthorityId;
|
||||
|
||||
// Ensure Babe and Aura use the same crypto to simplify things a bit.
|
||||
pub type AuraId = AuthorityId;
|
||||
// Ensure Babe and Aura use the same crypto to simplify things a bit.
|
||||
pub type BabeId = AuthorityId;
|
||||
|
||||
/// Test runtime version.
|
||||
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
@@ -146,10 +152,6 @@ impl Extrinsic {
|
||||
}
|
||||
}
|
||||
|
||||
/// The signature type used by authorities.
|
||||
pub type AuthoritySignature = sr25519::Signature;
|
||||
/// The identity type used by authorities.
|
||||
pub type AuthorityId = <AuthoritySignature as Verify>::Signer;
|
||||
/// The signature type used by accounts/transactions.
|
||||
pub type AccountSignature = sr25519::Signature;
|
||||
/// An identifier for an account on this system.
|
||||
@@ -161,13 +163,13 @@ pub type BlockNumber = u64;
|
||||
/// Index of a transaction.
|
||||
pub type Index = u64;
|
||||
/// The item of a block digest.
|
||||
pub type DigestItem = runtime_primitives::generic::DigestItem<H256, AuthorityId, AuthoritySignature>;
|
||||
pub type DigestItem = runtime_primitives::generic::DigestItem<H256>;
|
||||
/// The digest of a block.
|
||||
pub type Digest = runtime_primitives::generic::Digest<DigestItem>;
|
||||
pub type Digest = runtime_primitives::generic::Digest<H256>;
|
||||
/// A test block.
|
||||
pub type Block = runtime_primitives::generic::Block<Header, Extrinsic>;
|
||||
/// A test block's header.
|
||||
pub type Header = runtime_primitives::generic::Header<BlockNumber, BlakeTwo256, DigestItem>;
|
||||
pub type Header = runtime_primitives::generic::Header<BlockNumber, BlakeTwo256>;
|
||||
|
||||
/// Run whatever tests we have.
|
||||
pub fn run_tests(mut input: &[u8]) -> Vec<u8> {
|
||||
@@ -455,8 +457,9 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_aura::AuraApi<Block> for Runtime {
|
||||
impl consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> u64 { 1 }
|
||||
fn authorities() -> Vec<AuraId> { system::authorities() }
|
||||
}
|
||||
|
||||
impl consensus_babe::BabeApi<Block> for Runtime {
|
||||
@@ -467,6 +470,7 @@ cfg_if! {
|
||||
threshold: std::u64::MAX,
|
||||
}
|
||||
}
|
||||
fn authorities() -> Vec<BabeId> { system::authorities() }
|
||||
}
|
||||
|
||||
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
|
||||
@@ -475,12 +479,6 @@ cfg_if! {
|
||||
runtime_io::submit_transaction(&ex).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
|
||||
fn authorities() -> Vec<AuthorityIdFor<Block>> {
|
||||
system::authorities()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
impl_runtime_apis! {
|
||||
@@ -603,8 +601,9 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_aura::AuraApi<Block> for Runtime {
|
||||
impl consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> u64 { 1 }
|
||||
fn authorities() -> Vec<AuraId> { system::authorities() }
|
||||
}
|
||||
|
||||
impl consensus_babe::BabeApi<Block> for Runtime {
|
||||
@@ -615,6 +614,7 @@ cfg_if! {
|
||||
threshold: core::u64::MAX,
|
||||
}
|
||||
}
|
||||
fn authorities() -> Vec<BabeId> { system::authorities() }
|
||||
}
|
||||
|
||||
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
|
||||
@@ -623,12 +623,6 @@ cfg_if! {
|
||||
runtime_io::submit_transaction(&ex).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
|
||||
fn authorities() -> Vec<AuthorityIdFor<Block>> {
|
||||
system::authorities()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,14 @@ use rstd::prelude::*;
|
||||
use runtime_io::{storage_root, enumerated_trie_root, storage_changes_root, twox_128, blake2_256};
|
||||
use runtime_support::storage::{self, StorageValue, StorageMap};
|
||||
use runtime_support::storage_items;
|
||||
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT, Header as _};
|
||||
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _};
|
||||
use runtime_primitives::generic;
|
||||
use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity};
|
||||
use parity_codec::{KeyedVec, Encode};
|
||||
use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest};
|
||||
use super::{
|
||||
AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId
|
||||
};
|
||||
use primitives::{Blake2Hasher, storage::well_known_keys};
|
||||
use primitives::sr25519::Public as AuthorityId;
|
||||
|
||||
const NONCE_OF: &[u8] = b"nonce:";
|
||||
const BALANCE_OF: &[u8] = b"balance:";
|
||||
@@ -39,6 +40,7 @@ storage_items! {
|
||||
ParentHash: b"sys:pha" => required Hash;
|
||||
NewAuthorities: b"sys:new_auth" => Vec<AuthorityId>;
|
||||
StorageDigest: b"sys:digest" => Digest;
|
||||
Authorities get(authorities): b"sys:auth" => default Vec<AuthorityId>;
|
||||
}
|
||||
|
||||
pub fn balance_of_key(who: AccountId) -> Vec<u8> {
|
||||
@@ -53,17 +55,6 @@ pub fn nonce_of(who: AccountId) -> u64 {
|
||||
storage::hashed::get_or(&blake2_256, &who.to_keyed_vec(NONCE_OF), 0)
|
||||
}
|
||||
|
||||
/// Get authorities at given block.
|
||||
pub fn authorities() -> Vec<AuthorityId> {
|
||||
let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT)
|
||||
.expect("There are always authorities in test-runtime");
|
||||
(0..len)
|
||||
.map(|i| storage::unhashed::get(&i.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX))
|
||||
.expect("Authority is properly encoded in test-runtime")
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn initialize_block(header: &Header) {
|
||||
// populate environment.
|
||||
<Number>::put(&header.number);
|
||||
@@ -80,8 +71,25 @@ pub fn take_block_number() -> Option<BlockNumber> {
|
||||
Number::take()
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Mode {
|
||||
Verify,
|
||||
Overwrite,
|
||||
}
|
||||
|
||||
/// Actually execute all transitioning for `block`.
|
||||
pub fn polish_block(block: &mut Block) {
|
||||
execute_block_with_state_root_handler(block, Mode::Overwrite);
|
||||
}
|
||||
|
||||
pub fn execute_block(mut block: Block) {
|
||||
execute_block_with_state_root_handler(&mut block, Mode::Verify);
|
||||
}
|
||||
|
||||
fn execute_block_with_state_root_handler(
|
||||
block: &mut Block,
|
||||
mode: Mode,
|
||||
) {
|
||||
let header = &mut block.header;
|
||||
|
||||
// check transaction trie root represents the transactions.
|
||||
@@ -89,7 +97,11 @@ pub fn polish_block(block: &mut Block) {
|
||||
let txs = txs.iter().map(Vec::as_slice).collect::<Vec<_>>();
|
||||
let txs_root = enumerated_trie_root::<Blake2Hasher>(&txs).into();
|
||||
info_expect_equal_hash(&txs_root, &header.extrinsics_root);
|
||||
header.extrinsics_root = txs_root;
|
||||
if let Mode::Overwrite = mode {
|
||||
header.extrinsics_root = txs_root;
|
||||
} else {
|
||||
assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid.");
|
||||
}
|
||||
|
||||
// execute transactions
|
||||
block.extrinsics.iter().enumerate().for_each(|(i, e)| {
|
||||
@@ -98,7 +110,14 @@ pub fn polish_block(block: &mut Block) {
|
||||
storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX);
|
||||
});
|
||||
|
||||
header.state_root = storage_root().into();
|
||||
if let Mode::Overwrite = mode {
|
||||
header.state_root = storage_root().into();
|
||||
} else {
|
||||
// check storage root.
|
||||
let storage_root = storage_root().into();
|
||||
info_expect_equal_hash(&storage_root, &header.state_root);
|
||||
assert!(storage_root == header.state_root, "Storage root must match that calculated.");
|
||||
}
|
||||
|
||||
// check digest
|
||||
let digest = &mut header.digest;
|
||||
@@ -106,39 +125,8 @@ pub fn polish_block(block: &mut Block) {
|
||||
digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into()));
|
||||
}
|
||||
if let Some(new_authorities) = <NewAuthorities>::take() {
|
||||
digest.push(generic::DigestItem::AuthoritiesChange(new_authorities));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute_block(mut block: Block) {
|
||||
let header = &mut block.header;
|
||||
|
||||
// check transaction trie root represents the transactions.
|
||||
let txs = block.extrinsics.iter().map(Encode::encode).collect::<Vec<_>>();
|
||||
let txs = txs.iter().map(Vec::as_slice).collect::<Vec<_>>();
|
||||
let txs_root = enumerated_trie_root::<Blake2Hasher>(&txs).into();
|
||||
info_expect_equal_hash(&txs_root, &header.extrinsics_root);
|
||||
assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid.");
|
||||
|
||||
// execute transactions
|
||||
block.extrinsics.into_iter().enumerate().for_each(|(i, e)| {
|
||||
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32));
|
||||
execute_transaction_backend(&e).unwrap_or_else(|_| panic!("Invalid transaction"));
|
||||
storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX);
|
||||
});
|
||||
|
||||
// check storage root.
|
||||
let storage_root = storage_root().into();
|
||||
info_expect_equal_hash(&storage_root, &header.state_root);
|
||||
assert!(storage_root == header.state_root, "Storage root must match that calculated.");
|
||||
|
||||
// check digest
|
||||
let digest = &mut header.digest;
|
||||
if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into()) {
|
||||
digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into()));
|
||||
}
|
||||
if let Some(new_authorities) = <NewAuthorities>::take() {
|
||||
digest.push(generic::DigestItem::AuthoritiesChange(new_authorities));
|
||||
digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode()));
|
||||
digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +212,8 @@ pub fn finalize_block() -> Header {
|
||||
digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root));
|
||||
}
|
||||
if let Some(new_authorities) = <NewAuthorities>::take() {
|
||||
digest.push(generic::DigestItem::AuthoritiesChange(new_authorities));
|
||||
digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode()));
|
||||
digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode()));
|
||||
}
|
||||
|
||||
Header {
|
||||
@@ -309,25 +298,27 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use runtime_io::{with_externalities, twox_128, blake2_256, TestExternalities};
|
||||
use parity_codec::{Joiner, KeyedVec};
|
||||
use runtime_io::{with_externalities, TestExternalities};
|
||||
use substrate_test_runtime_client::{AuthorityKeyring, AccountKeyring};
|
||||
use crate::{Header, Transfer};
|
||||
use primitives::{Blake2Hasher, map};
|
||||
use primitives::storage::well_known_keys;
|
||||
use substrate_executor::WasmExecutor;
|
||||
|
||||
const WASM_CODE: &'static [u8] =
|
||||
include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm");
|
||||
|
||||
fn new_test_ext() -> TestExternalities<Blake2Hasher> {
|
||||
let authorities = vec![
|
||||
AuthorityKeyring::Alice.to_raw_public(),
|
||||
AuthorityKeyring::Bob.to_raw_public(),
|
||||
AuthorityKeyring::Charlie.to_raw_public()
|
||||
];
|
||||
TestExternalities::new(map![
|
||||
twox_128(b"latest").to_vec() => vec![69u8; 32],
|
||||
twox_128(well_known_keys::AUTHORITY_COUNT).to_vec() => vec![].and(&3u32),
|
||||
twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Alice.to_raw_public().to_vec(),
|
||||
twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Bob.to_raw_public().to_vec(),
|
||||
twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Charlie.to_raw_public().to_vec(),
|
||||
blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
|
||||
twox_128(b"sys:auth").to_vec() => authorities.encode(),
|
||||
blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0]
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
+2
-12
@@ -2500,21 +2500,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "substrate-consensus-aura-primitives"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-consensus-authorities"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
@@ -2525,8 +2514,10 @@ version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-slots 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2711,7 +2702,6 @@ dependencies = [
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-consensus-babe-primitives 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-keyring 2.0.0",
|
||||
|
||||
@@ -379,7 +379,9 @@ mod tests {
|
||||
let mut empty = TrieDBMut::<Blake2Hasher>::new(&mut db, &mut root);
|
||||
empty.commit();
|
||||
let root1 = empty.root().as_ref().to_vec();
|
||||
let root2: Vec<u8> = trie_root::<Blake2Hasher, _, Vec<u8>, Vec<u8>>(std::iter::empty()).as_ref().iter().cloned().collect();
|
||||
let root2: Vec<u8> = trie_root::<Blake2Hasher, _, Vec<u8>, Vec<u8>>(
|
||||
std::iter::empty(),
|
||||
).as_ref().iter().cloned().collect();
|
||||
|
||||
assert_eq!(root1, root2);
|
||||
}
|
||||
@@ -455,7 +457,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn single_long_leaf_is_equivalent() {
|
||||
let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), (&[0xba][..], &[0x11][..])];
|
||||
let input: Vec<(&[u8], &[u8])> = vec![
|
||||
(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]),
|
||||
(&[0xba][..], &[0x11][..]),
|
||||
];
|
||||
check_equivalent(&input);
|
||||
check_iteration(&input);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ version = { package = "sr-version", path = "../../core/sr-version", default_feat
|
||||
support = { package = "srml-support", path = "../../srml/support", default_features = false }
|
||||
primitives = { package = "substrate-primitives", path = "../../core/primitives", default_features = false }
|
||||
balances = { package = "srml-balances", path = "../../srml/balances", default_features = false }
|
||||
consensus = { package = "srml-consensus", path = "../../srml/consensus", default_features = false }
|
||||
aura = { package = "srml-aura", path = "../../srml/aura", default_features = false }
|
||||
executive = { package = "srml-executive", path = "../../srml/executive", default_features = false }
|
||||
indices = { package = "srml-indices", path = "../../srml/indices", default_features = false }
|
||||
@@ -25,7 +24,6 @@ runtime-primitives = { package = "sr-primitives", path = "../../core/sr-primitiv
|
||||
client = { package = "substrate-client", path = "../../core/client", default_features = false }
|
||||
consensus-aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false }
|
||||
offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false }
|
||||
consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -49,5 +47,4 @@ std = [
|
||||
"safe-mix/std",
|
||||
"consensus-aura/std",
|
||||
"offchain-primitives/std",
|
||||
"consensus_authorities/std",
|
||||
]
|
||||
|
||||
@@ -26,18 +26,17 @@ use version::NativeVersion;
|
||||
// A few exports that help ease life for downstream crates.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub use runtime_primitives::BuildStorage;
|
||||
pub use consensus::Call as ConsensusCall;
|
||||
pub use timestamp::Call as TimestampCall;
|
||||
pub use balances::Call as BalancesCall;
|
||||
pub use runtime_primitives::{Permill, Perbill};
|
||||
pub use timestamp::BlockPeriod;
|
||||
pub use support::{StorageValue, construct_runtime};
|
||||
|
||||
/// The type that is used for identifying authorities.
|
||||
pub type AuthorityId = <AuthoritySignature as Verify>::Signer;
|
||||
/// Alias to the signature scheme used for Aura authority signatures.
|
||||
pub type AuraSignature = ed25519::Signature;
|
||||
|
||||
/// The type used by authorities to prove their ID.
|
||||
pub type AuthoritySignature = ed25519::Signature;
|
||||
/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain.
|
||||
pub type AuraId = ed25519::Public;
|
||||
|
||||
/// Alias to pubkey that identifies an account on the chain.
|
||||
pub type AccountId = <AccountSignature as Verify>::Signer;
|
||||
@@ -80,13 +79,13 @@ pub mod opaque {
|
||||
}
|
||||
}
|
||||
/// Opaque block header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, generic::DigestItem<Hash, AuthorityId, AuthoritySignature>>;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Opaque block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Opaque block identifier type.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
/// Opaque session key type.
|
||||
pub type SessionKey = AuthorityId;
|
||||
pub type SessionKey = AuraId;
|
||||
}
|
||||
|
||||
/// This runtime version.
|
||||
@@ -121,30 +120,17 @@ impl system::Trait for Runtime {
|
||||
type Hash = Hash;
|
||||
/// The hashing algorithm used.
|
||||
type Hashing = BlakeTwo256;
|
||||
/// The header digest type.
|
||||
type Digest = generic::Digest<Log>;
|
||||
/// The header type.
|
||||
type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
|
||||
type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// The ubiquitous event type.
|
||||
type Event = Event;
|
||||
/// The ubiquitous log type.
|
||||
type Log = Log;
|
||||
/// The ubiquitous origin type.
|
||||
type Origin = Origin;
|
||||
}
|
||||
|
||||
impl aura::Trait for Runtime {
|
||||
type HandleReport = ();
|
||||
}
|
||||
|
||||
impl consensus::Trait for Runtime {
|
||||
/// The identifier we use to refer to authorities.
|
||||
type SessionKey = AuthorityId;
|
||||
// The aura module handles offline-reports internally
|
||||
// rather than using an explicit report system.
|
||||
type InherentOfflineReport = ();
|
||||
/// The ubiquitous log type.
|
||||
type Log = Log;
|
||||
type AuthorityId = AuraId;
|
||||
}
|
||||
|
||||
impl indices::Trait for Runtime {
|
||||
@@ -192,16 +178,15 @@ impl template::Trait for Runtime {
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Runtime with Log(InternalLog: DigestItem<Hash, AuthorityId, AuthoritySignature>) where
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = opaque::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system::{default, Log(ChangesTrieRoot)},
|
||||
System: system::{default, Config<T>},
|
||||
Timestamp: timestamp::{Module, Call, Storage, Config<T>, Inherent},
|
||||
Consensus: consensus::{Module, Call, Storage, Config<T>, Log(AuthoritiesChange), Inherent},
|
||||
Aura: aura::{Module, Log(PreRuntime)},
|
||||
Indices: indices,
|
||||
Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
|
||||
Indices: indices::{default, Config<T>},
|
||||
Balances: balances,
|
||||
Sudo: sudo,
|
||||
// Used for the module template in `./template.rs`
|
||||
@@ -214,7 +199,7 @@ type Context = system::ChainContext<Runtime>;
|
||||
/// The address format for describing accounts.
|
||||
type Address = <Indices as StaticLookup>::Source;
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Block type as expected by this runtime.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// BlockId type as expected by this runtime.
|
||||
@@ -276,10 +261,13 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_aura::AuraApi<Block> for Runtime {
|
||||
impl consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> u64 {
|
||||
Aura::slot_duration()
|
||||
}
|
||||
fn authorities() -> Vec<AuraId> {
|
||||
Aura::authorities()
|
||||
}
|
||||
}
|
||||
|
||||
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
|
||||
@@ -287,10 +275,4 @@ impl_runtime_apis! {
|
||||
Executive::offchain_worker(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
|
||||
fn authorities() -> Vec<AuthorityId> {
|
||||
Consensus::authorities()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ mod tests {
|
||||
use runtime_primitives::{
|
||||
BuildStorage,
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
testing::{Digest, DigestItem, Header}
|
||||
testing::Header,
|
||||
};
|
||||
|
||||
impl_outer_origin! {
|
||||
@@ -93,12 +93,10 @@ mod tests {
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type Log = DigestItem;
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Event = ();
|
||||
|
||||
+2
-29
@@ -1471,7 +1471,6 @@ dependencies = [
|
||||
"sr-version 2.0.0",
|
||||
"srml-aura 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-executive 2.0.0",
|
||||
"srml-indices 2.0.0",
|
||||
"srml-sudo 2.0.0",
|
||||
@@ -1480,7 +1479,6 @@ dependencies = [
|
||||
"srml-timestamp 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-offchain-primitives 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
@@ -2382,7 +2380,9 @@ dependencies = [
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2399,20 +2399,6 @@ dependencies = [
|
||||
"substrate-keyring 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srml-consensus"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srml-executive"
|
||||
version = "2.0.0"
|
||||
@@ -2461,7 +2447,6 @@ dependencies = [
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
@@ -2477,7 +2462,6 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
@@ -2653,21 +2637,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "substrate-consensus-aura-primitives"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-consensus-authorities"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use primitives::{ed25519, sr25519, Pair};
|
||||
use node_template_runtime::{
|
||||
AccountId, GenesisConfig, ConsensusConfig, TimestampConfig, BalancesConfig,
|
||||
SudoConfig, IndicesConfig,
|
||||
AccountId, AuraId as AuthorityId, GenesisConfig, AuraConfig, TimestampConfig, BalancesConfig,
|
||||
SudoConfig, IndicesConfig, SystemConfig
|
||||
};
|
||||
use substrate_service;
|
||||
|
||||
use ed25519::Public as AuthorityId;
|
||||
|
||||
// Note this is the URL for the telemetry server
|
||||
//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
|
||||
|
||||
@@ -92,11 +90,14 @@ impl Alternative {
|
||||
|
||||
fn testnet_genesis(initial_authorities: Vec<AuthorityId>, endowed_accounts: Vec<AccountId>, root_key: AccountId) -> GenesisConfig {
|
||||
GenesisConfig {
|
||||
consensus: Some(ConsensusConfig {
|
||||
system: Some(SystemConfig {
|
||||
code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm").to_vec(),
|
||||
changes_trie_config: Default::default(),
|
||||
_genesis_phantom_data: Default::default(),
|
||||
}),
|
||||
aura: Some(AuraConfig {
|
||||
authorities: initial_authorities.clone(),
|
||||
}),
|
||||
system: None,
|
||||
timestamp: Some(TimestampConfig {
|
||||
minimum_period: 5, // 10 second block time.
|
||||
}),
|
||||
|
||||
@@ -27,6 +27,7 @@ network = { package = "substrate-network", path = "../../core/network" }
|
||||
consensus = { package = "substrate-consensus-aura", path = "../../core/consensus/aura" }
|
||||
grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" }
|
||||
sr-primitives = { path = "../../core/sr-primitives" }
|
||||
aura_primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives" }
|
||||
node-executor = { path = "../executor" }
|
||||
substrate-keystore = { path = "../../core/keystore" }
|
||||
substrate-telemetry = { package = "substrate-telemetry", path = "../../core/telemetry" }
|
||||
|
||||
@@ -16,15 +16,16 @@
|
||||
|
||||
//! Substrate chain configurations.
|
||||
|
||||
use primitives::{ed25519::Public as AuthorityId, ed25519, sr25519, Pair, crypto::UncheckedInto};
|
||||
use node_primitives::AccountId;
|
||||
use node_runtime::{ConsensusConfig, CouncilSeatsConfig, DemocracyConfig,
|
||||
use primitives::{ed25519, sr25519, Pair, crypto::UncheckedInto};
|
||||
use node_primitives::{AccountId, AuraId};
|
||||
use node_runtime::{CouncilSeatsConfig, AuraConfig, DemocracyConfig, SystemConfig,
|
||||
SessionConfig, StakingConfig, StakerStatus, TimestampConfig, BalancesConfig, TreasuryConfig,
|
||||
SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, Permill, Perbill};
|
||||
SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, Permill, Perbill, SessionKeys};
|
||||
pub use node_runtime::GenesisConfig;
|
||||
use substrate_service;
|
||||
use hex_literal::hex;
|
||||
use substrate_telemetry::TelemetryEndpoints;
|
||||
use grandpa::AuthorityId as GrandpaId;
|
||||
|
||||
const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
|
||||
|
||||
@@ -43,27 +44,48 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
// and
|
||||
// for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done
|
||||
|
||||
let initial_authorities: Vec<(AccountId, AccountId, AuthorityId)> = vec![(
|
||||
hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].unchecked_into(), // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy
|
||||
hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].unchecked_into(), // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq
|
||||
hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC
|
||||
let initial_authorities: Vec<(AccountId, AccountId, AuraId, GrandpaId)> = vec![(
|
||||
// 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy
|
||||
hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].unchecked_into(),
|
||||
// 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq
|
||||
hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].unchecked_into(),
|
||||
// 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC
|
||||
hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(),
|
||||
// 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC
|
||||
hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(),
|
||||
),(
|
||||
hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].unchecked_into(), // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2
|
||||
hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].unchecked_into(), // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF
|
||||
hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE
|
||||
// 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2
|
||||
hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].unchecked_into(),
|
||||
// 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF
|
||||
hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].unchecked_into(),
|
||||
// 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE
|
||||
hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(),
|
||||
// 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE
|
||||
hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(),
|
||||
),(
|
||||
hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].unchecked_into(), // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp
|
||||
hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].unchecked_into(), // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9
|
||||
hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d
|
||||
// 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp
|
||||
hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].unchecked_into(),
|
||||
// 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9
|
||||
hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].unchecked_into(),
|
||||
// 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d
|
||||
hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(),
|
||||
// 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d
|
||||
hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(),
|
||||
),(
|
||||
hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].unchecked_into(), // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9
|
||||
hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].unchecked_into(), // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn
|
||||
hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4
|
||||
// 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9
|
||||
hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].unchecked_into(),
|
||||
// 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn
|
||||
hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].unchecked_into(),
|
||||
// 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4
|
||||
hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(),
|
||||
// 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4
|
||||
hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(),
|
||||
)];
|
||||
|
||||
// generated with secret: subkey inspect "$secret"/fir
|
||||
let endowed_accounts: Vec<AccountId> = vec![
|
||||
hex!["9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"].unchecked_into(), // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo
|
||||
// 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo
|
||||
hex!["9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"].unchecked_into(),
|
||||
];
|
||||
|
||||
const MILLICENTS: u128 = 1_000_000_000;
|
||||
@@ -79,11 +101,11 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
const STASH: u128 = 100 * DOLLARS;
|
||||
|
||||
GenesisConfig {
|
||||
consensus: Some(ConsensusConfig {
|
||||
system: Some(SystemConfig {
|
||||
code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), // FIXME change once we have #1252
|
||||
authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
|
||||
_genesis_phantom_data: Default::default(),
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
system: None,
|
||||
balances: Some(BalancesConfig {
|
||||
transaction_base_fee: 1 * CENTS,
|
||||
transaction_byte_fee: 10 * MILLICENTS,
|
||||
@@ -103,8 +125,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
}),
|
||||
session: Some(SessionConfig {
|
||||
validators: initial_authorities.iter().map(|x| x.1.clone()).collect(),
|
||||
session_length: 5 * MINUTES,
|
||||
keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::<Vec<_>>(),
|
||||
keys: initial_authorities.iter().map(|x| (x.1.clone(), SessionKeys(x.2.clone(),x.2.clone()))).collect::<Vec<_>>(),
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
@@ -112,8 +133,6 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
session_reward: Perbill::from_parts(2_065),
|
||||
current_session_reward: 0,
|
||||
validator_count: 7,
|
||||
sessions_per_era: 12,
|
||||
bonding_duration: 12,
|
||||
offline_slash_grace: 4,
|
||||
minimum_validator_count: 4,
|
||||
stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(),
|
||||
@@ -165,8 +184,12 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
sudo: Some(SudoConfig {
|
||||
key: endowed_accounts[0].clone(),
|
||||
}),
|
||||
aura: Some(AuraConfig {
|
||||
authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
|
||||
}),
|
||||
grandpa: Some(GrandpaConfig {
|
||||
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
|
||||
authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(),
|
||||
_genesis_phantom_data: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -193,25 +216,33 @@ pub fn get_account_id_from_seed(seed: &str) -> AccountId {
|
||||
.public()
|
||||
}
|
||||
|
||||
/// Helper function to generate AuthorityId from seed
|
||||
pub fn get_session_key_from_seed(seed: &str) -> AuthorityId {
|
||||
/// Helper function to generate AuraId from seed
|
||||
pub fn get_aura_id_from_seed(seed: &str) -> AuraId {
|
||||
ed25519::Pair::from_string(&format!("//{}", seed), None)
|
||||
.expect("static values are valid; qed")
|
||||
.public()
|
||||
}
|
||||
|
||||
/// Helper function to generate GrandpaId from seed
|
||||
pub fn get_grandpa_id_from_seed(seed: &str) -> GrandpaId {
|
||||
ed25519::Pair::from_string(&format!("//{}", seed), None)
|
||||
.expect("static values are valid; qed")
|
||||
.public()
|
||||
}
|
||||
|
||||
/// Helper function to generate stash, controller and session key from seed
|
||||
pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuthorityId) {
|
||||
pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuraId, GrandpaId) {
|
||||
(
|
||||
get_account_id_from_seed(&format!("{}//stash", seed)),
|
||||
get_account_id_from_seed(seed),
|
||||
get_session_key_from_seed(seed)
|
||||
get_aura_id_from_seed(seed),
|
||||
get_grandpa_id_from_seed(seed)
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper function to create GenesisConfig for testing
|
||||
pub fn testnet_genesis(
|
||||
initial_authorities: Vec<(AccountId, AccountId, AuthorityId)>,
|
||||
initial_authorities: Vec<(AccountId, AccountId, AuraId, GrandpaId)>,
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Option<Vec<AccountId>>,
|
||||
enable_println: bool,
|
||||
@@ -260,11 +291,11 @@ pub fn testnet_genesis(
|
||||
contract_config.current_schedule.enable_println = enable_println;
|
||||
|
||||
GenesisConfig {
|
||||
consensus: Some(ConsensusConfig {
|
||||
system: Some(SystemConfig {
|
||||
code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(),
|
||||
authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
|
||||
_genesis_phantom_data: Default::default(),
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
system: None,
|
||||
indices: Some(IndicesConfig {
|
||||
ids: endowed_accounts.clone(),
|
||||
}),
|
||||
@@ -279,15 +310,12 @@ pub fn testnet_genesis(
|
||||
}),
|
||||
session: Some(SessionConfig {
|
||||
validators: initial_authorities.iter().map(|x| x.1.clone()).collect(),
|
||||
session_length: 10,
|
||||
keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::<Vec<_>>(),
|
||||
keys: initial_authorities.iter().map(|x| (x.1.clone(), SessionKeys(x.2.clone(), x.2.clone()))).collect::<Vec<_>>(),
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
minimum_validator_count: 1,
|
||||
validator_count: 2,
|
||||
sessions_per_era: 5,
|
||||
bonding_duration: 12,
|
||||
offline_slash: Perbill::zero(),
|
||||
session_reward: Perbill::zero(),
|
||||
current_session_reward: 0,
|
||||
@@ -298,7 +326,7 @@ pub fn testnet_genesis(
|
||||
democracy: Some(DemocracyConfig::default()),
|
||||
council_seats: Some(CouncilSeatsConfig {
|
||||
active_council: endowed_accounts.iter()
|
||||
.filter(|&endowed| initial_authorities.iter().find(|&(_, controller, _)| controller == endowed).is_none())
|
||||
.filter(|&endowed| initial_authorities.iter().find(|&(_, controller, ..)| controller == endowed).is_none())
|
||||
.map(|a| (a.clone(), 1000000)).collect(),
|
||||
candidacy_bond: 10,
|
||||
voter_bond: 2,
|
||||
@@ -325,8 +353,12 @@ pub fn testnet_genesis(
|
||||
sudo: Some(SudoConfig {
|
||||
key: root_key,
|
||||
}),
|
||||
aura: Some(AuraConfig {
|
||||
authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
|
||||
}),
|
||||
grandpa: Some(GrandpaConfig {
|
||||
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
|
||||
authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(),
|
||||
_genesis_phantom_data: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,9 +224,9 @@ mod tests {
|
||||
use parity_codec::{Compact, Encode, Decode};
|
||||
use primitives::{
|
||||
crypto::Pair as CryptoPair, ed25519::Pair, blake2_256,
|
||||
sr25519::Public as AddressPublic,
|
||||
sr25519::Public as AddressPublic, H256,
|
||||
};
|
||||
use sr_primitives::{generic::{BlockId, Era, Digest}, traits::{Block, Digest as DigestT}, OpaqueExtrinsic};
|
||||
use sr_primitives::{generic::{BlockId, Era, Digest}, traits::Block, OpaqueExtrinsic};
|
||||
use timestamp;
|
||||
use finality_tracker;
|
||||
use keyring::{ed25519::Keyring as AuthorityKeyring, sr25519::Keyring as AccountKeyring};
|
||||
@@ -299,9 +299,9 @@ mod tests {
|
||||
client: service.client(),
|
||||
transaction_pool: service.transaction_pool(),
|
||||
});
|
||||
let mut digest = Digest::<DigestItem>::default();
|
||||
let mut digest = Digest::<H256>::default();
|
||||
digest.push(<DigestItem as CompatibleDigestItem<Pair>>::aura_pre_digest(slot_num * 10 / 2));
|
||||
let proposer = proposer_factory.init(&parent_header, &[]).unwrap();
|
||||
let proposer = proposer_factory.init(&parent_header).unwrap();
|
||||
let new_block = proposer.propose(
|
||||
inherent_data,
|
||||
digest,
|
||||
|
||||
@@ -25,7 +25,6 @@ balances = { package = "srml-balances", path = "../../srml/balances" }
|
||||
session = { package = "srml-session", path = "../../srml/session" }
|
||||
staking = { package = "srml-staking", path = "../../srml/staking" }
|
||||
system = { package = "srml-system", path = "../../srml/system" }
|
||||
consensus = { package = "srml-consensus", path = "../../srml/consensus" }
|
||||
timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" }
|
||||
treasury = { package = "srml-treasury", path = "../../srml/treasury" }
|
||||
contract = { package = "srml-contract", path = "../../srml/contract" }
|
||||
|
||||
@@ -37,14 +37,14 @@ mod tests {
|
||||
use primitives::{twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue,
|
||||
NativeOrEncoded};
|
||||
use node_primitives::{Hash, BlockNumber, AccountId};
|
||||
use runtime_primitives::traits::{Header as HeaderT, Hash as HashT, Digest, DigestItem};
|
||||
use runtime_primitives::traits::{Header as HeaderT, Hash as HashT};
|
||||
use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill};
|
||||
use {balances, indices, session, system, staking, consensus, timestamp, treasury, contract};
|
||||
use {balances, indices, system, staking, timestamp, treasury, contract};
|
||||
use contract::ContractAddressFor;
|
||||
use system::{EventRecord, Phase};
|
||||
use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
|
||||
BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System,
|
||||
SystemConfig, GrandpaConfig, IndicesConfig, Event};
|
||||
SystemConfig, GrandpaConfig, IndicesConfig, Event, SessionKeys};
|
||||
use wabt;
|
||||
use primitives::map;
|
||||
|
||||
@@ -121,15 +121,33 @@ mod tests {
|
||||
#[test]
|
||||
fn panic_execution_with_foreign_code_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![70u8; 16],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => {
|
||||
vec![0u8; 32]
|
||||
},
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => {
|
||||
vec![70u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
}
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
@@ -154,15 +172,33 @@ mod tests {
|
||||
#[test]
|
||||
fn bad_extrinsic_with_native_equivalent_code_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![70u8; 16],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => {
|
||||
vec![0u8; 32]
|
||||
},
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => {
|
||||
vec![70u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
}
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
@@ -187,8 +223,12 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
@@ -224,8 +264,12 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_with_foreign_code_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
@@ -258,10 +302,14 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
fn to_session_keys(ring: &AuthorityKeyring) -> SessionKeys {
|
||||
SessionKeys(ring.to_owned().into(), ring.to_owned().into())
|
||||
}
|
||||
|
||||
fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities<Blake2Hasher> {
|
||||
let three = AccountId::from_raw([3u8; 32]);
|
||||
let mut ext = TestExternalities::new_with_code(code, GenesisConfig {
|
||||
consensus: Some(Default::default()),
|
||||
aura: Some(Default::default()),
|
||||
system: Some(SystemConfig {
|
||||
changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration {
|
||||
digest_interval: 2,
|
||||
@@ -289,16 +337,14 @@ mod tests {
|
||||
vesting: vec![],
|
||||
}),
|
||||
session: Some(SessionConfig {
|
||||
session_length: 2,
|
||||
validators: vec![AccountKeyring::One.into(), AccountKeyring::Two.into(), three],
|
||||
keys: vec![
|
||||
(alice(), AuthorityKeyring::Alice.into()),
|
||||
(bob(), AuthorityKeyring::Bob.into()),
|
||||
(charlie(), AuthorityKeyring::Charlie.into())
|
||||
(alice(), to_session_keys(&AuthorityKeyring::Alice)),
|
||||
(bob(), to_session_keys(&AuthorityKeyring::Bob)),
|
||||
(charlie(), to_session_keys(&AuthorityKeyring::Charlie)),
|
||||
]
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
sessions_per_era: 2,
|
||||
current_era: 0,
|
||||
stakers: vec![
|
||||
(dave(), alice(), 111, staking::StakerStatus::Validator),
|
||||
@@ -307,7 +353,6 @@ mod tests {
|
||||
],
|
||||
validator_count: 3,
|
||||
minimum_validator_count: 0,
|
||||
bonding_duration: 0,
|
||||
offline_slash: Perbill::zero(),
|
||||
session_reward: Perbill::zero(),
|
||||
current_session_reward: 0,
|
||||
@@ -321,6 +366,7 @@ mod tests {
|
||||
contract: Some(Default::default()),
|
||||
sudo: Some(Default::default()),
|
||||
grandpa: Some(GrandpaConfig {
|
||||
_genesis_phantom_data: Default::default(),
|
||||
authorities: vec![],
|
||||
}),
|
||||
}.build_storage().unwrap().0);
|
||||
@@ -447,8 +493,8 @@ mod tests {
|
||||
|
||||
// session change => consensus authorities change => authorities change digest item appears
|
||||
let digest = Header::decode(&mut &block2.0[..]).unwrap().digest;
|
||||
assert_eq!(digest.logs().len(), 1);
|
||||
assert!(digest.logs()[0].as_authorities_change().is_some());
|
||||
assert_eq!(digest.logs().len(), 0);
|
||||
// assert!(digest.logs()[0].as_consensus().is_some());
|
||||
|
||||
(block1, block2)
|
||||
}
|
||||
@@ -465,7 +511,7 @@ mod tests {
|
||||
},
|
||||
CheckedExtrinsic {
|
||||
signed: Some((alice(), 0)),
|
||||
function: Call::Consensus(consensus::Call::remark(vec![0; 120000])),
|
||||
function: Call::System(system::Call::remark(vec![0; 120000])),
|
||||
}
|
||||
]
|
||||
)
|
||||
@@ -598,11 +644,6 @@ mod tests {
|
||||
event: Event::treasury(treasury::RawEvent::Rollover(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::session(session::RawEvent::NewSession(1)),
|
||||
topics: vec![],
|
||||
},
|
||||
]);
|
||||
});
|
||||
}
|
||||
@@ -782,7 +823,7 @@ mod tests {
|
||||
assert!(
|
||||
WasmExecutor::new().call(
|
||||
&mut t,
|
||||
8,
|
||||
4,
|
||||
COMPACT_CODE,
|
||||
"Core_execute_block",
|
||||
&big_block().0
|
||||
@@ -822,8 +863,12 @@ mod tests {
|
||||
fn panic_execution_gives_error() {
|
||||
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.wasm");
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(foreign_code, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
@@ -833,9 +878,11 @@ mod tests {
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
]);
|
||||
|
||||
let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64)));
|
||||
let r = WasmExecutor::new()
|
||||
.call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64)));
|
||||
assert!(r.is_ok());
|
||||
let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = WasmExecutor::new()
|
||||
.call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = ApplyResult::decode(&mut &r[..]).unwrap();
|
||||
assert_eq!(r, Err(ApplyError::CantPay));
|
||||
}
|
||||
@@ -844,8 +891,12 @@ mod tests {
|
||||
fn successful_execution_gives_ok() {
|
||||
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm");
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(foreign_code, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
@@ -855,9 +906,11 @@ mod tests {
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
]);
|
||||
|
||||
let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64)));
|
||||
let r = WasmExecutor::new()
|
||||
.call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64)));
|
||||
assert!(r.is_ok());
|
||||
let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = WasmExecutor::new()
|
||||
.call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = ApplyResult::decode(&mut &r[..]).unwrap();
|
||||
assert_eq!(r, Ok(ApplyOutcome::Success));
|
||||
|
||||
@@ -890,7 +943,8 @@ mod tests {
|
||||
let block1 = changes_trie_block();
|
||||
|
||||
let mut t = new_test_ext(COMPACT_CODE, true);
|
||||
WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap();
|
||||
WasmExecutor::new()
|
||||
.call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap();
|
||||
|
||||
assert!(t.storage_changes_root(GENESIS_HASH.into()).unwrap().is_some());
|
||||
}
|
||||
|
||||
@@ -41,12 +41,11 @@ pub type AccountIndex = u32;
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// The Ed25519 pub key of an session that belongs to an authority of the chain. This is
|
||||
/// exactly equivalent to what the substrate calls an "authority".
|
||||
pub type AuthorityId = <AuthoritySignature as Verify>::Signer;
|
||||
/// Alias to the signature scheme used for Aura authority signatures.
|
||||
pub type AuraSignature = primitives::ed25519::Signature;
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a session signature on the chain.
|
||||
pub type AuthoritySignature = primitives::ed25519::Signature;
|
||||
/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain.
|
||||
pub type AuraId = primitives::ed25519::Public;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Index = u64;
|
||||
@@ -58,9 +57,9 @@ pub type Hash = primitives::H256;
|
||||
pub type Timestamp = u64;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = generic::DigestItem<Hash, AuthorityId, AuthoritySignature>;
|
||||
pub type DigestItem = generic::DigestItem<Hash>;
|
||||
/// Header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, DigestItem>;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Block ID.
|
||||
|
||||
@@ -17,7 +17,6 @@ version = { package = "sr-version", path = "../../core/sr-version", default-feat
|
||||
support = { package = "srml-support", path = "../../srml/support", default-features = false }
|
||||
aura = { package = "srml-aura", path = "../../srml/aura", default-features = false }
|
||||
balances = { package = "srml-balances", path = "../../srml/balances", default-features = false }
|
||||
consensus = { package = "srml-consensus", path = "../../srml/consensus", default-features = false }
|
||||
contract = { package = "srml-contract", path = "../../srml/contract", default-features = false }
|
||||
council = { package = "srml-council", path = "../../srml/council", default-features = false }
|
||||
democracy = { package = "srml-democracy", path = "../../srml/democracy", default-features = false }
|
||||
@@ -36,7 +35,6 @@ consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../.
|
||||
rustc-hex = { version = "2.0", optional = true }
|
||||
serde = { version = "1.0", optional = true }
|
||||
substrate-keyring = { path = "../../core/keyring", optional = true }
|
||||
consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -51,7 +49,6 @@ std = [
|
||||
"support/std",
|
||||
"aura/std",
|
||||
"balances/std",
|
||||
"consensus/std",
|
||||
"contract/std",
|
||||
"council/std",
|
||||
"democracy/std",
|
||||
@@ -74,5 +71,4 @@ std = [
|
||||
"rustc-hex",
|
||||
"substrate-keyring",
|
||||
"offchain-primitives/std",
|
||||
"consensus_authorities/std",
|
||||
]
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
#![recursion_limit="256"]
|
||||
|
||||
use rstd::prelude::*;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use support::{construct_runtime, parameter_types};
|
||||
use substrate_primitives::u32_trait::{_1, _2, _3, _4};
|
||||
use node_primitives::{
|
||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, AuthorityId, Signature, AuthoritySignature
|
||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Signature, AuraId
|
||||
};
|
||||
use grandpa::fg_primitives::{self, ScheduledChange};
|
||||
use client::{
|
||||
@@ -34,7 +35,7 @@ use client::{
|
||||
use runtime_primitives::{ApplyResult, generic, create_runtime_str};
|
||||
use runtime_primitives::transaction_validity::TransactionValidity;
|
||||
use runtime_primitives::traits::{
|
||||
BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, AuthorityIdFor, Convert,
|
||||
BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, Convert,
|
||||
};
|
||||
use version::RuntimeVersion;
|
||||
use council::{motions as council_motions};
|
||||
@@ -43,13 +44,13 @@ use council::seats as council_seats;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use version::NativeVersion;
|
||||
use substrate_primitives::OpaqueMetadata;
|
||||
use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight};
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub use runtime_primitives::BuildStorage;
|
||||
pub use consensus::Call as ConsensusCall;
|
||||
pub use timestamp::Call as TimestampCall;
|
||||
pub use balances::Call as BalancesCall;
|
||||
pub use runtime_primitives::{Permill, Perbill};
|
||||
pub use runtime_primitives::{Permill, Perbill, impl_opaque_keys};
|
||||
pub use support::StorageValue;
|
||||
pub use staking::StakerStatus;
|
||||
|
||||
@@ -58,7 +59,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("node"),
|
||||
impl_name: create_runtime_str!("substrate-node"),
|
||||
authoring_version: 10,
|
||||
spec_version: 93,
|
||||
spec_version: 94,
|
||||
impl_version: 94,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
@@ -92,16 +93,15 @@ impl system::Trait for Runtime {
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = generic::Digest<Log>;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = Indices;
|
||||
type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
|
||||
type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
type Event = Event;
|
||||
type Log = Log;
|
||||
}
|
||||
|
||||
impl aura::Trait for Runtime {
|
||||
type HandleReport = aura::StakingSlasher<Runtime>;
|
||||
type AuthorityId = AuraId;
|
||||
}
|
||||
|
||||
impl indices::Trait for Runtime {
|
||||
@@ -121,24 +121,40 @@ impl balances::Trait for Runtime {
|
||||
type TransferPayment = ();
|
||||
}
|
||||
|
||||
impl consensus::Trait for Runtime {
|
||||
type Log = Log;
|
||||
type SessionKey = AuthorityId;
|
||||
|
||||
// The Aura module handles offline-reports internally
|
||||
// rather than using an explicit report system.
|
||||
type InherentOfflineReport = ();
|
||||
}
|
||||
|
||||
impl timestamp::Trait for Runtime {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = Aura;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const Period: BlockNumber = 10 * MINUTES;
|
||||
pub const Offset: BlockNumber = 0;
|
||||
}
|
||||
|
||||
type SessionHandlers = (Grandpa, Aura);
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Serialize, Deserialize};
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys(grandpa::AuthorityId, AuraId);
|
||||
}
|
||||
|
||||
// NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler.
|
||||
// The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in
|
||||
// `SessionKeys`.
|
||||
// TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This
|
||||
// should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858
|
||||
|
||||
impl session::Trait for Runtime {
|
||||
type ConvertAccountIdToSessionKey = ();
|
||||
type OnSessionChange = (Staking, grandpa::SyncedAuthorities<Runtime>);
|
||||
type OnSessionEnding = Staking;
|
||||
type SessionHandler = SessionHandlers;
|
||||
type ShouldEndSession = session::PeriodicSessions<Period, Offset>;
|
||||
type Event = Event;
|
||||
type Keys = SessionKeys;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const SessionsPerEra: session::SessionIndex = 6;
|
||||
pub const BondingDuration: staking::EraIndex = 24 * 28;
|
||||
}
|
||||
|
||||
impl staking::Trait for Runtime {
|
||||
@@ -148,6 +164,8 @@ impl staking::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type Slash = ();
|
||||
type Reward = ();
|
||||
type SessionsPerEra = SessionsPerEra;
|
||||
type BondingDuration = BondingDuration;
|
||||
}
|
||||
|
||||
const MINUTES: BlockNumber = 6;
|
||||
@@ -187,7 +205,6 @@ impl council::Trait for Runtime {
|
||||
type OnMembersChanged = CouncilMotions;
|
||||
}
|
||||
|
||||
|
||||
impl council::motions::Trait for Runtime {
|
||||
type Origin = Origin;
|
||||
type Proposal = Call;
|
||||
@@ -220,35 +237,32 @@ impl sudo::Trait for Runtime {
|
||||
}
|
||||
|
||||
impl grandpa::Trait for Runtime {
|
||||
type SessionKey = AuthorityId;
|
||||
type Log = Log;
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl finality_tracker::Trait for Runtime {
|
||||
type OnFinalizationStalled = grandpa::SyncedAuthorities<Runtime>;
|
||||
type OnFinalizationStalled = Grandpa;
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
pub enum Runtime with Log(InternalLog: DigestItem<Hash, AuthorityId, AuthoritySignature>) where
|
||||
pub enum Runtime where
|
||||
Block = Block,
|
||||
NodeBlock = node_primitives::Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system::{default, Log(ChangesTrieRoot)},
|
||||
Aura: aura::{Module, Inherent(Timestamp), Log(PreRuntime)},
|
||||
System: system::{Module, Call, Storage, Config<T>},
|
||||
Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
|
||||
Timestamp: timestamp::{Module, Call, Storage, Config<T>, Inherent},
|
||||
Consensus: consensus::{Module, Call, Storage, Config<T>, Log(AuthoritiesChange), Inherent},
|
||||
Indices: indices,
|
||||
Balances: balances,
|
||||
Session: session,
|
||||
Session: session::{Module, Call, Storage, Event, Config<T>},
|
||||
Staking: staking::{default, OfflineWorker},
|
||||
Democracy: democracy,
|
||||
Council: council::{Module, Call, Storage, Event<T>},
|
||||
CouncilMotions: council_motions::{Module, Call, Storage, Event<T>, Origin<T>},
|
||||
CouncilSeats: council_seats::{Config<T>},
|
||||
FinalityTracker: finality_tracker::{Module, Call, Inherent},
|
||||
Grandpa: grandpa::{Module, Call, Storage, Config<T>, Log(), Event<T>},
|
||||
Grandpa: grandpa::{Module, Call, Storage, Config<T>, Event},
|
||||
Treasury: treasury,
|
||||
Contract: contract::{Module, Call, Storage, Config<T>, Event<T>},
|
||||
Sudo: sudo,
|
||||
@@ -258,7 +272,7 @@ construct_runtime!(
|
||||
/// The address format for describing accounts.
|
||||
pub type Address = <Indices as StaticLookup>::Source;
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Block type as expected by this runtime.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// A Block signed with a Justification
|
||||
@@ -331,45 +345,26 @@ impl_runtime_apis! {
|
||||
fn grandpa_pending_change(digest: &DigestFor<Block>)
|
||||
-> Option<ScheduledChange<NumberFor<Block>>>
|
||||
{
|
||||
for log in digest.logs.iter().filter_map(|l| match l {
|
||||
Log(InternalLog::grandpa(grandpa_signal)) => Some(grandpa_signal),
|
||||
_ => None
|
||||
}) {
|
||||
if let Some(change) = Grandpa::scrape_digest_change(log) {
|
||||
return Some(change);
|
||||
}
|
||||
}
|
||||
None
|
||||
Grandpa::pending_change(digest)
|
||||
}
|
||||
|
||||
fn grandpa_forced_change(digest: &DigestFor<Block>)
|
||||
-> Option<(NumberFor<Block>, ScheduledChange<NumberFor<Block>>)>
|
||||
{
|
||||
for log in digest.logs.iter().filter_map(|l| match l {
|
||||
Log(InternalLog::grandpa(grandpa_signal)) => Some(grandpa_signal),
|
||||
_ => None
|
||||
}) {
|
||||
if let Some(change) = Grandpa::scrape_digest_forced_change(log) {
|
||||
return Some(change);
|
||||
}
|
||||
}
|
||||
None
|
||||
Grandpa::forced_change(digest)
|
||||
}
|
||||
|
||||
fn grandpa_authorities() -> Vec<(AuthorityId, u64)> {
|
||||
fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> {
|
||||
Grandpa::grandpa_authorities()
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_aura::AuraApi<Block> for Runtime {
|
||||
impl consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> u64 {
|
||||
Aura::slot_duration()
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_authorities::AuthoritiesApi<Block> for Runtime {
|
||||
fn authorities() -> Vec<AuthorityIdFor<Block>> {
|
||||
Consensus::authorities()
|
||||
fn authorities() -> Vec<AuraId> {
|
||||
Aura::authorities()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+3
-30
@@ -1484,7 +1484,6 @@ dependencies = [
|
||||
"sr-version 2.0.0",
|
||||
"srml-aura 2.0.0",
|
||||
"srml-balances 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-contract 2.0.0",
|
||||
"srml-council 2.0.0",
|
||||
"srml-democracy 2.0.0",
|
||||
@@ -1501,7 +1500,6 @@ dependencies = [
|
||||
"srml-treasury 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-consensus-authorities 2.0.0",
|
||||
"substrate-keyring 2.0.0",
|
||||
"substrate-offchain-primitives 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
@@ -2425,7 +2423,9 @@ dependencies = [
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
"substrate-consensus-aura-primitives 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2442,20 +2442,6 @@ dependencies = [
|
||||
"substrate-keyring 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srml-consensus"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"substrate-inherents 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srml-contract"
|
||||
version = "2.0.0"
|
||||
@@ -2539,7 +2525,6 @@ dependencies = [
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-finality-tracker 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
@@ -2583,7 +2568,6 @@ dependencies = [
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
"srml-timestamp 2.0.0",
|
||||
@@ -2599,7 +2583,6 @@ dependencies = [
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"srml-consensus 2.0.0",
|
||||
"srml-session 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"srml-system 2.0.0",
|
||||
@@ -2788,21 +2771,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "substrate-consensus-aura-primitives"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"sr-primitives 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-consensus-authorities"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-io 2.0.0",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"sr-version 2.0.0",
|
||||
"srml-support 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
"substrate-primitives 2.0.0",
|
||||
]
|
||||
@@ -2853,6 +2825,7 @@ name = "substrate-finality-grandpa-primitives"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 2.0.0",
|
||||
"sr-std 2.0.0",
|
||||
"substrate-client 2.0.0",
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
//!
|
||||
//! ### Terminology
|
||||
//!
|
||||
//! * **Asset issuance:** The creation of a new asset, whose total supply will belong to the account that issues the asset.
|
||||
//! * **Asset issuance:** The creation of a new asset, whose total supply will belong to the
|
||||
//! account that issues the asset.
|
||||
//! * **Asset transfer:** The action of transferring assets from one account to another.
|
||||
//! * **Asset destruction:** The process of an account removing its entire holding of an asset.
|
||||
//! * **Fungible asset:** An asset whose units are interchangeable.
|
||||
@@ -45,7 +46,8 @@
|
||||
//!
|
||||
//! * Issue a unique asset to its creator's account.
|
||||
//! * Move assets between accounts.
|
||||
//! * Remove an account's balance of an asset when requested by that account's owner and update the asset's total supply.
|
||||
//! * Remove an account's balance of an asset when requested by that account's owner and update
|
||||
//! the asset's total supply.
|
||||
//!
|
||||
//! ## Interface
|
||||
//!
|
||||
@@ -237,7 +239,7 @@ mod tests {
|
||||
use primitives::{
|
||||
BuildStorage,
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
testing::{Digest, DigestItem, Header}
|
||||
testing::Header
|
||||
};
|
||||
|
||||
impl_outer_origin! {
|
||||
@@ -255,12 +257,10 @@ mod tests {
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type Log = DigestItem;
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Event = ();
|
||||
|
||||
@@ -10,18 +10,18 @@ serde = { version = "1.0", optional = true }
|
||||
inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false }
|
||||
primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false }
|
||||
substrate-primitives = { path = "../../core/primitives", default-features = false }
|
||||
srml-support = { path = "../support", default-features = false }
|
||||
system = { package = "srml-system", path = "../system", default-features = false }
|
||||
timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false }
|
||||
staking = { package = "srml-staking", path = "../staking", default-features = false }
|
||||
session = { package = "srml-session", path = "../session", default-features = false }
|
||||
substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives", default-features = false}
|
||||
|
||||
[dev-dependencies]
|
||||
lazy_static = "1.0"
|
||||
parking_lot = "0.8.0"
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
runtime_io = { package = "sr-io", path = "../../core/sr-io" }
|
||||
consensus = { package = "srml-consensus", path = "../consensus" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -31,8 +31,10 @@ std = [
|
||||
"rstd/std",
|
||||
"srml-support/std",
|
||||
"primitives/std",
|
||||
"substrate-primitives/std",
|
||||
"system/std",
|
||||
"timestamp/std",
|
||||
"staking/std",
|
||||
"inherents/std",
|
||||
"substrate-consensus-aura-primitives/std",
|
||||
]
|
||||
|
||||
@@ -51,19 +51,18 @@
|
||||
pub use timestamp;
|
||||
|
||||
use rstd::{result, prelude::*};
|
||||
use parity_codec::{Encode, Decode};
|
||||
use srml_support::storage::StorageValue;
|
||||
use srml_support::{decl_storage, decl_module};
|
||||
use primitives::traits::{SaturatedConversion, Saturating, Zero, One};
|
||||
use parity_codec::Encode;
|
||||
use srml_support::{decl_storage, decl_module, Parameter, storage::StorageValue};
|
||||
use primitives::{traits::{SaturatedConversion, Saturating, Zero, One, Member}, generic::DigestItem};
|
||||
use timestamp::OnTimestampSet;
|
||||
use rstd::marker::PhantomData;
|
||||
#[cfg(feature = "std")]
|
||||
use timestamp::TimestampInherentData;
|
||||
use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError};
|
||||
#[cfg(feature = "std")]
|
||||
use inherents::{InherentDataProviders, ProvideInherentData};
|
||||
use substrate_consensus_aura_primitives::{AURA_ENGINE_ID, ConsensusLog};
|
||||
#[cfg(feature = "std")]
|
||||
use serde::Serialize;
|
||||
use parity_codec::Decode;
|
||||
|
||||
mod mock;
|
||||
mod tests;
|
||||
@@ -93,20 +92,6 @@ impl AuraInherentData for InherentData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Logs in this module.
|
||||
pub type Log<T> = RawLog<T>;
|
||||
|
||||
/// Logs in this module.
|
||||
///
|
||||
/// The type parameter distinguishes logs belonging to two different runtimes,
|
||||
/// which should not be mixed.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<T> {
|
||||
/// AuRa inherent digests
|
||||
PreRuntime([u8; 4], Vec<u8>, PhantomData<T>),
|
||||
}
|
||||
|
||||
/// Provides the slot duration inherent data for `Aura`.
|
||||
#[cfg(feature = "std")]
|
||||
pub struct InherentDataProvider {
|
||||
@@ -166,12 +151,18 @@ impl HandleReport for () {
|
||||
pub trait Trait: timestamp::Trait {
|
||||
/// The logic for handling reports.
|
||||
type HandleReport: HandleReport;
|
||||
|
||||
/// The identifier type for an authority.
|
||||
type AuthorityId: Member + Parameter + Default;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Aura {
|
||||
/// The last timestamp.
|
||||
LastTimestamp get(last) build(|_| 0.into()): T::Moment;
|
||||
|
||||
/// The current authorities
|
||||
pub Authorities get(authorities) config(): Vec<T::AuthorityId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +170,37 @@ decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin { }
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
fn change_authorities(new: Vec<T::AuthorityId>) {
|
||||
<Authorities<T>>::put(&new);
|
||||
|
||||
let log: DigestItem<T::Hash> = DigestItem::Consensus(
|
||||
AURA_ENGINE_ID,
|
||||
ConsensusLog::AuthoritiesChange(new).encode()
|
||||
);
|
||||
<system::Module<T>>::deposit_log(log.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
|
||||
type Key = T::AuthorityId;
|
||||
fn on_new_session<'a, I: 'a>(changed: bool, validators: I)
|
||||
where I: Iterator<Item=(&'a T::AccountId, T::AuthorityId)>
|
||||
{
|
||||
// instant changes
|
||||
if changed {
|
||||
let next_authorities = validators.map(|(_, k)| k).collect::<Vec<_>>();
|
||||
let last_authorities = <Module<T>>::authorities();
|
||||
if next_authorities != last_authorities {
|
||||
Self::change_authorities(next_authorities);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn on_disabled(_i: usize) {
|
||||
// ignore?
|
||||
}
|
||||
}
|
||||
|
||||
/// A report of skipped authorities in Aura.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header, UintAuthorityId}};
|
||||
use primitives::{BuildStorage, traits::IdentityLookup, testing::{Header, UintAuthorityId}};
|
||||
use srml_support::impl_outer_origin;
|
||||
use runtime_io;
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use crate::{Trait, Module};
|
||||
use crate::{Trait, Module, GenesisConfig};
|
||||
|
||||
impl_outer_origin!{
|
||||
pub enum Origin for Test {}
|
||||
@@ -32,24 +32,16 @@ impl_outer_origin!{
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Test;
|
||||
|
||||
impl consensus::Trait for Test {
|
||||
type Log = DigestItem;
|
||||
type SessionKey = UintAuthorityId;
|
||||
type InherentOfflineReport = ();
|
||||
}
|
||||
|
||||
impl system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = ::primitives::traits::BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type Log = DigestItem;
|
||||
}
|
||||
|
||||
impl timestamp::Trait for Test {
|
||||
@@ -59,17 +51,17 @@ impl timestamp::Trait for Test {
|
||||
|
||||
impl Trait for Test {
|
||||
type HandleReport = ();
|
||||
type AuthorityId = UintAuthorityId;
|
||||
}
|
||||
|
||||
pub fn new_test_ext(authorities: Vec<u64>) -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
|
||||
t.extend(consensus::GenesisConfig::<Test>{
|
||||
code: vec![],
|
||||
authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(),
|
||||
}.build_storage().unwrap().0);
|
||||
t.extend(timestamp::GenesisConfig::<Test>{
|
||||
minimum_period: 1,
|
||||
}.build_storage().unwrap().0);
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(),
|
||||
}.build_storage().unwrap().0);
|
||||
t.into()
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ primitives = { package = "sr-primitives", path = "../../core/sr-primitives", def
|
||||
srml-support = { path = "../support", default-features = false }
|
||||
system = { package = "srml-system", path = "../system", default-features = false }
|
||||
timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false }
|
||||
staking = { package = "srml-staking", path = "../staking", default-features = false }
|
||||
session = { package = "srml-session", path = "../session", default-features = false }
|
||||
babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false }
|
||||
|
||||
@@ -23,7 +22,6 @@ lazy_static = "1.3.0"
|
||||
parking_lot = "0.8.0"
|
||||
substrate-primitives = { path = "../../core/primitives" }
|
||||
runtime_io = { package = "sr-io", path = "../../core/sr-io" }
|
||||
consensus = { package = "srml-consensus", path = "../consensus" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
@@ -35,7 +33,6 @@ std = [
|
||||
"primitives/std",
|
||||
"system/std",
|
||||
"timestamp/std",
|
||||
"staking/std",
|
||||
"inherents/std",
|
||||
"babe-primitives/std",
|
||||
]
|
||||
|
||||
@@ -20,18 +20,19 @@
|
||||
#![forbid(unsafe_code)]
|
||||
pub use timestamp;
|
||||
|
||||
use rstd::{result, prelude::*, marker::PhantomData};
|
||||
use srml_support::{decl_storage, decl_module};
|
||||
use rstd::{result, prelude::*};
|
||||
use srml_support::{decl_storage, decl_module, StorageValue};
|
||||
use timestamp::{OnTimestampSet, Trait};
|
||||
use primitives::traits::{SaturatedConversion, Saturating};
|
||||
use primitives::{generic::DigestItem, traits::{SaturatedConversion, Saturating}};
|
||||
#[cfg(feature = "std")]
|
||||
use timestamp::TimestampInherentData;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError};
|
||||
#[cfg(feature = "std")]
|
||||
use inherents::{InherentDataProviders, ProvideInherentData};
|
||||
#[cfg(feature = "std")]
|
||||
use serde::Serialize;
|
||||
use babe_primitives::BABE_ENGINE_ID;
|
||||
|
||||
pub use babe_primitives::AuthorityId;
|
||||
|
||||
/// The BABE inherent identifier.
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot";
|
||||
@@ -58,20 +59,6 @@ impl BabeInherentData for InherentData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Logs in this module.
|
||||
pub type Log<T> = RawLog<T>;
|
||||
|
||||
/// Logs in this module.
|
||||
///
|
||||
/// The type parameter distinguishes logs belonging to two different runtimes,
|
||||
/// which should not be mixed.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<T> {
|
||||
/// BABE inherent digests
|
||||
PreRuntime([u8; 4], Vec<u8>, PhantomData<T>),
|
||||
}
|
||||
|
||||
/// Provides the slot duration inherent data for BABE.
|
||||
#[cfg(feature = "std")]
|
||||
pub struct InherentDataProvider {
|
||||
@@ -121,8 +108,11 @@ impl ProvideInherentData for InherentDataProvider {
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Babe {
|
||||
// The last timestamp.
|
||||
/// The last timestamp.
|
||||
LastTimestamp get(last): T::Moment;
|
||||
|
||||
/// The current authorities set.
|
||||
Authorities get(authorities): Vec<AuthorityId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +133,34 @@ impl<T: Trait> OnTimestampSet<T::Moment> for Module<T> {
|
||||
fn on_timestamp_set(_moment: T::Moment) { }
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
fn change_authorities(new: Vec<AuthorityId>) {
|
||||
<Authorities<T>>::put(&new);
|
||||
|
||||
let log: DigestItem<T::Hash> = DigestItem::Consensus(BABE_ENGINE_ID, new.encode());
|
||||
<system::Module<T>>::deposit_log(log.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
|
||||
type Key = AuthorityId;
|
||||
fn on_new_session<'a, I: 'a>(changed: bool, validators: I)
|
||||
where I: Iterator<Item=(&'a T::AccountId, AuthorityId)>
|
||||
{
|
||||
// instant changes
|
||||
if changed {
|
||||
let next_authorities = validators.map(|(_, k)| k).collect::<Vec<_>>();
|
||||
let last_authorities = <Module<T>>::authorities();
|
||||
if next_authorities != last_authorities {
|
||||
Self::change_authorities(next_authorities);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn on_disabled(_i: usize) {
|
||||
// ignore?
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> ProvideInherent for Module<T> {
|
||||
type Call = timestamp::Call<T>;
|
||||
type Error = MakeFatalError<RuntimeString>;
|
||||
|
||||
@@ -675,12 +675,10 @@ impl<T: Subtrait<I>, I: Instance> system::Trait for ElevatedTrait<T, I> {
|
||||
type BlockNumber = T::BlockNumber;
|
||||
type Hash = T::Hash;
|
||||
type Hashing = T::Hashing;
|
||||
type Digest = T::Digest;
|
||||
type AccountId = T::AccountId;
|
||||
type Lookup = T::Lookup;
|
||||
type Header = T::Header;
|
||||
type Event = ();
|
||||
type Log = T::Log;
|
||||
}
|
||||
impl<T: Subtrait<I>, I: Instance> Trait<I> for ElevatedTrait<T, I> {
|
||||
type Balance = T::Balance;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use primitives::BuildStorage;
|
||||
use primitives::{traits::{IdentityLookup}, testing::{Digest, DigestItem, Header}};
|
||||
use primitives::{traits::{IdentityLookup}, testing::Header};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use runtime_io;
|
||||
use srml_support::impl_outer_origin;
|
||||
@@ -38,12 +38,10 @@ impl system::Trait for Runtime {
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = ::primitives::traits::BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type Log = DigestItem;
|
||||
}
|
||||
impl Trait for Runtime {
|
||||
type Balance = u64;
|
||||
|
||||
@@ -36,7 +36,10 @@ fn basic_locking_should_work() {
|
||||
with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || {
|
||||
assert_eq!(Balances::free_balance(&1), 10);
|
||||
Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 5), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 5),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -89,11 +92,20 @@ fn combination_locking_should_work() {
|
||||
fn lock_value_extension_should_work() {
|
||||
with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || {
|
||||
Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 3),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -101,19 +113,28 @@ fn lock_value_extension_should_work() {
|
||||
fn lock_reasons_should_work() {
|
||||
with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).transaction_fees(0, 1).build(), || {
|
||||
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 1),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
assert_ok!(<Balances as ReservableCurrency<_>>::reserve(&1, 1));
|
||||
assert_ok!(<Balances as MakePayment<_>>::make_payment(&1, 1));
|
||||
|
||||
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1));
|
||||
assert_noop!(<Balances as ReservableCurrency<_>>::reserve(&1, 1), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as ReservableCurrency<_>>::reserve(&1, 1),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
assert_ok!(<Balances as MakePayment<_>>::make_payment(&1, 1));
|
||||
|
||||
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1));
|
||||
assert_ok!(<Balances as ReservableCurrency<_>>::reserve(&1, 1));
|
||||
assert_noop!(<Balances as MakePayment<_>>::make_payment(&1, 1), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as MakePayment<_>>::make_payment(&1, 1),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,7 +142,10 @@ fn lock_reasons_should_work() {
|
||||
fn lock_block_number_should_work() {
|
||||
with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || {
|
||||
Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 1),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
|
||||
System::set_block_number(2);
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1));
|
||||
@@ -132,12 +156,21 @@ fn lock_block_number_should_work() {
|
||||
fn lock_block_number_extension_should_work() {
|
||||
with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || {
|
||||
Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
System::set_block_number(2);
|
||||
Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 3),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -145,11 +178,20 @@ fn lock_block_number_extension_should_work() {
|
||||
fn lock_reasons_extension_should_work() {
|
||||
with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || {
|
||||
Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into());
|
||||
assert_noop!(<Balances as Currency<_>>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal");
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6),
|
||||
"account liquidity restrictions prevent withdrawal"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
[package]
|
||||
name = "srml-consensus"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
parity-codec = { version = "3.3", default-features = false, features = ["derive"] }
|
||||
substrate-primitives = { path = "../../core/primitives", default-features = false }
|
||||
inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false }
|
||||
rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false }
|
||||
primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false }
|
||||
srml-support = { path = "../support", default-features = false }
|
||||
system = { package = "srml-system", path = "../system", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
runtime_io = { package = "sr-io", path = "../../core/sr-io" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"serde",
|
||||
"parity-codec/std",
|
||||
"substrate-primitives/std",
|
||||
"rstd/std",
|
||||
"srml-support/std",
|
||||
"primitives/std",
|
||||
"system/std",
|
||||
"inherents/std",
|
||||
]
|
||||
@@ -1,438 +0,0 @@
|
||||
// Copyright 2017-2019 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/>.
|
||||
|
||||
//! # Consensus Module
|
||||
//!
|
||||
//! - [`consensus::Trait`](./trait.Trait.html)
|
||||
//! - [`Call`](./enum.Call.html)
|
||||
//! - [`Module`](./struct.Module.html)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The consensus module manages the authority set for the native code. It provides support for reporting offline
|
||||
//! behavior among validators and logging changes in the validator authority set.
|
||||
//!
|
||||
//! ## Interface
|
||||
//!
|
||||
//! ### Dispatchable Functions
|
||||
//!
|
||||
//! - `report_misbehavior` - Report some misbehavior. The origin of this call must be signed.
|
||||
//! - `note_offline` - Note that the previous block's validator missed its opportunity to propose a block.
|
||||
//! The origin of this call must be an inherent.
|
||||
//! - `remark` - Make some on-chain remark. The origin of this call must be signed.
|
||||
//! - `set_heap_pages` - Set the number of pages in the WebAssembly environment's heap.
|
||||
//! - `set_code` - Set the new code.
|
||||
//! - `set_storage` - Set some items of storage.
|
||||
//!
|
||||
//! ### Public Functions
|
||||
//!
|
||||
//! - `authorities` - Get the current set of authorities. These are the session keys.
|
||||
//! - `set_authorities` - Set the current set of authorities' session keys.
|
||||
//! - `set_authority_count` - Set the total number of authorities.
|
||||
//! - `set_authority` - Set a single authority by index.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! ### Simple Code Snippet
|
||||
//!
|
||||
//! Set authorities:
|
||||
//!
|
||||
//! ```
|
||||
//! # use srml_consensus as consensus;
|
||||
//! # fn not_executed<T: consensus::Trait>() {
|
||||
//! # let authority1 = T::SessionKey::default();
|
||||
//! # let authority2 = T::SessionKey::default();
|
||||
//! <consensus::Module<T>>::set_authorities(&[authority1, authority2])
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Log changes in the authorities set:
|
||||
//!
|
||||
//! ```
|
||||
//! # use srml_consensus as consensus;
|
||||
//! # use primitives::traits::Zero;
|
||||
//! # use primitives::traits::OnFinalize;
|
||||
//! # fn not_executed<T: consensus::Trait>() {
|
||||
//! <consensus::Module<T>>::on_finalize(T::BlockNumber::zero());
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ### Example from SRML
|
||||
//!
|
||||
//! In the staking module, the `consensus::OnOfflineReport` is implemented to monitor offline
|
||||
//! reporting among validators:
|
||||
//!
|
||||
//! ```
|
||||
//! # use srml_consensus as consensus;
|
||||
//! # trait Trait: consensus::Trait {
|
||||
//! # }
|
||||
//! #
|
||||
//! # srml_support::decl_module! {
|
||||
//! # pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
//! # }
|
||||
//! # }
|
||||
//! #
|
||||
//! impl<T: Trait> consensus::OnOfflineReport<Vec<u32>> for Module<T> {
|
||||
//! fn handle_report(reported_indices: Vec<u32>) {
|
||||
//! for validator_index in reported_indices {
|
||||
//! // Get validator from session module
|
||||
//! // Process validator
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! In the GRANDPA module, we use `srml-consensus` to get the set of `next_authorities` before changing
|
||||
//! this set according to the consensus algorithm (which does not rotate sessions in the *normal* way):
|
||||
//!
|
||||
//! ```
|
||||
//! # use srml_consensus as consensus;
|
||||
//! # use consensus::Trait;
|
||||
//! # fn not_executed<T: consensus::Trait>() {
|
||||
//! let next_authorities = <consensus::Module<T>>::authorities()
|
||||
//! .into_iter()
|
||||
//! .map(|key| (key, 1)) // evenly-weighted.
|
||||
//! .collect::<Vec<(<T as Trait>::SessionKey, u64)>>();
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Related Modules
|
||||
//!
|
||||
//! - [Staking](../srml_staking/index.html): This module uses `srml-consensus` to monitor offline
|
||||
//! reporting among validators.
|
||||
//! - [Aura](../srml_aura/index.html): This module does not relate directly to `srml-consensus`,
|
||||
//! but serves to manage offline reporting for the Aura consensus algorithm with its own `handle_report` method.
|
||||
//! - [Grandpa](../srml_grandpa/index.html): Although GRANDPA does its own voter-set management,
|
||||
//! it has a mode where it can track `consensus`, if desired.
|
||||
//!
|
||||
//! ## References
|
||||
//!
|
||||
//! If you're interested in hacking on this module, it is useful to understand the interaction with
|
||||
//! `substrate/core/inherents/src/lib.rs` and, specifically, the required implementation of `ProvideInherent`
|
||||
//! to create and check inherents.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use serde::Serialize;
|
||||
use rstd::prelude::*;
|
||||
use parity_codec as codec;
|
||||
use codec::{Encode, Decode};
|
||||
use srml_support::{storage, Parameter, decl_storage, decl_module};
|
||||
use srml_support::storage::StorageValue;
|
||||
use srml_support::storage::unhashed::StorageVec;
|
||||
use primitives::traits::{MaybeSerializeDebug, Member};
|
||||
use substrate_primitives::storage::well_known_keys;
|
||||
use system::{ensure_signed, ensure_none};
|
||||
use inherents::{
|
||||
ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use substrate_primitives::sr25519::Public as AuthorityId;
|
||||
|
||||
mod mock;
|
||||
mod tests;
|
||||
|
||||
/// The identifier for consensus inherents.
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"offlrep0";
|
||||
|
||||
/// The error type used by this inherent.
|
||||
pub type InherentError = RuntimeString;
|
||||
|
||||
struct AuthorityStorageVec<S: codec::Codec + Default>(rstd::marker::PhantomData<S>);
|
||||
impl<S: codec::Codec + Default> StorageVec for AuthorityStorageVec<S> {
|
||||
type Item = S;
|
||||
const PREFIX: &'static [u8] = well_known_keys::AUTHORITY_PREFIX;
|
||||
}
|
||||
|
||||
pub type Key = Vec<u8>;
|
||||
pub type KeyValue = (Vec<u8>, Vec<u8>);
|
||||
|
||||
/// Handling offline validator reports in a generic way.
|
||||
pub trait OnOfflineReport<Offline> {
|
||||
fn handle_report(offline: Offline);
|
||||
}
|
||||
|
||||
impl<T> OnOfflineReport<T> for () {
|
||||
fn handle_report(_: T) {}
|
||||
}
|
||||
|
||||
/// Describes the offline-reporting extrinsic.
|
||||
pub trait InherentOfflineReport {
|
||||
/// The report data type passed to the runtime during block authorship.
|
||||
type Inherent: codec::Codec + Parameter;
|
||||
|
||||
/// Whether an inherent is empty and doesn't need to be included.
|
||||
fn is_empty(inherent: &Self::Inherent) -> bool;
|
||||
|
||||
/// Handle the report.
|
||||
fn handle_report(report: Self::Inherent);
|
||||
|
||||
/// Whether two reports are compatible.
|
||||
fn check_inherent(contained: &Self::Inherent, expected: &Self::Inherent) -> Result<(), &'static str>;
|
||||
}
|
||||
|
||||
impl InherentOfflineReport for () {
|
||||
type Inherent = ();
|
||||
|
||||
fn is_empty(_inherent: &()) -> bool { true }
|
||||
fn handle_report(_: ()) { }
|
||||
fn check_inherent(_: &(), _: &()) -> Result<(), &'static str> {
|
||||
Err("Explicit reporting not allowed")
|
||||
}
|
||||
}
|
||||
|
||||
/// A variant of the `OfflineReport` that is useful for instant-finality blocks.
|
||||
///
|
||||
/// This assumes blocks are only finalized.
|
||||
pub struct InstantFinalityReportVec<T>(::rstd::marker::PhantomData<T>);
|
||||
|
||||
impl<T: OnOfflineReport<Vec<u32>>> InherentOfflineReport for InstantFinalityReportVec<T> {
|
||||
type Inherent = Vec<u32>;
|
||||
|
||||
fn is_empty(inherent: &Self::Inherent) -> bool { inherent.is_empty() }
|
||||
|
||||
fn handle_report(report: Vec<u32>) {
|
||||
T::handle_report(report)
|
||||
}
|
||||
|
||||
fn check_inherent(contained: &Self::Inherent, expected: &Self::Inherent) -> Result<(), &'static str> {
|
||||
contained.iter().try_for_each(|n|
|
||||
if !expected.contains(n) {
|
||||
Err("Node we believe online marked offline")
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Logs in this module.
|
||||
pub type Log<T> = RawLog<
|
||||
<T as Trait>::SessionKey,
|
||||
>;
|
||||
|
||||
/// Logs in this module.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<SessionKey> {
|
||||
/// Authorities set has been changed. Contains the new set of authorities.
|
||||
AuthoritiesChange(Vec<SessionKey>),
|
||||
}
|
||||
|
||||
impl<SessionKey: Member> RawLog<SessionKey> {
|
||||
/// Try to cast the log entry as AuthoritiesChange log entry.
|
||||
pub fn as_authorities_change(&self) -> Option<&[SessionKey]> {
|
||||
match *self {
|
||||
RawLog::AuthoritiesChange(ref item) => Some(item),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation for tests outside of this crate.
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl<N> From<RawLog<N>> for primitives::testing::DigestItem where N: Into<AuthorityId> {
|
||||
fn from(log: RawLog<N>) -> primitives::testing::DigestItem {
|
||||
match log {
|
||||
RawLog::AuthoritiesChange(authorities) =>
|
||||
primitives::generic::DigestItem::AuthoritiesChange(
|
||||
authorities.into_iter()
|
||||
.map(Into::into).collect()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Trait: system::Trait {
|
||||
/// Type for all log entries of this module.
|
||||
type Log: From<Log<Self>> + Into<system::DigestItemOf<Self>>;
|
||||
|
||||
type SessionKey: Parameter + Default + MaybeSerializeDebug;
|
||||
/// Defines the offline-report type of the trait.
|
||||
/// Set to `()` if offline-reports aren't needed for this runtime.
|
||||
type InherentOfflineReport: InherentOfflineReport;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Consensus {
|
||||
// Actual authorities set at the block execution start. Is `Some` iff
|
||||
// the set has been changed.
|
||||
OriginalAuthorities: Option<Vec<T::SessionKey>>;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(authorities): Vec<T::SessionKey>;
|
||||
#[serde(with = "substrate_primitives::bytes")]
|
||||
config(code): Vec<u8>;
|
||||
|
||||
build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig<T>| {
|
||||
use codec::{Encode, KeyedVec};
|
||||
|
||||
let auth_count = config.authorities.len() as u32;
|
||||
config.authorities.iter().enumerate().for_each(|(i, v)| {
|
||||
storage.insert((i as u32).to_keyed_vec(well_known_keys::AUTHORITY_PREFIX), v.encode());
|
||||
});
|
||||
storage.insert(well_known_keys::AUTHORITY_COUNT.to_vec(), auth_count.encode());
|
||||
storage.insert(well_known_keys::CODE.to_vec(), config.code.clone());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
/// Report some misbehavior.
|
||||
fn report_misbehavior(origin, _report: Vec<u8>) {
|
||||
ensure_signed(origin)?;
|
||||
}
|
||||
|
||||
/// Note that the previous block's validator missed its opportunity to propose a block.
|
||||
fn note_offline(origin, offline: <T::InherentOfflineReport as InherentOfflineReport>::Inherent) {
|
||||
ensure_none(origin)?;
|
||||
|
||||
T::InherentOfflineReport::handle_report(offline);
|
||||
}
|
||||
|
||||
/// Make some on-chain remark.
|
||||
fn remark(origin, _remark: Vec<u8>) {
|
||||
ensure_signed(origin)?;
|
||||
}
|
||||
|
||||
/// Set the number of pages in the WebAssembly environment's heap.
|
||||
fn set_heap_pages(pages: u64) {
|
||||
storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode());
|
||||
}
|
||||
|
||||
/// Set the new code.
|
||||
pub fn set_code(new: Vec<u8>) {
|
||||
storage::unhashed::put_raw(well_known_keys::CODE, &new);
|
||||
}
|
||||
|
||||
/// Set some items of storage.
|
||||
fn set_storage(items: Vec<KeyValue>) {
|
||||
for i in &items {
|
||||
storage::unhashed::put_raw(&i.0, &i.1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Kill some items from storage.
|
||||
fn kill_storage(keys: Vec<Key>) {
|
||||
for key in &keys {
|
||||
storage::unhashed::kill(&key);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_finalize() {
|
||||
if let Some(original_authorities) = <OriginalAuthorities<T>>::take() {
|
||||
let current_authorities = AuthorityStorageVec::<T::SessionKey>::items();
|
||||
if current_authorities != original_authorities {
|
||||
Self::deposit_log(RawLog::AuthoritiesChange(current_authorities));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
/// Get the current set of authorities. These are the session keys.
|
||||
pub fn authorities() -> Vec<T::SessionKey> {
|
||||
AuthorityStorageVec::<T::SessionKey>::items()
|
||||
}
|
||||
|
||||
/// Set the current set of authorities' session keys. Will not exceed the current
|
||||
/// authorities count, even if the given `authorities` is longer.
|
||||
///
|
||||
/// Called by `rotate_session` only.
|
||||
pub fn set_authorities(authorities: &[T::SessionKey]) {
|
||||
let current_authorities = AuthorityStorageVec::<T::SessionKey>::items();
|
||||
if current_authorities != authorities {
|
||||
Self::save_original_authorities(Some(current_authorities));
|
||||
AuthorityStorageVec::<T::SessionKey>::set_items(authorities);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the total number of authorities.
|
||||
pub fn set_authority_count(count: u32) {
|
||||
Self::save_original_authorities(None);
|
||||
AuthorityStorageVec::<T::SessionKey>::set_count(count);
|
||||
}
|
||||
|
||||
/// Set a single authority by index.
|
||||
pub fn set_authority(index: u32, key: &T::SessionKey) {
|
||||
let current_authority = AuthorityStorageVec::<T::SessionKey>::item(index);
|
||||
if current_authority != *key {
|
||||
Self::save_original_authorities(None);
|
||||
AuthorityStorageVec::<T::SessionKey>::set_item(index, key);
|
||||
}
|
||||
}
|
||||
|
||||
/// Save original authorities set.
|
||||
fn save_original_authorities(current_authorities: Option<Vec<T::SessionKey>>) {
|
||||
if OriginalAuthorities::<T>::get().is_some() {
|
||||
// if we have already saved original set before, do not overwrite
|
||||
return;
|
||||
}
|
||||
|
||||
<OriginalAuthorities<T>>::put(current_authorities.unwrap_or_else(||
|
||||
AuthorityStorageVec::<T::SessionKey>::items()));
|
||||
}
|
||||
|
||||
/// Deposit one of this module's logs.
|
||||
fn deposit_log(log: Log<T>) {
|
||||
<system::Module<T>>::deposit_log(<T as Trait>::Log::from(log).into());
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementing `ProvideInherent` enables this module to create and check inherents.
|
||||
impl<T: Trait> ProvideInherent for Module<T> {
|
||||
/// The call type of the module.
|
||||
type Call = Call<T>;
|
||||
/// The error returned by `check_inherent`.
|
||||
type Error = MakeFatalError<RuntimeString>;
|
||||
/// The inherent identifier used by this inherent.
|
||||
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
|
||||
|
||||
/// Creates an inherent from the `InherentData`.
|
||||
fn create_inherent(data: &InherentData) -> Option<Self::Call> {
|
||||
if let Ok(Some(data)) =
|
||||
data.get_data::<<T::InherentOfflineReport as InherentOfflineReport>::Inherent>(
|
||||
&INHERENT_IDENTIFIER
|
||||
)
|
||||
{
|
||||
if <T::InherentOfflineReport as InherentOfflineReport>::is_empty(&data) {
|
||||
None
|
||||
} else {
|
||||
Some(Call::note_offline(data))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify the validity of the given inherent.
|
||||
fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> {
|
||||
let offline = match call {
|
||||
Call::note_offline(ref offline) => offline,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
let expected = data
|
||||
.get_data::<<T::InherentOfflineReport as InherentOfflineReport>::Inherent>(&INHERENT_IDENTIFIER)?
|
||||
.ok_or(RuntimeString::from("No `offline_report` found in the inherent data!"))?;
|
||||
|
||||
<T::InherentOfflineReport as InherentOfflineReport>::check_inherent(
|
||||
&offline, &expected
|
||||
).map_err(|e| RuntimeString::from(e).into())
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright 2018-2019 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/>.
|
||||
|
||||
//! Test utilities
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header, UintAuthorityId}};
|
||||
use srml_support::impl_outer_origin;
|
||||
use runtime_io;
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use crate::{GenesisConfig, Trait, Module};
|
||||
|
||||
impl_outer_origin!{
|
||||
pub enum Origin for Test {}
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Test;
|
||||
impl Trait for Test {
|
||||
type Log = DigestItem;
|
||||
type SessionKey = UintAuthorityId;
|
||||
type InherentOfflineReport = crate::InstantFinalityReportVec<()>;
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = ::primitives::traits::BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type Log = DigestItem;
|
||||
}
|
||||
|
||||
pub fn new_test_ext(authorities: Vec<u64>) -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
code: vec![],
|
||||
authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(),
|
||||
}.build_storage().unwrap().0);
|
||||
t.into()
|
||||
}
|
||||
|
||||
pub type System = system::Module<Test>;
|
||||
pub type Consensus = Module<Test>;
|
||||
@@ -1,131 +0,0 @@
|
||||
// Copyright 2017-2019 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/>.
|
||||
|
||||
//! Tests for the module.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use primitives::{generic, testing::{self, UintAuthorityId}, traits::OnFinalize};
|
||||
use runtime_io::with_externalities;
|
||||
use crate::mock::{Consensus, System, new_test_ext};
|
||||
use inherents::{InherentData, ProvideInherent};
|
||||
|
||||
#[test]
|
||||
fn authorities_change_logged() {
|
||||
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
|
||||
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
|
||||
Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]);
|
||||
Consensus::on_finalize(1);
|
||||
let header = System::finalize();
|
||||
assert_eq!(header.digest, testing::Digest {
|
||||
logs: vec![
|
||||
generic::DigestItem::AuthoritiesChange(
|
||||
vec![
|
||||
UintAuthorityId(4).into(),
|
||||
UintAuthorityId(5).into(),
|
||||
UintAuthorityId(6).into()
|
||||
]
|
||||
),
|
||||
],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partial_authorities_change_logged() {
|
||||
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
|
||||
System::initialize(&2, &Default::default(), &Default::default(), &Default::default());
|
||||
Consensus::set_authorities(&[UintAuthorityId(2), UintAuthorityId(4), UintAuthorityId(5)]);
|
||||
Consensus::on_finalize(2);
|
||||
let header = System::finalize();
|
||||
assert_eq!(header.digest, testing::Digest {
|
||||
logs: vec![
|
||||
generic::DigestItem::AuthoritiesChange(
|
||||
vec![
|
||||
UintAuthorityId(2).into(),
|
||||
UintAuthorityId(4).into(),
|
||||
UintAuthorityId(5).into()
|
||||
]
|
||||
),
|
||||
],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authorities_change_is_not_logged_when_not_changed() {
|
||||
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
|
||||
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
|
||||
Consensus::on_finalize(1);
|
||||
let header = System::finalize();
|
||||
assert_eq!(header.digest, testing::Digest {
|
||||
logs: vec![],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authorities_change_is_not_logged_when_changed_back_to_original() {
|
||||
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
|
||||
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
|
||||
Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]);
|
||||
Consensus::set_authorities(&[UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
|
||||
Consensus::on_finalize(1);
|
||||
let header = System::finalize();
|
||||
assert_eq!(header.digest, testing::Digest {
|
||||
logs: vec![],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offline_report_can_be_excluded() {
|
||||
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
|
||||
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
|
||||
assert!(Consensus::create_inherent(&InherentData::new()).is_none());
|
||||
|
||||
let offline_report: Vec<u32> = vec![0];
|
||||
let mut data = InherentData::new();
|
||||
data.put_data(super::INHERENT_IDENTIFIER, &offline_report).unwrap();
|
||||
|
||||
assert!(Consensus::create_inherent(&data).is_some());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_and_kill_storage_work() {
|
||||
use srml_support::storage;
|
||||
|
||||
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
|
||||
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
|
||||
|
||||
let item = (vec![42u8], vec![42u8]);
|
||||
|
||||
Consensus::set_storage(vec![item.clone()]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
storage::unhashed::get_raw(&item.0),
|
||||
Some(item.1),
|
||||
);
|
||||
|
||||
Consensus::kill_storage(vec![item.0.clone()]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
storage::unhashed::get_raw(&item.0),
|
||||
None,
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -23,7 +23,6 @@ timestamp = { package = "srml-timestamp", path = "../timestamp", default-feature
|
||||
wabt = "~0.7.4"
|
||||
assert_matches = "1.1"
|
||||
hex-literal = "0.2.0"
|
||||
consensus = { package = "srml-consensus", path = "../consensus" }
|
||||
balances = { package = "srml-balances", path = "../balances" }
|
||||
hex = "0.3"
|
||||
|
||||
|
||||
@@ -216,7 +216,8 @@ pub struct RawTombstoneContractInfo<H, Hasher>(H, PhantomData<Hasher>);
|
||||
|
||||
impl<H, Hasher> RawTombstoneContractInfo<H, Hasher>
|
||||
where
|
||||
H: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + rstd::hash::Hash,
|
||||
H: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + rstd::hash::Hash
|
||||
+ Codec,
|
||||
Hasher: Hash<Output=H>,
|
||||
{
|
||||
fn new(storage_root: &[u8], code_hash: H) -> Self {
|
||||
|
||||
@@ -40,7 +40,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use substrate_primitives::storage::well_known_keys;
|
||||
use substrate_primitives::Blake2Hasher;
|
||||
use system::{self, EventRecord, Phase};
|
||||
use {balances, consensus, wabt};
|
||||
use {balances, wabt};
|
||||
|
||||
mod contract {
|
||||
// Re-export contents of the root. This basically
|
||||
@@ -72,12 +72,10 @@ impl system::Trait for Test {
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = MetaEvent;
|
||||
type Log = DigestItem;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
@@ -92,11 +90,6 @@ impl timestamp::Trait for Test {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = ();
|
||||
}
|
||||
impl consensus::Trait for Test {
|
||||
type Log = DigestItem;
|
||||
type SessionKey = UintAuthorityId;
|
||||
type InherentOfflineReport = ();
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Currency = Balances;
|
||||
type Call = Call;
|
||||
@@ -1002,7 +995,8 @@ const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#"
|
||||
)
|
||||
)
|
||||
"#;
|
||||
const HASH_CHECK_DEFAULT_RENT_ALLOWANCE: [u8; 32] = hex!("4f9ec2b94eea522cfff10b77ef4056c631045c00978a457d283950521ecf07b6");
|
||||
const HASH_CHECK_DEFAULT_RENT_ALLOWANCE: [u8; 32] =
|
||||
hex!("4f9ec2b94eea522cfff10b77ef4056c631045c00978a457d283950521ecf07b6");
|
||||
|
||||
#[test]
|
||||
fn default_rent_allowance_on_create() {
|
||||
|
||||
@@ -73,12 +73,10 @@ mod tests {
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = Event;
|
||||
type Log = DigestItem;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
|
||||
@@ -397,7 +397,12 @@ mod tests {
|
||||
assert_eq!(System::events(), vec![
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 3)),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(
|
||||
1,
|
||||
0,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
3,
|
||||
)),
|
||||
topics: vec![],
|
||||
}
|
||||
]);
|
||||
@@ -409,7 +414,10 @@ mod tests {
|
||||
with_externalities(&mut ExtBuilder::default().with_council(true).build(), || {
|
||||
System::set_block_number(1);
|
||||
let proposal = set_balance_proposal(42);
|
||||
assert_noop!(CouncilMotions::propose(Origin::signed(42), 3, Box::new(proposal.clone())), "proposer not on council");
|
||||
assert_noop!(
|
||||
CouncilMotions::propose(Origin::signed(42), 3, Box::new(proposal.clone())),
|
||||
"proposer not on council"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -457,12 +465,23 @@ mod tests {
|
||||
assert_eq!(System::events(), vec![
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 2)),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(
|
||||
1,
|
||||
0,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
2,
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Voted(1, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false, 0, 1)),
|
||||
event: OuterEvent::motions(RawEvent::Voted(
|
||||
1,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
false,
|
||||
0,
|
||||
1,
|
||||
)),
|
||||
topics: vec![],
|
||||
}
|
||||
]);
|
||||
@@ -481,17 +500,31 @@ mod tests {
|
||||
assert_eq!(System::events(), vec![
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 3)),
|
||||
event: OuterEvent::motions(
|
||||
RawEvent::Proposed(
|
||||
1,
|
||||
0,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
3,
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Voted(2, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false, 1, 1)),
|
||||
event: OuterEvent::motions(RawEvent::Voted(
|
||||
2,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
false,
|
||||
1,
|
||||
1,
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Disapproved(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into())),
|
||||
event: OuterEvent::motions(RawEvent::Disapproved(
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
)),
|
||||
topics: vec![],
|
||||
}
|
||||
]);
|
||||
@@ -510,22 +543,38 @@ mod tests {
|
||||
assert_eq!(System::events(), vec![
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 2)),
|
||||
event: OuterEvent::motions(RawEvent::Proposed(
|
||||
1,
|
||||
0,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
2,
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Voted(2, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), true, 2, 0)),
|
||||
event: OuterEvent::motions(RawEvent::Voted(
|
||||
2,
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
true,
|
||||
2,
|
||||
0,
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Approved(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into())),
|
||||
event: OuterEvent::motions(RawEvent::Approved(
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: OuterEvent::motions(RawEvent::Executed(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false)),
|
||||
event: OuterEvent::motions(RawEvent::Executed(
|
||||
hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(),
|
||||
false,
|
||||
)),
|
||||
topics: vec![],
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -919,7 +919,7 @@ mod tests {
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{BlakeTwo256, IdentityLookup, Bounded};
|
||||
use primitives::testing::{Digest, DigestItem, Header};
|
||||
use primitives::testing::Header;
|
||||
use balances::BalanceLock;
|
||||
use system::EnsureSignedBy;
|
||||
|
||||
@@ -948,12 +948,10 @@ mod tests {
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type Log = DigestItem;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user