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:
Gavin Wood
2019-06-14 16:34:34 +02:00
committed by GitHub
parent 0f44a28ce3
commit bda8641892
128 changed files with 2646 additions and 3671 deletions
+2 -2
View File
@@ -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
+7 -44
View File
@@ -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",
-1
View File
@@ -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
+18 -8
View File
@@ -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);
+4 -8
View File
@@ -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);
+3 -3
View File
@@ -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::*,
+4 -8
View File
@@ -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],
);
}
}
+7 -7
View File
@@ -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]
+1 -1
View File
@@ -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,
-2
View File
@@ -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>;
}
}
+15 -17
View File
@@ -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))
}
}
+48 -57
View File
@@ -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>>;
}
}
-2
View File
@@ -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>;
}
}
+7 -46
View File
@@ -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,
}
}
}
+34 -54
View File
@@ -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 dont 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,
+2 -11
View File
@@ -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]);
}
}
-1
View File
@@ -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" }
+166 -53
View File
@@ -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);
+12 -4
View File
@@ -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
+3 -3
View File
@@ -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>);
+3 -2
View File
@@ -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);
+2
View File
@@ -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"
+13 -8
View File
@@ -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))
}
}
+2 -2
View File
@@ -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))
-12
View File
@@ -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";
+6 -2
View File
@@ -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);
}
+3 -3
View File
@@ -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!();
/// # }
/// # }
+6 -3
View File
@@ -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)
+57 -10
View File
@@ -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
+173 -232
View File
@@ -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 blocks 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);
}
+3 -283
View File
@@ -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]);
+15 -36
View File
@@ -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,
+82 -55
View File
@@ -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.
-1
View File
@@ -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" }
-2
View File
@@ -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
}
}
+16 -22
View File
@@ -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()
}
}
}
}
}
+49 -58
View File
@@ -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
View File
@@ -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",
+7 -2
View File
@@ -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",
]
+17 -35
View File
@@ -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
View File
@@ -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",
]
+7 -6
View File
@@ -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.
}),
+1
View File
@@ -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" }
+72 -40
View File
@@ -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(),
}),
}
}
+4 -4
View File
@@ -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,
-1
View File
@@ -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" }
+104 -50
View File
@@ -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());
}
+6 -7
View File
@@ -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.
-4
View File
@@ -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",
]
+50 -55
View File
@@ -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()
}
}
}
+3 -30
View File
@@ -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",
+5 -5
View File
@@ -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 = ();
+4 -2
View File
@@ -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",
]
+42 -20
View File
@@ -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))]
+6 -14
View File
@@ -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()
}
-3
View File
@@ -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",
]
+38 -20
View File
@@ -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>;
-2
View File
@@ -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;
+1 -3
View File
@@ -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;
+56 -14
View File
@@ -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"
);
});
}
-31
View File
@@ -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",
]
-438
View File
@@ -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())
}
}
-63
View File
@@ -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>;
-131
View File
@@ -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,
);
});
}
-1
View File
@@ -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"
+2 -1
View File
@@ -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 {
+3 -9
View File
@@ -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() {
-2
View File
@@ -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;
+60 -11
View File
@@ -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![],
}
]);
+1 -3
View File
@@ -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