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
@@ -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);
}