Make substrate generic (#169)

* Some initial work on RPC and client

* Rephrase as params

* More work on traitifying substrate.

* Traitify in_mem.rs

* traitify client.rs

* Make new primitives (mainly traits) build again.

* Many (superficial) build fixes throughout.

* Fix remaining build issues up to bft interface.

* Make bft primitives be generic.

* Switch out MisBehaviorReport for generic version.

* Merge Hashing into Header.

* Update runtime for new generics (with Hashing).

* Update demo runtime.

* Make runtime compile.

* Build fixes for runtime

* Remove old modules.

* port substrate-bft to use generic substrate types

* port client

* port substrate-test-runtime

* mostly port test-runtime to get compiling for std

* Ensure `AccountId` has a `Default`.

* Fix type deps.

* finish porting

* initialize test_runtime from genesis correctly

* remove commented code

* maybe unsigned signatures

* runtimes compile

* port over most of network

* serialization for generic types

* fix comment

* remove some unnecessary trait bounds

* network compiles

* tests compile for sync

* fix deserialization

* temporarily remove deserialize derives

* workarounds for serde issues for deriving deserialization

* get demo-runtime compiling on std

* port extrinsic-pool

* primitives reshuffling

* get network compiling again

* remove debugging file

* runtime tests now passing

* port client-db

* start to port over substrate-rpc

* mostly port over PolkadotApi

* test_runtime follows normal conventions

* substrate runtime tests pass

* deal with inherent extrinsics correctly in polkadot-api

* port transaction-pool

* port polkadot-consensus

* port substrate-rpc

* everything compiles

* tests compile

* fix grumbles

* test-runtime uses its own transfer type

* switch to master branch of jsonrpc

* fix network tests and some warnings

* all tests pass locally

* [ci-skip] add another comment about issue

* remove some curlies
This commit is contained in:
Gav Wood
2018-06-06 17:58:45 +02:00
committed by Robert Habermeier
parent 4e844760a3
commit b94cf078af
132 changed files with 4695 additions and 4303 deletions
+700 -556
View File
File diff suppressed because it is too large Load Diff
+12 -11
View File
@@ -49,17 +49,18 @@ pub mod error;
use std::sync::Arc;
use client::genesis;
use codec::Slicable;
use demo_primitives::Hash;
use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
SessionConfig, StakingConfig, BuildExternalities};
use demo_runtime::{Block, Header, UncheckedExtrinsic};
use futures::{Future, Sink, Stream};
struct DummyPool;
impl extrinsic_pool::api::ExtrinsicPool for DummyPool {
impl extrinsic_pool::api::ExtrinsicPool<UncheckedExtrinsic, Hash> for DummyPool {
type Error = extrinsic_pool::txpool::Error;
fn submit(&self, _: Vec<primitives::block::Extrinsic>)
-> Result<Vec<primitives::block::ExtrinsicHash>, Self::Error>
fn submit(&self, _: Vec<UncheckedExtrinsic>)
-> Result<Vec<Hash>, Self::Error>
{
Err("unimplemented".into())
}
@@ -102,8 +103,8 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
struct GenesisBuilder;
impl client::GenesisBuilder for GenesisBuilder {
fn build(self) -> (primitives::Header, Vec<(Vec<u8>, Vec<u8>)>) {
impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"];
let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig {
@@ -113,7 +114,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
system: None,
// block_time: 5, // 5 second block time.
session: Some(SessionConfig {
validators: vec![god_key.clone()],
validators: vec![god_key.clone().into()],
session_length: 720, // that's 1 hour per session.
}),
staking: Some(StakingConfig {
@@ -121,7 +122,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
intentions: vec![],
transaction_base_fee: 100,
transaction_byte_fee: 1,
balances: vec![(god_key.clone(), 1u64 << 63)].into_iter().collect(),
balances: vec![(god_key.clone().into(), 1u64 << 63)].into_iter().collect(),
validator_count: 12,
sessions_per_era: 24, // 24 hours per era.
bonding_duration: 90, // 90 days per bond.
@@ -149,8 +150,8 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
};
let storage = genesis_config.build_externalities();
let block = genesis::construct_genesis_block(&storage);
(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
let block = genesis::construct_genesis_block::<Block>(&storage);
(block.header, storage.into_iter().collect())
}
}
@@ -160,7 +161,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
let _rpc_servers = {
let handler = || {
let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote());
rpc::rpc_handler(client.clone(), chain, Arc::new(DummyPool), DummySystem)
rpc::rpc_handler::<Block, _, _, _, _>(client.clone(), chain, Arc::new(DummyPool), DummySystem)
};
let http_address = "127.0.0.1:9933".parse().unwrap();
let ws_address = "127.0.0.1:9944".parse().unwrap();
+43 -35
View File
@@ -42,7 +42,7 @@ mod tests {
use super::Executor;
use substrate_executor::WasmExecutor;
use codec::{Slicable, Joiner};
use keyring::Keyring::{self, Alice, Bob};
use keyring::Keyring;
use runtime_support::{Hashable, StorageValue, StorageMap};
use state_machine::{CodeExecutor, TestExternalities};
use primitives::twox_128;
@@ -63,13 +63,21 @@ mod tests {
)
}
fn alice() -> Hash {
Keyring::Alice.to_raw_public().into()
}
fn bob() -> Hash {
Keyring::Bob.to_raw_public().into()
}
fn xt() -> UncheckedExtrinsic {
let extrinsic = Extrinsic {
signed: Alice.into(),
signed: alice(),
index: 0,
function: Call::Staking(staking::Call::transfer::<Concrete>(Bob.into(), 69)),
function: Call::Staking(staking::Call::transfer::<Concrete>(bob(), 69)),
};
let signature = Keyring::from_raw_public(extrinsic.signed).unwrap()
let signature = Keyring::from_raw_public(extrinsic.signed.0).unwrap()
.sign(&extrinsic.encode()).into();
UncheckedExtrinsic { extrinsic, signature }
@@ -82,7 +90,7 @@ mod tests {
#[test]
fn panic_execution_with_foreign_code_gives_error() {
let mut t: TestExternalities = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -97,7 +105,7 @@ mod tests {
#[test]
fn panic_execution_with_native_equivalent_code_gives_error() {
let mut t: TestExternalities = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -112,7 +120,7 @@ mod tests {
#[test]
fn successful_execution_with_native_equivalent_code_gives_ok() {
let mut t: TestExternalities = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -124,15 +132,15 @@ mod tests {
assert!(r.is_ok());
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 42);
assert_eq!(Staking::balance(&Bob), 69);
assert_eq!(Staking::balance(&alice()), 42);
assert_eq!(Staking::balance(&bob()), 69);
});
}
#[test]
fn successful_execution_with_foreign_code_gives_ok() {
let mut t: TestExternalities = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -144,26 +152,26 @@ mod tests {
assert!(r.is_ok());
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 42);
assert_eq!(Staking::balance(&Bob), 69);
assert_eq!(Staking::balance(&alice()), 42);
assert_eq!(Staking::balance(&bob()), 69);
});
}
fn new_test_ext() -> TestExternalities {
use keyring::Keyring::*;
let three = [3u8; 32];
let three = [3u8; 32].into();
GenesisConfig {
consensus: Some(Default::default()),
system: Some(Default::default()),
session: Some(SessionConfig {
session_length: 2,
validators: vec![One.into(), Two.into(), three],
validators: vec![One.to_raw_public().into(), Two.to_raw_public().into(), three],
}),
staking: Some(StakingConfig {
sessions_per_era: 2,
current_era: 0,
balances: vec![(Alice.into(), 111)],
intentions: vec![Alice.into(), Bob.into(), Charlie.into()],
balances: vec![(alice(), 111)],
intentions: vec![alice(), bob(), Charlie.to_raw_public().into()],
validator_count: 3,
bonding_duration: 0,
transaction_base_fee: 1,
@@ -178,7 +186,7 @@ mod tests {
use triehash::ordered_trie_root;
let extrinsics = extrinsics.into_iter().map(|extrinsic| {
let signature = Pair::from(Keyring::from_public(Public::from_raw(extrinsic.signed)).unwrap())
let signature = Pair::from(Keyring::from_public(Public::from_raw(extrinsic.signed.0)).unwrap())
.sign(&extrinsic.encode()).into();
UncheckedExtrinsic { extrinsic, signature }
@@ -204,9 +212,9 @@ mod tests {
[69u8; 32].into(),
hex!("76b0393b4958d3cb98bb51d9f4edb316af48485142b8721e94c3b52c75ec3243").into(),
vec![Extrinsic {
signed: Alice.into(),
signed: alice(),
index: 0,
function: Call::Staking(staking::Call::transfer(Bob.into(), 69)),
function: Call::Staking(staking::Call::transfer(bob(), 69)),
}]
)
}
@@ -218,14 +226,14 @@ mod tests {
hex!("8ae9828a5988459d35fb428086170dead660176ee0766e89bc1a4b48153d4e88").into(),
vec![
Extrinsic {
signed: Bob.into(),
signed: bob(),
index: 0,
function: Call::Staking(staking::Call::transfer(Alice.into(), 5)),
function: Call::Staking(staking::Call::transfer(alice(), 5)),
},
Extrinsic {
signed: Alice.into(),
signed: alice(),
index: 1,
function: Call::Staking(staking::Call::transfer(Bob.into(), 15)),
function: Call::Staking(staking::Call::transfer(bob(), 15)),
}
]
)
@@ -238,15 +246,15 @@ mod tests {
Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 41);
assert_eq!(Staking::balance(&Bob), 69);
assert_eq!(Staking::balance(&alice()), 41);
assert_eq!(Staking::balance(&bob()), 69);
});
Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 30);
assert_eq!(Staking::balance(&Bob), 78);
assert_eq!(Staking::balance(&alice()), 30);
assert_eq!(Staking::balance(&bob()), 78);
});
}
@@ -257,22 +265,22 @@ mod tests {
WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 41);
assert_eq!(Staking::balance(&Bob), 69);
assert_eq!(Staking::balance(&alice()), 41);
assert_eq!(Staking::balance(&bob()), 69);
});
WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 30);
assert_eq!(Staking::balance(&Bob), 78);
assert_eq!(Staking::balance(&alice()), 30);
assert_eq!(Staking::balance(&bob()), 78);
});
}
#[test]
fn panic_execution_gives_error() {
let mut t: TestExternalities = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -288,7 +296,7 @@ mod tests {
#[test]
fn successful_execution_gives_ok() {
let mut t: TestExternalities = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -301,8 +309,8 @@ mod tests {
assert!(r.is_ok());
runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 42);
assert_eq!(Staking::balance(&Bob), 69);
assert_eq!(Staking::balance(&alice()), 42);
assert_eq!(Staking::balance(&bob()), 69);
});
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ pub type BlockNumber = u64;
/// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost
/// certainly continue to be the same as the substrate's `AuthorityId`.
pub type AccountId = primitives::AuthorityId;
pub type AccountId = ::primitives::H256;
/// Balance of an account.
pub type Balance = u64;
+25 -7
View File
@@ -22,11 +22,18 @@
extern crate substrate_runtime_io as runtime_io;
#[macro_use]
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_support;
#[macro_use]
extern crate substrate_runtime_primitives as runtime_primitives;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
extern crate serde;
extern crate substrate_runtime_std as rstd;
extern crate substrate_runtime_consensus as consensus;
extern crate substrate_runtime_council as council;
@@ -39,10 +46,9 @@ extern crate substrate_runtime_timestamp as timestamp;
extern crate demo_primitives;
use rstd::prelude::*;
use runtime_io::BlakeTwo256;
use demo_primitives::{AccountId, Balance, BlockNumber, Hash, Index, SessionKey, Signature};
use runtime_primitives::generic;
use runtime_primitives::traits::{Identity, HasPublicAux};
use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256};
#[cfg(any(feature = "std", test))]
pub use runtime_primitives::BuildExternalities;
@@ -61,7 +67,7 @@ impl system::Trait for Concrete {
type Hashing = BlakeTwo256;
type Digest = generic::Digest<Vec<u8>>;
type AccountId = AccountId;
type Header = generic::Header<BlockNumber, Hash, Vec<u8>>;
type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
}
/// System module for this concrete runtime.
@@ -84,8 +90,16 @@ impl timestamp::Trait for Concrete {
/// Timestamp module for this concrete runtime.
pub type Timestamp = timestamp::Module<Concrete>;
/// Session key conversion.
pub struct SessionKeyConversion;
impl Convert<AccountId, SessionKey> for SessionKeyConversion {
fn convert(a: AccountId) -> SessionKey {
a.0
}
}
impl session::Trait for Concrete {
type ConvertAccountIdToSessionKey = Identity;
type ConvertAccountIdToSessionKey = SessionKeyConversion;
}
/// Session module for this concrete runtime.
@@ -114,6 +128,8 @@ pub type Council = council::Module<Concrete>;
pub type CouncilVoting = council::voting::Module<Concrete>;
impl_outer_dispatch! {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
Consensus = 0,
Session = 1,
@@ -124,6 +140,8 @@ impl_outer_dispatch! {
CouncilVoting = 7,
}
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum PrivCall {
Consensus = 0,
Session = 1,
@@ -135,9 +153,9 @@ impl_outer_dispatch! {
}
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, Hash, Vec<u8>>;
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<BlockNumber, Hash, Vec<u8>, AccountId, Index, Call, Signature>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
/// Extrinsic type as expected by this runtime.
+246 -192
View File
@@ -11,19 +11,9 @@ name = "base58"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bigint"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.0.1"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -37,33 +27,55 @@ dependencies = [
[[package]]
name = "byteorder"
version = "1.2.1"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.4"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "coco"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crossbeam-deque"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crunchy"
version = "0.1.6"
@@ -73,8 +85,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "demo-primitives"
version = "0.1.0"
dependencies = [
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0",
@@ -110,20 +122,15 @@ version = "0.1.0"
dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "elastic-array"
version = "0.9.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -134,15 +141,37 @@ name = "environmental"
version = "0.1.0"
[[package]]
name = "ethcore-bigint"
name = "ethbloom"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethereum-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethereum-types-serialize"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -154,12 +183,23 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fixed-hash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -183,16 +223,16 @@ dependencies = [
[[package]]
name = "hex-literal"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hex-literal-impl"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -205,12 +245,12 @@ source = "git+https://github.com/paritytech/integer-sqrt-rs.git#886e9cb983c46498
[[package]]
name = "keccak-hash"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -220,12 +260,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.36"
version = "0.2.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -241,9 +281,14 @@ name = "log"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memoffset"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memory_units"
version = "0.3.0"
@@ -264,7 +309,7 @@ name = "num_cpus"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -280,9 +325,9 @@ name = "parity-wasm"
version = "0.27.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -290,37 +335,29 @@ name = "parity-wasm"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.5.4"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.2.10"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "plain_hasher"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro-hack"
version = "0.4.0"
@@ -334,12 +371,20 @@ name = "proc-macro-hack-impl"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pwasm-alloc"
version = "0.1.0"
dependencies = [
"pwasm-libc 0.1.0",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -351,15 +396,18 @@ name = "pwasm-utils"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.3.15"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
@@ -367,7 +415,7 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -377,7 +425,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -386,19 +434,19 @@ name = "rayon"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -408,20 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rlp"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -437,17 +484,17 @@ source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc
[[package]]
name = "rustc_version"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "safe-mix"
version = "0.1.0"
dependencies = [
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -457,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.6.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -470,31 +517,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.27"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.27"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive_internals"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smallvec"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -511,8 +549,8 @@ name = "substrate-keyring"
version = "0.1.0"
dependencies = [
"ed25519 0.1.0",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -520,25 +558,26 @@ name = "substrate-primitives"
version = "0.1.0"
dependencies = [
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-runtime-consensus"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -563,10 +602,11 @@ dependencies = [
name = "substrate-runtime-council"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
@@ -585,9 +625,10 @@ dependencies = [
name = "substrate-runtime-democracy"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0",
@@ -604,8 +645,8 @@ dependencies = [
name = "substrate-runtime-executive"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-primitives 0.1.0",
@@ -620,12 +661,12 @@ version = "0.1.0"
dependencies = [
"ed25519 0.1.0",
"environmental 0.1.0",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-state-machine 0.1.0",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -634,8 +675,8 @@ version = "0.1.0"
dependencies = [
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -647,21 +688,22 @@ dependencies = [
name = "substrate-runtime-sandbox"
version = "0.1.0"
dependencies = [
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-std 0.1.0",
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-runtime-session"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
@@ -677,9 +719,10 @@ dependencies = [
name = "substrate-runtime-staking"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
@@ -700,7 +743,7 @@ version = "0.1.0"
dependencies = [
"pwasm-alloc 0.1.0",
"pwasm-libc 0.1.0",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -708,9 +751,9 @@ name = "substrate-runtime-support"
version = "0.1.0"
dependencies = [
"ed25519 0.1.0",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -721,9 +764,9 @@ dependencies = [
name = "substrate-runtime-system"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -736,8 +779,9 @@ dependencies = [
name = "substrate-runtime-timestamp"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -751,43 +795,39 @@ dependencies = [
name = "substrate-state-machine"
version = "0.1.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.11.11"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tiny-keccak"
version = "1.4.0"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "triehash"
version = "0.1.0"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -803,14 +843,25 @@ name = "uint"
version = "0.1.2"
source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "uint"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.0.4"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -820,10 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasmi"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -850,32 +901,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
"checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
"checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6"
"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002"
"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
"checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
"checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb"
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631"
"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a"
"checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "<none>"
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
"checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
"checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
@@ -883,39 +938,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd"
"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe"
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8"
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892"
"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46"
"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9"
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0"
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
"checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce"
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435"
"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
"checksum wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26b20dbeb7caee04597a5d2c93e2b3e64872c6ea2af732d7ad49dbec44067c35"
"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb"
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+87 -156
View File
@@ -17,20 +17,20 @@
//! Strongly typed API for full Polkadot client.
use client::backend::{Backend, LocalBackend};
use client::{self, Client, LocalCallExecutor};
use client::block_builder::BlockBuilder as ClientBlockBuilder;
use client::{Client, LocalCallExecutor};
use polkadot_executor::Executor as LocalDispatch;
use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
use state_machine::{self, OverlayedChanges};
use state_machine;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
use runtime::{self, Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall, ParachainsCall};
use primitives::{AccountId, Block, Header, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
/// A checked block ID used for the substrate-client implementation of CheckedBlockId;
#[derive(Debug, Clone, Copy)]
pub struct CheckedId(pub BlockId);
pub struct CheckedId(pub(crate) BlockId);
impl CheckedBlockId for CheckedId {
fn block_id(&self) -> &BlockId {
@@ -44,14 +44,16 @@ macro_rules! with_runtime {
($client: ident, $at: expr, $exec: expr) => {{
let parent = $at.block_id();
let header = Header {
parent_hash: $client.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?,
number: $client.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1,
parent_hash: $client.block_hash_from_id(&parent)?
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
number: $client.block_number_from_id(&parent)?
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))? + 1,
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
};
$client.state_at(parent).map_err(Error::from).and_then(|state| {
$client.state_at(&parent).map_err(Error::from).and_then(|state| {
let mut changes = Default::default();
let mut ext = state_machine::Ext::new(&mut changes, &state);
@@ -63,105 +65,28 @@ macro_rules! with_runtime {
}}
}
/// A polkadot block builder.
#[derive(Debug, Clone)]
pub struct ClientBlockBuilder<S> {
parent: BlockId,
changes: OverlayedChanges,
state: S,
header: Header,
timestamp: Timestamp,
extrinsics: Vec<UncheckedExtrinsic>,
}
impl<S: state_machine::Backend> ClientBlockBuilder<S>
where S::Error: Into<client::error::Error>
{
// initialises a block, ready to allow extrinsics to be applied.
fn initialise_block(&mut self) -> Result<()> {
let result = {
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
let h = self.header.clone();
::substrate_executor::with_native_environment(
&mut ext,
|| runtime::Executive::initialise_block(&h),
).map_err(Into::into)
};
match result {
Ok(_) => {
self.changes.commit_prospective();
Ok(())
}
Err(e) => {
self.changes.discard_prospective();
Err(e)
}
}
}
// executes a extrinsic, inherent or otherwise, without appending to the list.
fn apply_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
let result = {
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
::substrate_executor::with_native_environment(
&mut ext,
move || runtime::Executive::apply_extrinsic(extrinsic),
).map_err(Into::into)
};
match result {
Ok(_) => {
self.changes.commit_prospective();
Ok(())
}
Err(e) => {
self.changes.discard_prospective();
Err(e)
}
}
}
}
impl<S: state_machine::Backend> BlockBuilder for ClientBlockBuilder<S>
where S::Error: Into<client::error::Error>
impl<B: LocalBackend<Block>> BlockBuilder for ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
// Check that this is not an "inherent" extrinsic.
if extrinsic.signature == Default::default() {
bail!(ErrorKind::PushedInherentTransaction(extrinsic));
} else {
self.apply_extrinsic(extrinsic.clone())?;
self.extrinsics.push(extrinsic);
Ok(())
}
self.push(extrinsic).map_err(Into::into)
}
fn bake(mut self) -> Block {
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
let final_header = ::substrate_executor::with_native_environment(
&mut ext,
move || runtime::Executive::finalise_block()
).expect("all inherent extrinsics pushed; all other extrinsics executed correctly; qed");
Block {
header: final_header,
extrinsics: self.extrinsics,
}
/// Bake the block with provided extrinsics.
fn bake(self) -> Result<Block> {
ClientBlockBuilder::bake(self).map_err(Into::into)
}
}
impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
impl<B: LocalBackend<Block>> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{
type CheckedBlockId = CheckedId;
type BlockBuilder = ClientBlockBuilder<B::State>;
type BlockBuilder = ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>;
fn check_id(&self, id: BlockId) -> Result<CheckedId> {
// bail if the code is not the same as the natively linked.
if self.code_at(&id)? != LocalDispatch::native_equivalent() {
if self.code_at(&id.into())? != LocalDispatch::native_equivalent() {
bail!("This node is out of date. Block authoring may not work correctly. Bailing.")
}
@@ -190,8 +115,16 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu
fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<bool> {
use substrate_executor::error::ErrorKind as ExecErrorKind;
use codec::Slicable;
use runtime::Block as RuntimeBlock;
let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(block));
let encoded = block.encode();
let runtime_block = match RuntimeBlock::decode(&mut &encoded[..]) {
Some(x) => x,
None => return Ok(false),
};
let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(runtime_block));
match res {
Ok(()) => Ok(true),
Err(err) => match err.kind() {
@@ -217,85 +150,65 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu
with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain))
}
fn build_block(&self, parent: &CheckedId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
let parent = parent.block_id();
let header = Header {
parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?,
number: self.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1,
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
};
let extrinsics = vec![
UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: Default::default(),
index: Default::default(),
function: Call::Timestamp(TimestampCall::set(timestamp)),
},
signature: Default::default(),
},
UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: Default::default(),
index: Default::default(),
function: Call::Parachains(ParachainsCall::set_heads(parachains)),
},
signature: Default::default(),
}
];
let mut builder = ClientBlockBuilder {
parent: *parent,
changes: OverlayedChanges::default(),
state: self.state_at(parent)?,
header,
timestamp,
extrinsics: extrinsics.clone(),
};
builder.initialise_block()?;
for inherent in extrinsics {
builder.apply_extrinsic(inherent)?;
fn build_block(&self, at: &CheckedId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
let mut block_builder = self.new_block_at(at.block_id())?;
for inherent in self.inherent_extrinsics(at, timestamp, new_heads)? {
block_builder.push(inherent)?;
}
Ok(builder)
Ok(block_builder)
}
fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Vec<UncheckedExtrinsic>> {
use codec::Slicable;
with_runtime!(self, at, || {
let extrinsics = ::runtime::inherent_extrinsics(timestamp, new_heads);
extrinsics.into_iter()
.map(|x| x.encode()) // get encoded representation
.map(|x| Slicable::decode(&mut &x[..])) // get byte-vec equivalent to extrinsic
.map(|x| x.expect("UncheckedExtrinsic has encoded representation equivalent to Vec<u8>; qed"))
.collect()
})
}
}
impl<B: LocalBackend> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
impl<B: LocalBackend<Block>> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{}
#[cfg(test)]
mod tests {
use super::*;
use keyring::Keyring;
use codec::Slicable;
use client::{self, LocalCallExecutor};
use client::in_mem::Backend as InMemory;
use substrate_executor::NativeExecutionDispatch;
use substrate_primitives::{self, Header};
use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities};
fn validators() -> Vec<AccountId> {
vec![
Keyring::One.to_raw_public().into(),
Keyring::Two.to_raw_public().into(),
]
}
fn session_keys() -> Vec<SessionKey> {
vec![
Keyring::One.to_raw_public(),
Keyring::Two.to_raw_public(),
]
}
fn client() -> Client<InMemory, LocalCallExecutor<InMemory, NativeExecutor<LocalDispatch>>> {
fn client() -> Client<InMemory<Block>, LocalCallExecutor<InMemory<Block>, NativeExecutor<LocalDispatch>>, Block> {
struct GenesisBuilder;
impl client::GenesisBuilder for GenesisBuilder {
impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig {
code: LocalDispatch::native_equivalent().to_vec(),
authorities: validators(),
authorities: session_keys(),
}),
system: None,
session: Some(SessionConfig {
@@ -309,8 +222,8 @@ mod tests {
};
let storage = genesis_config.build_externalities();
let block = ::client::genesis::construct_genesis_block(&storage);
(substrate_primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
let block = ::client::genesis::construct_genesis_block::<Block>(&storage);
(block.header, storage.into_iter().collect())
}
}
@@ -320,18 +233,36 @@ mod tests {
#[test]
fn gets_session_and_validator_keys() {
let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap();
assert_eq!(client.session_keys(&id).unwrap(), validators());
let id = client.check_id(BlockId::number(0)).unwrap();
assert_eq!(client.session_keys(&id).unwrap(), session_keys());
assert_eq!(client.validators(&id).unwrap(), validators());
}
#[test]
fn build_block() {
fn build_block_implicit_succeeds() {
let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap();
let id = client.check_id(BlockId::number(0)).unwrap();
let block_builder = client.build_block(&id, 1_000_000, Vec::new()).unwrap();
let block = block_builder.bake();
let block = block_builder.bake().unwrap();
assert_eq!(block.header.number, 1);
assert!(block.header.extrinsics_root != Default::default());
}
#[test]
fn build_block_with_inherent_succeeds() {
let client = client();
let id = client.check_id(BlockId::number(0)).unwrap();
let inherent = client.inherent_extrinsics(&id, 1_000_000, Vec::new()).unwrap();
let mut block_builder = client.new_block_at(id.block_id()).unwrap();
for extrinsic in inherent {
block_builder.push(extrinsic).unwrap();
}
let block = block_builder.bake().unwrap();
assert_eq!(block.header.number, 1);
assert!(block.header.extrinsics_root != Default::default());
@@ -339,14 +270,14 @@ mod tests {
#[test]
fn fails_to_check_id_for_unknown_block() {
assert!(client().check_id(BlockId::Number(100)).is_err());
assert!(client().check_id(BlockId::number(100)).is_err());
}
#[test]
fn gets_random_seed_with_genesis() {
let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap();
let id = client.check_id(BlockId::number(0)).unwrap();
assert!(client.random_seed(&id).is_ok());
}
}
+21 -28
View File
@@ -18,8 +18,8 @@
//! runtime.
extern crate polkadot_executor;
extern crate polkadot_runtime as runtime;
extern crate polkadot_primitives as primitives;
extern crate polkadot_runtime as runtime;
extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_client as client;
@@ -37,9 +37,8 @@ extern crate substrate_keyring as keyring;
pub mod full;
pub mod light;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
use runtime::{Block, UncheckedExtrinsic};
use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
error_chain! {
errors {
@@ -49,19 +48,9 @@ error_chain! {
display("Unknown runtime code")
}
/// Unknown block ID.
UnknownBlock(b: BlockId) {
UnknownBlock(b: String) {
description("Unknown block")
display("Unknown block")
}
/// Attempted to push an inherent extrinsic manually.
PushedInherentTransaction(xt: UncheckedExtrinsic) {
description("Attempted to push an inherent extrinsic to a block."),
display("Pushed inherent extrinsic to a block: {:?}", xt),
}
/// Badly-formed extrinsic.
BadlyFormedTransaction(xt: UncheckedExtrinsic) {
description("Attempted to push a badly-formed extrinsic to a block."),
display("Pushed badly-formed extrinsic to a block: {:?}", xt),
display("Unknown block {}", b)
}
/// Some other error.
// TODO: allow to be specified as associated type of PolkadotApi
@@ -85,28 +74,28 @@ impl From<client::error::Error> for Error {
}
}
/// A builder for blocks.
pub trait BlockBuilder: Sized {
/// Push a non-inherent extrinsic.
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
/// Finalise the block.
fn bake(self) -> Block;
}
/// A checked block identifier.
pub trait CheckedBlockId: Clone + 'static {
/// Yield the underlying block ID.
fn block_id(&self) -> &BlockId;
}
/// Build new blocks.
pub trait BlockBuilder {
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
/// Bake the block with provided extrinsics.
fn bake(self) -> Result<Block>;
}
/// Trait encapsulating the Polkadot API.
///
/// All calls should fail when the exact runtime is unknown.
pub trait PolkadotApi {
/// A checked block ID. Used to avoid redundancy of code check.
type CheckedBlockId: CheckedBlockId;
/// The type used to build blocks.
/// The block builder for this API type.
type BlockBuilder: BlockBuilder;
/// Check whether requests at the given block ID can be served.
@@ -146,8 +135,12 @@ pub trait PolkadotApi {
/// and an error if we can't evaluate for some reason.
fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<bool>;
/// Create a block builder on top of the parent block.
fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>;
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
fn build_block(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>;
/// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given.
/// This may vary by runtime and will fail if a runtime doesn't follow the same API.
fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Vec<UncheckedExtrinsic>>;
}
/// Mark for all Polkadot API implementations, that are making use of state data, stored locally.
+27 -23
View File
@@ -21,20 +21,30 @@ use client::backend::{Backend, RemoteBackend};
use client::{Client, CallExecutor};
use codec::Slicable;
use state_machine;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
use runtime::{Block, UncheckedExtrinsic};
use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use full::CheckedId;
use {PolkadotApi, RemotePolkadotApi, BlockBuilder, CheckedBlockId, Result, ErrorKind};
use {PolkadotApi, BlockBuilder, RemotePolkadotApi, CheckedBlockId, Result, ErrorKind};
/// Remote polkadot API implementation.
pub struct RemotePolkadotApiWrapper<B: Backend, E: CallExecutor>(pub Arc<Client<B, E>>);
/// Block builder for light client.
/// Light block builder. TODO: make this work (efficiently)
#[derive(Clone, Copy)]
pub struct LightBlockBuilder;
impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
impl BlockBuilder for LightBlockBuilder {
fn push_extrinsic(&mut self, _xt: UncheckedExtrinsic) -> Result<()> {
Err(ErrorKind::UnknownRuntime.into())
}
fn bake(self) -> Result<Block> {
Err(ErrorKind::UnknownRuntime.into())
}
}
/// Remote polkadot API implementation.
pub struct RemotePolkadotApiWrapper<B: Backend<Block>, E: CallExecutor<Block>>(pub Arc<Client<B, E, Block>>);
impl<B: Backend<Block>, E: CallExecutor<Block>> PolkadotApi for RemotePolkadotApiWrapper<B, E>
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{
type CheckedBlockId = CheckedId;
type BlockBuilder = LightBlockBuilder;
@@ -86,21 +96,15 @@ impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E>
Err(ErrorKind::UnknownRuntime.into())
}
fn build_block(&self, _parent: &CheckedId, _timestamp: Timestamp, _parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
fn build_block(&self, _at: &Self::CheckedBlockId, _timestamp: Timestamp, _new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
Err(ErrorKind::UnknownRuntime.into())
}
fn inherent_extrinsics(&self, _at: &Self::CheckedBlockId, _timestamp: Timestamp, _new_heads: Vec<CandidateReceipt>) -> Result<Vec<Vec<u8>>> {
Err(ErrorKind::UnknownRuntime.into())
}
}
impl<B: RemoteBackend, E: CallExecutor> RemotePolkadotApi for RemotePolkadotApiWrapper<B, E>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
impl<B: RemoteBackend<Block>, E: CallExecutor<Block>> RemotePolkadotApi for RemotePolkadotApiWrapper<B, E>
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{}
impl BlockBuilder for LightBlockBuilder {
fn push_extrinsic(&mut self, _extrinsic: UncheckedExtrinsic) -> Result<()> {
Err(ErrorKind::UnknownRuntime.into())
}
fn bake(self) -> Block {
unimplemented!()
}
}
+1 -7
View File
@@ -24,16 +24,10 @@ ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
fdlimit = "0.1"
parking_lot = "0.4"
substrate-client = { path = "../../substrate/client" }
substrate-network = { path = "../../substrate/network" }
substrate-codec = { path = "../../substrate/codec" }
substrate-runtime-support = { path = "../../substrate/runtime-support" }
substrate-state-machine = { path = "../../substrate/state-machine" }
substrate-executor = { path = "../../substrate/executor" }
substrate-primitives = { path = "../../substrate/primitives" }
substrate-rpc = { path = "../../substrate/rpc" }
substrate-rpc-servers = { path = "../../substrate/rpc-servers" }
substrate-network = { path = "../../substrate/network" }
polkadot-primitives = { path = "../primitives" }
polkadot-executor = { path = "../executor" }
polkadot-runtime = { path = "../runtime" }
polkadot-service = { path = "../service" }
polkadot-transaction-pool = { path = "../transaction-pool" }
+5 -6
View File
@@ -21,8 +21,7 @@ use futures::stream::Stream;
use service::Service;
use tokio_core::reactor;
use network::{SyncState, SyncProvider};
use runtime_support::Hashable;
use primitives::block::HeaderHash;
use polkadot_primitives::Block;
use state_machine;
use client::{self, BlockchainEvents};
@@ -31,9 +30,9 @@ const TIMER_INTERVAL_MS: u64 = 5000;
/// Spawn informant on the event loop
pub fn start<B, E>(service: &Service<B, E>, handle: reactor::Handle)
where
B: client::backend::Backend + Send + Sync + 'static,
E: client::CallExecutor + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>
B: client::backend::Backend<Block> + Send + Sync + 'static,
E: client::CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>
{
let interval = reactor::Interval::new_at(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS), &handle)
.expect("Error creating informant timer");
@@ -45,7 +44,7 @@ pub fn start<B, E>(service: &Service<B, E>, handle: reactor::Handle)
let sync_status = network.status();
if let Ok(best_block) = client.best_block_header() {
let hash: HeaderHash = best_block.blake2_256().into();
let hash = best_block.hash();
let status = match (sync_status.sync.state, sync_status.sync.best_seen_block) {
(SyncState::Idle, _) => "Idle".into(),
(SyncState::Downloading, None) => "Syncing".into(),
+5 -9
View File
@@ -32,17 +32,12 @@ extern crate ed25519;
extern crate triehash;
extern crate parking_lot;
extern crate substrate_codec as codec;
extern crate substrate_state_machine as state_machine;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate substrate_network as network;
extern crate substrate_rpc;
extern crate substrate_rpc_servers as rpc;
extern crate substrate_runtime_support as runtime_support;
extern crate polkadot_primitives;
extern crate polkadot_executor;
extern crate polkadot_runtime;
extern crate polkadot_service as service;
extern crate polkadot_transaction_pool as txpool;
@@ -61,6 +56,7 @@ mod informant;
use std::io;
use std::net::SocketAddr;
use std::path::{Path, PathBuf};
use polkadot_primitives::Block;
use futures::sync::mpsc;
use futures::{Sink, Future, Stream};
@@ -188,9 +184,9 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
fn run_until_exit<B, E>(mut core: reactor::Core, service: service::Service<B, E>, matches: &clap::ArgMatches, config: service::Configuration) -> error::Result<()>
where
B: client::backend::Backend + Send + Sync + 'static,
E: client::CallExecutor + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>
B: client::backend::Backend<Block> + Send + Sync + 'static,
E: client::CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>
{
let exit = {
// can't use signal directly here because CtrlC takes only `Fn`.
@@ -210,7 +206,7 @@ fn run_until_exit<B, E>(mut core: reactor::Core, service: service::Service<B, E>
let handler = || {
let chain = rpc::apis::chain::Chain::new(service.client(), core.remote());
rpc::rpc_handler(
rpc::rpc_handler::<Block, _, _, _, _>(
service.client(),
chain,
service.transaction_pool(),
+2 -1
View File
@@ -8,5 +8,6 @@ description = "Abstract collation logic"
futures = "0.1.17"
substrate-codec = { path = "../../substrate/codec", version = "0.1" }
substrate-primitives = { path = "../../substrate/primitives", version = "0.1" }
polkadot-primitives = { path = "../primitives", version = "0.1" }
polkadot-runtime = { path = "../runtime", version = "0.1" }
polkadot-parachain = { path = "../parachain", version = "0.1" }
polkadot-primitives = { path = "../primitives", version = "0.1" }
+3 -2
View File
@@ -47,12 +47,13 @@
extern crate futures;
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate polkadot_runtime;
extern crate polkadot_primitives;
use std::collections::{BTreeSet, BTreeMap};
use futures::{stream, Stream, Future, IntoFuture};
use polkadot_primitives::parachain::{self, ConsolidatedIngress, Message, Id as ParaId};
use polkadot_primitives::parachain::{self, CandidateSignature, ConsolidatedIngress, Message, Id as ParaId};
/// Parachain context needed for collation.
///
@@ -62,7 +63,7 @@ pub trait ParachainContext {
fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>(
&self,
ingress: I,
) -> (parachain::BlockData, polkadot_primitives::AccountId, polkadot_primitives::Signature);
) -> (parachain::BlockData, polkadot_primitives::AccountId, CandidateSignature);
}
/// Relay chain context needed to collate.
+1
View File
@@ -25,3 +25,4 @@ substrate-runtime-support = { path = "../../substrate/runtime-support" }
substrate-network = { path = "../../substrate/network" }
substrate-keyring = { path = "../../substrate/keyring" }
substrate-client = { path = "../../substrate/client" }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
+2 -2
View File
@@ -16,7 +16,7 @@
//! Errors that can occur during the consensus process.
use polkadot_primitives::AccountId;
use primitives::AuthorityId;
error_chain! {
links {
@@ -29,7 +29,7 @@ error_chain! {
description("Duty Roster had invalid length"),
display("Invalid duty roster length: expected {}, got {}", expected, got),
}
NotValidator(id: AccountId) {
NotValidator(id: AuthorityId) {
description("Local account ID not a validator at this block."),
display("Local account ID ({:?}) not a validator at this block.", id),
}
@@ -19,11 +19,9 @@
use super::MAX_TRANSACTIONS_SIZE;
use codec::Slicable;
use polkadot_runtime::Block as PolkadotGenericBlock;
use polkadot_primitives::Timestamp;
use polkadot_runtime::{Block as PolkadotGenericBlock, CheckedBlock};
use polkadot_primitives::{Block, Hash, BlockNumber, Timestamp};
use polkadot_primitives::parachain::Id as ParaId;
use primitives::block::{Block as SubstrateBlock, HeaderHash, Number as BlockNumber};
use transaction_pool::PolkadotBlock;
error_chain! {
links {
@@ -51,7 +49,7 @@ error_chain! {
description("Proposal included unregistered parachain."),
display("Proposal included unregistered parachain {:?}", id),
}
WrongParentHash(expected: HeaderHash, got: HeaderHash) {
WrongParentHash(expected: Hash, got: Hash) {
description("Proposal had wrong parent hash."),
display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got),
}
@@ -72,17 +70,17 @@ error_chain! {
/// Attempt to evaluate a substrate block as a polkadot block, returning error
/// upon any initial validity checks failing.
pub fn evaluate_initial(
proposal: &SubstrateBlock,
proposal: &Block,
now: Timestamp,
parent_hash: &HeaderHash,
parent_hash: &Hash,
parent_number: BlockNumber,
active_parachains: &[ParaId],
) -> Result<PolkadotBlock> {
) -> Result<CheckedBlock> {
const MAX_TIMESTAMP_DRIFT: Timestamp = 60;
let encoded = Slicable::encode(proposal);
let proposal = PolkadotGenericBlock::decode(&mut &encoded[..])
.and_then(|b| PolkadotBlock::from(b).ok())
.and_then(|b| CheckedBlock::new(b).ok())
.ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?;
let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| {
+38 -35
View File
@@ -35,14 +35,15 @@ extern crate polkadot_api;
extern crate polkadot_collator as collator;
extern crate polkadot_statement_table as table;
extern crate polkadot_parachain as parachain;
extern crate polkadot_primitives;
extern crate polkadot_transaction_pool as transaction_pool;
extern crate polkadot_runtime;
extern crate polkadot_primitives;
extern crate substrate_bft as bft;
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_network;
extern crate exit_future;
@@ -68,10 +69,9 @@ use std::time::{Duration, Instant};
use codec::Slicable;
use table::generic::Statement as GenericStatement;
use runtime_support::Hashable;
use polkadot_api::{PolkadotApi, BlockBuilder};
use polkadot_primitives::{Hash, Timestamp};
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic, CandidateReceipt};
use primitives::block::{Block as SubstrateBlock, Header as SubstrateHeader, HeaderHash, Id as BlockId, Number as BlockNumber};
use polkadot_api::PolkadotApi;
use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp};
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt};
use primitives::AuthorityId;
use transaction_pool::{Ready, TransactionPool};
use tokio_core::reactor::{Handle, Timeout, Interval};
@@ -105,10 +105,10 @@ pub trait TableRouter: Clone {
/// Future that resolves when candidate data is fetched.
type FetchCandidate: IntoFuture<Item=BlockData,Error=Self::Error>;
/// Future that resolves when extrinsic candidate data is fetched.
type FetchExtrinsic: IntoFuture<Item=Extrinsic,Error=Self::Error>;
type FetchExtrinsic: IntoFuture<Item=ParachainExtrinsic,Error=Self::Error>;
/// Note local candidate data, making it available on the network to other validators.
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, extrinsic: Extrinsic);
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, extrinsic: ParachainExtrinsic);
/// Fetch block data for a specific candidate.
fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate;
@@ -236,7 +236,7 @@ pub struct ProposerFactory<C, N, P> {
pub parachain_empty_duration: Duration,
}
impl<C, N, P> bft::ProposerFactory for ProposerFactory<C, N, P>
impl<C, N, P> bft::ProposerFactory<Block> for ProposerFactory<C, N, P>
where
C: PolkadotApi,
N: Network,
@@ -245,14 +245,14 @@ impl<C, N, P> bft::ProposerFactory for ProposerFactory<C, N, P>
type Proposer = Proposer<C, N::TableRouter, P>;
type Error = Error;
fn init(&self, parent_header: &SubstrateHeader, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Error> {
fn init(&self, parent_header: &Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Error> {
use std::time::Duration;
const DELAY_UNTIL: Duration = Duration::from_millis(5000);
let parent_hash = parent_header.blake2_256().into();
let checked_id = self.client.check_id(BlockId::Hash(parent_hash))?;
let checked_id = self.client.check_id(BlockId::hash(parent_hash))?;
let duty_roster = self.client.duty_roster(&checked_id)?;
let random_seed = self.client.random_seed(&checked_id)?;
@@ -312,7 +312,7 @@ pub struct Proposer<C: PolkadotApi, R, P> {
handle: Handle,
local_duty: LocalDuty,
local_key: Arc<ed25519::Pair>,
parent_hash: HeaderHash,
parent_hash: Hash,
parent_id: C::CheckedBlockId,
parent_number: BlockNumber,
random_seed: Hash,
@@ -321,7 +321,7 @@ pub struct Proposer<C: PolkadotApi, R, P> {
transaction_pool: Arc<TransactionPool>,
}
impl<C, R, P> bft::Proposer for Proposer<C, R, P>
impl<C, R, P> bft::Proposer<Block> for Proposer<C, R, P>
where
C: PolkadotApi,
R: TableRouter,
@@ -330,7 +330,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
type Error = Error;
type Create = future::Either<
CreateProposal<C, R, P>,
future::FutureResult<SubstrateBlock, Error>,
future::FutureResult<Block, Error>,
>;
type Evaluate = Box<Future<Item=bool, Error=Error>>;
@@ -385,7 +385,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
})
}
fn evaluate(&self, proposal: &SubstrateBlock) -> Self::Evaluate {
fn evaluate(&self, unchecked_proposal: &Block) -> Self::Evaluate {
debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash);
let active_parachains = match self.client.active_parachains(&self.parent_id) {
@@ -397,7 +397,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
// do initial serialization and structural integrity checks.
let maybe_proposal = evaluation::evaluate_initial(
proposal,
unchecked_proposal,
current_timestamp,
&self.parent_hash,
self.parent_number,
@@ -461,7 +461,10 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
// evaluate whether the block is actually valid.
// TODO: is it better to delay this until the delays are finished?
let evaluated = self.client.evaluate_block(&self.parent_id, proposal.into()).map_err(Into::into);
let evaluated = self.client
.evaluate_block(&self.parent_id, unchecked_proposal.clone())
.map_err(Into::into);
let future = future::result(evaluated).and_then(move |good| {
let end_result = future::ok(good);
if good {
@@ -489,13 +492,13 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
proposer
}
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior)>) {
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior<Hash>)>) {
use bft::generic::Misbehavior as GenericMisbehavior;
use primitives::bft::{MisbehaviorKind, MisbehaviorReport};
use runtime_primitives::bft::{MisbehaviorKind, MisbehaviorReport};
use runtime_primitives::MaybeUnsigned;
use polkadot_runtime::{Call, Extrinsic, UncheckedExtrinsic, ConsensusCall};
let local_id = self.local_key.public().0;
let local_id = self.local_key.public().0.into();
let mut next_index = {
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client);
let cur_index = self.transaction_pool.cull_and_get_pending(readiness_evaluator, |pending| pending
@@ -536,10 +539,11 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
next_index += 1;
let signature = self.local_key.sign(&extrinsic.encode()).into();
let signature = MaybeUnsigned(self.local_key.sign(&extrinsic.encode()).into());
let uxt = UncheckedExtrinsic { extrinsic, signature };
self.transaction_pool.import_unchecked_extrinsic(uxt).expect("locally signed extrinsic is valid; qed");
self.transaction_pool.import_unchecked_extrinsic(uxt)
.expect("locally signed extrinsic is valid; qed");
}
}
}
@@ -603,7 +607,7 @@ impl ProposalTiming {
/// Future which resolves upon the creation of a proposal.
pub struct CreateProposal<C: PolkadotApi, R, P: Collators> {
parent_hash: HeaderHash,
parent_hash: Hash,
parent_number: BlockNumber,
parent_id: C::CheckedBlockId,
client: Arc<C>,
@@ -620,14 +624,13 @@ impl<C, R, P> CreateProposal<C, R, P>
R: TableRouter,
P: Collators,
{
fn propose_with(&self, candidates: Vec<CandidateReceipt>) -> Result<SubstrateBlock, Error> {
fn propose_with(&self, candidates: Vec<CandidateReceipt>) -> Result<Block, Error> {
use polkadot_api::BlockBuilder;
use runtime_primitives::traits::{Hashing, BlakeTwo256};
// TODO: handle case when current timestamp behind that in state.
let timestamp = current_timestamp();
let mut block_builder = self.client.build_block(
&self.parent_id,
timestamp,
candidates,
)?;
let mut block_builder = self.client.build_block(&self.parent_id, timestamp, candidates)?;
{
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client);
@@ -643,7 +646,7 @@ impl<C, R, P> CreateProposal<C, R, P>
if pending_size + pending.encoded_size() >= MAX_TRANSACTIONS_SIZE { break }
match block_builder.push_extrinsic(pending.as_transaction().clone()) {
match block_builder.push_extrinsic(pending.primitive_extrinsic()) {
Ok(()) => {
pending_size += pending.encoded_size();
}
@@ -658,14 +661,14 @@ impl<C, R, P> CreateProposal<C, R, P>
self.transaction_pool.remove(&unqueue_invalid, false);
}
let polkadot_block = block_builder.bake();
let polkadot_block = block_builder.bake()?;
info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
polkadot_block.header.number,
Hash::from(polkadot_block.header.blake2_256()),
Hash::from(polkadot_block.header.hash()),
polkadot_block.header.parent_hash,
polkadot_block.extrinsics.iter()
.map(|xt| format!("{}", Hash::from(xt.blake2_256())))
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
.collect::<Vec<_>>()
.join(", ")
);
@@ -693,10 +696,10 @@ impl<C, R, P> Future for CreateProposal<C, R, P>
R: TableRouter,
P: Collators,
{
type Item = SubstrateBlock;
type Item = Block;
type Error = Error;
fn poll(&mut self) -> Poll<SubstrateBlock, Error> {
fn poll(&mut self) -> Poll<Block, Error> {
// 1. poll local collation future.
match self.collation.poll() {
Ok(Async::Ready((collation, extrinsic))) => {
+45 -57
View File
@@ -29,10 +29,9 @@ use ed25519;
use futures::prelude::*;
use futures::{future, Canceled};
use polkadot_api::LocalPolkadotApi;
use polkadot_primitives::AccountId;
use polkadot_primitives::{BlockId, Block, Header, Hash, AccountId};
use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt};
use primitives::{Hash, AuthorityId};
use primitives::block::{Id as BlockId, HeaderHash, Header};
use primitives::AuthorityId;
use runtime_support::Hashable;
use substrate_network as net;
use tokio_core::reactor;
@@ -45,19 +44,19 @@ const TIMER_DELAY_MS: u64 = 5000;
const TIMER_INTERVAL_MS: u64 = 500;
struct BftSink<E> {
network: Arc<net::ConsensusService>,
parent_hash: HeaderHash,
network: Arc<net::ConsensusService<Block>>,
parent_hash: Hash,
_e: ::std::marker::PhantomData<E>,
}
struct Messages {
network_stream: net::BftMessageStream,
network_stream: net::BftMessageStream<Block>,
local_id: AuthorityId,
authorities: Vec<AuthorityId>,
}
impl Stream for Messages {
type Item = bft::Communication;
type Item = bft::Communication<Block>;
type Error = bft::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
@@ -81,10 +80,10 @@ impl Stream for Messages {
}
}
fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, authorities: &[AuthorityId]) -> Result<Option<bft::Communication>, bft::Error> {
fn process_message(msg: net::LocalizedBftMessage<Block>, local_id: &AuthorityId, authorities: &[AuthorityId]) -> Result<Option<bft::Communication<Block>>, bft::Error> {
Ok(Some(match msg.message {
net::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c {
net::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({
net::generic_message::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c {
net::generic_message::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({
if &proposal.sender == local_id { return Ok(None) }
let proposal = bft::generic::LocalizedProposal {
round_number: proposal.round_number as usize,
@@ -105,7 +104,7 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
trace!(target: "bft", "importing proposal message for round {} from {}", proposal.round_number, Hash::from(proposal.sender));
proposal
}),
net::SignedConsensusMessage::Vote(vote) => bft::generic::LocalizedMessage::Vote({
net::generic_message::SignedConsensusMessage::Vote(vote) => bft::generic::LocalizedMessage::Vote({
if &vote.sender == local_id { return Ok(None) }
let vote = bft::generic::LocalizedVote {
sender: vote.sender,
@@ -114,21 +113,21 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
signer: ed25519::Public(vote.sender),
},
vote: match vote.vote {
net::ConsensusVote::Prepare(r, h) => bft::generic::Vote::Prepare(r as usize, h),
net::ConsensusVote::Commit(r, h) => bft::generic::Vote::Commit(r as usize, h),
net::ConsensusVote::AdvanceRound(r) => bft::generic::Vote::AdvanceRound(r as usize),
net::generic_message::ConsensusVote::Prepare(r, h) => bft::generic::Vote::Prepare(r as usize, h),
net::generic_message::ConsensusVote::Commit(r, h) => bft::generic::Vote::Commit(r as usize, h),
net::generic_message::ConsensusVote::AdvanceRound(r) => bft::generic::Vote::AdvanceRound(r as usize),
}
};
bft::check_vote(authorities, &msg.parent_hash, &vote)?;
bft::check_vote::<Block>(authorities, &msg.parent_hash, &vote)?;
trace!(target: "bft", "importing vote {:?} from {}", vote.vote, Hash::from(vote.sender));
vote
}),
}),
net::BftMessage::Auxiliary(a) => {
let justification = bft::UncheckedJustification::from(a);
net::generic_message::BftMessage::Auxiliary(a) => {
let justification = bft::UncheckedJustification::<Hash>::from(a);
// TODO: get proper error
let justification: Result<_, bft::Error> = bft::check_prepare_justification(authorities, msg.parent_hash, justification)
let justification: Result<_, bft::Error> = bft::check_prepare_justification::<Block>(authorities, msg.parent_hash, justification)
.map_err(|_| bft::ErrorKind::InvalidJustification.into());
bft::generic::Communication::Auxiliary(justification?)
},
@@ -136,15 +135,15 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
}
impl<E> Sink for BftSink<E> {
type SinkItem = bft::Communication;
type SinkItem = bft::Communication<Block>;
// TODO: replace this with the ! type when that's stabilized
type SinkError = E;
fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend<bft::Communication, E> {
let network_message = net::LocalizedBftMessage {
fn start_send(&mut self, message: bft::Communication<Block>) -> ::futures::StartSend<bft::Communication<Block>, E> {
let network_message = net::generic_message::LocalizedBftMessage {
message: match message {
bft::generic::Communication::Consensus(c) => net::BftMessage::Consensus(match c {
bft::generic::LocalizedMessage::Propose(proposal) => net::SignedConsensusMessage::Propose(net::SignedConsensusProposal {
bft::generic::Communication::Consensus(c) => net::generic_message::BftMessage::Consensus(match c {
bft::generic::LocalizedMessage::Propose(proposal) => net::generic_message::SignedConsensusMessage::Propose(net::generic_message::SignedConsensusProposal {
round_number: proposal.round_number as u32,
proposal: proposal.proposal,
digest: proposal.digest,
@@ -152,17 +151,17 @@ impl<E> Sink for BftSink<E> {
digest_signature: proposal.digest_signature.signature,
full_signature: proposal.full_signature.signature,
}),
bft::generic::LocalizedMessage::Vote(vote) => net::SignedConsensusMessage::Vote(net::SignedConsensusVote {
bft::generic::LocalizedMessage::Vote(vote) => net::generic_message::SignedConsensusMessage::Vote(net::generic_message::SignedConsensusVote {
sender: vote.sender,
signature: vote.signature.signature,
vote: match vote.vote {
bft::generic::Vote::Prepare(r, h) => net::ConsensusVote::Prepare(r as u32, h),
bft::generic::Vote::Commit(r, h) => net::ConsensusVote::Commit(r as u32, h),
bft::generic::Vote::AdvanceRound(r) => net::ConsensusVote::AdvanceRound(r as u32),
bft::generic::Vote::Prepare(r, h) => net::generic_message::ConsensusVote::Prepare(r as u32, h),
bft::generic::Vote::Commit(r, h) => net::generic_message::ConsensusVote::Commit(r as u32, h),
bft::generic::Vote::AdvanceRound(r) => net::generic_message::ConsensusVote::AdvanceRound(r as u32),
}
}),
}),
bft::generic::Communication::Auxiliary(justification) => net::BftMessage::Auxiliary(justification.uncheck().into()),
bft::generic::Communication::Auxiliary(justification) => net::generic_message::BftMessage::Auxiliary(justification.uncheck().into()),
},
parent_hash: self.parent_hash,
};
@@ -175,7 +174,7 @@ impl<E> Sink for BftSink<E> {
}
}
struct Network(Arc<net::ConsensusService>);
struct Network(Arc<net::ConsensusService<Block>>);
impl super::Network for Network {
type TableRouter = Router;
@@ -189,20 +188,20 @@ impl super::Network for Network {
fn start_bft<F, C>(
header: &Header,
handle: reactor::Handle,
client: &bft::Authorities,
network: Arc<net::ConsensusService>,
bft_service: &BftService<F, C>,
client: &bft::Authorities<Block>,
network: Arc<net::ConsensusService<Block>>,
bft_service: &BftService<Block, F, C>,
) where
F: bft::ProposerFactory + 'static,
C: bft::BlockImport + bft::Authorities + 'static,
<F as bft::ProposerFactory>::Error: ::std::fmt::Debug,
<F::Proposer as bft::Proposer>::Error: ::std::fmt::Display + Into<error::Error>,
F: bft::ProposerFactory<Block> + 'static,
C: bft::BlockImport<Block> + bft::Authorities<Block> + 'static,
<F as bft::ProposerFactory<Block>>::Error: ::std::fmt::Debug,
<F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
{
let parent_hash = header.blake2_256().into();
let parent_hash = header.hash();
if bft_service.live_agreement().map_or(false, |h| h == parent_hash) {
return;
}
let authorities = match client.authorities(&BlockId::Hash(parent_hash)) {
let authorities = match client.authorities(&BlockId::hash(parent_hash)) {
Ok(authorities) => authorities,
Err(e) => {
debug!("Error reading authorities: {:?}", e);
@@ -235,14 +234,14 @@ impl Service {
pub fn new<A, C>(
client: Arc<C>,
api: Arc<A>,
network: Arc<net::ConsensusService>,
network: Arc<net::ConsensusService<Block>>,
transaction_pool: Arc<TransactionPool>,
parachain_empty_duration: Duration,
key: ed25519::Pair,
) -> Service
where
A: LocalPolkadotApi + Send + Sync + 'static,
C: BlockchainEvents + ChainHead + bft::BlockImport + bft::Authorities + Send + Sync + 'static,
C: BlockchainEvents<Block> + ChainHead<Block> + bft::BlockImport<Block> + bft::Authorities<Block> + Send + Sync + 'static,
{
let (signal, exit) = ::exit_future::signal();
let thread = thread::spawn(move || {
@@ -346,36 +345,25 @@ impl ::collation::Collators for NoCollators {
fn note_bad_collator(&self, _collator: AccountId) { }
}
type FetchCandidateAdapter = future::Map<net::FetchFuture, fn(Vec<u8>) -> BlockData>;
#[derive(Clone)]
struct Router {
network: Arc<net::ConsensusService>,
}
impl Router {
fn fetch_candidate_adapter(data: Vec<u8>) -> BlockData {
BlockData(data)
}
network: Arc<net::ConsensusService<Block>>,
}
impl TableRouter for Router {
type Error = Canceled;
type FetchCandidate = FetchCandidateAdapter;
type FetchCandidate = future::Empty<BlockData, Self::Error>;
type FetchExtrinsic = future::FutureResult<Extrinsic, Self::Error>;
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, _extrinsic: Extrinsic) {
let data = block_data.0;
self.network.set_local_candidate(Some((hash, data)))
fn local_candidate_data(&self, _hash: Hash, _block_data: BlockData, _extrinsic: Extrinsic) {
// TODO
}
fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate {
let hash = candidate.hash();
self.network.fetch_candidate(&hash).map(Self::fetch_candidate_adapter)
fn fetch_block_data(&self, _candidate: &CandidateReceipt) -> Self::FetchCandidate {
future::empty()
}
fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic {
future::ok(Extrinsic)
}
}
@@ -486,7 +486,7 @@ mod tests {
let candidate = CandidateReceipt {
parachain_index: para_id,
collator: [1; 32],
collator: [1; 32].into(),
head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]),
balance_uploads: Vec::new(),
egress_queue_roots: Vec::new(),
@@ -536,7 +536,7 @@ mod tests {
let candidate = CandidateReceipt {
parachain_index: para_id,
collator: [1; 32],
collator: [1; 32].into(),
head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]),
balance_uploads: Vec::new(),
egress_queue_roots: Vec::new(),
-12
View File
@@ -5,17 +5,5 @@ authors = ["Parity Technologies <admin@parity.io>"]
description = "Polkadot node implementation in Rust."
[dependencies]
hex-literal = "0.1"
triehash = { version = "0.1" }
ed25519 = { path = "../../substrate/ed25519" }
substrate-codec = { path = "../../substrate/codec" }
substrate-runtime-io = { path = "../../substrate/runtime-io" }
substrate-runtime-support = { path = "../../substrate/runtime-support" }
substrate-state-machine = { path = "../../substrate/state-machine" }
substrate-executor = { path = "../../substrate/executor" }
substrate-primitives = { path = "../../substrate/primitives" }
polkadot-primitives = { path = "../primitives" }
polkadot-runtime = { path = "../runtime" }
[dev-dependencies]
substrate-keyring = { path = "../../substrate/keyring" }
-7
View File
@@ -19,12 +19,5 @@
extern crate polkadot_runtime;
#[macro_use] extern crate substrate_executor;
extern crate substrate_codec as codec;
extern crate substrate_state_machine as state_machine;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives;
extern crate polkadot_primitives as polkadot_primitives;
extern crate ed25519;
extern crate triehash;
native_executor_instance!(pub Executor, polkadot_runtime::api::dispatch, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm"));
+51 -21
View File
@@ -21,12 +21,6 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
extern crate serde;
extern crate substrate_runtime_std as rstd;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_primitives as runtime_primitives;
@@ -35,27 +29,43 @@ extern crate substrate_serializer;
extern crate substrate_codec as codec;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
use primitives::bytes;
use rstd::prelude::*;
use runtime_primitives::traits::BlakeTwo256;
use runtime_primitives::generic;
use codec::{Input, Slicable};
pub mod parachain;
/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody
/// (who matters). Essentially this means that a majority of validators have decided it is
/// "correct".
pub const EVERYBODY: AccountId = [255u8; 32];
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
/// Something that identifies a block.
pub use primitives::block::Id as BlockId;
/// Opaque, encoded, unchecked extrinsic.
pub type UncheckedExtrinsic = Vec<u8>;
/// The type of digest item.
pub use primitives::block::Log as Log;
/// A "future-proof" block type for Polkadot. This will be resilient to upgrades in transaction
/// format, because it doesn't attempt to decode extrinsics.
///
/// Specialized code needs to link to (at least one version of) the runtime directly
/// in order to handle the extrinsics within.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// An index to a block.
/// 32-bits will allow for 136 years of blocks assuming 1 block per second.
/// TODO: switch to u32
pub type BlockNumber = u64;
/// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost
/// certainly continue to be the same as the substrate's `AuthorityId`.
pub type AccountId = primitives::AuthorityId;
/// Alias to Ed25519 pubkey that identifies an account on the relay chain.
pub type AccountId = primitives::hash::H256;
/// The Ed25519 pub key of an session that belongs to an authority of the relay chain. This is
/// exactly equivalent to what the substrate calls an "authority".
@@ -64,14 +74,15 @@ pub type SessionKey = primitives::AuthorityId;
/// Indentifier for a chain. 32-bit should be plenty.
pub type ChainId = u32;
/// Index of a transaction in the relay chain. 32-bit should be plenty.
pub type Index = u32;
/// A hash of some data used by the relay chain.
pub type Hash = primitives::H256;
/// Index of a transaction in the relay chain. 32-bit should be plenty.
pub type Index = u32;
/// Alias to 512-bit hash when used in the context of a signature on the relay chain.
pub type Signature = runtime_primitives::Ed25519Signature;
/// Equipped with logic for possibly "unsigned" messages.
pub type Signature = runtime_primitives::MaybeUnsigned<runtime_primitives::Ed25519Signature>;
/// A timestamp: seconds since the unix epoch.
pub type Timestamp = u64;
@@ -84,3 +95,22 @@ pub type Timestamp = u64;
/// We round denomination to 10^12 (12 sdf), and leave the other redundancy at the upper end so
/// that 32 bits may be multiplied with a balance in 128 bits without worrying about overflow.
pub type Balance = u128;
/// "generic" block ID for the future-proof block type.
// TODO: parameterize blockid only as necessary.
pub type BlockId = generic::BlockId<Block>;
/// A log entry in the block.
#[derive(PartialEq, Eq, Clone, Default)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Log {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Log)
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
+26 -63
View File
@@ -14,19 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Parachain data types.
//! Polkadot parachain types.
use codec::{Slicable, Input};
use rstd::prelude::*;
use rstd::cmp::Ordering;
use super::Hash;
#[cfg(feature = "std")]
use primitives::bytes;
use primitives;
use codec::{Input, Slicable};
use rstd::cmp::{PartialOrd, Ord, Ordering};
use rstd::vec::Vec;
use ::Hash;
/// Signature on candidate's block data by a collator.
pub type CandidateSignature = ::runtime_primitives::Ed25519Signature;
/// Unique identifier of a parachain.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Id(u32);
impl From<Id> for u32 {
@@ -67,7 +70,6 @@ pub enum Chain {
impl Slicable for Chain {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let disc = input.read_byte()?;
match disc {
0 => Some(Chain::Relay),
1 => Some(Chain::Parachain(Slicable::decode(input)?)),
@@ -84,7 +86,6 @@ impl Slicable for Chain {
id.using_encoded(|s| v.extend(s));
}
}
v
}
@@ -128,7 +129,7 @@ impl Slicable for DutyRoster {
/// Extrinsic data for a parachain.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Extrinsic;
@@ -137,14 +138,14 @@ pub struct Extrinsic;
///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Candidate {
/// The ID of the parachain this is a proposal for.
pub parachain_index: Id,
/// Collator's signature
pub collator_signature: ::Signature,
pub collator_signature: CandidateSignature,
/// Unprocessed ingress queue.
///
/// Ordered by parachain ID and block number.
@@ -155,20 +156,20 @@ pub struct Candidate {
/// Candidate receipt type.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct CandidateReceipt {
/// The ID of the parachain this is a candidate for.
pub parachain_index: Id,
/// The collator's relay-chain account ID
pub collator: ::AccountId,
pub collator: super::AccountId,
/// The head-data
pub head_data: HeadData,
/// Balance uploads to the relay chain.
pub balance_uploads: Vec<(::AccountId, u64)>,
pub balance_uploads: Vec<(super::AccountId, u64)>,
/// Egress queue roots.
pub egress_queue_roots: Vec<(Id, primitives::H256)>,
pub egress_queue_roots: Vec<(Id, Hash)>,
/// Fees paid from the chain to the relay chain validators
pub fees: u64,
}
@@ -203,8 +204,8 @@ impl CandidateReceipt {
/// Get the blake2_256 hash
#[cfg(feature = "std")]
pub fn hash(&self) -> Hash {
let encoded = self.encode();
primitives::hashing::blake2_256(&encoded).into()
use runtime_primitives::traits::{BlakeTwo256, Hashing};
BlakeTwo256::hash_of(self)
}
}
@@ -224,7 +225,7 @@ impl Ord for CandidateReceipt {
/// Parachain ingress queue message.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Consolidated ingress queue data.
@@ -232,34 +233,34 @@ pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>
/// This is just an ordered vector of other parachains' egress queues,
/// obtained according to the routing rules.
#[derive(Default, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct ConsolidatedIngress(pub Vec<(Id, Vec<Message>)>);
/// Parachain block data.
///
/// contains everything required to validate para-block, may contain block and witness data
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain header raw bytes wrapper type.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain head data included in the chain.
#[derive(PartialEq, Eq, Clone, PartialOrd, Ord)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain validation code.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Activitiy bit field
#[derive(PartialEq, Eq, Clone, Default)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Activity {
@@ -339,41 +340,3 @@ impl Slicable for Statement {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use substrate_serializer as ser;
#[test]
fn test_candidate() {
assert_eq!(ser::to_string_pretty(&Candidate {
parachain_index: 5.into(),
collator_signature: primitives::hash::H512::from(10).into(),
unprocessed_ingress: ConsolidatedIngress(vec![
(Id(1), vec![Message(vec![2])]),
(Id(2), vec![Message(vec![2]), Message(vec![3])]),
]),
block: BlockData(vec![1, 2, 3]),
}), r#"{
"parachainIndex": 5,
"collatorSignature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a",
"unprocessedIngress": [
[
1,
[
"0x02"
]
],
[
2,
[
"0x02",
"0x03"
]
]
],
"block": "0x010203"
}"#);
}
}
+2 -2
View File
@@ -9,6 +9,7 @@ log = { version = "0.3", optional = true }
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../safe-mix", default_features = false}
polkadot-primitives = { path = "../primitives", default_features = false }
substrate-codec = { path = "../../substrate/codec" }
substrate-serializer = { path = "../../substrate/serializer" }
substrate-runtime-std = { path = "../../substrate/runtime-std" }
@@ -25,7 +26,6 @@ substrate-runtime-session = { path = "../../substrate/runtime/session" }
substrate-runtime-staking = { path = "../../substrate/runtime/staking" }
substrate-runtime-system = { path = "../../substrate/runtime/system" }
substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" }
polkadot-primitives = { path = "../primitives" }
[dev-dependencies]
hex-literal = "0.1.0"
@@ -33,6 +33,7 @@ hex-literal = "0.1.0"
[features]
default = ["std"]
std = [
"polkadot-primitives/std",
"substrate-codec/std",
"substrate-primitives/std",
"substrate-runtime-std/std",
@@ -47,7 +48,6 @@ std = [
"substrate-runtime-staking/std",
"substrate-runtime-system/std",
"substrate-runtime-timestamp/std",
"polkadot-primitives/std",
"serde_derive",
"serde/std",
"log",
+168 -23
View File
@@ -18,11 +18,18 @@
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
extern crate serde;
#[macro_use]
extern crate substrate_runtime_io as runtime_io;
#[macro_use]
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_support;
#[macro_use]
extern crate substrate_runtime_primitives as runtime_primitives;
@@ -37,7 +44,10 @@ extern crate substrate_serializer;
#[cfg_attr(feature = "std", macro_use)]
extern crate substrate_primitives;
#[macro_use]
extern crate substrate_runtime_std as rstd;
extern crate polkadot_primitives as primitives;
extern crate substrate_codec as codec;
extern crate substrate_runtime_consensus as consensus;
extern crate substrate_runtime_council as council;
@@ -47,14 +57,13 @@ extern crate substrate_runtime_session as session;
extern crate substrate_runtime_staking as staking;
extern crate substrate_runtime_system as system;
extern crate substrate_runtime_timestamp as timestamp;
extern crate polkadot_primitives;
mod parachains;
use runtime_io::BlakeTwo256;
use polkadot_primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature};
use runtime_primitives::generic;
use runtime_primitives::traits::{Identity, HasPublicAux};
use rstd::prelude::*;
use primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature};
use primitives::parachain::CandidateReceipt;
use runtime_primitives::{generic, traits::{HasPublicAux, BlakeTwo256, Convert}};
#[cfg(feature = "std")]
pub use runtime_primitives::BuildExternalities;
@@ -62,13 +71,113 @@ pub use runtime_primitives::BuildExternalities;
pub use consensus::Call as ConsensusCall;
pub use timestamp::Call as TimestampCall;
pub use parachains::Call as ParachainsCall;
pub use primitives::Header;
/// The position of the timestamp set extrinsic.
pub const TIMESTAMP_SET_POSITION: u32 = 0;
/// The position of the parachains set extrinsic.
pub const PARACHAINS_SET_POSITION: u32 = 1;
/// Block Id type for this block.
pub type BlockId = generic::BlockId<Block>;
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
/// Extrinsic type as expected by this runtime.
pub type Extrinsic = generic::Extrinsic<AccountId, Index, Call>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Provides a type-safe wrapper around a structurally valid block.
#[cfg(feature = "std")]
pub struct CheckedBlock {
inner: Block,
file_line: Option<(&'static str, u32)>,
}
#[cfg(feature = "std")]
impl CheckedBlock {
/// Create a new checked block. Fails if the block is not structurally valid.
pub fn new(block: Block) -> Result<Self, Block> {
let has_timestamp = block.extrinsics.get(TIMESTAMP_SET_POSITION as usize).map_or(false, |xt| {
!xt.is_signed() && match xt.extrinsic.function {
Call::Timestamp(TimestampCall::set(_)) => true,
_ => false,
}
});
if !has_timestamp { return Err(block) }
let has_heads = block.extrinsics.get(PARACHAINS_SET_POSITION as usize).map_or(false, |xt| {
!xt.is_signed() && match xt.extrinsic.function {
Call::Parachains(ParachainsCall::set_heads(_)) => true,
_ => false,
}
});
if !has_heads { return Err(block) }
Ok(CheckedBlock {
inner: block,
file_line: None,
})
}
// Creates a new checked block, asserting that it is valid.
#[doc(hidden)]
pub fn new_unchecked(block: Block, file: &'static str, line: u32) -> Self {
CheckedBlock {
inner: block,
file_line: Some((file, line)),
}
}
/// Extract the timestamp from the block.
pub fn timestamp(&self) -> ::primitives::Timestamp {
let x = self.inner.extrinsics.get(TIMESTAMP_SET_POSITION as usize).and_then(|xt| match xt.extrinsic.function {
Call::Timestamp(TimestampCall::set(x)) => Some(x),
_ => None
});
match x {
Some(x) => x,
None => panic!("Invalid polkadot block asserted at {:?}", self.file_line),
}
}
/// Extract the parachain heads from the block.
pub fn parachain_heads(&self) -> &[CandidateReceipt] {
let x = self.inner.extrinsics.get(PARACHAINS_SET_POSITION as usize).and_then(|xt| match xt.extrinsic.function {
Call::Parachains(ParachainsCall::set_heads(ref x)) => Some(&x[..]),
_ => None
});
match x {
Some(x) => x,
None => panic!("Invalid polkadot block asserted at {:?}", self.file_line),
}
}
/// Convert into inner block.
pub fn into_inner(self) -> Block { self.inner }
}
#[cfg(feature = "std")]
impl ::std::ops::Deref for CheckedBlock {
type Target = Block;
fn deref(&self) -> &Block { &self.inner }
}
/// Assert that a block is structurally valid. May lead to panic in the future
/// in case it isn't.
#[cfg(feature = "std")]
#[macro_export]
macro_rules! assert_polkadot_block {
($block: expr) => {
$crate::CheckedBlock::new_unchecked($block, file!(), line!())
}
}
/// Concrete runtime type used to parameterize the various modules.
pub struct Concrete;
@@ -83,7 +192,7 @@ impl system::Trait for Concrete {
type Hashing = BlakeTwo256;
type Digest = generic::Digest<Log>;
type AccountId = AccountId;
type Header = generic::Header<BlockNumber, Hash, Log>;
type Header = Header;
}
/// System module for this concrete runtime.
pub type System = system::Module<Concrete>;
@@ -102,8 +211,16 @@ impl timestamp::Trait for Concrete {
/// Timestamp module for this concrete runtime.
pub type Timestamp = timestamp::Module<Concrete>;
/// Session key conversion.
pub struct SessionKeyConversion;
impl Convert<AccountId, SessionKey> for SessionKeyConversion {
fn convert(a: AccountId) -> SessionKey {
a.0
}
}
impl session::Trait for Concrete {
type ConvertAccountIdToSessionKey = Identity;
type ConvertAccountIdToSessionKey = SessionKeyConversion;
}
/// Session module for this concrete runtime.
pub type Session = session::Module<Concrete>;
@@ -135,6 +252,9 @@ impl parachains::Trait for Concrete {
pub type Parachains = parachains::Module<Concrete>;
impl_outer_dispatch! {
/// Call type for polkadot transactions.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
Consensus = 0,
Session = 1,
@@ -146,6 +266,9 @@ impl_outer_dispatch! {
Parachains = 8,
}
/// Internal calls.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum PrivCall {
Consensus = 0,
Session = 1,
@@ -156,14 +279,6 @@ impl_outer_dispatch! {
}
}
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, Hash, Log>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<BlockNumber, Hash, Log, AccountId, Index, Call, Signature>;
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
/// Extrinsic type as expected by this runtime.
pub type Extrinsic = generic::Extrinsic<AccountId, Index, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Concrete, Block, Staking,
(((((((), Parachains), Council), Democracy), Staking), Session), Timestamp)>;
@@ -180,6 +295,35 @@ impl_outer_config! {
}
}
/// Produces the list of inherent extrinsics.
pub fn inherent_extrinsics(timestamp: ::primitives::Timestamp, parachain_heads: Vec<CandidateReceipt>) -> Vec<UncheckedExtrinsic> {
vec![
UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: Default::default(),
function: Call::Timestamp(TimestampCall::set(timestamp)),
index: 0,
},
signature: Default::default(),
},
UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: Default::default(),
function: Call::Parachains(ParachainsCall::set_heads(parachain_heads)),
index: 0,
},
signature: Default::default(),
},
]
}
/// Checks an unchecked extrinsic for validity.
pub fn check_extrinsic(xt: UncheckedExtrinsic) -> bool {
use runtime_primitives::traits::Checkable;
xt.check().is_ok()
}
pub mod api {
impl_stubs!(
authorities => |()| super::Consensus::authorities(),
@@ -187,6 +331,7 @@ pub mod api {
apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic),
execute_block => |block| super::Executive::execute_block(block),
finalise_block => |()| super::Executive::finalise_block(),
inherent_extrinsics => |(timestamp, heads)| super::inherent_extrinsics(timestamp, heads),
validator_count => |()| super::Session::validator_count(),
validators => |()| super::Session::validators()
);
@@ -290,9 +435,9 @@ mod tests {
});
let raw = block.encode();
let decoded_substrate = primitives::block::Block::decode(&mut &raw[..]).unwrap();
let encoded_substrate = decoded_substrate.encode();
let decoded = Block::decode(&mut &encoded_substrate[..]).unwrap();
let decoded_primitive = ::primitives::Block::decode(&mut &raw[..]).unwrap();
let encoded_primitive = decoded_primitive.encode();
let decoded = Block::decode(&mut &encoded_primitive[..]).unwrap();
assert_eq!(block, decoded);
}
@@ -301,11 +446,11 @@ mod tests {
fn serialize_unchecked() {
let tx = UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: [1; 32],
signed: [1; 32].into(),
index: 999,
function: Call::Timestamp(TimestampCall::set(135135)),
},
signature: primitives::hash::H512([0; 64]).into(),
signature: runtime_primitives::Ed25519Signature(primitives::hash::H512([0; 64])).into(),
};
// 71000000
// 0101010101010101010101010101010101010101010101010101010101010101
@@ -322,7 +467,7 @@ mod tests {
#[test]
fn serialize_checked() {
let xt = Extrinsic {
signed: hex!["0d71d1a9cad6f2ab773435a7dec1bac019994d05d1dd5eb3108211dcf25c9d1e"],
signed: hex!["0d71d1a9cad6f2ab773435a7dec1bac019994d05d1dd5eb3108211dcf25c9d1e"].into(),
index: 0,
function: Call::CouncilVoting(council::voting::Call::propose(Box::new(
PrivCall::Consensus(consensus::PrivCall::set_code(
+11 -8
View File
@@ -16,17 +16,16 @@
//! Main parachains logic. For now this is just the determination of which validators do what.
use polkadot_primitives;
use primitives;
use rstd::prelude::*;
use codec::{Slicable, Joiner};
use runtime_support::Hashable;
use runtime_primitives::traits::{Executable, RefInto, MaybeEmpty};
use polkadot_primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt};
use primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt};
use {system, session};
use runtime_support::{StorageValue, StorageMap};
use runtime_support::dispatch::Result;
use substrate_runtime_support::{Hashable, StorageValue, StorageMap};
use substrate_runtime_support::dispatch::Result;
#[cfg(any(feature = "std", test))]
use rstd::marker::PhantomData;
@@ -34,7 +33,7 @@ use rstd::marker::PhantomData;
#[cfg(any(feature = "std", test))]
use {runtime_io, runtime_primitives};
pub trait Trait: system::Trait<Hash = polkadot_primitives::Hash> + session::Trait {
pub trait Trait: system::Trait<Hash = primitives::Hash> + session::Trait {
/// The position of the set_heads call in the block.
const SET_POSITION: u32;
@@ -42,7 +41,11 @@ pub trait Trait: system::Trait<Hash = polkadot_primitives::Hash> + session::Trai
}
decl_module! {
/// Parachains module.
pub struct Module<T: Trait>;
/// Call type for parachains.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: <T as Trait>::PublicAux {
// provide candidate receipts for parachains, in ascending order by id.
fn set_heads(aux, heads: Vec<CandidateReceipt>) -> Result = 0;
@@ -227,7 +230,7 @@ mod tests {
use runtime_io::with_externalities;
use substrate_primitives::H256;
use runtime_primitives::BuildExternalities;
use runtime_primitives::traits::{HasPublicAux, Identity};
use runtime_primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
use runtime_primitives::testing::{Digest, Header};
use consensus;
@@ -243,7 +246,7 @@ mod tests {
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = runtime_io::BlakeTwo256;
type Hashing = BlakeTwo256;
type Digest = Digest;
type AccountId = u64;
type Header = Header;
+246 -192
View File
@@ -11,19 +11,9 @@ name = "base58"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bigint"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.0.1"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -37,33 +27,55 @@ dependencies = [
[[package]]
name = "byteorder"
version = "1.2.1"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.4"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "coco"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crossbeam-deque"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crunchy"
version = "0.1.6"
@@ -75,20 +87,15 @@ version = "0.1.0"
dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "elastic-array"
version = "0.9.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -99,15 +106,37 @@ name = "environmental"
version = "0.1.0"
[[package]]
name = "ethcore-bigint"
name = "ethbloom"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethereum-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethereum-types-serialize"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -119,12 +148,23 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fixed-hash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -148,16 +188,16 @@ dependencies = [
[[package]]
name = "hex-literal"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hex-literal-impl"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -170,12 +210,12 @@ source = "git+https://github.com/paritytech/integer-sqrt-rs.git#886e9cb983c46498
[[package]]
name = "keccak-hash"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -185,12 +225,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.36"
version = "0.2.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -206,9 +246,14 @@ name = "log"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memoffset"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memory_units"
version = "0.3.0"
@@ -229,7 +274,7 @@ name = "num_cpus"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -245,9 +290,9 @@ name = "parity-wasm"
version = "0.27.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -255,43 +300,35 @@ name = "parity-wasm"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.5.4"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.2.10"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "plain_hasher"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "polkadot-primitives"
version = "0.1.0"
dependencies = [
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0",
@@ -334,12 +371,20 @@ name = "proc-macro-hack-impl"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pwasm-alloc"
version = "0.1.0"
dependencies = [
"pwasm-libc 0.1.0",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -351,15 +396,18 @@ name = "pwasm-utils"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.3.15"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
@@ -367,7 +415,7 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -377,7 +425,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -386,19 +434,19 @@ name = "rayon"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -408,20 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rlp"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -437,17 +484,17 @@ source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc
[[package]]
name = "rustc_version"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "safe-mix"
version = "0.1.0"
dependencies = [
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -457,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.6.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -470,31 +517,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.27"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.27"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive_internals"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smallvec"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -511,8 +549,8 @@ name = "substrate-keyring"
version = "0.1.0"
dependencies = [
"ed25519 0.1.0",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -520,25 +558,26 @@ name = "substrate-primitives"
version = "0.1.0"
dependencies = [
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-runtime-consensus"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -563,10 +602,11 @@ dependencies = [
name = "substrate-runtime-council"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
@@ -585,9 +625,10 @@ dependencies = [
name = "substrate-runtime-democracy"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0",
@@ -604,8 +645,8 @@ dependencies = [
name = "substrate-runtime-executive"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-primitives 0.1.0",
@@ -620,12 +661,12 @@ version = "0.1.0"
dependencies = [
"ed25519 0.1.0",
"environmental 0.1.0",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-state-machine 0.1.0",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -634,8 +675,8 @@ version = "0.1.0"
dependencies = [
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -647,21 +688,22 @@ dependencies = [
name = "substrate-runtime-sandbox"
version = "0.1.0"
dependencies = [
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-std 0.1.0",
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-runtime-session"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
@@ -677,9 +719,10 @@ dependencies = [
name = "substrate-runtime-staking"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
@@ -700,7 +743,7 @@ version = "0.1.0"
dependencies = [
"pwasm-alloc 0.1.0",
"pwasm-libc 0.1.0",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -708,9 +751,9 @@ name = "substrate-runtime-support"
version = "0.1.0"
dependencies = [
"ed25519 0.1.0",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -721,9 +764,9 @@ dependencies = [
name = "substrate-runtime-system"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safe-mix 0.1.0",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -736,8 +779,9 @@ dependencies = [
name = "substrate-runtime-timestamp"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -751,43 +795,39 @@ dependencies = [
name = "substrate-state-machine"
version = "0.1.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.11.11"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tiny-keccak"
version = "1.4.0"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "triehash"
version = "0.1.0"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -803,14 +843,25 @@ name = "uint"
version = "0.1.2"
source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "uint"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.0.4"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -820,10 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasmi"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -850,32 +901,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
"checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
"checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6"
"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002"
"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
"checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
"checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb"
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631"
"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a"
"checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "<none>"
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
"checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
"checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
@@ -883,39 +938,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd"
"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe"
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8"
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892"
"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46"
"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9"
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0"
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
"checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce"
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435"
"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
"checksum wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26b20dbeb7caee04597a5d2c93e2b3e64872c6ea2af732d7ad49dbec44067c35"
"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb"
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+2 -2
View File
@@ -8,6 +8,7 @@ crate-type = ["cdylib"]
[dependencies]
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
polkadot-primitives = { path = "../../primitives", default-features = false }
safe-mix = { path = "../../../safe-mix", default-features = false }
substrate-codec = { path = "../../../substrate/codec", default-features = false }
substrate-primitives = { path = "../../../substrate/primitives", default-features = false }
@@ -23,11 +24,11 @@ substrate-runtime-session = { path = "../../../substrate/runtime/session", defau
substrate-runtime-staking = { path = "../../../substrate/runtime/staking", default-features = false }
substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false }
substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false }
polkadot-primitives = { path = "../../primitives", default-features = false }
[features]
default = []
std = [
"polkadot-primitives/std",
"safe-mix/std",
"substrate-codec/std",
"substrate-primitives/std",
@@ -43,7 +44,6 @@ std = [
"substrate-runtime-staking/std",
"substrate-runtime-system/std",
"substrate-runtime-timestamp/std",
"polkadot-primitives/std",
]
[profile.release]
+58 -48
View File
@@ -19,6 +19,7 @@
extern crate futures;
extern crate ed25519;
extern crate exit_future;
extern crate parking_lot;
extern crate tokio_timer;
extern crate polkadot_primitives;
@@ -28,17 +29,16 @@ extern crate polkadot_api;
extern crate polkadot_consensus as consensus;
extern crate polkadot_transaction_pool as transaction_pool;
extern crate polkadot_keystore as keystore;
extern crate substrate_client as client;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives;
extern crate substrate_network as network;
extern crate substrate_codec as codec;
extern crate substrate_client_db as client_db;
extern crate substrate_executor;
extern crate substrate_state_machine as state_machine;
extern crate exit_future;
extern crate tokio_core;
extern crate substrate_client as client;
extern crate substrate_client_db as client_db;
#[macro_use]
extern crate error_chain;
@@ -56,13 +56,13 @@ use std::thread;
use futures::prelude::*;
use tokio_core::reactor::Core;
use codec::Slicable;
use primitives::block::{Id as BlockId, ExtrinsicHash, HeaderHash, Header};
use primitives::{AuthorityId};
use primitives::AuthorityId;
use transaction_pool::TransactionPool;
use substrate_executor::NativeExecutor;
use polkadot_executor::Executor as LocalDispatch;
use keystore::Store as Keystore;
use polkadot_api::PolkadotApi;
use polkadot_primitives::{Block, BlockId, Hash, Header};
use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
SessionConfig, StakingConfig, BuildExternalities};
use client::backend::Backend;
@@ -78,8 +78,8 @@ type CodeExecutor = NativeExecutor<LocalDispatch>;
/// Polkadot service.
pub struct Service<B, E> {
thread: Option<thread::JoinHandle<()>>,
client: Arc<Client<B, E>>,
network: Arc<network::Service>,
client: Arc<Client<B, E, Block>>,
network: Arc<network::Service<Block>>,
transaction_pool: Arc<TransactionPool>,
signal: Option<Signal>,
_consensus: Option<consensus::Service>,
@@ -87,18 +87,18 @@ pub struct Service<B, E> {
struct TransactionPoolAdapter<B, E, A> where A: Send + Sync, E: Send + Sync {
pool: Arc<TransactionPool>,
client: Arc<Client<B, E>>,
client: Arc<Client<B, E, Block>>,
api: Arc<A>,
}
impl<B, E, A> network::TransactionPool for TransactionPoolAdapter<B, E, A>
impl<B, E, A> network::TransactionPool<Block> for TransactionPoolAdapter<B, E, A>
where
B: Backend + Send + Sync,
E: client::CallExecutor + Send + Sync,
client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>,
B: Backend<Block> + Send + Sync,
E: client::CallExecutor<Block> + Send + Sync,
client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>,
A: PolkadotApi + Send + Sync,
{
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)> {
fn transactions(&self) -> Vec<(Hash, Vec<u8>)> {
let best_block = match self.client.info() {
Ok(info) => info.chain.best_hash,
Err(e) => {
@@ -107,21 +107,25 @@ impl<B, E, A> network::TransactionPool for TransactionPoolAdapter<B, E, A>
}
};
let id = self.api.check_id(BlockId::Hash(best_block)).expect("Best block is always valid; qed.");
let id = match self.api.check_id(BlockId::hash(best_block)) {
Ok(id) => id,
Err(_) => return Vec::new(),
};
let ready = transaction_pool::Ready::create(id, &*self.api);
self.pool.cull_and_get_pending(ready, |pending| pending
.map(|t| {
let hash = ::primitives::Hash::from(&t.hash()[..]);
let tx = codec::Slicable::encode(t.as_transaction());
(hash, tx)
let hash = t.hash().clone();
(hash, t.primitive_extrinsic())
})
.collect()
)
}
fn import(&self, transaction: &[u8]) -> Option<ExtrinsicHash> {
if let Some(uxt) = codec::Slicable::decode(&mut &transaction[..]) {
fn import(&self, transaction: &Vec<u8>) -> Option<Hash> {
let encoded = transaction.encode();
if let Some(uxt) = codec::Slicable::decode(&mut &encoded[..]) {
match self.pool.import_unchecked_extrinsic(uxt) {
Ok(xt) => Some(*xt.hash()),
Err(e) => match *e.kind() {
@@ -138,7 +142,7 @@ impl<B, E, A> network::TransactionPool for TransactionPoolAdapter<B, E, A>
}
}
fn on_broadcasted(&self, propagations: HashMap<ExtrinsicHash, Vec<String>>) {
fn on_broadcasted(&self, propagations: HashMap<Hash, Vec<String>>) {
self.pool.on_broadcasted(propagations)
}
}
@@ -165,12 +169,12 @@ fn poc_2_testnet_config() -> ChainConfig {
}),
system: None,
session: Some(SessionConfig {
validators: initial_authorities.clone(),
validators: initial_authorities.iter().cloned().map(Into::into).collect(),
session_length: 720, // that's 1 hour per session.
}),
staking: Some(StakingConfig {
current_era: 0,
intentions: initial_authorities.clone(),
intentions: initial_authorities.iter().cloned().map(Into::into).collect(),
transaction_base_fee: 100,
transaction_byte_fee: 1,
balances: endowed_accounts.iter().map(|&k|(k, 1u128 << 60)).collect(),
@@ -210,12 +214,12 @@ fn poc_2_testnet_config() -> ChainConfig {
fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
let endowed_accounts = vec![
ed25519::Pair::from_seed(b"Alice ").public().into(),
ed25519::Pair::from_seed(b"Bob ").public().into(),
ed25519::Pair::from_seed(b"Charlie ").public().into(),
ed25519::Pair::from_seed(b"Dave ").public().into(),
ed25519::Pair::from_seed(b"Eve ").public().into(),
ed25519::Pair::from_seed(b"Ferdie ").public().into(),
ed25519::Pair::from_seed(b"Alice ").public().0.into(),
ed25519::Pair::from_seed(b"Bob ").public().0.into(),
ed25519::Pair::from_seed(b"Charlie ").public().0.into(),
ed25519::Pair::from_seed(b"Dave ").public().0.into(),
ed25519::Pair::from_seed(b"Eve ").public().0.into(),
ed25519::Pair::from_seed(b"Ferdie ").public().0.into(),
];
let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig {
@@ -224,12 +228,12 @@ fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
}),
system: None,
session: Some(SessionConfig {
validators: initial_authorities.clone(),
validators: initial_authorities.iter().cloned().map(Into::into).collect(),
session_length: 10,
}),
staking: Some(StakingConfig {
current_era: 0,
intentions: initial_authorities.clone(),
intentions: initial_authorities.iter().cloned().map(Into::into).collect(),
transaction_base_fee: 1,
transaction_byte_fee: 0,
balances: endowed_accounts.iter().map(|&k|(k, (1u128 << 60))).collect(),
@@ -243,7 +247,7 @@ fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
minimum_deposit: 10,
}),
council: Some(CouncilConfig {
active_council: endowed_accounts.iter().filter(|a| initial_authorities.iter().find(|b| a == b).is_none()).map(|a| (a.clone(), 1000000)).collect(),
active_council: endowed_accounts.iter().filter(|a| initial_authorities.iter().find(|&b| &a.0 == b).is_none()).map(|a| (a.clone(), 1000000)).collect(),
candidacy_bond: 10,
voter_bond: 2,
present_slash_per_voter: 1,
@@ -280,16 +284,23 @@ struct GenesisBuilder {
config: GenesisConfig,
}
impl client::GenesisBuilder for GenesisBuilder {
impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let storage = self.config.build_externalities();
let block = genesis::construct_genesis_block(&storage);
(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
let block = genesis::construct_genesis_block::<Block>(&storage);
(block.header, storage.into_iter().collect())
}
}
/// Creates light client and register protocol with the network service
pub fn new_light(config: Configuration) -> Result<Service<client::light::Backend, client::RemoteCallExecutor<client::light::Backend, network::OnDemand<network::Service>>>, error::Error> {
pub fn new_light(config: Configuration)
-> Result<
Service<
client::light::Backend<Block>,
client::RemoteCallExecutor<client::light::Backend<Block>, network::OnDemand<Block, network::Service<Block>>>
>,
error::Error,
> {
Service::new(move |_, executor, genesis_builder: GenesisBuilder| {
let client_backend = client::light::new_light_backend();
let fetch_checker = Arc::new(client::light::new_fetch_checker(client_backend.clone(), executor));
@@ -303,7 +314,7 @@ pub fn new_light(config: Configuration) -> Result<Service<client::light::Backend
}
/// Creates full client and register protocol with the network service
pub fn new_full(config: Configuration) -> Result<Service<client_db::Backend, client::LocalCallExecutor<client_db::Backend, CodeExecutor>>, error::Error> {
pub fn new_full(config: Configuration) -> Result<Service<client_db::Backend<Block>, client::LocalCallExecutor<client_db::Backend<Block>, CodeExecutor>>, error::Error> {
let is_validator = (config.roles & Role::VALIDATOR) == Role::VALIDATOR;
Service::new(|db_settings, executor, genesis_builder: GenesisBuilder|
Ok((Arc::new(client_db::new_client(db_settings, executor, genesis_builder)?), None)),
@@ -330,9 +341,9 @@ pub fn new_full(config: Configuration) -> Result<Service<client_db::Backend, cli
impl<B, E> Service<B, E>
where
B: Backend + Send + Sync + 'static,
E: CallExecutor + Send + Sync + 'static,
client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{
/// Creates and register protocol with the network service
fn new<F, G, C, A>(client_creator: F, api_creator: G, consensus_creator: C, mut config: Configuration) -> Result<Self, error::Error>
@@ -341,13 +352,13 @@ impl<B, E> Service<B, E>
client_db::DatabaseSettings,
CodeExecutor,
GenesisBuilder,
) -> Result<(Arc<Client<B, E>>, Option<Arc<network::OnDemand<network::Service>>>), error::Error>,
) -> Result<(Arc<Client<B, E, Block>>, Option<Arc<network::OnDemand<Block, network::Service<Block>>>>), error::Error>,
G: Fn(
Arc<Client<B, E>>,
Arc<Client<B, E, Block>>,
) -> Arc<A>,
C: Fn(
Arc<Client<B, E>>,
Arc<network::Service>,
Arc<Client<B, E, Block>>,
Arc<network::Service<Block>>,
Arc<TransactionPool>,
&Keystore
) -> Result<Option<consensus::Service>, error::Error>,
@@ -405,7 +416,6 @@ impl<B, E> Service<B, E>
on_demand: on_demand.clone().map(|d| d as Arc<network::OnDemandService>),
transaction_pool: transaction_pool_adapter,
};
let network = network::Service::new(network_params)?;
let barrier = ::std::sync::Arc::new(Barrier::new(2));
on_demand.map(|on_demand| on_demand.set_service_link(Arc::downgrade(&network)));
@@ -468,12 +478,12 @@ impl<B, E> Service<B, E>
}
/// Get shared client instance.
pub fn client(&self) -> Arc<Client<B, E>> {
pub fn client(&self) -> Arc<Client<B, E, Block>> {
self.client.clone()
}
/// Get shared network instance.
pub fn network(&self) -> Arc<network::Service> {
pub fn network(&self) -> Arc<network::Service<Block>> {
self.network.clone()
}
@@ -484,11 +494,11 @@ impl<B, E> Service<B, E>
}
/// Produce a task which prunes any finalized transactions from the pool.
pub fn prune_imported<A>(api: &A, pool: &TransactionPool, hash: HeaderHash)
pub fn prune_imported<A>(api: &A, pool: &TransactionPool, hash: Hash)
where
A: PolkadotApi,
{
match api.check_id(BlockId::Hash(hash)) {
match api.check_id(BlockId::hash(hash)) {
Ok(id) => {
let ready = transaction_pool::Ready::create(id, api);
pool.cull(None, ready);
@@ -21,8 +21,8 @@ pub mod generic;
pub use generic::Table;
use primitives::parachain::{Id, CandidateReceipt};
use primitives::{SessionKey, Hash, Signature};
use primitives::parachain::{Id, CandidateReceipt, CandidateSignature as Signature};
use primitives::{SessionKey, Hash};
/// Statements about candidates on the network.
pub type Statement = generic::Statement<CandidateReceipt, Hash>;
+38 -107
View File
@@ -40,106 +40,23 @@ use std::{
use codec::Slicable;
use extrinsic_pool::{Pool, txpool::{self, Readiness, scoring::{Change, Choice}}};
use extrinsic_pool::api::ExtrinsicPool;
use polkadot_api::PolkadotApi;
use primitives::parachain::CandidateReceipt;
use primitives::{AccountId, Timestamp, Hash};
use runtime::{Block, UncheckedExtrinsic, TimestampCall, ParachainsCall, Call};
use substrate_primitives::block::{Extrinsic, ExtrinsicHash};
use substrate_primitives::hexdisplay::HexDisplay;
use substrate_runtime_primitives::traits::{Bounded, Checkable};
use primitives::{AccountId, Hash, UncheckedExtrinsic as FutureProofUncheckedExtrinsic};
use runtime::UncheckedExtrinsic;
use substrate_runtime_primitives::traits::{Bounded, Checkable, BlakeTwo256, Hashing};
pub use extrinsic_pool::txpool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps};
pub use error::{Error, ErrorKind, Result};
/// Useful functions for working with Polkadot blocks.
pub struct PolkadotBlock {
block: Block,
location: Option<(&'static str, usize)>,
}
impl PolkadotBlock {
/// Create a new block, checking high-level well-formedness.
pub fn from(unchecked: Block) -> ::std::result::Result<Self, Block> {
if unchecked.extrinsics.len() < 2 {
return Err(unchecked);
}
if unchecked.extrinsics[0].is_signed() {
return Err(unchecked);
}
if unchecked.extrinsics[1].is_signed() {
return Err(unchecked);
}
match unchecked.extrinsics[0].extrinsic.function {
Call::Timestamp(TimestampCall::set(_)) => {},
_ => return Err(unchecked),
}
match unchecked.extrinsics[1].extrinsic.function {
Call::Parachains(ParachainsCall::set_heads(_)) => {},
_ => return Err(unchecked),
}
// any further checks...
Ok(PolkadotBlock { block: unchecked, location: None })
}
/// Create a new block, skipping any high-level well-formedness checks. WARNING: This could
/// result in internal functions panicking if the block is, in fact, not well-formed.
pub fn force_from(known_good: Block, file: &'static str, line: usize) -> Self {
PolkadotBlock { block: known_good, location: Some((file, line)) }
}
/// Retrieve the timestamp of a Polkadot block.
pub fn timestamp(&self) -> Timestamp {
if let Call::Timestamp(TimestampCall::set(t)) = self.block.extrinsics[0].extrinsic.function {
t
} else {
if let Some((file, line)) = self.location {
panic!("Invalid block used in `PolkadotBlock::force_from` at {}:{}", file, line);
} else {
panic!("Invalid block made it through the PolkadotBlock verification!?");
}
}
}
/// Retrieve the parachain candidates proposed for this block.
pub fn parachain_heads(&self) -> &[CandidateReceipt] {
if let Call::Parachains(ParachainsCall::set_heads(ref t)) = self.block.extrinsics[1].extrinsic.function {
&t[..]
} else {
if let Some((file, line)) = self.location {
panic!("Invalid block used in `PolkadotBlock::force_from` at {}:{}", file, line);
} else {
panic!("Invalid block made it through the PolkadotBlock verification!?");
}
}
}
}
#[macro_export]
macro_rules! assert_polkadot_block {
($known_good:expr) => ( PolkadotBlock::force_from(known_good, file!(), line!()) )
}
impl ::std::ops::Deref for PolkadotBlock {
type Target = Block;
fn deref(&self) -> &Block {
&self.block
}
}
impl From<PolkadotBlock> for Block {
fn from(pd: PolkadotBlock) -> Self {
pd.block
}
}
/// Type alias for convenience.
pub type CheckedExtrinsic = <UncheckedExtrinsic as Checkable>::Checked;
/// A verified transaction which should be includable and non-inherent.
#[derive(Debug, Clone)]
pub struct VerifiedTransaction {
inner: <UncheckedExtrinsic as Checkable>::Checked,
hash: ExtrinsicHash,
inner: CheckedExtrinsic,
hash: Hash,
encoded_size: usize,
}
@@ -150,10 +67,10 @@ impl VerifiedTransaction {
bail!(ErrorKind::IsInherent(xt))
}
let message = codec::Slicable::encode(&xt);
let message = Slicable::encode(&xt);
match xt.check() {
Ok(xt) => {
let hash = substrate_primitives::hashing::blake2_256(&message);
let hash = BlakeTwo256::hash(&message);
Ok(VerifiedTransaction {
inner: xt,
hash: hash.into(),
@@ -169,8 +86,14 @@ impl VerifiedTransaction {
self.as_ref().as_unchecked()
}
/// Convert to primitive unchecked extrinsic.
pub fn primitive_extrinsic(&self) -> ::primitives::UncheckedExtrinsic {
Slicable::decode(&mut self.as_transaction().encode().as_slice())
.expect("UncheckedExtrinsic shares repr with Vec<u8>; qed")
}
/// Consume the verified transaciton, yielding the unchecked counterpart.
pub fn into_inner(self) -> <UncheckedExtrinsic as Checkable>::Checked {
pub fn into_inner(self) -> CheckedExtrinsic {
self.inner
}
@@ -190,8 +113,8 @@ impl VerifiedTransaction {
}
}
impl AsRef< <UncheckedExtrinsic as Checkable>::Checked > for VerifiedTransaction {
fn as_ref(&self) -> &<UncheckedExtrinsic as Checkable>::Checked {
impl AsRef<CheckedExtrinsic> for VerifiedTransaction {
fn as_ref(&self) -> &CheckedExtrinsic {
&self.inner
}
}
@@ -303,15 +226,12 @@ impl<'a, T: 'a + PolkadotApi> txpool::Ready<VerifiedTransaction> for Ready<'a, T
pub struct Verifier;
impl txpool::Verifier<Extrinsic> for Verifier {
impl txpool::Verifier<UncheckedExtrinsic> for Verifier {
type VerifiedTransaction = VerifiedTransaction;
type Error = Error;
fn verify_transaction(&self, xt: Extrinsic) -> Result<Self::VerifiedTransaction> {
info!("Extrinsic submitted: {}", HexDisplay::from(&xt.0));
let uxt = xt.using_encoded(|ref mut s| UncheckedExtrinsic::decode(s))
.ok_or_else(|| ErrorKind::InvalidExtrinsicFormat)?;
info!("Correctly formatted: {:?}", uxt);
fn verify_transaction(&self, uxt: UncheckedExtrinsic) -> Result<Self::VerifiedTransaction> {
info!("Extrinsic Submitted: {:?}", uxt);
VerifiedTransaction::create(uxt)
}
}
@@ -320,7 +240,7 @@ impl txpool::Verifier<Extrinsic> for Verifier {
///
/// Wraps a `extrinsic_pool::Pool`.
pub struct TransactionPool {
inner: Pool<Verifier, Scoring, Error>,
inner: Pool<UncheckedExtrinsic, Hash, Verifier, Scoring, Error>,
}
impl TransactionPool {
@@ -337,14 +257,25 @@ impl TransactionPool {
}
impl Deref for TransactionPool {
type Target = Pool<Verifier, Scoring, Error>;
type Target = Pool<UncheckedExtrinsic, Hash, Verifier, Scoring, Error>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[cfg(test)]
mod tests {
}
impl ExtrinsicPool<FutureProofUncheckedExtrinsic, Hash> for TransactionPool {
type Error = Error;
fn submit(&self, xts: Vec<FutureProofUncheckedExtrinsic>) -> Result<Vec<Hash>> {
// TODO: more general transaction pool, which can handle more kinds of vec-encoded transactions,
// even when runtime is out of date.
xts.into_iter()
.map(|xt| xt.encode())
.map(|encoded| UncheckedExtrinsic::decode(&mut &encoded[..]))
.map(|maybe_decoded| maybe_decoded.ok_or_else(|| ErrorKind::InvalidExtrinsicFormat.into()))
.map(|x| x.and_then(|x| self.import_unchecked_extrinsic(x)))
.map(|x| x.map(|x| x.hash().clone()))
.collect()
}
}
+1
View File
@@ -8,6 +8,7 @@ futures = "0.1.17"
substrate-codec = { path = "../codec" }
substrate-primitives = { path = "../primitives" }
substrate-runtime-support = { path = "../runtime-support" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
ed25519 = { path = "../ed25519" }
tokio-timer = "0.1.2"
parking_lot = "0.4"
+3 -3
View File
@@ -18,10 +18,10 @@
error_chain! {
errors {
/// Missing state at block with given Id.
StateUnavailable(b: ::primitives::block::Id) {
/// Missing state at block with given descriptor.
StateUnavailable(b: String) {
description("State missing at given block."),
display("State unavailable at block {:?}", b),
display("State unavailable at block {}", b),
}
/// I/O terminated unexpectedly
+169 -142
View File
@@ -22,6 +22,7 @@ pub mod generic;
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate ed25519;
extern crate tokio_timer;
extern crate parking_lot;
@@ -41,9 +42,9 @@ use std::sync::atomic::{AtomicBool, Ordering};
use codec::Slicable;
use ed25519::LocalizedSignature;
use runtime_support::Hashable;
use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification};
use primitives::block::{Block, Id as BlockId, Header, HeaderHash};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block, Header};
use runtime_primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification};
use primitives::AuthorityId;
use futures::{task, Async, Stream, Sink, Future, IntoFuture};
@@ -56,27 +57,27 @@ pub use error::{Error, ErrorKind};
/// Messages over the proposal.
/// Each message carries an associated round number.
pub type Message = generic::Message<Block, HeaderHash>;
pub type Message<B> = generic::Message<B, <B as Block>::Hash>;
/// Localized message type.
pub type LocalizedMessage = generic::LocalizedMessage<
Block,
HeaderHash,
pub type LocalizedMessage<B> = generic::LocalizedMessage<
B,
<B as Block>::Hash,
AuthorityId,
LocalizedSignature
>;
/// Justification of some hash.
pub type Justification = generic::Justification<HeaderHash, LocalizedSignature>;
pub type Justification<H> = generic::Justification<H, LocalizedSignature>;
/// Justification of a prepare message.
pub type PrepareJustification = generic::PrepareJustification<HeaderHash, LocalizedSignature>;
pub type PrepareJustification<H> = generic::PrepareJustification<H, LocalizedSignature>;
/// Unchecked justification.
pub type UncheckedJustification = generic::UncheckedJustification<HeaderHash, LocalizedSignature>;
pub type UncheckedJustification<H> = generic::UncheckedJustification<H, LocalizedSignature>;
impl From<PrimitiveJustification> for UncheckedJustification {
fn from(just: PrimitiveJustification) -> Self {
impl<H> From<PrimitiveJustification<H>> for UncheckedJustification<H> {
fn from(just: PrimitiveJustification<H>) -> Self {
UncheckedJustification {
round_number: just.round_number as usize,
digest: just.hash,
@@ -88,46 +89,46 @@ impl From<PrimitiveJustification> for UncheckedJustification {
}
}
impl From<UncheckedJustification> for PrimitiveJustification {
fn from(just: UncheckedJustification) -> Self {
impl<H> Into<PrimitiveJustification<H>> for UncheckedJustification<H> {
fn into(self) -> PrimitiveJustification<H> {
PrimitiveJustification {
round_number: just.round_number as u32,
hash: just.digest,
signatures: just.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(),
round_number: self.round_number as u32,
hash: self.digest,
signatures: self.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(),
}
}
}
/// Result of a committed round of BFT
pub type Committed = generic::Committed<Block, HeaderHash, LocalizedSignature>;
pub type Committed<B> = generic::Committed<B, <B as Block>::Hash, LocalizedSignature>;
/// Communication between BFT participants.
pub type Communication = generic::Communication<Block, HeaderHash, AuthorityId, LocalizedSignature>;
pub type Communication<B> = generic::Communication<B, <B as Block>::Hash, AuthorityId, LocalizedSignature>;
/// Misbehavior observed from BFT participants.
pub type Misbehavior = generic::Misbehavior<HeaderHash, LocalizedSignature>;
pub type Misbehavior<H> = generic::Misbehavior<H, LocalizedSignature>;
/// Proposer factory. Can be used to create a proposer instance.
pub trait ProposerFactory {
pub trait ProposerFactory<B: Block> {
/// The proposer type this creates.
type Proposer: Proposer;
type Proposer: Proposer<B>;
/// Error which can occur upon creation.
type Error: From<Error>;
/// Initialize the proposal logic on top of a specific header.
// TODO: provide state context explicitly?
fn init(&self, parent_header: &Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Self::Error>;
fn init(&self, parent_header: &B::Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Self::Error>;
}
/// Logic for a proposer.
///
/// This will encapsulate creation and evaluation of proposals at a specific
/// block.
pub trait Proposer {
pub trait Proposer<B: Block> {
/// Error type which can occur when proposing or evaluating.
type Error: From<Error> + From<InputStreamConcluded> + 'static;
/// Future that resolves to a created proposal.
type Create: IntoFuture<Item=Block,Error=Self::Error>;
/// Future that resolves to a committed proposal.
type Create: IntoFuture<Item=B,Error=Self::Error>;
/// Future that resolves when a proposal is evaluated.
type Evaluate: IntoFuture<Item=bool,Error=Self::Error>;
@@ -135,10 +136,10 @@ pub trait Proposer {
fn propose(&self) -> Self::Create;
/// Evaluate proposal. True means valid.
fn evaluate(&self, proposal: &Block) -> Self::Evaluate;
fn evaluate(&self, proposal: &B) -> Self::Evaluate;
/// Import witnessed misbehavior.
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, Misbehavior)>);
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, Misbehavior<B::Hash>)>);
/// Determine the proposer for a given round. This should be a deterministic function
/// with consistent results across all authorities.
@@ -146,33 +147,37 @@ pub trait Proposer {
}
/// Block import trait.
pub trait BlockImport {
pub trait BlockImport<B: Block> {
/// Import a block alongside its corresponding justification.
fn import_block(&self, block: Block, justification: Justification);
fn import_block(&self, block: B, justification: Justification<B::Hash>);
}
/// Trait for getting the authorities at a given block.
pub trait Authorities {
pub trait Authorities<B: Block> {
/// Get the authorities at the given block.
fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, Error>;
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityId>, Error>;
}
/// Instance of BFT agreement.
struct BftInstance<P> {
struct BftInstance<B: Block, P> {
key: Arc<ed25519::Pair>,
authorities: Vec<AuthorityId>,
parent_hash: HeaderHash,
parent_hash: B::Hash,
timer: Timer,
round_timeout_multiplier: u64,
proposer: P,
}
impl<P: Proposer> generic::Context for BftInstance<P> {
impl<B: Block, P: Proposer<B>> generic::Context for BftInstance<B, P>
where
B: Clone + Eq,
B::Hash: ::std::hash::Hash,
{
type Error = P::Error;
type AuthorityId = AuthorityId;
type Digest = HeaderHash;
type Digest = B::Hash;
type Signature = LocalizedSignature;
type Candidate = Block;
type Candidate = B;
type RoundTimeout = Box<Future<Item=(),Error=Self::Error> + Send>;
type CreateProposal = <P::Create as IntoFuture>::Future;
type EvaluateProposal = <P::Evaluate as IntoFuture>::Future;
@@ -185,11 +190,11 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
self.proposer.propose().into_future()
}
fn candidate_digest(&self, proposal: &Block) -> HeaderHash {
proposal.header.blake2_256().into()
fn candidate_digest(&self, proposal: &B) -> B::Hash {
proposal.hash()
}
fn sign_local(&self, message: Message) -> LocalizedMessage {
fn sign_local(&self, message: Message<B>) -> LocalizedMessage<B> {
sign_message(message, &*self.key, self.parent_hash.clone())
}
@@ -197,7 +202,7 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
self.proposer.round_proposer(round, &self.authorities[..])
}
fn proposal_valid(&self, proposal: &Block) -> Self::EvaluateProposal {
fn proposal_valid(&self, proposal: &B) -> Self::EvaluateProposal {
self.proposer.evaluate(proposal).into_future()
}
@@ -217,23 +222,27 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
/// A future that resolves either when canceled (witnessing a block from the network at same height)
/// or when agreement completes.
pub struct BftFuture<P, I, InStream, OutSink> where
P: Proposer,
InStream: Stream<Item=Communication, Error=P::Error>,
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>,
pub struct BftFuture<B, P, I, InStream, OutSink> where
B: Block + Clone + Eq,
B::Hash: ::std::hash::Hash,
P: Proposer<B>,
InStream: Stream<Item=Communication<B>, Error=P::Error>,
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
{
inner: generic::Agreement<BftInstance<P>, InStream, OutSink>,
inner: generic::Agreement<BftInstance<B, P>, InStream, OutSink>,
cancel: Arc<AtomicBool>,
send_task: Option<oneshot::Sender<task::Task>>,
import: Arc<I>,
}
impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> where
P: Proposer,
impl<B, P, I, InStream, OutSink> Future for BftFuture<B, P, I, InStream, OutSink> where
B: Block + Clone + Eq,
B::Hash: ::std::hash::Hash,
P: Proposer<B>,
P::Error: ::std::fmt::Display,
I: BlockImport,
InStream: Stream<Item=Communication, Error=P::Error>,
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>,
I: BlockImport<B>,
InStream: Stream<Item=Communication<B>, Error=P::Error>,
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
{
type Item = ();
type Error = ();
@@ -258,7 +267,7 @@ impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> wher
// we will get the block from the network later.
if let Some(justified_block) = committed.candidate {
info!(target: "bft", "Importing block #{} ({}) directly from BFT consensus",
justified_block.header.number, HeaderHash::from(justified_block.header.blake2_256()));
justified_block.header().number(), justified_block.hash());
self.import.import_block(justified_block, committed.justification)
}
@@ -267,10 +276,12 @@ impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> wher
}
}
impl<P, I, InStream, OutSink> Drop for BftFuture<P, I, InStream, OutSink> where
P: Proposer,
InStream: Stream<Item=Communication, Error=P::Error>,
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>,
impl<B, P, I, InStream, OutSink> Drop for BftFuture<B, P, I, InStream, OutSink> where
B: Block + Clone + Eq,
B::Hash: ::std::hash::Hash,
P: Proposer<B>,
InStream: Stream<Item=Communication<B>, Error=P::Error>,
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
{
fn drop(&mut self) {
// TODO: have a trait member to pass misbehavior reports into.
@@ -301,24 +312,26 @@ impl Drop for AgreementHandle {
/// The BftService kicks off the agreement process on top of any blocks it
/// is notified of.
pub struct BftService<P, I> {
pub struct BftService<B: Block, P, I> {
client: Arc<I>,
live_agreement: Mutex<Option<(HeaderHash, AgreementHandle)>>,
live_agreement: Mutex<Option<(B::Hash, AgreementHandle)>>,
timer: Timer,
round_timeout_multiplier: u64,
key: Arc<ed25519::Pair>, // TODO: key changing over time.
factory: P,
}
impl<P, I> BftService<P, I>
impl<B, P, I> BftService<B, P, I>
where
P: ProposerFactory,
<P::Proposer as Proposer>::Error: ::std::fmt::Display,
I: BlockImport + Authorities,
B: Block + Clone + Eq,
B::Hash: ::std::hash::Hash,
P: ProposerFactory<B>,
<P::Proposer as Proposer<B>>::Error: ::std::fmt::Display,
I: BlockImport<B> + Authorities<B>,
{
/// Create a new service instance.
pub fn new(client: Arc<I>, key: Arc<ed25519::Pair>, factory: P) -> BftService<P, I> {
pub fn new(client: Arc<I>, key: Arc<ed25519::Pair>, factory: P) -> BftService<B, P, I> {
BftService {
client: client,
live_agreement: Mutex::new(None),
@@ -340,17 +353,17 @@ impl<P, I> BftService<P, I>
/// If the local signing key is an authority, this will begin the consensus process to build a
/// block on top of it. If the executor fails to run the future, an error will be returned.
/// Returns `None` if the agreement on the block with given parent is already in progress.
pub fn build_upon<InStream, OutSink>(&self, header: &Header, input: InStream, output: OutSink)
-> Result<Option<BftFuture<<P as ProposerFactory>::Proposer, I, InStream, OutSink>>, P::Error> where
InStream: Stream<Item=Communication, Error=<<P as ProposerFactory>::Proposer as Proposer>::Error>,
OutSink: Sink<SinkItem=Communication, SinkError=<<P as ProposerFactory>::Proposer as Proposer>::Error>,
pub fn build_upon<InStream, OutSink>(&self, header: &B::Header, input: InStream, output: OutSink)
-> Result<Option<BftFuture<B, <P as ProposerFactory<B>>::Proposer, I, InStream, OutSink>>, P::Error> where
InStream: Stream<Item=Communication<B>, Error=<<P as ProposerFactory<B>>::Proposer as Proposer<B>>::Error>,
OutSink: Sink<SinkItem=Communication<B>, SinkError=<<P as ProposerFactory<B>>::Proposer as Proposer<B>>::Error>,
{
let hash = header.blake2_256().into();
if self.live_agreement.lock().as_ref().map_or(false, |&(h, _)| h == hash) {
let hash = header.hash();
if self.live_agreement.lock().as_ref().map_or(false, |&(ref h, _)| h == &hash) {
return Ok(None);
}
let authorities = self.client.authorities(&BlockId::Hash(hash))?;
let authorities = self.client.authorities(&BlockId::Hash(hash.clone()))?;
let n = authorities.len();
let max_faulty = max_faulty_of(n);
@@ -368,7 +381,7 @@ impl<P, I> BftService<P, I>
let bft_instance = BftInstance {
proposer,
parent_hash: hash,
parent_hash: hash.clone(),
round_timeout_multiplier: self.round_timeout_multiplier,
timer: self.timer.clone(),
key: self.key.clone(),
@@ -409,8 +422,8 @@ impl<P, I> BftService<P, I>
}
/// Get current agreement parent hash if any.
pub fn live_agreement(&self) -> Option<HeaderHash> {
self.live_agreement.lock().as_ref().map(|&(h, _)| h.clone())
pub fn live_agreement(&self) -> Option<B::Hash> {
self.live_agreement.lock().as_ref().map(|&(ref h, _)| h.clone())
}
}
@@ -427,8 +440,8 @@ pub fn bft_threshold(n: usize) -> usize {
n - max_faulty_of(n)
}
fn check_justification_signed_message(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification)
-> Result<Justification, UncheckedJustification>
fn check_justification_signed_message<H>(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification<H>)
-> Result<Justification<H>, UncheckedJustification<H>>
{
// TODO: return additional error information.
just.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| {
@@ -447,12 +460,12 @@ fn check_justification_signed_message(authorities: &[AuthorityId], message: &[u8
/// Provide all valid authorities.
///
/// On failure, returns the justification back.
pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification)
-> Result<Justification, UncheckedJustification>
pub fn check_justification<B: Block>(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification<B::Hash>)
-> Result<Justification<B::Hash>, UncheckedJustification<B::Hash>>
{
let message = Slicable::encode(&PrimitiveMessage {
let message = Slicable::encode(&PrimitiveMessage::<B, _> {
parent,
action: PrimitiveAction::Commit(just.round_number as u32, just.digest),
action: PrimitiveAction::Commit(just.round_number as u32, just.digest.clone()),
});
check_justification_signed_message(authorities, &message[..], just)
@@ -462,12 +475,12 @@ pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just
/// Provide all valid authorities.
///
/// On failure, returns the justification back.
pub fn check_prepare_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification)
-> Result<PrepareJustification, UncheckedJustification>
pub fn check_prepare_justification<B: Block>(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification<B::Hash>)
-> Result<PrepareJustification<B::Hash>, UncheckedJustification<B::Hash>>
{
let message = Slicable::encode(&PrimitiveMessage {
let message = Slicable::encode(&PrimitiveMessage::<B, _> {
parent,
action: PrimitiveAction::Prepare(just.round_number as u32, just.digest),
action: PrimitiveAction::Prepare(just.round_number as u32, just.digest.clone()),
});
check_justification_signed_message(authorities, &message[..], just)
@@ -475,10 +488,10 @@ pub fn check_prepare_justification(authorities: &[AuthorityId], parent: HeaderHa
/// Check proposal message signatures and authority.
/// Provide all valid authorities.
pub fn check_proposal(
pub fn check_proposal<B: Block + Clone>(
authorities: &[AuthorityId],
parent_hash: &HeaderHash,
propose: &::generic::LocalizedProposal<Block, HeaderHash, AuthorityId, LocalizedSignature>)
parent_hash: &B::Hash,
propose: &::generic::LocalizedProposal<B, B::Hash, AuthorityId, LocalizedSignature>)
-> Result<(), Error>
{
if !authorities.contains(&propose.sender) {
@@ -487,16 +500,16 @@ pub fn check_proposal(
let action_header = PrimitiveAction::ProposeHeader(propose.round_number as u32, propose.digest.clone());
let action_propose = PrimitiveAction::Propose(propose.round_number as u32, propose.proposal.clone());
check_action(action_header, parent_hash, &propose.digest_signature)?;
check_action(action_propose, parent_hash, &propose.full_signature)
check_action::<B>(action_header, parent_hash, &propose.digest_signature)?;
check_action::<B>(action_propose, parent_hash, &propose.full_signature)
}
/// Check vote message signatures and authority.
/// Provide all valid authorities.
pub fn check_vote(
pub fn check_vote<B: Block>(
authorities: &[AuthorityId],
parent_hash: &HeaderHash,
vote: &::generic::LocalizedVote<HeaderHash, AuthorityId, LocalizedSignature>)
parent_hash: &B::Hash,
vote: &::generic::LocalizedVote<B::Hash, AuthorityId, LocalizedSignature>)
-> Result<(), Error>
{
if !authorities.contains(&vote.sender) {
@@ -504,14 +517,14 @@ pub fn check_vote(
}
let action = match vote.vote {
::generic::Vote::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
::generic::Vote::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()),
::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()),
::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
};
check_action(action, parent_hash, &vote.signature)
check_action::<B>(action, parent_hash, &vote.signature)
}
fn check_action(action: PrimitiveAction, parent_hash: &HeaderHash, sig: &LocalizedSignature) -> Result<(), Error> {
fn check_action<B: Block>(action: PrimitiveAction<B, B::Hash>, parent_hash: &B::Hash, sig: &LocalizedSignature) -> Result<(), Error> {
let primitive = PrimitiveMessage {
parent: parent_hash.clone(),
action,
@@ -526,12 +539,12 @@ fn check_action(action: PrimitiveAction, parent_hash: &HeaderHash, sig: &Localiz
}
/// Sign a BFT message with the given key.
pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHash) -> LocalizedMessage {
pub fn sign_message<B: Block + Clone>(message: Message<B>, key: &ed25519::Pair, parent_hash: B::Hash) -> LocalizedMessage<B> {
let signer = key.public();
let sign_action = |action| {
let sign_action = |action: PrimitiveAction<B, B::Hash>| {
let primitive = PrimitiveMessage {
parent: parent_hash,
parent: parent_hash.clone(),
action,
};
@@ -544,7 +557,7 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
match message {
::generic::Message::Propose(r, proposal) => {
let header_hash: HeaderHash = proposal.header.blake2_256().into();
let header_hash = proposal.hash();
let action_header = PrimitiveAction::ProposeHeader(r as u32, header_hash.clone());
let action_propose = PrimitiveAction::Propose(r as u32, proposal.clone());
@@ -559,8 +572,8 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
}
::generic::Message::Vote(vote) => {
let action = match vote {
::generic::Vote::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
::generic::Vote::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()),
::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()),
::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
};
@@ -577,7 +590,8 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
mod tests {
use super::*;
use std::collections::HashSet;
use primitives::block;
use runtime_primitives::testing::{Block as GenericTestBlock, Header as TestHeader};
use primitives::H256;
use self::tokio_core::reactor::{Core};
use self::keyring::Keyring;
use futures::stream;
@@ -586,19 +600,21 @@ mod tests {
extern crate substrate_keyring as keyring;
extern crate tokio_core;
type TestBlock = GenericTestBlock<()>;
struct FakeClient {
authorities: Vec<AuthorityId>,
imported_heights: Mutex<HashSet<block::Number>>
imported_heights: Mutex<HashSet<u64>>
}
impl BlockImport for FakeClient {
fn import_block(&self, block: Block, _justification: Justification) {
impl BlockImport<TestBlock> for FakeClient {
fn import_block(&self, block: TestBlock, _justification: Justification<H256>) {
assert!(self.imported_heights.lock().insert(block.header.number))
}
}
impl Authorities for FakeClient {
fn authorities(&self, _at: &BlockId) -> Result<Vec<AuthorityId>, Error> {
impl Authorities<TestBlock> for FakeClient {
fn authorities(&self, _at: &BlockId<TestBlock>) -> Result<Vec<AuthorityId>, Error> {
Ok(self.authorities.clone())
}
}
@@ -607,10 +623,10 @@ mod tests {
struct Output<E>(::std::marker::PhantomData<E>);
impl<E> Sink for Output<E> {
type SinkItem = Communication;
type SinkItem = Communication<TestBlock>;
type SinkError = E;
fn start_send(&mut self, _item: Communication) -> ::futures::StartSend<Communication, E> {
fn start_send(&mut self, _item: Communication<TestBlock>) -> ::futures::StartSend<Communication<TestBlock>, E> {
Ok(::futures::AsyncSink::Ready)
}
@@ -620,34 +636,35 @@ mod tests {
}
struct DummyFactory;
struct DummyProposer(block::Number);
struct DummyProposer(u64);
impl ProposerFactory for DummyFactory {
impl ProposerFactory<TestBlock> for DummyFactory {
type Proposer = DummyProposer;
type Error = Error;
fn init(&self, parent_header: &Header, _authorities: &[AuthorityId], _sign_with: Arc<ed25519::Pair>) -> Result<DummyProposer, Error> {
fn init(&self, parent_header: &TestHeader, _authorities: &[AuthorityId], _sign_with: Arc<ed25519::Pair>) -> Result<DummyProposer, Error> {
Ok(DummyProposer(parent_header.number + 1))
}
}
impl Proposer for DummyProposer {
impl Proposer<TestBlock> for DummyProposer {
type Error = Error;
type Create = Result<Block, Error>;
type Create = Result<TestBlock, Error>;
type Evaluate = Result<bool, Error>;
fn propose(&self) -> Result<Block, Error> {
Ok(Block {
header: Header::from_block_number(self.0),
transactions: Default::default()
fn propose(&self) -> Result<TestBlock, Error> {
Ok(TestBlock {
header: from_block_number(self.0),
extrinsics: Default::default()
})
}
fn evaluate(&self, proposal: &Block) -> Result<bool, Error> {
fn evaluate(&self, proposal: &TestBlock) -> Result<bool, Error> {
Ok(proposal.header.number == self.0)
}
fn import_misbehavior(&self, _misbehavior: Vec<(AuthorityId, Misbehavior)>) {}
fn import_misbehavior(&self, _misbehavior: Vec<(AuthorityId, Misbehavior<H256>)>) {}
fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId {
authorities[round_number % authorities.len()].clone()
@@ -655,7 +672,7 @@ mod tests {
}
fn make_service(client: FakeClient)
-> BftService<DummyFactory, FakeClient>
-> BftService<TestBlock, DummyFactory, FakeClient>
{
BftService {
client: Arc::new(client),
@@ -667,13 +684,23 @@ mod tests {
}
}
fn sign_vote(vote: ::generic::Vote<HeaderHash>, key: &ed25519::Pair, parent_hash: HeaderHash) -> LocalizedSignature {
match sign_message(vote.into(), key, parent_hash) {
fn sign_vote(vote: ::generic::Vote<H256>, key: &ed25519::Pair, parent_hash: H256) -> LocalizedSignature {
match sign_message::<TestBlock>(vote.into(), key, parent_hash) {
::generic::LocalizedMessage::Vote(vote) => vote.signature,
_ => panic!("signing vote leads to signed vote"),
}
}
fn from_block_number(num: u64) -> TestHeader {
TestHeader::new(
num,
Default::default(),
Default::default(),
Default::default(),
Default::default(),
)
}
#[test]
fn future_gets_preempted() {
let client = FakeClient {
@@ -690,12 +717,12 @@ mod tests {
let service = make_service(client);
let first = Header::from_block_number(2);
let first_hash = first.blake2_256().into();
let first = from_block_number(2);
let first_hash = first.hash();
let mut second = Header::from_block_number(3);
let mut second = from_block_number(3);
second.parent_hash = first_hash;
let second_hash = second.blake2_256().into();
let second_hash = second.hash();
let bft = service.build_upon(&first, stream::empty(), Output(Default::default())).unwrap();
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash);
@@ -749,7 +776,7 @@ mod tests {
}).collect(),
};
assert!(check_justification(&authorities, parent_hash, unchecked).is_ok());
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_ok());
let unchecked = UncheckedJustification {
digest: hash,
@@ -759,7 +786,7 @@ mod tests {
}).collect(),
};
assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
// not enough signatures.
let unchecked = UncheckedJustification {
@@ -770,7 +797,7 @@ mod tests {
}).collect(),
};
assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
// wrong hash.
let unchecked = UncheckedJustification {
@@ -781,7 +808,7 @@ mod tests {
}).collect(),
};
assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
}
#[test]
@@ -793,9 +820,9 @@ mod tests {
Keyring::Eve.to_raw_public(),
];
let block = Block {
header: Header::from_block_number(1),
transactions: Default::default()
let block = TestBlock {
header: from_block_number(1),
extrinsics: Default::default()
};
let proposal = sign_message(::generic::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);;
@@ -812,7 +839,7 @@ mod tests {
}
// Not an authority
let proposal = sign_message(::generic::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);;
let proposal = sign_message::<TestBlock>(::generic::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);;
if let ::generic::LocalizedMessage::Propose(proposal) = proposal {
assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err());
} else {
@@ -822,28 +849,28 @@ mod tests {
#[test]
fn vote_check_works() {
let parent_hash = Default::default();
let hash = [0xff; 32].into();
let parent_hash: H256 = Default::default();
let hash: H256 = [0xff; 32].into();
let authorities = vec![
Keyring::Alice.to_raw_public(),
Keyring::Eve.to_raw_public(),
];
let vote = sign_message(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);;
let vote = sign_message::<TestBlock>(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);;
if let ::generic::LocalizedMessage::Vote(vote) = vote {
assert!(check_vote(&authorities, &parent_hash, &vote).is_ok());
assert!(check_vote::<TestBlock>(&authorities, &parent_hash, &vote).is_ok());
let mut invalid_sender = vote.clone();
invalid_sender.signature.signer = Keyring::Eve.into();
assert!(check_vote(&authorities, &parent_hash, &invalid_sender).is_err());
assert!(check_vote::<TestBlock>(&authorities, &parent_hash, &invalid_sender).is_err());
} else {
assert!(false);
}
// Not an authority
let vote = sign_message(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);;
let vote = sign_message::<TestBlock>(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);;
if let ::generic::LocalizedMessage::Vote(vote) = vote {
assert!(check_vote(&authorities, &parent_hash, &vote).is_err());
assert!(check_vote::<TestBlock>(&authorities, &parent_hash, &vote).is_err());
} else {
assert!(false);
}
+1
View File
@@ -17,6 +17,7 @@ substrate-executor = { path = "../executor" }
substrate-primitives = { path = "../primitives" }
substrate-runtime-io = { path = "../runtime-io" }
substrate-runtime-support = { path = "../runtime-support" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
substrate-state-machine = { path = "../state-machine" }
substrate-keyring = { path = "../../substrate/keyring" }
+1
View File
@@ -13,6 +13,7 @@ hashdb = { git = "https://github.com/paritytech/parity.git" }
patricia-trie = { git = "https://github.com/paritytech/parity.git" }
memorydb = { git = "https://github.com/paritytech/parity.git" }
substrate-primitives = { path = "../../../substrate/primitives" }
substrate-runtime-primitives = { path = "../../../substrate/runtime/primitives" }
substrate-client = { path = "../../../substrate/client" }
substrate-state-machine = { path = "../../../substrate/state-machine" }
substrate-runtime-support = { path = "../../../substrate/runtime-support" }
+90 -74
View File
@@ -27,6 +27,7 @@ extern crate patricia_trie;
extern crate substrate_state_machine as state_machine;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_codec as codec;
#[macro_use]
@@ -47,9 +48,9 @@ use kvdb::{KeyValueDB, DBTransaction};
use memorydb::MemoryDB;
use parking_lot::RwLock;
use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut};
use primitives::blake2_256;
use primitives::block::{self, Id as BlockId, HeaderHash};
use runtime_support::Hashable;
use runtime_primitives::generic::BlockId;
use runtime_primitives::bft::Justification;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, Hashing, HashingFor, Zero};
use state_machine::backend::Backend as StateBackend;
use state_machine::CodeExecutor;
@@ -62,14 +63,17 @@ pub struct DatabaseSettings {
}
/// Create an instance of db-backed client.
pub fn new_client<E, F>(
pub fn new_client<E, F, Block>(
settings: DatabaseSettings,
executor: E,
genesis_builder: F,
) -> Result<client::Client<Backend, client::LocalCallExecutor<Backend, E>>, client::error::Error>
) -> Result<client::Client<Backend<Block>, client::LocalCallExecutor<Backend<Block>, E>, Block>, client::error::Error>
where
Block: BlockT,
<Block::Header as HeaderT>::Number: As<u32>,
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
E: CodeExecutor,
F: client::GenesisBuilder,
F: client::GenesisBuilder<Block>,
{
let backend = Arc::new(Backend::new(&settings)?);
let executor = client::LocalCallExecutor::new(backend.clone(), executor);
@@ -90,24 +94,26 @@ mod meta {
pub const BEST_BLOCK: &[u8; 4] = b"best";
}
struct PendingBlock {
header: block::Header,
justification: Option<primitives::bft::Justification>,
body: Option<block::Body>,
struct PendingBlock<Block: BlockT> {
header: Block::Header,
justification: Option<Justification<Block::Hash>>,
body: Option<Vec<Block::Extrinsic>>,
is_best: bool,
}
#[derive(Clone)]
struct Meta {
best_hash: HeaderHash,
best_number: block::Number,
genesis_hash: HeaderHash,
struct Meta<N, H> {
best_hash: H,
best_number: N,
genesis_hash: H,
}
type BlockKey = [u8; 4];
// Little endian
fn number_to_db_key(n: block::Number) -> BlockKey {
fn number_to_db_key<N>(n: N) -> BlockKey where N: As<u32> {
let n: u32 = n.as_();
[
(n >> 24) as u8,
((n >> 16) & 0xff) as u8,
@@ -127,13 +133,13 @@ fn db_err(err: kvdb::Error) -> client::error::Error {
}
/// Block database
pub struct BlockchainDb {
pub struct BlockchainDb<Block: BlockT> {
db: Arc<KeyValueDB>,
meta: RwLock<Meta>,
meta: RwLock<Meta<<Block::Header as HeaderT>::Number, Block::Hash>>,
}
impl BlockchainDb {
fn id(&self, id: BlockId) -> Result<Option<BlockKey>, client::error::Error> {
impl<Block: BlockT> BlockchainDb<Block> where <Block::Header as HeaderT>::Number: As<u32> {
fn id(&self, id: BlockId<Block>) -> Result<Option<BlockKey>, client::error::Error> {
match id {
BlockId::Hash(h) => {
{
@@ -142,7 +148,7 @@ impl BlockchainDb {
return Ok(Some(number_to_db_key(meta.best_number)));
}
}
self.db.get(columns::BLOCK_INDEX, &h).map(|v| v.map(|v| {
self.db.get(columns::BLOCK_INDEX, h.as_ref()).map(|v| v.map(|v| {
let mut key: [u8; 4] = [0; 4];
key.copy_from_slice(&v);
key
@@ -152,21 +158,21 @@ impl BlockchainDb {
}
}
fn new(db: Arc<KeyValueDB>) -> Result<BlockchainDb, client::error::Error> {
fn new(db: Arc<KeyValueDB>) -> Result<Self, client::error::Error> {
let (best_hash, best_number) = if let Some(Some(header)) = db.get(columns::META, meta::BEST_BLOCK).and_then(|id|
match id {
Some(id) => db.get(columns::HEADER, &id).map(|h| h.map(|b| block::Header::decode(&mut &b[..]))),
Some(id) => db.get(columns::HEADER, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]))),
None => Ok(None),
}).map_err(db_err)?
{
let hash = header.blake2_256().into();
debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number);
(hash, header.number)
let hash = header.hash();
debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number());
(hash, header.number().clone())
} else {
(Default::default(), Default::default())
(Default::default(), Zero::zero())
};
let genesis_hash = db.get(columns::HEADER, &number_to_db_key(0)).map_err(db_err)?
.map(|b| blake2_256(&b)).unwrap_or_default().into();
let genesis_hash = db.get(columns::HEADER, &number_to_db_key(<Block::Header as HeaderT>::Number::zero())).map_err(db_err)?
.map(|b| HashingFor::<Block>::hash(&b)).unwrap_or_default().into();
Ok(BlockchainDb {
db,
@@ -178,7 +184,7 @@ impl BlockchainDb {
})
}
fn read_db(&self, id: BlockId, column: Option<u32>) -> Result<Option<DBValue>, client::error::Error> {
fn read_db(&self, id: BlockId<Block>, column: Option<u32>) -> Result<Option<DBValue>, client::error::Error> {
self.id(id).and_then(|key|
match key {
Some(key) => self.db.get(column, &key).map_err(db_err),
@@ -186,10 +192,10 @@ impl BlockchainDb {
})
}
fn update_meta(&self, hash: block::HeaderHash, number: block::Number, is_best: bool) {
fn update_meta(&self, hash: Block::Hash, number: <Block::Header as HeaderT>::Number, is_best: bool) {
if is_best {
let mut meta = self.meta.write();
if number == 0 {
if number == Zero::zero() {
meta.genesis_hash = hash;
}
meta.best_number = number;
@@ -198,10 +204,10 @@ impl BlockchainDb {
}
}
impl client::blockchain::Backend for BlockchainDb {
fn header(&self, id: BlockId) -> Result<Option<block::Header>, client::error::Error> {
impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> where <Block::Header as HeaderT>::Number: As<u32> {
fn header(&self, id: BlockId<Block>) -> Result<Option<Block::Header>, client::error::Error> {
match self.read_db(id, columns::HEADER)? {
Some(header) => match block::Header::decode(&mut &header[..]) {
Some(header) => match Block::Header::decode(&mut &header[..]) {
Some(header) => Ok(Some(header)),
None => return Err(client::error::ErrorKind::Backend("Error decoding header".into()).into()),
}
@@ -209,9 +215,9 @@ impl client::blockchain::Backend for BlockchainDb {
}
}
fn body(&self, id: BlockId) -> Result<Option<block::Body>, client::error::Error> {
fn body(&self, id: BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, client::error::Error> {
match self.read_db(id, columns::BODY)? {
Some(body) => match block::Body::decode(&mut &body[..]) {
Some(body) => match Slicable::decode(&mut &body[..]) {
Some(body) => Ok(Some(body)),
None => return Err(client::error::ErrorKind::Backend("Error decoding body".into()).into()),
}
@@ -219,9 +225,9 @@ impl client::blockchain::Backend for BlockchainDb {
}
}
fn justification(&self, id: BlockId) -> Result<Option<primitives::bft::Justification>, client::error::Error> {
fn justification(&self, id: BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, client::error::Error> {
match self.read_db(id, columns::JUSTIFICATION)? {
Some(justification) => match primitives::bft::Justification::decode(&mut &justification[..]) {
Some(justification) => match Slicable::decode(&mut &justification[..]) {
Some(justification) => Ok(Some(justification)),
None => return Err(client::error::ErrorKind::Backend("Error decoding justification".into()).into()),
}
@@ -229,7 +235,7 @@ impl client::blockchain::Backend for BlockchainDb {
}
}
fn info(&self) -> Result<client::blockchain::Info, client::error::Error> {
fn info(&self) -> Result<client::blockchain::Info<Block>, client::error::Error> {
let meta = self.meta.read();
Ok(client::blockchain::Info {
best_hash: meta.best_hash,
@@ -238,7 +244,7 @@ impl client::blockchain::Backend for BlockchainDb {
})
}
fn status(&self, id: BlockId) -> Result<client::blockchain::BlockStatus, client::error::Error> {
fn status(&self, id: BlockId<Block>) -> Result<client::blockchain::BlockStatus, client::error::Error> {
let exists = match id {
BlockId::Hash(_) => self.id(id)?.is_some(),
BlockId::Number(n) => n <= self.meta.read().best_number,
@@ -249,28 +255,28 @@ impl client::blockchain::Backend for BlockchainDb {
}
}
fn hash(&self, number: block::Number) -> Result<Option<block::HeaderHash>, client::error::Error> {
fn hash(&self, number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, client::error::Error> {
self.read_db(BlockId::Number(number), columns::HEADER).map(|x|
x.map(|raw| blake2_256(&raw[..])).map(Into::into)
x.map(|raw| HashingFor::<Block>::hash(&raw[..])).map(Into::into)
)
}
}
/// Database transaction
pub struct BlockImportOperation {
pub struct BlockImportOperation<Block: BlockT> {
old_state: DbState,
updates: MemoryDB,
pending_block: Option<PendingBlock>,
pending_block: Option<PendingBlock<Block>>,
}
impl client::backend::BlockImportOperation for BlockImportOperation {
impl<Block: BlockT> client::backend::BlockImportOperation<Block> for BlockImportOperation<Block> {
type State = DbState;
fn state(&self) -> Result<Option<&Self::State>, client::error::Error> {
Ok(Some(&self.old_state))
}
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_best: bool) -> Result<(), client::error::Error> {
fn set_block_data(&mut self, header: Block::Header, body: Option<Vec<Block::Extrinsic>>, justification: Option<Justification<Block::Hash>>, is_best: bool) -> Result<(), client::error::Error> {
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
self.pending_block = Some(PendingBlock {
header,
@@ -423,15 +429,15 @@ impl state_machine::Backend for DbState {
/// Disk backend. Keeps data in a key-value store. In archive mode, trie nodes are kept from all blocks.
/// Otherwise, trie nodes are kept only from the most recent block.
pub struct Backend {
pub struct Backend<Block: BlockT> {
db: Arc<KeyValueDB>,
blockchain: BlockchainDb,
blockchain: BlockchainDb<Block>,
archive: bool,
}
impl Backend {
impl<Block: BlockT> Backend<Block> where <Block::Header as HeaderT>::Number: As<u32> {
/// Create a new instance of database backend.
pub fn new(config: &DatabaseSettings) -> Result<Backend, client::error::Error> {
pub fn new(config: &DatabaseSettings) -> Result<Self, client::error::Error> {
let mut db_config = DatabaseConfig::with_columns(Some(columns::NUM_COLUMNS));
db_config.memory_budget = config.cache_size;
db_config.wal = true;
@@ -442,13 +448,13 @@ impl Backend {
}
#[cfg(test)]
fn new_test() -> Backend {
fn new_test() -> Self {
let db = Arc::new(::kvdb_memorydb::create(columns::NUM_COLUMNS));
Backend::from_kvdb(db as Arc<_>, false).expect("failed to create test-db")
}
fn from_kvdb(db: Arc<KeyValueDB>, archive: bool) -> Result<Backend, client::error::Error> {
fn from_kvdb(db: Arc<KeyValueDB>, archive: bool) -> Result<Self, client::error::Error> {
let blockchain = BlockchainDb::new(db.clone())?;
Ok(Backend {
@@ -459,12 +465,15 @@ impl Backend {
}
}
impl client::backend::Backend for Backend {
type BlockImportOperation = BlockImportOperation;
type Blockchain = BlockchainDb;
impl<Block: BlockT> client::backend::Backend<Block> for Backend<Block> where
<Block::Header as HeaderT>::Number: As<u32>,
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
{
type BlockImportOperation = BlockImportOperation<Block>;
type Blockchain = BlockchainDb<Block>;
type State = DbState;
fn begin_operation(&self, block: BlockId) -> Result<Self::BlockImportOperation, client::error::Error> {
fn begin_operation(&self, block: BlockId<Block>) -> Result<Self::BlockImportOperation, client::error::Error> {
let state = self.state_at(block)?;
Ok(BlockImportOperation {
pending_block: None,
@@ -476,9 +485,9 @@ impl client::backend::Backend for Backend {
fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> Result<(), client::error::Error> {
let mut transaction = DBTransaction::new();
if let Some(pending_block) = operation.pending_block {
let hash: block::HeaderHash = pending_block.header.blake2_256().into();
let number = pending_block.header.number;;
let key = number_to_db_key(pending_block.header.number);
let hash = pending_block.header.hash();
let number = pending_block.header.number().clone();
let key = number_to_db_key(pending_block.header.number().clone());
transaction.put(columns::HEADER, &key, &pending_block.header.encode());
if let Some(body) = pending_block.body {
transaction.put(columns::BODY, &key, &body.encode());
@@ -486,7 +495,7 @@ impl client::backend::Backend for Backend {
if let Some(justification) = pending_block.justification {
transaction.put(columns::JUSTIFICATION, &key, &justification.encode());
}
transaction.put(columns::BLOCK_INDEX, &hash, &key);
transaction.put(columns::BLOCK_INDEX, hash.as_ref(), &key);
if pending_block.is_best {
transaction.put(columns::META, meta::BEST_BLOCK, &key);
}
@@ -504,11 +513,11 @@ impl client::backend::Backend for Backend {
Ok(())
}
fn blockchain(&self) -> &BlockchainDb {
fn blockchain(&self) -> &BlockchainDb<Block> {
&self.blockchain
}
fn state_at(&self, block: BlockId) -> Result<Self::State, client::error::Error> {
fn state_at(&self, block: BlockId<Block>) -> Result<Self::State, client::error::Error> {
use client::blockchain::Backend as BcBackend;
// special case for genesis initialization
@@ -527,15 +536,19 @@ impl client::backend::Backend for Backend {
}
self.blockchain.header(block).and_then(|maybe_hdr| maybe_hdr.map(|hdr| {
let root: [u8; 32] = hdr.state_root().clone().into();
DbState {
db: self.db.clone(),
root: hdr.state_root.0.into(),
root: root.into(),
}
}).ok_or_else(|| client::error::ErrorKind::UnknownBlock(block).into()))
}).ok_or_else(|| client::error::ErrorKind::UnknownBlock(format!("{:?}", block)).into()))
}
}
impl client::backend::LocalBackend for Backend {}
impl<Block: BlockT> client::backend::LocalBackend<Block> for Backend<Block> where
<Block::Header as HeaderT>::Number: As<u32>,
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
{}
#[cfg(test)]
mod tests {
@@ -543,10 +556,13 @@ mod tests {
use client::backend::Backend as BTrait;
use client::backend::BlockImportOperation as Op;
use client::blockchain::Backend as BCTrait;
use runtime_primitives::testing::{Header, Block as RawBlock};
type Block = RawBlock<u64>;
#[test]
fn block_hash_inserted_correctly() {
let db = Backend::new_test();
let db = Backend::<Block>::new_test();
for i in 0..10 {
assert!(db.blockchain().hash(i).unwrap().is_none());
@@ -558,7 +574,7 @@ mod tests {
};
let mut op = db.begin_operation(id).unwrap();
let header = block::Header {
let header = Header {
number: i,
parent_hash: Default::default(),
state_root: Default::default(),
@@ -581,10 +597,10 @@ mod tests {
#[test]
fn set_state_data() {
let db = Backend::new_test();
let db = Backend::<Block>::new_test();
{
let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
let mut header = block::Header {
let mut header = Header {
number: 0,
parent_hash: Default::default(),
state_root: Default::default(),
@@ -623,7 +639,7 @@ mod tests {
{
let mut op = db.begin_operation(BlockId::Number(0)).unwrap();
let mut header = block::Header {
let mut header = Header {
number: 1,
parent_hash: Default::default(),
state_root: Default::default(),
@@ -660,11 +676,11 @@ mod tests {
#[test]
fn delete_only_when_negative_rc() {
let key;
let db = Backend::new_test();
let db = Backend::<Block>::new_test();
{
let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
let mut header = block::Header {
let mut header = Header {
number: 0,
parent_hash: Default::default(),
state_root: Default::default(),
@@ -697,7 +713,7 @@ mod tests {
{
let mut op = db.begin_operation(BlockId::Number(0)).unwrap();
let mut header = block::Header {
let mut header = Header {
number: 1,
parent_hash: Default::default(),
state_root: Default::default(),
@@ -729,7 +745,7 @@ mod tests {
{
let mut op = db.begin_operation(BlockId::Number(1)).unwrap();
let mut header = block::Header {
let mut header = Header {
number: 1,
parent_hash: Default::default(),
state_root: Default::default(),
+19 -11
View File
@@ -18,18 +18,26 @@
use state_machine::backend::Backend as StateBackend;
use error;
use primitives::block::{self, Id as BlockId};
use primitives;
use runtime_primitives::bft::Justification;
use runtime_primitives::traits::Block as BlockT;
use runtime_primitives::generic::BlockId;
/// Block insertion operation. Keeps hold if the inserted block state and data.
pub trait BlockImportOperation {
pub trait BlockImportOperation<Block: BlockT> {
/// Associated state backend type.
type State: StateBackend;
/// Returns pending state. Returns None for backends with locally-unavailable state data.
fn state(&self) -> error::Result<Option<&Self::State>>;
/// Append block data to the transaction.
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()>;
fn set_block_data(
&mut self,
header: Block::Header,
body: Option<Vec<Block::Extrinsic>>,
justification: Option<Justification<Block::Hash>>,
is_new_best: bool
) -> error::Result<()>;
/// Inject storage data into the database.
fn update_storage(&mut self, update: <Self::State as StateBackend>::Transaction) -> error::Result<()>;
/// Inject storage data into the database replacing any existing data.
@@ -44,27 +52,27 @@ pub trait BlockImportOperation {
///
/// The same applies for live `BlockImportOperation`s: while an import operation building on a parent `P`
/// is alive, the state for `P` should not be pruned.
pub trait Backend: Send + Sync {
pub trait Backend<Block: BlockT>: Send + Sync {
/// Associated block insertion operation type.
type BlockImportOperation: BlockImportOperation;
type BlockImportOperation: BlockImportOperation<Block>;
/// Associated blockchain backend type.
type Blockchain: ::blockchain::Backend;
type Blockchain: ::blockchain::Backend<Block>;
/// Associated state backend type.
type State: StateBackend;
/// Begin a new block insertion transaction with given parent block id.
/// When constructing the genesis, this is called with all-zero hash.
fn begin_operation(&self, block: BlockId) -> error::Result<Self::BlockImportOperation>;
fn begin_operation(&self, block: BlockId<Block>) -> error::Result<Self::BlockImportOperation>;
/// Commit block insertion.
fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>;
/// Returns reference to blockchain backend.
fn blockchain(&self) -> &Self::Blockchain;
/// Returns state backend with post-state of given block.
fn state_at(&self, block: BlockId) -> error::Result<Self::State>;
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State>;
}
/// Mark for all Backend implementations, that are making use of state data, stored locally.
pub trait LocalBackend: Backend {}
pub trait LocalBackend<Block: BlockT>: Backend<Block> {}
/// Mark for all Backend implementations, that are fetching required state data from remote nodes.
pub trait RemoteBackend: Backend {}
pub trait RemoteBackend<Block: BlockT>: Backend<Block> {}
+67 -46
View File
@@ -17,80 +17,101 @@
//! Utility struct to build a block.
use std::vec::Vec;
use codec::{Joiner, Slicable};
use codec::Slicable;
use state_machine;
use primitives::{Header, Block};
use primitives::block::{Id as BlockId, Extrinsic};
use runtime_primitives::traits::{Header as HeaderT, Hashing as HashingT, Block as BlockT, One, HashingFor};
use runtime_primitives::generic::BlockId;
use {backend, error, Client, CallExecutor};
use triehash::ordered_trie_root;
/// Utility for building new (valid) blocks from a stream of transactions.
pub struct BlockBuilder<B, E> where
B: backend::Backend,
E: CallExecutor + Clone,
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
/// Utility for building new (valid) blocks from a stream of extrinsics.
pub struct BlockBuilder<B, E, Block> where
B: backend::Backend<Block>,
E: CallExecutor<Block> + Clone,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
{
header: Header,
transactions: Vec<Extrinsic>,
header: <Block as BlockT>::Header,
extrinsics: Vec<<Block as BlockT>::Extrinsic>,
executor: E,
state: B::State,
changes: state_machine::OverlayedChanges,
}
impl<B, E> BlockBuilder<B, E> where
B: backend::Backend,
E: CallExecutor + Clone,
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
impl<B, E, Block> BlockBuilder<B, E, Block> where
B: backend::Backend<Block>,
E: CallExecutor<Block> + Clone,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
{
/// Create a new instance of builder from the given client, building on the latest block.
pub fn new(client: &Client<B, E>) -> error::Result<Self> {
pub fn new(client: &Client<B, E, Block>) -> error::Result<Self> {
client.info().and_then(|i| Self::at_block(&BlockId::Hash(i.chain.best_hash), client))
}
/// Create a new instance of builder from the given client using a particular block's ID to
/// build upon.
pub fn at_block(block_id: &BlockId, client: &Client<B, E>) -> error::Result<Self> {
pub fn at_block(block_id: &BlockId<Block>, client: &Client<B, E, Block>) -> error::Result<Self> {
let number = client.block_number_from_id(block_id)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?
+ One::one();
let parent_hash = client.block_hash_from_id(block_id)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?;
let executor = client.executor().clone();
let state = client.state_at(block_id)?;
let mut changes = Default::default();
let header = <<Block as BlockT>::Header as HeaderT>::new(
number,
Default::default(),
Default::default(),
parent_hash,
Default::default()
);
executor.call_at_state(&state, &mut changes, "initialise_block", &header.encode())?;
Ok(BlockBuilder {
header: Header {
number: client.block_number_from_id(block_id)?.ok_or(error::ErrorKind::UnknownBlock(*block_id))? + 1,
parent_hash: client.block_hash_from_id(block_id)?.ok_or(error::ErrorKind::UnknownBlock(*block_id))?,
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
},
transactions: Default::default(),
executor: client.executor().clone(),
state: client.state_at(block_id)?,
changes: Default::default(),
header,
extrinsics: Vec::new(),
executor,
state,
changes,
})
}
/// Push a transaction onto the block's list of transactions. This will ensure the transaction
/// Push onto the block's list of extrinsics. This will ensure the extrinsic
/// can be validly executed (by executing it); if it is invalid, it'll be returned along with
/// the error. Otherwise, it will return a mutable reference to self (in order to chain).
pub fn push(&mut self, tx: Extrinsic) -> error::Result<()> {
let (output, _) = self.executor.call_at_state(
&self.state,
&mut self.changes,
"execute_transaction",
&vec![].and(&self.header).and(&tx))?;
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime so must be valid");
self.transactions.push(tx);
Ok(())
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> error::Result<()> {
match self.executor.call_at_state(&self.state, &mut self.changes, "apply_extrinsic", &xt.encode()) {
Ok(_) => {
self.extrinsics.push(xt);
Ok(())
}
Err(e) => {
self.changes.discard_prospective();
Err(e)
}
}
}
/// Consume the builder to return a valid `Block` containing all pushed transactions.
/// Consume the builder to return a valid `Block` containing all pushed extrinsics.
pub fn bake(mut self) -> error::Result<Block> {
self.header.extrinsics_root = ordered_trie_root(self.transactions.iter().map(Slicable::encode)).0.into();
let (output, _) = self.executor.call_at_state(
&self.state,
&mut self.changes,
"finalise_block",
&self.header.encode())?;
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime so must be valid");
Ok(Block {
header: self.header,
transactions: self.transactions,
})
&[],
)?;
self.header = <<Block as BlockT>::Header as Slicable>::decode(&mut &output[..])
.expect("Header came straight out of runtime so must be valid");
debug_assert_eq!(
self.header.extrinsics_root().clone(),
HashingFor::<Block>::ordered_trie_root(self.extrinsics.iter().map(Slicable::encode)),
);
Ok(<Block as BlockT>::new(self.header, self.extrinsics))
}
}
+15 -13
View File
@@ -16,24 +16,26 @@
//! Polkadot blockchain trait
use primitives::block::{self, Id as BlockId};
use primitives;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
use runtime_primitives::bft::Justification;
use error::Result;
/// Blockchain database backend. Does not perform any validation.
pub trait Backend: Send + Sync {
pub trait Backend<Block: BlockT>: Send + Sync {
/// Get block header. Returns `None` if block is not found.
fn header(&self, id: BlockId) -> Result<Option<block::Header>>;
fn header(&self, id: BlockId<Block>) -> Result<Option<<Block as BlockT>::Header>>;
/// Get block body. Returns `None` if block is not found.
fn body(&self, id: BlockId) -> Result<Option<block::Body>>;
fn body(&self, id: BlockId<Block>) -> Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
/// Get block justification. Returns `None` if justification does not exist.
fn justification(&self, id: BlockId) -> Result<Option<primitives::bft::Justification>>;
fn justification(&self, id: BlockId<Block>) -> Result<Option<Justification<Block::Hash>>>;
/// Get blockchain info.
fn info(&self) -> Result<Info>;
fn info(&self) -> Result<Info<Block>>;
/// Get block status.
fn status(&self, id: BlockId) -> Result<BlockStatus>;
fn status(&self, id: BlockId<Block>) -> Result<BlockStatus>;
/// Get block hash by number. Returns `None` if the header is not in the chain.
fn hash(&self, number: block::Number) -> Result<Option<block::HeaderHash>>;
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> Result<Option<<<Block as BlockT>::Header as HeaderT>::Hash>>;
}
/// Block import outcome
@@ -50,13 +52,13 @@ pub enum ImportResult<E> {
/// Blockchain info
#[derive(Debug)]
pub struct Info {
pub struct Info<Block: BlockT> {
/// Best block hash.
pub best_hash: block::HeaderHash,
pub best_hash: <<Block as BlockT>::Header as HeaderT>::Hash,
/// Best block number.
pub best_number: block::Number,
pub best_number: <<Block as BlockT>::Header as HeaderT>::Number,
/// Genesis block hash.
pub genesis_hash: block::HeaderHash,
pub genesis_hash: <<Block as BlockT>::Header as HeaderT>::Hash,
}
/// Block status.
+26 -21
View File
@@ -16,10 +16,10 @@
use std::sync::Arc;
use futures::{IntoFuture, Future};
use primitives::block::Id as BlockId;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::Block as BlockT;
use state_machine::{self, OverlayedChanges, Backend as StateBackend, CodeExecutor};
use state_machine::backend::InMemory as InMemoryStateBackend;
use triehash::trie_root;
use backend;
use blockchain::Backend as ChainBackend;
@@ -36,14 +36,14 @@ pub struct CallResult {
}
/// Method call executor.
pub trait CallExecutor {
pub trait CallExecutor<B: BlockT> {
/// Externalities error type.
type Error: state_machine::Error;
/// Execute a call to a contract on top of state in a block of given hash.
///
/// No changes are made.
fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> Result<CallResult, error::Error>;
fn call(&self, id: &BlockId<B>, method: &str, call_data: &[u8]) -> Result<CallResult, error::Error>;
/// Execute a call to a contract on top of given state.
///
@@ -81,15 +81,16 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
}
}
impl<B, E> CallExecutor for LocalCallExecutor<B, E>
impl<B, E, Block> CallExecutor<Block> for LocalCallExecutor<B, E>
where
B: backend::LocalBackend,
B: backend::LocalBackend<Block>,
E: CodeExecutor,
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
{
type Error = E::Error;
fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
fn call(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
let mut changes = OverlayedChanges::default();
let (return_data, _) = self.call_at_state(&self.backend.state_at(*id)?, &mut changes, method, call_data)?;
Ok(CallResult{ return_data, changes })
@@ -113,19 +114,20 @@ impl<B, F> RemoteCallExecutor<B, F> {
}
}
impl<B, F> CallExecutor for RemoteCallExecutor<B, F>
impl<B, F, Block> CallExecutor<Block> for RemoteCallExecutor<B, F>
where
B: backend::RemoteBackend,
F: Fetcher,
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
B: backend::RemoteBackend<Block>,
F: Fetcher<Block>,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
{
type Error = error::Error;
fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
fn call(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
let block_hash = match *id {
BlockId::Hash(hash) => hash,
BlockId::Number(number) => self.backend.blockchain().hash(number)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(BlockId::Number(number)))?,
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", number)))?,
};
self.fetcher.remote_call(RemoteCallRequest {
@@ -141,22 +143,25 @@ impl<B, F> CallExecutor for RemoteCallExecutor<B, F>
}
/// Check remote execution proof.
pub fn check_execution_proof<B, E>(backend: &B, executor: &E, request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> Result<CallResult, error::Error>
pub fn check_execution_proof<B, E, Block>(backend: &B, executor: &E, request: &RemoteCallRequest<Block::Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> Result<CallResult, error::Error>
where
B: backend::RemoteBackend,
B: backend::RemoteBackend<Block>,
E: CodeExecutor,
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
{
use runtime_primitives::traits::{Header, Hashing, HashingFor};
let (remote_result, remote_proof) = remote_proof;
let remote_state = state_from_execution_proof(remote_proof);
let remote_state_root = trie_root(remote_state.pairs().into_iter()).0;
let remote_state_root = HashingFor::<Block>::trie_root(remote_state.pairs().into_iter());
let local_header = backend.blockchain().header(BlockId::Hash(request.block))?;
let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(BlockId::Hash(request.block)))?;
let local_state_root = local_header.state_root;
let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", request.block)))?;
let local_state_root = local_header.state_root().clone();
if remote_state_root != *local_state_root {
if remote_state_root != local_state_root {
return Err(error::ErrorKind::InvalidExecutionProof.into());
}
+123 -115
View File
@@ -19,11 +19,11 @@
use std::sync::Arc;
use futures::sync::mpsc;
use parking_lot::{Mutex, RwLock};
use primitives::{self, block, AuthorityId};
use primitives::block::{Id as BlockId, HeaderHash};
use primitives::AuthorityId;
use runtime_primitives::{bft::Justification, generic::BlockId};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One};
use primitives::storage::{StorageKey, StorageData};
use runtime_support::Hashable;
use codec::Slicable;
use codec::{Slicable};
use state_machine::{self, Ext, OverlayedChanges, Backend as StateBackend, CodeExecutor};
use backend::{self, BlockImportOperation};
@@ -32,45 +32,45 @@ use call_executor::{CallExecutor, LocalCallExecutor};
use {error, in_mem, block_builder, runtime_io, bft};
/// Type that implements `futures::Stream` of block import events.
pub type BlockchainEventStream = mpsc::UnboundedReceiver<BlockImportNotification>;
pub type BlockchainEventStream<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
/// Polkadot Client genesis block builder.
pub trait GenesisBuilder {
pub trait GenesisBuilder<B: BlockT> {
/// Build genesis block.
fn build(self) -> (block::Header, Vec<(Vec<u8>, Vec<u8>)>);
fn build(self) -> (B::Header, Vec<(Vec<u8>, Vec<u8>)>);
}
/// Polkadot Client
pub struct Client<B, E> {
pub struct Client<B, E, Block> where Block: BlockT {
backend: Arc<B>,
executor: E,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification>>>,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification<Block>>>>,
import_lock: Mutex<()>,
importing_block: RwLock<Option<HeaderHash>>, // holds the block hash currently being imported. TODO: replace this with block queue
importing_block: RwLock<Option<Block::Hash>>, // holds the block hash currently being imported. TODO: replace this with block queue
}
/// A source of blockchain evenets.
pub trait BlockchainEvents {
pub trait BlockchainEvents<Block: BlockT> {
/// Get block import event stream.
fn import_notification_stream(&self) -> BlockchainEventStream;
fn import_notification_stream(&self) -> mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
}
/// Chain head information.
pub trait ChainHead {
pub trait ChainHead<Block: BlockT> {
/// Get best block header.
fn best_block_header(&self) -> Result<block::Header, error::Error>;
fn best_block_header(&self) -> Result<<Block as BlockT>::Header, error::Error>;
}
/// Client info
// TODO: split queue info from chain info and amalgamate into single struct.
#[derive(Debug)]
pub struct ClientInfo {
pub struct ClientInfo<Block: BlockT> {
/// Best block hash.
pub chain: ChainInfo,
pub chain: ChainInfo<Block>,
/// Best block number in the queue.
pub best_queued_number: Option<block::Number>,
pub best_queued_number: Option<<<Block as BlockT>::Header as HeaderT>::Number>,
/// Best queued block hash.
pub best_queued_hash: Option<block::HeaderHash>,
pub best_queued_hash: Option<Block::Hash>,
}
/// Block import result.
@@ -120,49 +120,51 @@ pub enum BlockOrigin {
/// Summary of an imported block
#[derive(Clone, Debug)]
pub struct BlockImportNotification {
pub struct BlockImportNotification<Block: BlockT> {
/// Imported block header hash.
pub hash: block::HeaderHash,
pub hash: Block::Hash,
/// Imported block origin.
pub origin: BlockOrigin,
/// Imported block header.
pub header: block::Header,
pub header: Block::Header,
/// Is this the new best block.
pub is_new_best: bool,
}
/// A header paired with a justification which has already been checked.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct JustifiedHeader {
header: block::Header,
justification: bft::Justification,
pub struct JustifiedHeader<Block: BlockT> {
header: <Block as BlockT>::Header,
justification: ::bft::Justification<Block::Hash>,
}
impl JustifiedHeader {
impl<Block: BlockT> JustifiedHeader<Block> {
/// Deconstruct the justified header into parts.
pub fn into_inner(self) -> (block::Header, bft::Justification) {
pub fn into_inner(self) -> (<Block as BlockT>::Header, ::bft::Justification<Block::Hash>) {
(self.header, self.justification)
}
}
/// Create an instance of in-memory client.
pub fn new_in_mem<E, F>(
pub fn new_in_mem<E, F, Block>(
executor: E,
genesis_builder: F
) -> error::Result<Client<in_mem::Backend, LocalCallExecutor<in_mem::Backend, E>>>
) -> error::Result<Client<in_mem::Backend<Block>, LocalCallExecutor<in_mem::Backend<Block>, E>, Block>>
where
E: CodeExecutor,
F: GenesisBuilder,
F: GenesisBuilder<Block>,
Block: BlockT,
{
let backend = Arc::new(in_mem::Backend::new());
let executor = LocalCallExecutor::new(backend.clone(), executor);
Client::new(backend, executor, genesis_builder)
}
impl<B, E> Client<B, E> where
B: backend::Backend,
E: CallExecutor,
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
impl<B, E, Block: BlockT> Client<B, E, Block> where
B: backend::Backend<Block>,
E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
{
/// Creates new Polkadot Client with given blockchain and code executor.
pub fn new<F>(
@@ -171,12 +173,12 @@ impl<B, E> Client<B, E> where
genesis_builder: F,
) -> error::Result<Self>
where
F: GenesisBuilder
F: GenesisBuilder<Block>
{
if backend.blockchain().header(BlockId::Number(0))?.is_none() {
if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() {
trace!("Empty database, writing genesis block");
let (genesis_header, genesis_store) = genesis_builder.build();
let mut op = backend.begin_operation(BlockId::Hash(block::HeaderHash::default()))?;
let mut op = backend.begin_operation(BlockId::Hash(Default::default()))?;
op.reset_storage(genesis_store.into_iter())?;
op.set_block_data(genesis_header, Some(vec![]), None, true)?;
backend.commit_operation(op)?;
@@ -191,7 +193,7 @@ impl<B, E> Client<B, E> where
}
/// Get a reference to the state at a given block.
pub fn state_at(&self, block: &BlockId) -> error::Result<B::State> {
pub fn state_at(&self, block: &BlockId<Block>) -> error::Result<B::State> {
self.backend.state_at(*block)
}
@@ -201,7 +203,7 @@ impl<B, E> Client<B, E> where
}
/// Return single storage entry of contract under given address in state in a block of given hash.
pub fn storage(&self, id: &BlockId, key: &StorageKey) -> error::Result<StorageData> {
pub fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> error::Result<StorageData> {
Ok(StorageData(self.state_at(id)?
.storage(&key.0)?
.ok_or_else(|| error::ErrorKind::NoValueForKey(key.0.clone()))?
@@ -209,12 +211,12 @@ impl<B, E> Client<B, E> where
}
/// Get the code at a given block.
pub fn code_at(&self, id: &BlockId) -> error::Result<Vec<u8>> {
pub fn code_at(&self, id: &BlockId<Block>) -> error::Result<Vec<u8>> {
self.storage(id, &StorageKey(b":code".to_vec())).map(|data| data.0)
}
/// Get the set of authorities at a given block.
pub fn authorities_at(&self, id: &BlockId) -> error::Result<Vec<AuthorityId>> {
pub fn authorities_at(&self, id: &BlockId<Block>) -> error::Result<Vec<AuthorityId>> {
self.executor.call(id, "authorities",&[])
.and_then(|r| Vec::<AuthorityId>::decode(&mut &r.return_data[..])
.ok_or(error::ErrorKind::AuthLenInvalid.into()))
@@ -229,7 +231,7 @@ impl<B, E> Client<B, E> where
/// AND returning execution proof.
///
/// No changes are made.
pub fn execution_proof(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<(Vec<u8>, Vec<Vec<u8>>)> {
pub fn execution_proof(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<(Vec<u8>, Vec<Vec<u8>>)> {
use call_executor::state_to_execution_proof;
let result = self.executor.call(id, method, call_data);
@@ -248,7 +250,7 @@ impl<B, E> Client<B, E> where
/// Set up the native execution environment to call into a native runtime code.
pub fn using_environment_at<F: FnOnce() -> T, T>(
&self,
id: &BlockId,
id: &BlockId<Block>,
overlay: &mut OverlayedChanges,
f: F
) -> error::Result<T> {
@@ -256,24 +258,29 @@ impl<B, E> Client<B, E> where
}
/// Create a new block, built on the head of the chain.
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E>> where E: Clone {
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E, Block>> where E: Clone {
block_builder::BlockBuilder::new(self)
}
/// Create a new block, built on top of `parent`.
pub fn new_block_at(&self, parent: &BlockId) -> error::Result<block_builder::BlockBuilder<B, E>> where E: Clone {
pub fn new_block_at(&self, parent: &BlockId<Block>) -> error::Result<block_builder::BlockBuilder<B, E, Block>> where E: Clone {
block_builder::BlockBuilder::at_block(parent, &self)
}
/// Check a header's justification.
pub fn check_justification(
&self,
header: block::Header,
justification: bft::UncheckedJustification,
) -> error::Result<JustifiedHeader> {
let authorities = self.authorities_at(&BlockId::Hash(header.parent_hash))?;
let just = bft::check_justification(&authorities[..], header.parent_hash, justification)
.map_err(|_| error::ErrorKind::BadJustification(BlockId::Hash(header.blake2_256().into())))?;
header: <Block as BlockT>::Header,
justification: ::bft::UncheckedJustification<Block::Hash>,
) -> error::Result<JustifiedHeader<Block>> {
let parent_hash = header.parent_hash().clone();
let authorities = self.authorities_at(&BlockId::Hash(parent_hash))?;
let just = ::bft::check_justification::<Block>(&authorities[..], parent_hash, justification)
.map_err(|_|
error::ErrorKind::BadJustification(
format!("{}", header.hash())
)
)?;
Ok(JustifiedHeader {
header,
justification: just,
@@ -284,16 +291,16 @@ impl<B, E> Client<B, E> where
pub fn import_block(
&self,
origin: BlockOrigin,
header: JustifiedHeader,
body: Option<block::Body>,
header: JustifiedHeader<Block>,
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
) -> error::Result<ImportResult> {
let (header, justification) = header.into_inner();
match self.backend.blockchain().status(BlockId::Hash(header.parent_hash))? {
let parent_hash = header.parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(parent_hash))? {
blockchain::BlockStatus::InChain => {},
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
}
let hash: block::HeaderHash = header.blake2_256().into();
let hash = header.hash();
let _import_lock = self.import_lock.lock();
*self.importing_block.write() = Some(hash);
let result = self.execute_and_import_block(origin, hash, header, justification, body);
@@ -304,17 +311,18 @@ impl<B, E> Client<B, E> where
fn execute_and_import_block(
&self,
origin: BlockOrigin,
hash: HeaderHash,
header: block::Header,
justification: bft::Justification,
body: Option<block::Body>,
hash: Block::Hash,
header: Block::Header,
justification: bft::Justification<Block::Hash>,
body: Option<Vec<Block::Extrinsic>>,
) -> error::Result<ImportResult> {
let parent_hash = header.parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(hash))? {
blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain),
blockchain::BlockStatus::Unknown => {},
}
let mut transaction = self.backend.begin_operation(BlockId::Hash(header.parent_hash))?;
let mut transaction = self.backend.begin_operation(BlockId::Hash(parent_hash))?;
let storage_update = match transaction.state()? {
Some(transaction_state) => {
let mut overlay = Default::default();
@@ -322,7 +330,7 @@ impl<B, E> Client<B, E> where
transaction_state,
&mut overlay,
"execute_block",
&block::Block { header: header.clone(), transactions: body.clone().unwrap_or_default().clone() }.encode(),
&<Block as BlockT>::new(header.clone(), body.clone().unwrap_or_default()).encode()
)?;
Some(storage_update)
@@ -330,15 +338,15 @@ impl<B, E> Client<B, E> where
None => None,
};
let is_new_best = header.number == self.backend.blockchain().info()?.best_number + 1;
trace!("Imported {}, (#{}), best={}, origin={:?}", hash, header.number, is_new_best, origin);
let is_new_best = header.number() == &(self.backend.blockchain().info()?.best_number + One::one());
trace!("Imported {}, (#{}), best={}, origin={:?}", hash, header.number(), is_new_best, origin);
transaction.set_block_data(header.clone(), body, Some(justification.uncheck().into()), is_new_best)?;
if let Some(storage_update) = storage_update {
transaction.update_storage(storage_update)?;
}
self.backend.commit_operation(transaction)?;
if origin == BlockOrigin::NetworkBroadcast || origin == BlockOrigin::Own || origin == BlockOrigin::ConsensusBroadcast {
let notification = BlockImportNotification {
let notification = BlockImportNotification::<Block> {
hash: hash,
origin: origin,
header: header,
@@ -351,7 +359,7 @@ impl<B, E> Client<B, E> where
}
/// Get blockchain info.
pub fn info(&self) -> error::Result<ClientInfo> {
pub fn info(&self) -> error::Result<ClientInfo<Block>> {
let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?;
Ok(ClientInfo {
chain: info,
@@ -361,7 +369,7 @@ impl<B, E> Client<B, E> where
}
/// Get block status.
pub fn block_status(&self, id: &BlockId) -> error::Result<BlockStatus> {
pub fn block_status(&self, id: &BlockId<Block>) -> error::Result<BlockStatus> {
// TODO: more efficient implementation
if let BlockId::Hash(ref h) = id {
if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) {
@@ -375,12 +383,12 @@ impl<B, E> Client<B, E> where
}
/// Get block hash by number.
pub fn block_hash(&self, block_number: block::Number) -> error::Result<Option<block::HeaderHash>> {
pub fn block_hash(&self, block_number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
self.backend.blockchain().hash(block_number)
}
/// Convert an arbitrary block ID into a block hash.
pub fn block_hash_from_id(&self, id: &BlockId) -> error::Result<Option<block::HeaderHash>> {
pub fn block_hash_from_id(&self, id: &BlockId<Block>) -> error::Result<Option<Block::Hash>> {
match *id {
BlockId::Hash(h) => Ok(Some(h)),
BlockId::Number(n) => self.block_hash(n),
@@ -388,83 +396,91 @@ impl<B, E> Client<B, E> where
}
/// Convert an arbitrary block ID into a block hash.
pub fn block_number_from_id(&self, id: &BlockId) -> error::Result<Option<block::Number>> {
pub fn block_number_from_id(&self, id: &BlockId<Block>) -> error::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
match *id {
BlockId::Hash(_) => Ok(self.header(id)?.map(|h| h.number)),
BlockId::Hash(_) => Ok(self.header(id)?.map(|h| h.number().clone())),
BlockId::Number(n) => Ok(Some(n)),
}
}
/// Get block header by id.
pub fn header(&self, id: &BlockId) -> error::Result<Option<block::Header>> {
pub fn header(&self, id: &BlockId<Block>) -> error::Result<Option<<Block as BlockT>::Header>> {
self.backend.blockchain().header(*id)
}
/// Get block body by id.
pub fn body(&self, id: &BlockId) -> error::Result<Option<block::Body>> {
pub fn body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
self.backend.blockchain().body(*id)
}
/// Get block justification set by id.
pub fn justification(&self, id: &BlockId) -> error::Result<Option<primitives::bft::Justification>> {
pub fn justification(&self, id: &BlockId<Block>) -> error::Result<Option<Justification<Block::Hash>>> {
self.backend.blockchain().justification(*id)
}
/// Get best block header.
pub fn best_block_header(&self) -> error::Result<block::Header> {
pub fn best_block_header(&self) -> error::Result<<Block as BlockT>::Header> {
let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?;
Ok(self.header(&BlockId::Hash(info.best_hash))?.expect("Best block header must always exist"))
}
}
impl<B, E> bft::BlockImport for Client<B, E>
impl<B, E, Block> bft::BlockImport<Block> for Client<B, E, Block>
where
B: backend::Backend,
E: CallExecutor,
B: backend::Backend<Block>,
E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
{
fn import_block(&self, block: block::Block, justification: bft::Justification) {
fn import_block(&self, block: Block, justification: ::bft::Justification<Block::Hash>) {
let (header, extrinsics) = block.deconstruct();
let justified_header = JustifiedHeader {
header: block.header,
header: header,
justification,
};
let _ = self.import_block(BlockOrigin::ConsensusBroadcast, justified_header, Some(block.transactions));
let _ = self.import_block(BlockOrigin::ConsensusBroadcast, justified_header, Some(extrinsics));
}
}
impl<B, E> bft::Authorities for Client<B, E>
impl<B, E, Block> bft::Authorities<Block> for Client<B, E, Block>
where
B: backend::Backend,
E: CallExecutor,
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
B: backend::Backend<Block>,
E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error>,
{
fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, bft::Error> {
self.authorities_at(at).map_err(|_| bft::ErrorKind::StateUnavailable(*at).into())
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, bft::Error> {
self.authorities_at(at).map_err(|_| {
let descriptor = format!("{:?}", at);
bft::ErrorKind::StateUnavailable(descriptor).into()
})
}
}
impl<B, E> BlockchainEvents for Client<B, E>
impl<B, E, Block> BlockchainEvents<Block> for Client<B, E, Block>
where
B: backend::Backend,
E: CallExecutor,
B: backend::Backend<Block>,
E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
{
/// Get block import event stream.
fn import_notification_stream(&self) -> BlockchainEventStream {
fn import_notification_stream(&self) -> mpsc::UnboundedReceiver<BlockImportNotification<Block>> {
let (sink, stream) = mpsc::unbounded();
self.import_notification_sinks.lock().push(sink);
stream
}
}
impl<B, E> ChainHead for Client<B, E>
impl<B, E, Block> ChainHead<Block> for Client<B, E, Block>
where
B: backend::Backend,
E: CallExecutor,
B: backend::Backend<Block>,
E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
{
fn best_block_header(&self) -> error::Result<block::Header> {
fn best_block_header(&self) -> error::Result<<Block as BlockT>::Header> {
Client::best_block_header(self)
}
}
@@ -474,20 +490,18 @@ mod tests {
use super::*;
use codec::Slicable;
use keyring::Keyring;
use primitives::block::Extrinsic as PrimitiveExtrinsic;
use test_client::{self, TestClient};
use test_client::client::BlockOrigin;
use test_client::runtime as test_runtime;
use test_client::runtime::{UncheckedTransaction, Transaction};
use test_client::runtime::{Transfer, Extrinsic};
#[test]
fn client_initialises_from_genesis_ok() {
let client = test_client::new();
let genesis_hash = client.block_hash(0).unwrap().unwrap();
assert_eq!(client.using_environment(|| test_runtime::system::latest_block_hash()).unwrap(), genesis_hash);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public())).unwrap(), 1000);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public())).unwrap(), 0);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public().into())).unwrap(), 1000);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public().into())).unwrap(), 0);
}
#[test]
@@ -511,17 +525,11 @@ mod tests {
client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
assert_eq!(client.info().unwrap().chain.best_number, 1);
assert_eq!(client.using_environment(|| test_runtime::system::latest_block_hash()).unwrap(), client.block_hash(1).unwrap().unwrap());
}
trait Signable {
fn signed(self) -> PrimitiveExtrinsic;
}
impl Signable for Transaction {
fn signed(self) -> PrimitiveExtrinsic {
let signature = Keyring::from_raw_public(self.from.clone()).unwrap().sign(&self.encode());
PrimitiveExtrinsic::decode(&mut UncheckedTransaction { signature, tx: self }.encode().as_ref()).unwrap()
}
fn sign_tx(tx: Transfer) -> Extrinsic {
let signature = Keyring::from_raw_public(tx.from.0.clone()).unwrap().sign(&tx.encode()).into();
Extrinsic { transfer: tx, signature }
}
#[test]
@@ -530,18 +538,18 @@ mod tests {
let mut builder = client.new_block().unwrap();
builder.push(Transaction {
from: Keyring::Alice.to_raw_public(),
to: Keyring::Ferdie.to_raw_public(),
builder.push(sign_tx(Transfer {
from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Ferdie.to_raw_public().into(),
amount: 42,
nonce: 0
}.signed()).unwrap();
nonce: 0,
})).unwrap();
client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
assert_eq!(client.info().unwrap().chain.best_number, 1);
assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap());
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public())).unwrap(), 958);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public())).unwrap(), 42);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public().into())).unwrap(), 958);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public().into())).unwrap(), 42);
}
}
+6 -6
View File
@@ -29,9 +29,9 @@ error_chain! {
}
/// Unknown block.
UnknownBlock(h: ::primitives::block::Id) {
UnknownBlock(h: String) {
description("unknown block"),
display("UnknownBlock: {}", h),
display("UnknownBlock: {}", &*h),
}
/// Execution error.
@@ -77,9 +77,9 @@ error_chain! {
}
/// Bad justification for header.
BadJustification(h: ::primitives::block::Id) {
BadJustification(h: String) {
description("bad justification for header"),
display("bad justification for header: {}", h),
display("bad justification for header: {}", &*h),
}
/// Not available on light client.
@@ -110,8 +110,8 @@ impl From<Box<state_machine::Error>> for Error {
}
impl From<state_machine::backend::Void> for Error {
fn from(_e: state_machine::backend::Void) -> Self {
unreachable!()
fn from(e: state_machine::backend::Void) -> Self {
match e {}
}
}
+48 -39
View File
@@ -17,54 +17,56 @@
//! Tool for creating the genesis block.
use std::collections::HashMap;
use primitives::{Block, Header};
use triehash::trie_root;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing as HashingT, Zero};
/// Create a genesis block, given the initial storage.
pub fn construct_genesis_block(storage: &HashMap<Vec<u8>, Vec<u8>>) -> Block {
let state_root = trie_root(storage.clone().into_iter()).0.into();
let header = Header {
parent_hash: Default::default(),
number: 0,
state_root,
extrinsics_root: trie_root(vec![].into_iter()).0.into(),
digest: Default::default(),
};
Block {
header,
transactions: vec![],
}
pub fn construct_genesis_block<
Block: BlockT
> (
storage: &HashMap<Vec<u8>, Vec<u8>>
) -> Block {
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashingT>::trie_root(storage.clone().into_iter());
let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashingT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>());
Block::new(
<<Block as BlockT>::Header as HeaderT>::new(
Zero::zero(),
extrinsics_root,
state_root,
Default::default(),
Default::default()
),
Default::default()
)
}
#[cfg(test)]
mod tests {
use super::*;
use codec::{Slicable, Joiner};
use runtime_support::Hashable;
use keyring::Keyring;
use executor::WasmExecutor;
use state_machine::{execute, OverlayedChanges};
use state_machine::backend::InMemory;
use test_client;
use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
use test_client::runtime::{Hash, Block, BlockNumber, Header, Digest, Transaction,
UncheckedTransaction};
use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic};
use ed25519::{Public, Pair};
native_executor_instance!(Executor, test_client::runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transaction>) -> (Vec<u8>, Hash) {
fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transfer>) -> (Vec<u8>, Hash) {
use triehash::ordered_trie_root;
let transactions = txs.into_iter().map(|tx| {
let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from)).unwrap())
.sign(&tx.encode());
let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from.0)).unwrap())
.sign(&tx.encode()).into();
UncheckedTransaction { tx, signature }
Extrinsic { transfer: tx, signature }
}).collect::<Vec<_>>();
let extrinsics_root = ordered_trie_root(transactions.iter().map(Slicable::encode)).0.into();
println!("root before: {:?}", extrinsics_root);
let mut header = Header {
parent_hash,
number,
@@ -72,19 +74,25 @@ mod tests {
extrinsics_root,
digest: Digest { logs: vec![], },
};
let hash = header.blake2_256();
let hash = header.hash();
let mut overlay = OverlayedChanges::default();
execute(
backend,
&mut overlay,
&Executor::new(),
"initialise_block",
&header.encode(),
).unwrap();
for tx in transactions.iter() {
let (ret_data, _) = execute(
execute(
backend,
&mut overlay,
&Executor::new(),
"execute_transaction",
&vec![].and(&header).and(tx)
"apply_extrinsic",
&tx.encode(),
).unwrap();
header = Header::decode(&mut &ret_data[..]).unwrap();
}
let (ret_data, _) = execute(
@@ -92,11 +100,12 @@ mod tests {
&mut overlay,
&Executor::new(),
"finalise_block",
&vec![].and(&header)
&[]
).unwrap();
header = Header::decode(&mut &ret_data[..]).unwrap();
println!("root after: {:?}", header.extrinsics_root);
(vec![].and(&Block { header, transactions }), hash.into())
(vec![].and(&Block { header, extrinsics: transactions }), hash)
}
fn block1(genesis_hash: Hash, backend: &InMemory) -> (Vec<u8>, Hash) {
@@ -105,9 +114,9 @@ mod tests {
1,
genesis_hash,
hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(),
vec![Transaction {
from: Keyring::One.to_raw_public(),
to: Keyring::Two.to_raw_public(),
vec![Transfer {
from: Keyring::One.to_raw_public().into(),
to: Keyring::Two.to_raw_public().into(),
amount: 69,
nonce: 0,
}]
@@ -119,8 +128,8 @@ mod tests {
let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
).genesis_map();
let block = construct_genesis_block(&storage);
let genesis_hash = block.header.blake2_256().into();
let block = construct_genesis_block::<Block>(&storage);
let genesis_hash = block.header.hash();
storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage);
@@ -141,8 +150,8 @@ mod tests {
let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
).genesis_map();
let block = construct_genesis_block(&storage);
let genesis_hash = block.header.blake2_256().into();
let block = construct_genesis_block::<Block>(&storage);
let genesis_hash = block.header.hash();
storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage);
@@ -164,8 +173,8 @@ mod tests {
let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 68
).genesis_map();
let block = construct_genesis_block(&storage);
let genesis_hash = block.header.blake2_256().into();
let block = construct_genesis_block::<Block>(&storage);
let genesis_hash = block.header.hash();
storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage);
+144 -86
View File
@@ -20,95 +20,136 @@ use std::collections::HashMap;
use parking_lot::RwLock;
use error;
use backend;
use runtime_support::Hashable;
use primitives;
use primitives::block::{self, Id as BlockId, HeaderHash};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero};
use runtime_primitives::bft::Justification;
use blockchain::{self, BlockStatus};
use state_machine::backend::{Backend as StateBackend, InMemory};
struct PendingBlock {
block: Block,
struct PendingBlock<B: BlockT> {
block: StoredBlock<B>,
is_best: bool,
}
#[derive(PartialEq, Eq, Clone)]
struct Block {
header: block::Header,
justification: Option<primitives::bft::Justification>,
body: Option<block::Body>,
enum StoredBlock<B: BlockT> {
Header(B::Header, Option<Justification<B::Hash>>),
Full(B, Option<Justification<B::Hash>>),
}
impl<B: BlockT> StoredBlock<B> {
fn new(header: B::Header, body: Option<Vec<B::Extrinsic>>, just: Option<Justification<B::Hash>>) -> Self {
match body {
Some(body) => StoredBlock::Full(B::new(header, body), just),
None => StoredBlock::Header(header, just),
}
}
fn header(&self) -> &B::Header {
match *self {
StoredBlock::Header(ref h, _) => h,
StoredBlock::Full(ref b, _) => b.header(),
}
}
fn justification(&self) -> Option<&Justification<B::Hash>> {
match *self {
StoredBlock::Header(_, ref j) | StoredBlock::Full(_, ref j) => j.as_ref()
}
}
fn extrinsics(&self) -> Option<&[B::Extrinsic]> {
match *self {
StoredBlock::Header(_, _) => None,
StoredBlock::Full(ref b, _) => Some(b.extrinsics())
}
}
fn into_inner(self) -> (B::Header, Option<Vec<B::Extrinsic>>, Option<Justification<B::Hash>>) {
match self {
StoredBlock::Header(header, just) => (header, None, just),
StoredBlock::Full(block, just) => {
let (header, body) = block.deconstruct();
(header, Some(body), just)
}
}
}
}
#[derive(Clone)]
struct BlockchainStorage {
blocks: HashMap<HeaderHash, Block>,
hashes: HashMap<block::Number, HeaderHash>,
best_hash: HeaderHash,
best_number: block::Number,
genesis_hash: HeaderHash,
struct BlockchainStorage<Block: BlockT> {
blocks: HashMap<Block::Hash, StoredBlock<Block>>,
hashes: HashMap<<<Block as BlockT>::Header as HeaderT>::Number, Block::Hash>,
best_hash: Block::Hash,
best_number: <<Block as BlockT>::Header as HeaderT>::Number,
genesis_hash: Block::Hash,
}
/// In-memory blockchain. Supports concurrent reads.
pub struct Blockchain {
storage: RwLock<BlockchainStorage>,
pub struct Blockchain<Block: BlockT> {
storage: RwLock<BlockchainStorage<Block>>,
}
impl Clone for Blockchain {
fn clone(&self) -> Blockchain {
impl<Block: BlockT + Clone> Clone for Blockchain<Block> {
fn clone(&self) -> Self {
Blockchain {
storage: RwLock::new(self.storage.read().clone()),
}
}
}
impl Blockchain {
/// Create new in-memory blockchain storage.
pub fn new() -> Blockchain {
Blockchain {
storage: RwLock::new(
BlockchainStorage {
blocks: HashMap::new(),
hashes: HashMap::new(),
best_hash: HeaderHash::default(),
best_number: 0,
genesis_hash: HeaderHash::default(),
})
}
}
impl<Block: BlockT> Blockchain<Block> {
/// Get header hash of given block.
pub fn id(&self, id: BlockId) -> Option<HeaderHash> {
pub fn id(&self, id: BlockId<Block>) -> Option<Block::Hash> {
match id {
BlockId::Hash(h) => Some(h),
BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(),
}
}
/// Insert block.
pub fn insert(&self, hash: HeaderHash, header: block::Header, justification: Option<primitives::bft::Justification>, body: Option<block::Body>, is_new_best: bool) {
let number = header.number;
let mut storage = self.storage.write();
storage.blocks.insert(hash, Block {
header: header,
body: body,
justification: justification,
});
storage.hashes.insert(number, hash);
if is_new_best {
storage.best_hash = hash;
storage.best_number = number;
/// Create new in-memory blockchain storage.
pub fn new() -> Self {
Blockchain {
storage: RwLock::new(
BlockchainStorage {
blocks: HashMap::new(),
hashes: HashMap::new(),
best_hash: Default::default(),
best_number: Zero::zero(),
genesis_hash: Default::default(),
})
}
if number == 0 {
}
/// Insert a block header and associated data.
pub fn insert(
&self,
hash: Block::Hash,
header: <Block as BlockT>::Header,
justification: Option<Justification<Block::Hash>>,
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
is_new_best: bool
) {
let number = header.number().clone();
let mut storage = self.storage.write();
storage.blocks.insert(hash.clone(), StoredBlock::new(header, body, justification));
storage.hashes.insert(number, hash.clone());
if is_new_best {
storage.best_hash = hash.clone();
storage.best_number = number.clone();
}
if number == Zero::zero() {
storage.genesis_hash = hash;
}
}
/// Compare this blockchain with another in-mem blockchain
pub fn equals_to(&self, other: &Blockchain) -> bool {
pub fn equals_to(&self, other: &Self) -> bool {
self.canon_equals_to(other) && self.storage.read().blocks == other.storage.read().blocks
}
/// Compare canonical chain to other canonical chain.
pub fn canon_equals_to(&self, other: &Blockchain) -> bool {
pub fn canon_equals_to(&self, other: &Self) -> bool {
let this = self.storage.read();
let other = other.storage.read();
this.hashes == other.hashes
@@ -118,20 +159,27 @@ impl Blockchain {
}
}
impl blockchain::Backend for Blockchain {
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> {
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).map(|b| b.header.clone())))
impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
fn header(&self, id: BlockId<Block>) -> error::Result<Option<<Block as BlockT>::Header>> {
Ok(self.id(id).and_then(|hash| {
self.storage.read().blocks.get(&hash).map(|b| b.header().clone())
}))
}
fn body(&self, id: BlockId) -> error::Result<Option<block::Body>> {
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.body.clone())))
fn body(&self, id: BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
Ok(self.id(id).and_then(|hash| {
self.storage.read().blocks.get(&hash)
.and_then(|b| b.extrinsics().map(|x| x.to_vec()))
}))
}
fn justification(&self, id: BlockId) -> error::Result<Option<primitives::bft::Justification>> {
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.justification.clone())))
fn justification(&self, id: BlockId<Block>) -> error::Result<Option<Justification<Block::Hash>>> {
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b|
b.justification().map(|x| x.clone()))
))
}
fn info(&self) -> error::Result<blockchain::Info> {
fn info(&self) -> error::Result<blockchain::Info<Block>> {
let storage = self.storage.read();
Ok(blockchain::Info {
best_hash: storage.best_hash,
@@ -140,40 +188,42 @@ impl blockchain::Backend for Blockchain {
})
}
fn status(&self, id: BlockId) -> error::Result<BlockStatus> {
fn status(&self, id: BlockId<Block>) -> error::Result<BlockStatus> {
match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) {
true => Ok(BlockStatus::InChain),
false => Ok(BlockStatus::Unknown),
}
}
fn hash(&self, number: block::Number) -> error::Result<Option<block::HeaderHash>> {
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
Ok(self.id(BlockId::Number(number)))
}
}
/// In-memory operation.
pub struct BlockImportOperation {
pending_block: Option<PendingBlock>,
pub struct BlockImportOperation<Block: BlockT> {
pending_block: Option<PendingBlock<Block>>,
old_state: InMemory,
new_state: Option<InMemory>,
}
impl backend::BlockImportOperation for BlockImportOperation {
impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperation<Block> {
type State = InMemory;
fn state(&self) -> error::Result<Option<&Self::State>> {
Ok(Some(&self.old_state))
}
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()> {
fn set_block_data(
&mut self,
header: <Block as BlockT>::Header,
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
justification: Option<Justification<Block::Hash>>,
is_new_best: bool
) -> error::Result<()> {
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
self.pending_block = Some(PendingBlock {
block: Block {
header: header,
body: body,
justification: justification,
},
block: StoredBlock::new(header, body, justification),
is_best: is_new_best,
});
Ok(())
@@ -191,14 +241,18 @@ impl backend::BlockImportOperation for BlockImportOperation {
}
/// In-memory backend. Keeps all states and blocks in memory. Useful for testing.
pub struct Backend {
states: RwLock<HashMap<block::HeaderHash, InMemory>>,
blockchain: Blockchain,
pub struct Backend<Block> where
Block: BlockT,
{
states: RwLock<HashMap<Block::Hash, InMemory>>,
blockchain: Blockchain<Block>,
}
impl Backend {
impl<Block> Backend<Block> where
Block: BlockT,
{
/// Create a new instance of in-mem backend.
pub fn new() -> Backend {
pub fn new() -> Backend<Block> {
Backend {
states: RwLock::new(HashMap::new()),
blockchain: Blockchain::new(),
@@ -206,14 +260,16 @@ impl Backend {
}
}
impl backend::Backend for Backend {
type BlockImportOperation = BlockImportOperation;
type Blockchain = Blockchain;
impl<Block> backend::Backend<Block> for Backend<Block> where
Block: BlockT,
{
type BlockImportOperation = BlockImportOperation<Block>;
type Blockchain = Blockchain<Block>;
type State = InMemory;
fn begin_operation(&self, block: BlockId) -> error::Result<Self::BlockImportOperation> {
fn begin_operation(&self, block: BlockId<Block>) -> error::Result<Self::BlockImportOperation> {
let state = match block {
BlockId::Hash(h) if h.is_zero() => Self::State::default(),
BlockId::Hash(ref h) if h.clone() == Default::default() => Self::State::default(),
_ => self.state_at(block)?,
};
@@ -226,24 +282,26 @@ impl backend::Backend for Backend {
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
if let Some(pending_block) = operation.pending_block {
let hash = pending_block.block.header.blake2_256().into();
let old_state = &operation.old_state;
let (header, body, justification) = pending_block.block.into_inner();
let hash = header.hash();
self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone()));
self.blockchain.insert(hash, pending_block.block.header, pending_block.block.justification, pending_block.block.body, pending_block.is_best);
self.blockchain.insert(hash, header, justification, body, pending_block.is_best);
}
Ok(())
}
fn blockchain(&self) -> &Blockchain {
fn blockchain(&self) -> &Self::Blockchain {
&self.blockchain
}
fn state_at(&self, block: BlockId) -> error::Result<Self::State> {
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State> {
match self.blockchain.id(block).and_then(|id| self.states.read().get(&id).cloned()) {
Some(state) => Ok(state),
None => Err(error::ErrorKind::UnknownBlock(block).into()),
None => Err(error::ErrorKind::UnknownBlock(format!("{}", block)).into()),
}
}
}
impl backend::LocalBackend for Backend {}
impl<Block: BlockT> backend::LocalBackend<Block> for Backend<Block> {}
+1
View File
@@ -24,6 +24,7 @@ extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_state_machine as state_machine;
#[cfg(test)] extern crate substrate_keyring as keyring;
#[cfg(test)] extern crate substrate_test_client as test_client;
+60 -56
View File
@@ -19,11 +19,11 @@
use std::sync::Arc;
use futures::future::IntoFuture;
use primitives;
use primitives::block::{self, Id as BlockId, HeaderHash};
use runtime_support::Hashable;
use state_machine::CodeExecutor;
use state_machine::backend::Backend as StateBackend;
use runtime_primitives::generic::BlockId;
use runtime_primitives::bft::Justification;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use blockchain::{self, BlockStatus};
use backend;
use call_executor::{CallResult, RemoteCallExecutor, check_execution_proof};
@@ -32,9 +32,9 @@ use error;
use in_mem::Blockchain as InMemBlockchain;
/// Remote call request.
pub struct RemoteCallRequest {
/// Call at state of given block.
pub block: HeaderHash,
pub struct RemoteCallRequest<H> {
/// Call at state of block referenced by given header hash.
pub block: H,
/// Method to call.
pub method: String,
/// Call data.
@@ -43,62 +43,62 @@ pub struct RemoteCallRequest {
/// Light client data fetcher. Implementations of this trait must check if remote data
/// is correct (see FetchedDataChecker) and return already checked data.
pub trait Fetcher: Send + Sync {
pub trait Fetcher<B: BlockT>: Send + Sync {
/// Remote call result future.
type RemoteCallResult: IntoFuture<Item=CallResult, Error=error::Error>;
/// Fetch remote call result.
fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult;
fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Self::RemoteCallResult;
}
/// Light client remote data checker.
pub trait FetchChecker: Send + Sync {
pub trait FetchChecker<B: BlockT>: Send + Sync {
/// Check remote method execution proof.
fn check_execution_proof(&self, request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult>;
fn check_execution_proof(&self, request: &RemoteCallRequest<B::Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult>;
}
/// Light client backend.
pub struct Backend {
blockchain: Blockchain,
pub struct Backend<B: BlockT> {
blockchain: Blockchain<B>,
}
/// Light client blockchain.
pub struct Blockchain {
storage: InMemBlockchain,
pub struct Blockchain<B: BlockT> {
storage: InMemBlockchain<B>,
}
/// Block (header and justification) import operation.
pub struct BlockImportOperation {
pending_block: Option<PendingBlock>,
pub struct BlockImportOperation<B: BlockT> {
pending_block: Option<PendingBlock<B>>,
}
/// On-demand state.
#[derive(Clone)]
pub struct OnDemandState {
pub struct OnDemandState<H> {
/// Hash of the block, state is valid for.
_block: HeaderHash,
_block: H,
}
/// Remote data checker.
pub struct LightDataChecker<E> {
pub struct LightDataChecker<E, B: BlockT> {
/// Backend reference.
backend: Arc<Backend>,
backend: Arc<Backend<B>>,
/// Executor.
executor: E,
}
struct PendingBlock {
header: block::Header,
justification: Option<primitives::bft::Justification>,
struct PendingBlock<B: BlockT> {
header: B::Header,
justification: Option<Justification<B::Hash>>,
is_best: bool,
}
impl backend::Backend for Backend {
type BlockImportOperation = BlockImportOperation;
type Blockchain = Blockchain;
type State = OnDemandState;
impl<B: BlockT> backend::Backend<B> for Backend<B> {
type BlockImportOperation = BlockImportOperation<B>;
type Blockchain = Blockchain<B>;
type State = OnDemandState<B::Hash>;
fn begin_operation(&self, _block: BlockId) -> error::Result<Self::BlockImportOperation> {
fn begin_operation(&self, _block: BlockId<B>) -> error::Result<Self::BlockImportOperation> {
Ok(BlockImportOperation {
pending_block: None,
})
@@ -106,34 +106,34 @@ impl backend::Backend for Backend {
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
if let Some(pending_block) = operation.pending_block {
let hash = pending_block.header.blake2_256().into();
let hash = pending_block.header.hash();
self.blockchain.storage.insert(hash, pending_block.header, pending_block.justification, None, pending_block.is_best);
}
Ok(())
}
fn blockchain(&self) -> &Blockchain {
fn blockchain(&self) -> &Blockchain<B> {
&self.blockchain
}
fn state_at(&self, block: BlockId) -> error::Result<Self::State> {
fn state_at(&self, block: BlockId<B>) -> error::Result<Self::State> {
Ok(OnDemandState {
_block: self.blockchain.storage.id(block).ok_or(error::ErrorKind::UnknownBlock(block))?,
_block: self.blockchain.storage.id(block).ok_or(error::ErrorKind::UnknownBlock(format!("{:?}", block)))?,
})
}
}
impl backend::RemoteBackend for Backend {}
impl<B: BlockT> backend::RemoteBackend<B> for Backend<B> {}
impl backend::BlockImportOperation for BlockImportOperation {
type State = OnDemandState;
impl<B: BlockT> backend::BlockImportOperation<B> for BlockImportOperation<B> {
type State = OnDemandState<B::Hash>;
fn state(&self) -> error::Result<Option<&Self::State>> {
// None means 'locally-stateless' backend
Ok(None)
}
fn set_block_data(&mut self, header: block::Header, _body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()> {
fn set_block_data(&mut self, header: B::Header, _body: Option<Vec<B::Extrinsic>>, justification: Option<Justification<B::Hash>>, is_new_best: bool) -> error::Result<()> {
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
self.pending_block = Some(PendingBlock {
header,
@@ -154,34 +154,34 @@ impl backend::BlockImportOperation for BlockImportOperation {
}
}
impl blockchain::Backend for Blockchain {
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> {
impl<B: BlockT> blockchain::Backend<B> for Blockchain<B> {
fn header(&self, id: BlockId<B>) -> error::Result<Option<B::Header>> {
self.storage.header(id)
}
fn body(&self, _id: BlockId) -> error::Result<Option<block::Body>> {
fn body(&self, _id: BlockId<B>) -> error::Result<Option<Vec<B::Extrinsic>>> {
// TODO [light]: fetch from remote node
Ok(None)
}
fn justification(&self, id: BlockId) -> error::Result<Option<primitives::bft::Justification>> {
fn justification(&self, id: BlockId<B>) -> error::Result<Option<Justification<B::Hash>>> {
self.storage.justification(id)
}
fn info(&self) -> error::Result<blockchain::Info> {
fn info(&self) -> error::Result<blockchain::Info<B>> {
self.storage.info()
}
fn status(&self, id: BlockId) -> error::Result<BlockStatus> {
fn status(&self, id: BlockId<B>) -> error::Result<BlockStatus> {
self.storage.status(id)
}
fn hash(&self, number: block::Number) -> error::Result<Option<block::HeaderHash>> {
fn hash(&self, number: <B::Header as HeaderT>::Number) -> error::Result<Option<B::Hash>> {
self.storage.hash(number)
}
}
impl StateBackend for OnDemandState {
impl<H: Clone> StateBackend for OnDemandState<H> {
type Error = error::Error;
type Transaction = ();
@@ -191,7 +191,8 @@ impl StateBackend for OnDemandState {
}
fn storage_root<I>(&self, _delta: I) -> ([u8; 32], Self::Transaction)
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)> {
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
([0; 32], ())
}
@@ -201,43 +202,46 @@ impl StateBackend for OnDemandState {
}
}
impl<E> FetchChecker for LightDataChecker<E>
impl<E, B> FetchChecker<B> for LightDataChecker<E, B>
where
E: CodeExecutor,
B: BlockT,
{
fn check_execution_proof(&self, request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult> {
fn check_execution_proof(&self, request: &RemoteCallRequest<B::Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult> {
check_execution_proof(&*self.backend, &self.executor, request, remote_proof)
}
}
/// Create an instance of light client backend.
pub fn new_light_backend() -> Arc<Backend> {
pub fn new_light_backend<B: BlockT>() -> Arc<Backend<B>> {
let storage = InMemBlockchain::new();
let blockchain = Blockchain { storage };
Arc::new(Backend { blockchain })
}
/// Create an instance of light client.
pub fn new_light<F, B>(
backend: Arc<Backend>,
pub fn new_light<F, B, Block>(
backend: Arc<Backend<Block>>,
fetcher: Arc<F>,
genesis_builder: B,
) -> error::Result<Client<Backend, RemoteCallExecutor<Backend, F>>>
) -> error::Result<Client<Backend<Block>, RemoteCallExecutor<Backend<Block>, F>, Block>>
where
F: Fetcher,
B: GenesisBuilder,
F: Fetcher<Block>,
B: GenesisBuilder<Block>,
Block: BlockT,
{
let executor = RemoteCallExecutor::new(backend.clone(), fetcher);
Client::new(backend, executor, genesis_builder)
}
/// Create an instance of fetch data checker.
pub fn new_fetch_checker<E>(
backend: Arc<Backend>,
pub fn new_fetch_checker<E, Block>(
backend: Arc<Backend<Block>>,
executor: E,
) -> LightDataChecker<E>
) -> LightDataChecker<E, Block>
where
E: CodeExecutor,
Block: BlockT,
{
LightDataChecker { backend, executor }
}
@@ -8,5 +8,4 @@ error-chain = "0.11"
futures = "0.1"
log = "0.3"
parking_lot = "0.4"
substrate-primitives = { path = "../primitives" }
transaction-pool = "1.12"
+8 -10
View File
@@ -16,12 +16,9 @@
//! External API for extrinsic pool.
use std::fmt;
use std::ops::Deref;
use txpool::{self, VerifiedTransaction};
use primitives::{
Hash,
block::{Extrinsic, ExtrinsicHash},
};
/// Extrinsic pool error.
pub trait Error: ::std::error::Error + Send + Sized {
@@ -38,18 +35,19 @@ impl Error for txpool::Error {
}
/// Extrinsic pool.
pub trait ExtrinsicPool: Send + Sync + 'static {
pub trait ExtrinsicPool<Ex, Hash>: Send + Sync + 'static {
/// Error type
type Error: Error;
/// Submit a collection of extrinsics to the pool.
fn submit(&self, xt: Vec<Extrinsic>) -> Result<Vec<ExtrinsicHash>, Self::Error>;
fn submit(&self, xt: Vec<Ex>) -> Result<Vec<Hash>, Self::Error>;
}
// Blanket implementation for anything that `Derefs` to the pool.
impl<V, S, E, T> ExtrinsicPool for T where
T: Deref<Target=super::Pool<V, S, E>> + Send + Sync + 'static,
V: txpool::Verifier<Extrinsic>,
impl<Ex, Hash, V, S, E, T> ExtrinsicPool<Ex, Hash> for T where
Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
T: Deref<Target=super::Pool<Ex, Hash, V, S, E>> + Send + Sync + 'static,
V: txpool::Verifier<Ex>,
S: txpool::Scoring<V::VerifiedTransaction>,
V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>,
E: From<V::Error>,
@@ -58,7 +56,7 @@ impl<V, S, E, T> ExtrinsicPool for T where
{
type Error = E;
fn submit(&self, xt: Vec<Extrinsic>) -> Result<Vec<ExtrinsicHash>, Self::Error> {
fn submit(&self, xt: Vec<Ex>) -> Result<Vec<Hash>, Self::Error> {
self.deref().submit(xt).map(|result| result.into_iter().map(|xt| *xt.hash()).collect())
}
}
@@ -20,7 +20,6 @@
extern crate futures;
extern crate parking_lot;
extern crate substrate_primitives as primitives;
#[macro_use]
extern crate log;
@@ -16,29 +16,29 @@
use std::{
sync::Arc,
fmt,
collections::HashMap,
};
use primitives::Hash;
use txpool;
use watcher;
#[derive(Default)]
pub struct Listener {
watchers: HashMap<Hash, watcher::Sender>
pub struct Listener<H: ::std::hash::Hash + Eq> {
watchers: HashMap<H, watcher::Sender<H>>
}
impl Listener {
pub fn create_watcher<T: txpool::VerifiedTransaction<Hash=Hash>>(&mut self, xt: Arc<T>) -> watcher::Watcher {
impl<H: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default> Listener<H> {
pub fn create_watcher<T: txpool::VerifiedTransaction<Hash=H>>(&mut self, xt: Arc<T>) -> watcher::Watcher<H> {
let sender = self.watchers.entry(*xt.hash()).or_insert_with(watcher::Sender::default);
sender.new_watcher()
}
pub fn broadcasted(&mut self, hash: &Hash, peers: Vec<String>) {
pub fn broadcasted(&mut self, hash: &H, peers: Vec<String>) {
self.fire(hash, |watcher| watcher.broadcast(peers));
}
fn fire<F: FnOnce(&mut watcher::Sender)>(&mut self, hash: &Hash, fun: F) {
fn fire<F>(&mut self, hash: &H, fun: F) where F: FnOnce(&mut watcher::Sender<H>) {
let clean = if let Some(h) = self.watchers.get_mut(hash) {
fun(h);
h.is_done()
@@ -52,7 +52,10 @@ impl Listener {
}
}
impl<T: txpool::VerifiedTransaction<Hash=Hash>> txpool::Listener<T> for Listener {
impl<H, T> txpool::Listener<T> for Listener<H> where
H: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
T: txpool::VerifiedTransaction<Hash=H>,
{
fn added(&mut self, tx: &Arc<T>, old: Option<&Arc<T>>) {
if let Some(old) = old {
let hash = tx.hash();
@@ -81,9 +84,7 @@ impl<T: txpool::VerifiedTransaction<Hash=Hash>> txpool::Listener<T> for Listener
fn mined(&mut self, tx: &Arc<T>) {
// TODO [ToDr] latest block number?
let header_hash = 1.into();
let header_hash = Default::default();
self.fire(tx.hash(), |watcher| watcher.finalised(header_hash))
}
}
+11 -9
View File
@@ -16,6 +16,7 @@
use std::{
collections::HashMap,
fmt,
marker::PhantomData,
sync::{Arc, Weak},
};
@@ -23,28 +24,29 @@ use std::{
use futures::sync::mpsc;
use parking_lot::{RwLock, Mutex};
use txpool;
use primitives::{Hash, block::Extrinsic};
use listener::Listener;
use watcher::Watcher;
/// Extrinsics pool.
pub struct Pool<V, S, E> where
V: txpool::Verifier<Extrinsic>,
pub struct Pool<Ex, Hash, V, S, E> where
Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex,
V: txpool::Verifier<Ex>,
S: txpool::Scoring<V::VerifiedTransaction>,
{
_error: Mutex<PhantomData<E>>,
pool: RwLock<txpool::Pool<
V::VerifiedTransaction,
S,
Listener,
Listener<Hash>,
>>,
verifier: V,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<Weak<V::VerifiedTransaction>>>>,
}
impl<V, S, E> Pool<V, S, E> where
V: txpool::Verifier<Extrinsic>,
impl<Ex, Hash, V, S, E> Pool<Ex, Hash, V, S, E> where
Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
V: txpool::Verifier<Ex>,
S: txpool::Scoring<V::VerifiedTransaction>,
V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>,
E: From<V::Error>,
@@ -86,7 +88,7 @@ impl<V, S, E> Pool<V, S, E> where
}
/// Imports a bunch of extrinsics to the pool
pub fn submit(&self, xts: Vec<Extrinsic>) -> Result<Vec<Arc<V::VerifiedTransaction>>, E> {
pub fn submit(&self, xts: Vec<Ex>) -> Result<Vec<Arc<V::VerifiedTransaction>>, E> {
xts
.into_iter()
.map(|xt| self.verifier.verify_transaction(xt))
@@ -97,7 +99,7 @@ impl<V, S, E> Pool<V, S, E> where
}
/// Import a single extrinsic and starts to watch their progress in the pool.
pub fn submit_and_watch(&self, xt: Extrinsic) -> Result<Watcher, E> {
pub fn submit_and_watch(&self, xt: Ex) -> Result<Watcher<Hash>, E> {
let xt = self.submit(vec![xt])?.pop().expect("One extrinsic passed; one result returned; qed");
Ok(self.pool.write().listener_mut().create_watcher(xt))
}
@@ -122,7 +124,7 @@ impl<V, S, E> Pool<V, S, E> where
/// Cull transactions from the queue and then compute the pending set.
pub fn cull_and_get_pending<R, F, T>(&self, ready: R, f: F) -> T where
R: txpool::Ready<V::VerifiedTransaction> + Clone,
F: FnOnce(txpool::PendingIterator<V::VerifiedTransaction, R, S, Listener>) -> T,
F: FnOnce(txpool::PendingIterator<V::VerifiedTransaction, R, S, Listener<Hash>>) -> T,
{
let mut pool = self.pool.write();
pool.cull(None, ready.clone());
@@ -15,17 +15,14 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use futures::sync::mpsc;
use primitives::{
block::{HeaderHash, ExtrinsicHash}
};
/// Possible extrinsic status events
#[derive(Debug, Clone)]
pub enum Status {
pub enum Status<H> {
/// Extrinsic has been finalised in block with given hash.
Finalised(HeaderHash),
Finalised(H),
/// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid.
Usurped(ExtrinsicHash),
Usurped(H),
/// The extrinsic has been broadcast to the given peers.
Broadcast(Vec<String>),
/// Extrinsic has been dropped from the pool because of the limit.
@@ -36,19 +33,19 @@ pub enum Status {
///
/// Represents a stream of status updates for particular extrinsic.
#[derive(Debug)]
pub struct Watcher {
receiver: mpsc::UnboundedReceiver<Status>,
pub struct Watcher<H> {
receiver: mpsc::UnboundedReceiver<Status<H>>,
}
#[derive(Debug, Default)]
pub(crate) struct Sender {
receivers: Vec<mpsc::UnboundedSender<Status>>,
pub(crate) struct Sender<H> {
receivers: Vec<mpsc::UnboundedSender<Status<H>>>,
finalised: bool,
}
impl Sender {
impl<H: Clone> Sender<H> {
/// Add a new watcher to this sender object.
pub fn new_watcher(&mut self) -> Watcher {
pub fn new_watcher(&mut self) -> Watcher<H> {
let (tx, receiver) = mpsc::unbounded();
self.receivers.push(tx);
Watcher {
@@ -57,12 +54,12 @@ impl Sender {
}
/// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid.
pub fn usurped(&mut self, hash: ExtrinsicHash) {
pub fn usurped(&mut self, hash: H) {
self.send(Status::Usurped(hash))
}
/// Extrinsic has been finalised in block with given hash.
pub fn finalised(&mut self, hash: HeaderHash) {
pub fn finalised(&mut self, hash: H) {
self.send(Status::Finalised(hash));
self.finalised = true;
}
@@ -82,7 +79,7 @@ impl Sender {
self.finalised || self.receivers.is_empty()
}
fn send(&mut self, status: Status) {
fn send(&mut self, status: Status<H>) {
self.receivers.retain(|sender| sender.unbounded_send(status.clone()).is_ok())
}
}
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
substrate-codec = { path = "../codec", default-features = false }
substrate-primitives = { path = "../primitives", default-features = false }
substrate-runtime-primitives = { path = "../runtime/primitives", default-features = false }
substrate-runtime-io = { path = "../runtime-io", default-features = false }
[dev-dependencies]
@@ -14,4 +15,4 @@ substrate-keyring = { path = "../keyring" }
[features]
default = ["std"]
std = ["substrate-codec/std", "substrate-primitives/std", "substrate-runtime-io/std"]
std = ["substrate-codec/std", "substrate-primitives/std", "substrate-runtime-primitives/std", "substrate-runtime-io/std"]
@@ -21,6 +21,7 @@
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_primitives as runtime_primitives;
#[cfg(test)]
extern crate substrate_bft;
@@ -29,23 +30,27 @@ extern crate substrate_keyring as keyring;
use codec::Slicable;
use primitives::{AuthorityId, Signature};
use primitives::block::HeaderHash;
use primitives::bft::{Action, Message, MisbehaviorKind};
use runtime_primitives::bft::{Action, Message, MisbehaviorKind};
// check a message signature. returns true if signed by that authority.
fn check_message_sig(message: Message, signature: &Signature, from: &AuthorityId) -> bool {
let msg = message.encode();
fn check_message_sig<B: Slicable, H: Slicable>(
message: Message<B, H>,
signature: &Signature,
from: &AuthorityId
) -> bool {
let msg: Vec<u8> = message.encode();
runtime_io::ed25519_verify(&signature.0, &msg, from)
}
fn prepare(parent: HeaderHash, round_number: u32, hash: HeaderHash) -> Message {
fn prepare<B, H>(parent: H, round_number: u32, hash: H) -> Message<B, H> {
Message {
parent,
action: Action::Prepare(round_number, hash),
}
}
fn commit(parent: HeaderHash, round_number: u32, hash: HeaderHash) -> Message {
fn commit<B, H>(parent: H, round_number: u32, hash: H) -> Message<B, H> {
Message {
parent,
action: Action::Commit(round_number, hash),
@@ -57,21 +62,21 @@ fn commit(parent: HeaderHash, round_number: u32, hash: HeaderHash) -> Message {
/// Doesn't check that the header hash in question is
/// valid or whether the misbehaving authority was part of
/// the set at that block.
pub fn evaluate_misbehavior(
pub fn evaluate_misbehavior<B: Slicable, H: Slicable + Copy>(
misbehaved: &AuthorityId,
parent_hash: HeaderHash,
kind: &MisbehaviorKind,
parent_hash: H,
kind: &MisbehaviorKind<H>,
) -> bool {
match *kind {
MisbehaviorKind::BftDoublePrepare(round, (h_1, ref s_1), (h_2, ref s_2)) => {
s_1 != s_2 &&
check_message_sig(prepare(parent_hash, round, h_1), s_1, misbehaved) &&
check_message_sig(prepare(parent_hash, round, h_2), s_2, misbehaved)
check_message_sig::<B, H>(prepare::<B, H>(parent_hash, round, h_1), s_1, misbehaved) &&
check_message_sig::<B, H>(prepare::<B, H>(parent_hash, round, h_2), s_2, misbehaved)
}
MisbehaviorKind::BftDoubleCommit(round, (h_1, ref s_1), (h_2, ref s_2)) => {
s_1 != s_2 &&
check_message_sig(commit(parent_hash, round, h_1), s_1, misbehaved) &&
check_message_sig(commit(parent_hash, round, h_2), s_2, misbehaved)
check_message_sig::<B, H>(commit::<B, H>(parent_hash, round, h_1), s_1, misbehaved) &&
check_message_sig::<B, H>(commit::<B, H>(parent_hash, round, h_2), s_2, misbehaved)
}
}
}
@@ -84,8 +89,12 @@ mod tests {
use keyring::ed25519;
use keyring::Keyring;
fn sign_prepare(key: &ed25519::Pair, round: u32, hash: HeaderHash, parent_hash: HeaderHash) -> (HeaderHash, Signature) {
let msg = substrate_bft::sign_message(
use runtime_primitives::testing::{H256, Block as RawBlock};
type Block = RawBlock<u64>;
fn sign_prepare(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
let msg = substrate_bft::sign_message::<Block>(
generic::Message::Vote(generic::Vote::Prepare(round as _, hash)),
key,
parent_hash
@@ -97,8 +106,8 @@ mod tests {
}
}
fn sign_commit(key: &ed25519::Pair, round: u32, hash: HeaderHash, parent_hash: HeaderHash) -> (HeaderHash, Signature) {
let msg = substrate_bft::sign_message(
fn sign_commit(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
let msg = substrate_bft::sign_message::<Block>(
generic::Message::Vote(generic::Vote::Commit(round as _, hash)),
key,
parent_hash
@@ -117,7 +126,7 @@ mod tests {
let hash_1 = [0; 32].into();
let hash_2 = [1; 32].into();
assert!(evaluate_misbehavior(
assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0,
parent_hash,
&MisbehaviorKind::BftDoublePrepare(
@@ -129,7 +138,7 @@ mod tests {
// same signature twice is not misbehavior.
let signed = sign_prepare(&key, 1, hash_1, parent_hash);
assert!(evaluate_misbehavior(
assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0,
parent_hash,
&MisbehaviorKind::BftDoublePrepare(
@@ -140,7 +149,7 @@ mod tests {
) == false);
// misbehavior has wrong target.
assert!(evaluate_misbehavior(
assert!(evaluate_misbehavior::<Block, H256>(
&Keyring::Two.to_raw_public(),
parent_hash,
&MisbehaviorKind::BftDoublePrepare(
@@ -158,7 +167,7 @@ mod tests {
let hash_1 = [0; 32].into();
let hash_2 = [1; 32].into();
assert!(evaluate_misbehavior(
assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0,
parent_hash,
&MisbehaviorKind::BftDoubleCommit(
@@ -170,7 +179,7 @@ mod tests {
// same signature twice is not misbehavior.
let signed = sign_commit(&key, 1, hash_1, parent_hash);
assert!(evaluate_misbehavior(
assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0,
parent_hash,
&MisbehaviorKind::BftDoubleCommit(
@@ -181,7 +190,7 @@ mod tests {
) == false);
// misbehavior has wrong target.
assert!(evaluate_misbehavior(
assert!(evaluate_misbehavior::<Block, H256>(
&Keyring::Two.to_raw_public(),
parent_hash,
&MisbehaviorKind::BftDoubleCommit(
+1
View File
@@ -27,6 +27,7 @@ substrate-client = { path = "../../substrate/client" }
substrate-state-machine = { path = "../../substrate/state-machine" }
substrate-serializer = { path = "../../substrate/serializer" }
substrate-runtime-support = { path = "../../substrate/runtime-support" }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
substrate-bft = { path = "../../substrate/bft" }
[dev-dependencies]
+28 -25
View File
@@ -20,47 +20,47 @@ use std::ops::Range;
use std::collections::{HashMap, BTreeMap};
use std::collections::hash_map::Entry;
use network::PeerId;
use primitives::block::Number as BlockNumber;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use message;
const MAX_PARALLEL_DOWNLOADS: u32 = 1;
/// Block data with origin.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlockData {
pub block: message::BlockData,
pub struct BlockData<B: BlockT> {
pub block: message::BlockData<B>,
pub origin: PeerId,
}
#[derive(Debug)]
enum BlockRangeState {
enum BlockRangeState<B: BlockT> {
Downloading {
len: BlockNumber,
len: u64,
downloading: u32,
},
Complete(Vec<BlockData>),
Complete(Vec<BlockData<B>>),
}
impl BlockRangeState {
pub fn len(&self) -> BlockNumber {
impl<B: BlockT> BlockRangeState<B> where B::Header: HeaderT<Number=u64> {
pub fn len(&self) -> u64 {
match *self {
BlockRangeState::Downloading { len, .. } => len,
BlockRangeState::Complete(ref blocks) => blocks.len() as BlockNumber,
BlockRangeState::Complete(ref blocks) => blocks.len() as u64,
}
}
}
/// A collection of blocks being downloaded.
#[derive(Default)]
pub struct BlockCollection {
pub struct BlockCollection<B: BlockT> {
/// Downloaded blocks.
blocks: BTreeMap<BlockNumber, BlockRangeState>,
peer_requests: HashMap<PeerId, BlockNumber>,
blocks: BTreeMap<u64, BlockRangeState<B>>,
peer_requests: HashMap<PeerId, u64>,
}
impl BlockCollection {
impl<B: BlockT> BlockCollection<B> where B::Header: HeaderT<Number=u64> {
/// Create a new instance.
pub fn new() -> BlockCollection {
pub fn new() -> Self {
BlockCollection {
blocks: BTreeMap::new(),
peer_requests: HashMap::new(),
@@ -74,7 +74,7 @@ impl BlockCollection {
}
/// Insert a set of blocks into collection.
pub fn insert(&mut self, start: BlockNumber, blocks: Vec<message::BlockData>, peer_id: PeerId) {
pub fn insert(&mut self, start: u64, blocks: Vec<message::BlockData<B>>, peer_id: PeerId) {
if blocks.is_empty() {
return;
}
@@ -96,13 +96,13 @@ impl BlockCollection {
}
/// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded.
pub fn needed_blocks(&mut self, peer_id: PeerId, count: usize, peer_best: BlockNumber, common: BlockNumber) -> Option<Range<BlockNumber>> {
pub fn needed_blocks(&mut self, peer_id: PeerId, count: usize, peer_best: u64, common: u64) -> Option<Range<u64>> {
// First block number that we need to download
let first_different = common + 1;
let count = count as BlockNumber;
let count = count as u64;
let (mut range, downloading) = {
let mut downloading_iter = self.blocks.iter().peekable();
let mut prev: Option<(&BlockNumber, &BlockRangeState)> = None;
let mut prev: Option<(&u64, &BlockRangeState<B>)> = None;
loop {
let next = downloading_iter.next();
break match &(prev, next) {
@@ -137,7 +137,7 @@ impl BlockCollection {
}
/// Get a valid chain of blocks ordered in descending order and ready for importing into blockchain.
pub fn drain(&mut self, from: BlockNumber) -> Vec<BlockData> {
pub fn drain(&mut self, from: u64) -> Vec<BlockData<B>> {
let mut drained = Vec::new();
let mut ranges = Vec::new();
{
@@ -145,7 +145,7 @@ impl BlockCollection {
for (start, range_data) in &mut self.blocks {
match range_data {
&mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => {
prev = *start + blocks.len() as BlockNumber;
prev = *start + blocks.len() as u64;
let mut blocks = mem::replace(blocks, Vec::new());
drained.append(&mut blocks);
ranges.push(*start);
@@ -191,16 +191,19 @@ impl BlockCollection {
mod test {
use super::{BlockCollection, BlockData};
use message;
use primitives::block::HeaderHash;
use runtime_primitives::testing::Block as RawBlock;
use primitives::H256;
fn is_empty(bc: &BlockCollection) -> bool {
type Block = RawBlock<u64>;
fn is_empty(bc: &BlockCollection<Block>) -> bool {
bc.blocks.is_empty() &&
bc.peer_requests.is_empty()
}
fn generate_blocks(n: usize) -> Vec<message::BlockData> {
(0 .. n).map(|_| message::BlockData {
hash: HeaderHash::random(),
fn generate_blocks(n: usize) -> Vec<message::BlockData<Block>> {
(0 .. n).map(|_| message::generic::BlockData {
hash: H256::random(),
header: None,
body: None,
message_queue: None,
+33 -31
View File
@@ -19,72 +19,74 @@
use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus, BlockOrigin, CallExecutor};
use client::error::Error;
use state_machine;
use primitives::block::{self, Id as BlockId};
use primitives::bft::Justification;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
use runtime_primitives::bft::Justification;
pub trait Client: Send + Sync {
pub trait Client<Block: BlockT>: Send + Sync {
/// Import a new block. Parent is supposed to be existing in the blockchain.
fn import(&self, is_best: bool, header: block::Header, justification: Justification, body: Option<block::Body>) -> Result<ImportResult, Error>;
fn import(&self, is_best: bool, header: Block::Header, justification: Justification<Block::Hash>, body: Option<Vec<Block::Extrinsic>>) -> Result<ImportResult, Error>;
/// Get blockchain info.
fn info(&self) -> Result<ClientInfo, Error>;
fn info(&self) -> Result<ClientInfo<Block>, Error>;
/// Get block status.
fn block_status(&self, id: &BlockId) -> Result<BlockStatus, Error>;
fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error>;
/// Get block hash by number.
fn block_hash(&self, block_number: block::Number) -> Result<Option<block::HeaderHash>, Error>;
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error>;
/// Get block header.
fn header(&self, id: &BlockId) -> Result<Option<block::Header>, Error>;
fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error>;
/// Get block body.
fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error>;
fn body(&self, id: &BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, Error>;
/// Get block justification.
fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error>;
fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, Error>;
/// Get method execution proof.
fn execution_proof(&self, block: &block::HeaderHash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error>;
fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error>;
}
impl<B, E> Client for PolkadotClient<B, E> where
B: client::backend::Backend + Send + Sync + 'static,
E: CallExecutor + Send + Sync + 'static,
Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>, {
impl<B, E, Block> Client<Block> for PolkadotClient<B, E, Block> where
B: client::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
Block: BlockT,
Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>, {
fn import(&self, is_best: bool, header: block::Header, justification: Justification, body: Option<block::Body>) -> Result<ImportResult, Error> {
fn import(&self, is_best: bool, header: Block::Header, justification: Justification<Block::Hash>, body: Option<Vec<Block::Extrinsic>>) -> Result<ImportResult, Error> {
// TODO: defer justification check.
let justified_header = self.check_justification(header, justification.into())?;
let origin = if is_best { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync };
(self as &PolkadotClient<B, E>).import_block(origin, justified_header, body)
(self as &PolkadotClient<B, E, Block>).import_block(origin, justified_header, body)
}
fn info(&self) -> Result<ClientInfo, Error> {
(self as &PolkadotClient<B, E>).info()
fn info(&self) -> Result<ClientInfo<Block>, Error> {
(self as &PolkadotClient<B, E, Block>).info()
}
fn block_status(&self, id: &BlockId) -> Result<BlockStatus, Error> {
(self as &PolkadotClient<B, E>).block_status(id)
fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error> {
(self as &PolkadotClient<B, E, Block>).block_status(id)
}
fn block_hash(&self, block_number: block::Number) -> Result<Option<block::HeaderHash>, Error> {
(self as &PolkadotClient<B, E>).block_hash(block_number)
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error> {
(self as &PolkadotClient<B, E, Block>).block_hash(block_number)
}
fn header(&self, id: &BlockId) -> Result<Option<block::Header>, Error> {
(self as &PolkadotClient<B, E>).header(id)
fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error> {
(self as &PolkadotClient<B, E, Block>).header(id)
}
fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error> {
(self as &PolkadotClient<B, E>).body(id)
fn body(&self, id: &BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, Error> {
(self as &PolkadotClient<B, E, Block>).body(id)
}
fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error> {
(self as &PolkadotClient<B, E>).justification(id)
fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, Error> {
(self as &PolkadotClient<B, E, Block>).justification(id)
}
fn execution_proof(&self, block: &block::HeaderHash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error> {
(self as &PolkadotClient<B, E>).execution_proof(&BlockId::Hash(block.clone()), method, data)
fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error> {
(self as &PolkadotClient<B, E, Block>).execution_proof(&BlockId::Hash(block.clone()), method, data)
}
}
+48 -160
View File
@@ -17,46 +17,35 @@
//! Consensus related bits of the network service.
use std::collections::{HashMap, HashSet};
use futures::sync::{oneshot, mpsc};
use futures::sync::mpsc;
use std::time::{Instant, Duration};
use io::SyncIo;
use protocol::Protocol;
use network::PeerId;
use primitives::{Hash, block::Id as BlockId, block::Header};
use message::{self, Message};
use runtime_support::Hashable;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
use message::{self, generic::Message as GenericMessage};
// TODO: Add additional spam/DoS attack protection.
const MESSAGE_LIFETIME: Duration = Duration::from_secs(600);
struct CandidateRequest {
id: message::RequestId,
completion: oneshot::Sender<Vec<u8>>,
}
struct PeerConsensus {
candidate_fetch: Option<CandidateRequest>,
candidate_available: Option<Hash>,
known_messages: HashSet<Hash>,
struct PeerConsensus<H> {
known_messages: HashSet<H>,
}
/// Consensus network protocol handler. Manages statements and candidate requests.
pub struct Consensus {
peers: HashMap<PeerId, PeerConsensus>,
our_candidate: Option<(Hash, Vec<u8>)>,
statement_sink: Option<mpsc::UnboundedSender<message::Statement>>,
bft_message_sink: Option<(mpsc::UnboundedSender<message::LocalizedBftMessage>, Hash)>,
messages: Vec<(Hash, Instant, message::Message)>,
message_hashes: HashSet<Hash>,
pub struct Consensus<B: BlockT> {
peers: HashMap<PeerId, PeerConsensus<B::Hash>>,
bft_message_sink: Option<(mpsc::UnboundedSender<message::LocalizedBftMessage<B>>, B::Hash)>,
messages: Vec<(B::Hash, Instant, message::Message<B>)>,
message_hashes: HashSet<B::Hash>,
}
impl Consensus {
impl<B: BlockT> Consensus<B> where B::Header: HeaderT<Number=u64> {
/// Create a new instance.
pub fn new() -> Consensus {
pub fn new() -> Self {
Consensus {
peers: HashMap::new(),
our_candidate: None,
statement_sink: None,
bft_message_sink: None,
messages: Default::default(),
message_hashes: Default::default(),
@@ -65,12 +54,11 @@ impl Consensus {
/// Closes all notification streams.
pub fn restart(&mut self) {
self.statement_sink = None;
self.bft_message_sink = None;
}
/// Handle new connected peer.
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, roles: &[message::Role]) {
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, roles: &[message::Role]) {
if roles.iter().any(|r| *r == message::Role::Validator) {
trace!(target:"sync", "Registering validator {}", peer_id);
// Send out all known messages.
@@ -81,14 +69,12 @@ impl Consensus {
protocol.send_message(io, peer_id, message.clone());
}
self.peers.insert(peer_id, PeerConsensus {
candidate_fetch: None,
candidate_available: None,
known_messages,
});
}
}
fn propagate(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::Message, hash: Hash) {
fn propagate(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, message: message::Message<B>, hash: B::Hash) {
for (id, ref mut peer) in self.peers.iter_mut() {
if peer.known_messages.insert(hash.clone()) {
protocol.send_message(io, *id, message.clone());
@@ -96,48 +82,13 @@ impl Consensus {
}
}
fn register_message(&mut self, hash: Hash, message: message::Message) {
fn register_message(&mut self, hash: B::Hash, message: message::Message<B>) {
if self.message_hashes.insert(hash) {
self.messages.push((hash, Instant::now(), message));
}
}
pub fn on_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, statement: message::Statement, hash: Hash) {
if self.message_hashes.contains(&hash) {
trace!(target:"sync", "Ignored already known statement from {}", peer_id);
}
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
// TODO: validate signature?
match &statement.statement {
&message::UnsignedStatement::Candidate(ref receipt) => peer.candidate_available = Some(Hash::from(receipt.blake2_256())),
&message::UnsignedStatement::Available(ref hash) => peer.candidate_available = Some(*hash),
&message::UnsignedStatement::Valid(_) | &message::UnsignedStatement::Invalid(_) => (),
}
peer.known_messages.insert(hash);
if let Some(sink) = self.statement_sink.take() {
if let Err(e) = sink.unbounded_send(statement.clone()) {
trace!(target:"sync", "Error broadcasting statement notification: {:?}", e);
} else {
self.statement_sink = Some(sink);
}
}
} else {
trace!(target:"sync", "Ignored statement from unregistered peer {}", peer_id);
return;
}
let message = Message::Statement(statement);
self.register_message(hash.clone(), message.clone());
// Propagate to other peers.
self.propagate(io, protocol, message, hash);
}
pub fn statements(&mut self) -> mpsc::UnboundedReceiver<message::Statement>{
let (sink, stream) = mpsc::unbounded();
self.statement_sink = Some(sink);
stream
}
pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::LocalizedBftMessage, hash: Hash) {
pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, message: message::LocalizedBftMessage<B>, hash: B::Hash) {
if self.message_hashes.contains(&hash) {
trace!(target:"sync", "Ignored already known BFT message from {}", peer_id);
return;
@@ -149,7 +100,7 @@ impl Consensus {
return;
},
(Ok(info), Ok(Some(header))) => {
if header.number < info.chain.best_number {
if header.number() < &info.chain.best_number {
trace!(target:"sync", "Ignored ancient BFT message from {}, hash={}", peer_id, message.parent_hash);
return;
}
@@ -174,18 +125,18 @@ impl Consensus {
return;
}
let message = Message::BftMessage(message);
let message = GenericMessage::BftMessage(message);
self.register_message(hash.clone(), message.clone());
// Propagate to other peers.
self.propagate(io, protocol, message, hash);
}
pub fn bft_messages(&mut self, parent_hash: Hash) -> mpsc::UnboundedReceiver<message::LocalizedBftMessage>{
pub fn bft_messages(&mut self, parent_hash: B::Hash) -> mpsc::UnboundedReceiver<message::LocalizedBftMessage<B>> {
let (sink, stream) = mpsc::unbounded();
for &(_, _, ref message) in self.messages.iter() {
let bft_message = match *message {
Message::BftMessage(ref msg) => msg,
GenericMessage::BftMessage(ref msg) => msg,
_ => continue,
};
@@ -198,90 +149,20 @@ impl Consensus {
stream
}
pub fn fetch_candidate(&mut self, io: &mut SyncIo, protocol: &Protocol, hash: &Hash) -> oneshot::Receiver<Vec<u8>> {
// Request from the first peer that has it available.
// TODO: random peer selection.
trace!(target:"sync", "Trying to fetch candidate {:?}", hash);
let (sender, receiver) = oneshot::channel();
if let Some((peer_id, ref mut peer)) = self.peers.iter_mut()
.find(|&(_, ref peer)| peer.candidate_fetch.is_none() && peer.candidate_available.as_ref().map_or(false, |h| h == hash)) {
trace!(target:"sync", "Fetching candidate from {}", peer_id);
let id = 0; //TODO: generate unique id
peer.candidate_fetch = Some(CandidateRequest {
id: id,
completion: sender,
});
let request = message::CandidateRequest {
id: id,
hash: *hash,
};
protocol.send_message(io, *peer_id, Message::CandidateRequest(request));
}
// If no peer found `sender` is dropped and `receiver` is canceled immediatelly.
return receiver;
}
pub fn send_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, statement: message::Statement) {
// Broadcast statement to all validators.
trace!(target:"sync", "Broadcasting statement {:?}", statement);
let message = Message::Statement(statement);
let hash = Protocol::hash_message(&message);
self.register_message(hash.clone(), message.clone());
self.propagate(io, protocol, message, hash);
}
pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::LocalizedBftMessage) {
pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, message: message::LocalizedBftMessage<B>) {
// Broadcast message to all validators.
trace!(target:"sync", "Broadcasting BFT message {:?}", message);
let message = Message::BftMessage(message);
let message = GenericMessage::BftMessage(message);
let hash = Protocol::hash_message(&message);
self.register_message(hash.clone(), message.clone());
self.propagate(io, protocol, message, hash);
}
pub fn set_local_candidate(&mut self, candidate: Option<(Hash, Vec<u8>)>) {
trace!(target:"sync", "Set local candidate to {:?}", candidate.as_ref().map(|&(h, _)| h));
self.our_candidate = candidate;
}
pub fn on_candidate_request(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, request: message::CandidateRequest) {
let response = match self.our_candidate {
Some((ref hash, ref data)) if *hash == request.hash => Some(data.clone()),
_ => None,
};
let msg = message::CandidateResponse {
id: request.id,
data: response,
};
protocol.send_message(io, peer_id, Message::CandidateResponse(msg));
}
pub fn on_candidate_response(&mut self, io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId, response: message::CandidateResponse) {
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
if let Some(request) = peer.candidate_fetch.take() {
if response.id == request.id {
if let Some(data) = response.data {
if let Err(e) = request.completion.send(data) {
trace!(target:"sync", "Error sending candidate data notification: {:?}", e);
}
}
} else {
trace!(target:"sync", "Unexpected candidate response from {}", peer_id);
io.disable_peer(peer_id);
}
} else {
trace!(target:"sync", "Unexpected candidate response from {}", peer_id);
io.disable_peer(peer_id);
}
}
}
pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId) {
pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol<B>, peer_id: PeerId) {
self.peers.remove(&peer_id);
}
pub fn collect_garbage(&mut self, best_header: Option<&Header>) {
pub fn collect_garbage(&mut self, best_header: Option<&B::Header>) {
let hashes = &mut self.message_hashes;
let before = self.messages.len();
let now = Instant::now();
@@ -289,8 +170,7 @@ impl Consensus {
if timestamp >= now - MESSAGE_LIFETIME &&
best_header.map_or(true, |header|
match *message {
Message::BftMessage(ref msg) => msg.parent_hash != header.parent_hash,
Message::Statement(ref msg) => msg.parent_hash != header.parent_hash,
GenericMessage::BftMessage(ref msg) => &msg.parent_hash != header.parent_hash(),
_ => true,
})
{
@@ -311,32 +191,33 @@ impl Consensus {
#[cfg(test)]
mod tests {
use primitives::Hash;
use primitives::bft::Justification;
use primitives::block::{HeaderHash, Header};
use runtime_primitives::bft::Justification;
use runtime_primitives::testing::{H256, Header, Block as RawBlock};
use std::time::Instant;
use message::{self, Message};
use message::{self, generic::Message as GenericMessage};
use super::{Consensus, MESSAGE_LIFETIME};
type Block = RawBlock<u64>;
#[test]
fn collects_garbage() {
let prev_hash = HeaderHash::random();
let best_hash = HeaderHash::random();
let mut consensus = Consensus::new();
let prev_hash = H256::random();
let best_hash = H256::random();
let mut consensus = Consensus::<Block>::new();
let now = Instant::now();
let m1_hash = Hash::random();
let m2_hash = Hash::random();
let m1 = Message::BftMessage(message::LocalizedBftMessage {
let m1_hash = H256::random();
let m2_hash = H256::random();
let m1 = GenericMessage::BftMessage(message::LocalizedBftMessage {
parent_hash: prev_hash,
message: message::BftMessage::Auxiliary(Justification {
message: message::generic::BftMessage::Auxiliary(Justification {
round_number: 0,
hash: Default::default(),
signatures: Default::default(),
}),
});
let m2 = Message::BftMessage(message::LocalizedBftMessage {
let m2 = GenericMessage::BftMessage(message::LocalizedBftMessage {
parent_hash: best_hash,
message: message::BftMessage::Auxiliary(Justification {
message: message::generic::BftMessage::Auxiliary(Justification {
round_number: 0,
hash: Default::default(),
signatures: Default::default(),
@@ -353,7 +234,14 @@ mod tests {
assert_eq!(consensus.message_hashes.len(), 2);
// random header, nothing should be cleared
let mut header = Header::from_block_number(0);
let mut header = Header {
parent_hash: H256::default(),
number: 0,
state_root: H256::default(),
extrinsics_root: H256::default(),
digest: Default::default(),
};
consensus.collect_garbage(Some(&header));
assert_eq!(consensus.messages.len(), 2);
assert_eq!(consensus.message_hashes.len(), 2);
+4 -10
View File
@@ -30,6 +30,7 @@ extern crate substrate_state_machine as state_machine;
extern crate substrate_serializer as ser;
extern crate substrate_client as client;
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_bft;
extern crate serde;
extern crate serde_json;
@@ -59,19 +60,12 @@ pub mod error;
#[cfg(test)] mod test;
pub use service::{Service, FetchFuture, StatementStream, ConsensusService, BftMessageStream,
pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream,
TransactionPool, Params, ManageNetwork, SyncProvider};
pub use protocol::{ProtocolStatus};
pub use sync::{Status as SyncStatus, SyncState};
pub use network::{NonReservedPeerMode, NetworkConfiguration};
pub use network_devp2p::{ConnectionFilter, ConnectionDirection};
pub use message::{Statement, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal};
pub use network::{NonReservedPeerMode, NetworkConfiguration, ConnectionFilter, ConnectionDirection};
pub use message::{generic as generic_message, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal};
pub use error::Error;
pub use config::{Role, ProtocolConfig};
pub use on_demand::{OnDemand, OnDemandService, Response as OnDemandResponse};
// TODO: move it elsewhere
fn header_hash(header: &primitives::Header) -> primitives::block::HeaderHash {
use runtime_support::Hashable;
header.blake2_256().into()
}
+255 -246
View File
@@ -16,14 +16,74 @@
//! Network packet message types. These get serialized and put into the lower level protocol payload.
use primitives::{AuthorityId, Hash};
use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body, Block};
use primitives::bft::Justification;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use service::Role as RoleFlags;
use ed25519;
pub use self::generic::{BlockAnnounce, RemoteCallRequest, ConsensusVote, SignedConsensusVote, FromBlock};
pub type RequestId = u64;
type Bytes = Vec<u8>;
/// Type alias for using the message type using block type parameters.
pub type Message<B> = generic::Message<
B,
<B as BlockT>::Header,
<B as BlockT>::Hash,
<<B as BlockT>::Header as HeaderT>::Number,
<B as BlockT>::Extrinsic,
>;
/// Type alias for using the status type using block type parameters.
pub type Status<B> = generic::Status<
<B as BlockT>::Hash,
<<B as BlockT>::Header as HeaderT>::Number,
>;
/// Type alias for using the block request type using block type parameters.
pub type BlockRequest<B> = generic::BlockRequest<
<B as BlockT>::Hash,
<<B as BlockT>::Header as HeaderT>::Number,
>;
/// Type alias for using the localized bft message type using block type parameters.
pub type LocalizedBftMessage<B> = generic::LocalizedBftMessage<
B,
<B as BlockT>::Hash,
>;
/// Type alias for using the BlockData type using block type parameters.
pub type BlockData<B> = generic::BlockData<
<B as BlockT>::Header,
<B as BlockT>::Hash,
<B as BlockT>::Extrinsic,
>;
/// Type alias for using the BlockResponse type using block type parameters.
pub type BlockResponse<B> = generic::BlockResponse<
<B as BlockT>::Header,
<B as BlockT>::Hash,
<B as BlockT>::Extrinsic,
>;
/// Type alias for using the BftMessage type using block type parameters.
pub type BftMessage<B> = generic::BftMessage<
B,
<B as BlockT>::Hash,
>;
/// Type alias for using the SignedConsensusProposal type using block type parameters.
pub type SignedConsensusProposal<B> = generic::SignedConsensusProposal<
B,
<B as BlockT>::Hash,
>;
/// Type alias for using the SignedConsensusProposal type using block type parameters.
pub type SignedConsensusMessage<B> = generic::SignedConsensusProposal<
B,
<B as BlockT>::Hash,
>;
/// A set of transactions.
pub type Transactions<E> = Vec<E>;
/// Configured node role.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
@@ -73,8 +133,8 @@ impl From<RoleFlags> for Vec<Role> where {
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
/// Bits of block data and associated artefacts to request.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
pub enum BlockAttribute {
/// Include block header.
Header,
@@ -88,33 +148,6 @@ pub enum BlockAttribute {
Justification,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Block data sent in the response.
pub struct BlockData {
/// Block header hash.
pub hash: HeaderHash,
/// Block header if requested.
pub header: Option<Header>,
/// Block body if requested.
pub body: Option<Body>,
/// Block receipt if requested.
pub receipt: Option<Bytes>,
/// Block message queue if requested.
pub message_queue: Option<Bytes>,
/// Justification if requested.
pub justification: Option<Justification>,
}
#[serde(untagged)]
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Identifies starting point of a block sequence.
pub enum FromBlock {
/// Start with given hash.
Hash(HeaderHash),
/// Start with given block number.
Number(BlockNumber),
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Block enumeration direction.
pub enum Direction {
@@ -124,219 +157,6 @@ pub enum Direction {
Descending,
}
/// A set of transactions.
pub type Transactions = Vec<Vec<u8>>;
/// Statements circulated among peers.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum UnsignedStatement {
/// Broadcast by a authority to indicate that this is his candidate for
/// inclusion.
///
/// Broadcasting two different candidate messages per round is not allowed.
Candidate(Vec<u8>),
/// Broadcast by a authority to attest that the candidate with given digest
/// is valid.
Valid(Hash),
/// Broadcast by a authority to attest that the auxiliary data for a candidate
/// with given digest is available.
Available(Hash),
/// Broadcast by a authority to attest that the candidate with given digest
/// is invalid.
Invalid(Hash),
}
/// A signed statement.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Statement {
/// Parent relay chain block header hash.
pub parent_hash: HeaderHash,
/// The statement.
pub statement: UnsignedStatement,
/// The signature.
pub signature: ed25519::Signature,
/// The sender.
pub sender: AuthorityId,
}
/// Communication that can occur between participants in consensus.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum BftMessage {
/// A consensus message (proposal or vote)
Consensus(SignedConsensusMessage),
/// Auxiliary communication (just proof-of-lock for now).
Auxiliary(Justification),
}
/// BFT Consensus message with parent header hash attached to it.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct LocalizedBftMessage {
/// Consensus message.
pub message: BftMessage,
/// Parent header hash.
pub parent_hash: HeaderHash,
}
/// A localized proposal message. Contains two signed pieces of data.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct SignedConsensusProposal {
/// The round number.
pub round_number: u32,
/// The proposal sent.
pub proposal: Block,
/// The digest of the proposal.
pub digest: Hash,
/// The sender of the proposal
pub sender: AuthorityId,
/// The signature on the message (propose, round number, digest)
pub digest_signature: ed25519::Signature,
/// The signature on the message (propose, round number, proposal)
pub full_signature: ed25519::Signature,
}
/// A localized vote message, including the sender.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct SignedConsensusVote {
/// The message sent.
pub vote: ConsensusVote,
/// The sender of the message
pub sender: AuthorityId,
/// The signature of the message.
pub signature: ed25519::Signature,
}
/// Votes during a consensus round.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum ConsensusVote {
/// Prepare to vote for proposal with digest D.
Prepare(u32, Hash),
/// Commit to proposal with digest D..
Commit(u32, Hash),
/// Propose advancement to a new round.
AdvanceRound(u32),
}
/// A localized message.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum SignedConsensusMessage {
/// A proposal.
Propose(SignedConsensusProposal),
/// A vote.
Vote(SignedConsensusVote),
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// A network message.
pub enum Message {
/// Status packet.
Status(Status),
/// Block request.
BlockRequest(BlockRequest),
/// Block response.
BlockResponse(BlockResponse),
/// Block announce.
BlockAnnounce(BlockAnnounce),
/// Transactions.
Transactions(Transactions),
/// Consensus statement.
Statement(Statement),
/// Candidate data request.
CandidateRequest(CandidateRequest),
/// Candidate response.
CandidateResponse(CandidateResponse),
/// BFT Consensus statement.
BftMessage(LocalizedBftMessage),
/// Remote method call request.
RemoteCallRequest(RemoteCallRequest),
/// Remote method call response.
RemoteCallResponse(RemoteCallResponse),
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Status {
/// Protocol version.
pub version: u32,
/// Supported roles.
pub roles: Vec<Role>,
/// Best block number.
pub best_number: BlockNumber,
/// Best block hash.
pub best_hash: HeaderHash,
/// Genesis block hash.
pub genesis_hash: HeaderHash,
/// Signatue of `best_hash` made with validator address. Required for the validator role.
pub validator_signature: Option<ed25519::Signature>,
/// Validator address. Required for the validator role.
pub validator_id: Option<AuthorityId>,
/// Parachain id. Required for the collator role.
pub parachain_id: Option<u64>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Request block data from a peer.
pub struct BlockRequest {
/// Unique request id.
pub id: RequestId,
/// Bits of block data to request.
pub fields: Vec<BlockAttribute>,
/// Start from this block.
pub from: FromBlock,
/// End at this block. An implementation defined maximum is used when unspecified.
pub to: Option<HeaderHash>,
/// Sequence direction.
pub direction: Direction,
/// Maximum number of blocks to return. An implementation defined maximum is used when unspecified.
pub max: Option<u32>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Request candidate block data from a peer.
pub struct CandidateRequest {
/// Unique request id.
pub id: RequestId,
/// Candidate receipt hash.
pub hash: Hash,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Candidate block data response.
pub struct CandidateResponse {
/// Unique request id.
pub id: RequestId,
/// Candidate data. Empty if the peer does not have the candidate anymore.
pub data: Option<Vec<u8>>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Response to `BlockRequest`
pub struct BlockResponse {
/// Id of a request this response was made for.
pub id: RequestId,
/// Block data for the requested sequence.
pub blocks: Vec<BlockData>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Announce a new complete relay chain block on the network.
pub struct BlockAnnounce {
/// New block header.
pub header: Header,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Remote call request.
pub struct RemoteCallRequest {
/// Unique request id.
pub id: RequestId,
/// Block at which to perform call.
pub block: HeaderHash,
/// Method name.
pub method: String,
/// Call data.
pub data: Vec<u8>,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Remote call response.
pub struct RemoteCallResponse {
@@ -347,3 +167,192 @@ pub struct RemoteCallResponse {
/// Execution proof.
pub proof: Vec<Vec<u8>>,
}
/// Generic types.
pub mod generic {
use primitives::AuthorityId;
use runtime_primitives::bft::Justification;
use ed25519;
use super::{Role, BlockAttribute, RemoteCallResponse, RequestId, Transactions, Direction};
/// Block data sent in the response.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct BlockData<Header, Hash, Extrinsic> {
/// Block header hash.
pub hash: Hash,
/// Block header if requested.
pub header: Option<Header>,
/// Block body if requested.
pub body: Option<Vec<Extrinsic>>,
/// Block receipt if requested.
pub receipt: Option<Vec<u8>>,
/// Block message queue if requested.
pub message_queue: Option<Vec<u8>>,
/// Justification if requested.
pub justification: Option<Justification<Hash>>,
}
/// Identifies starting point of a block sequence.
#[serde(untagged)]
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum FromBlock<Hash, Number> {
/// Start with given hash.
Hash(Hash),
/// Start with given block number.
Number(Number),
}
/// Communication that can occur between participants in consensus.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum BftMessage<Block, Hash> {
/// A consensus message (proposal or vote)
Consensus(SignedConsensusMessage<Block, Hash>),
/// Auxiliary communication (just proof-of-lock for now).
Auxiliary(Justification<Hash>),
}
/// BFT Consensus message with parent header hash attached to it.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct LocalizedBftMessage<Block, Hash> {
/// Consensus message.
pub message: BftMessage<Block, Hash>,
/// Parent header hash.
pub parent_hash: Hash,
}
/// A localized proposal message. Contains two signed pieces of data.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct SignedConsensusProposal<Block, Hash> {
/// The round number.
pub round_number: u32,
/// The proposal sent.
pub proposal: Block,
/// The digest of the proposal.
pub digest: Hash,
/// The sender of the proposal
pub sender: AuthorityId,
/// The signature on the message (propose, round number, digest)
pub digest_signature: ed25519::Signature,
/// The signature on the message (propose, round number, proposal)
pub full_signature: ed25519::Signature,
}
/// A localized vote message, including the sender.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct SignedConsensusVote<H> {
/// The message sent.
pub vote: ConsensusVote<H>,
/// The sender of the message
pub sender: AuthorityId,
/// The signature of the message.
pub signature: ed25519::Signature,
}
/// Votes during a consensus round.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum ConsensusVote<H> {
/// Prepare to vote for proposal with digest D.
Prepare(u32, H),
/// Commit to proposal with digest D..
Commit(u32, H),
/// Propose advancement to a new round.
AdvanceRound(u32),
}
/// A localized message.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum SignedConsensusMessage<Block, Hash> {
/// A proposal.
Propose(SignedConsensusProposal<Block, Hash>),
/// A vote.
Vote(SignedConsensusVote<Hash>),
}
/// A network message.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum Message<Block, Header, Hash, Number, Extrinsic> {
/// Status packet.
Status(Status<Hash, Number>),
/// Block request.
BlockRequest(BlockRequest<Hash, Number>),
/// Block response.
BlockResponse(BlockResponse<Header, Hash, Extrinsic>),
/// Block announce.
BlockAnnounce(BlockAnnounce<Header>),
/// Transactions.
Transactions(Transactions<Extrinsic>),
/// BFT Consensus statement.
BftMessage(LocalizedBftMessage<Block, Hash>),
/// Remote method call request.
RemoteCallRequest(RemoteCallRequest<Hash>),
/// Remote method call response.
RemoteCallResponse(RemoteCallResponse),
}
/// Status sent on connection.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Status<Hash, Number> {
/// Protocol version.
pub version: u32,
/// Supported roles.
pub roles: Vec<Role>,
/// Best block number.
pub best_number: Number,
/// Best block hash.
pub best_hash: Hash,
/// Genesis block hash.
pub genesis_hash: Hash,
/// Signatue of `best_hash` made with validator address. Required for the validator role.
pub validator_signature: Option<ed25519::Signature>,
/// Validator address. Required for the validator role.
pub validator_id: Option<AuthorityId>,
/// Parachain id. Required for the collator role.
pub parachain_id: Option<u64>,
}
/// Request block data from a peer.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct BlockRequest<Hash, Number> {
/// Unique request id.
pub id: RequestId,
/// Bits of block data to request.
pub fields: Vec<BlockAttribute>,
/// Start from this block.
pub from: FromBlock<Hash, Number>,
/// End at this block. An implementation defined maximum is used when unspecified.
pub to: Option<Hash>,
/// Sequence direction.
pub direction: Direction,
/// Maximum number of blocks to return. An implementation defined maximum is used when unspecified.
pub max: Option<u32>,
}
/// Response to `BlockRequest`
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct BlockResponse<Header, Hash, Extrinsic> {
/// Id of a request this response was made for.
pub id: RequestId,
/// Block data for the requested sequence.
pub blocks: Vec<BlockData<Header, Hash, Extrinsic>>,
}
/// Announce a new complete relay chain block on the network.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct BlockAnnounce<H> {
/// New block header.
pub header: H,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Remote call request.
pub struct RemoteCallRequest<H> {
/// Unique request id.
pub id: RequestId,
/// Block at which to perform call.
pub block: H,
/// Method name.
pub method: String,
/// Call data.
pub data: Vec<u8>,
}
}
+43 -26
View File
@@ -30,6 +30,7 @@ use io::SyncIo;
use message;
use network::PeerId;
use service;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
/// Remote request timeout.
const REQUEST_TIMEOUT: Duration = Duration::from_secs(15);
@@ -50,9 +51,9 @@ pub trait OnDemandService: Send + Sync {
}
/// On-demand requests service. Dispatches requests to appropriate peers.
pub struct OnDemand<E: service::ExecuteInContext> {
core: Mutex<OnDemandCore<E>>,
checker: Arc<FetchChecker>,
pub struct OnDemand<B: BlockT, E: service::ExecuteInContext<B>> {
core: Mutex<OnDemandCore<B, E>>,
checker: Arc<FetchChecker<B>>,
}
/// On-demand response.
@@ -61,19 +62,19 @@ pub struct Response {
}
#[derive(Default)]
struct OnDemandCore<E: service::ExecuteInContext> {
struct OnDemandCore<B: BlockT, E: service::ExecuteInContext<B>> {
service: Weak<E>,
next_request_id: u64,
pending_requests: VecDeque<Request>,
active_peers: LinkedHashMap<PeerId, Request>,
pending_requests: VecDeque<Request<B::Hash>>,
active_peers: LinkedHashMap<PeerId, Request<B::Hash>>,
idle_peers: VecDeque<PeerId>,
}
struct Request {
struct Request<H> {
id: u64,
timestamp: Instant,
sender: Sender<client::CallResult>,
request: RemoteCallRequest,
request: RemoteCallRequest<H>,
}
impl Future for Response {
@@ -86,9 +87,12 @@ impl Future for Response {
}
}
impl<E> OnDemand<E> where E: service::ExecuteInContext {
impl<B: BlockT, E> OnDemand<B, E> where
E: service::ExecuteInContext<B>,
B::Header: HeaderT<Number=u64>,
{
/// Creates new on-demand service.
pub fn new(checker: Arc<FetchChecker>) -> Self {
pub fn new(checker: Arc<FetchChecker<B>>) -> Self {
OnDemand {
checker,
core: Mutex::new(OnDemandCore {
@@ -107,7 +111,7 @@ impl<E> OnDemand<E> where E: service::ExecuteInContext {
}
/// Execute method call on remote node, returning execution result and proof.
pub fn remote_call(&self, request: RemoteCallRequest) -> Response {
pub fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Response {
let (sender, receiver) = channel();
let result = Response {
receiver: receiver,
@@ -123,7 +127,11 @@ impl<E> OnDemand<E> where E: service::ExecuteInContext {
}
}
impl<E> OnDemandService for OnDemand<E> where E: service::ExecuteInContext {
impl<B, E> OnDemandService for OnDemand<B, E> where
B: BlockT,
E: service::ExecuteInContext<B>,
B::Header: HeaderT<Number=u64>,
{
fn on_connect(&self, peer: PeerId, role: service::Role) {
if !role.intersects(service::Role::FULL | service::Role::COLLATOR | service::Role::VALIDATOR) { // TODO: correct?
return;
@@ -175,15 +183,23 @@ impl<E> OnDemandService for OnDemand<E> where E: service::ExecuteInContext {
}
}
impl<E> Fetcher for OnDemand<E> where E: service::ExecuteInContext {
impl<B, E> Fetcher<B> for OnDemand<B, E> where
B: BlockT,
E: service::ExecuteInContext<B>,
B::Header: HeaderT<Number=u64>,
{
type RemoteCallResult = Response;
fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult {
self.remote_call(request)
fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Self::RemoteCallResult {
OnDemand::remote_call(self, request)
}
}
impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
impl<B, E> OnDemandCore<B, E> where
B: BlockT,
E: service::ExecuteInContext<B> ,
B::Header: HeaderT<Number=u64>
{
pub fn add_peer(&mut self, peer: PeerId) {
self.idle_peers.push_back(peer);
}
@@ -214,7 +230,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
}
}
pub fn insert(&mut self, sender: Sender<client::CallResult>, request: RemoteCallRequest) {
pub fn insert(&mut self, sender: Sender<client::CallResult>, request: RemoteCallRequest<B::Hash>) {
let request_id = self.next_request_id;
self.next_request_id += 1;
@@ -226,7 +242,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
});
}
pub fn remove(&mut self, peer: PeerId, id: u64) -> Option<Request> {
pub fn remove(&mut self, peer: PeerId, id: u64) -> Option<Request<B::Hash>> {
match self.active_peers.entry(peer) {
Entry::Occupied(entry) => match entry.get().id == id {
true => {
@@ -263,7 +279,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
data: request.request.call_data.clone(),
};
protocol.send_message(ctx, peer, message::Message::RemoteCallRequest(message))
protocol.send_message(ctx, peer, message::generic::Message::RemoteCallRequest(message))
});
self.active_peers.insert(peer, request);
}
@@ -286,16 +302,17 @@ mod tests {
use service::{Role, ExecuteInContext};
use test::TestIo;
use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService};
use test_client::runtime::{Block, Hash};
struct DummyExecutor;
struct DummyFetchChecker { ok: bool }
impl ExecuteInContext for DummyExecutor {
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, _closure: F) {}
impl ExecuteInContext<Block> for DummyExecutor {
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<Block>)>(&self, _closure: F) {}
}
impl FetchChecker for DummyFetchChecker {
fn check_execution_proof(&self, _request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> client::error::Result<client::CallResult> {
impl FetchChecker<Block> for DummyFetchChecker {
fn check_execution_proof(&self, _request: &RemoteCallRequest<Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> client::error::Result<client::CallResult> {
match self.ok {
true => Ok(client::CallResult {
return_data: remote_proof.0,
@@ -306,19 +323,19 @@ mod tests {
}
}
fn dummy(ok: bool) -> (Arc<DummyExecutor>, Arc<OnDemand<DummyExecutor>>) {
fn dummy(ok: bool) -> (Arc<DummyExecutor>, Arc<OnDemand<Block, DummyExecutor>>) {
let executor = Arc::new(DummyExecutor);
let service = Arc::new(OnDemand::new(Arc::new(DummyFetchChecker { ok })));
service.set_service_link(Arc::downgrade(&executor));
(executor, service)
}
fn total_peers(on_demand: &OnDemand<DummyExecutor>) -> usize {
fn total_peers(on_demand: &OnDemand<Block, DummyExecutor>) -> usize {
let core = on_demand.core.lock();
core.idle_peers.len() + core.active_peers.len()
}
fn receive_response(on_demand: &OnDemand<DummyExecutor>, network: &mut TestIo, peer: PeerId, id: message::RequestId) {
fn receive_response(on_demand: &OnDemand<Block, DummyExecutor>, network: &mut TestIo, peer: PeerId, id: message::RequestId) {
on_demand.on_remote_response(network, peer, message::RemoteCallResponse {
id: id,
value: vec![1],
+68 -101
View File
@@ -19,23 +19,21 @@ use std::{mem, cmp};
use std::sync::Arc;
use std::time;
use parking_lot::{RwLock, Mutex};
use futures::sync::oneshot;
use serde_json;
use primitives::block::{HeaderHash, ExtrinsicHash, Number as BlockNumber, Header, Id as BlockId};
use primitives::{Hash, blake2_256};
use runtime_support::Hashable;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing, HashingFor};
use runtime_primitives::generic::BlockId;
use network::PeerId;
use message::{self, Message};
use message::generic::Message as GenericMessage;
use sync::{ChainSync, Status as SyncStatus, SyncState};
use consensus::Consensus;
use service::{Role, TransactionPool, StatementStream, BftMessageStream};
use service::{Role, TransactionPool, BftMessageStream};
use config::ProtocolConfig;
use chain::Client;
use on_demand::OnDemandService;
use io::SyncIo;
use error;
use super::header_hash;
const REQUEST_TIMEOUT_SEC: u64 = 40;
const PROTOCOL_VERSION: u32 = 0;
@@ -44,25 +42,25 @@ const PROTOCOL_VERSION: u32 = 0;
const MAX_BLOCK_DATA_RESPONSE: u32 = 128;
// Lock must always be taken in order declared here.
pub struct Protocol {
pub struct Protocol<B: BlockT> {
config: ProtocolConfig,
chain: Arc<Client>,
chain: Arc<Client<B>>,
on_demand: Option<Arc<OnDemandService>>,
genesis_hash: HeaderHash,
sync: RwLock<ChainSync>,
consensus: Mutex<Consensus>,
genesis_hash: B::Hash,
sync: RwLock<ChainSync<B>>,
consensus: Mutex<Consensus<B>>,
// All connected peers
peers: RwLock<HashMap<PeerId, Peer>>,
peers: RwLock<HashMap<PeerId, Peer<B>>>,
// Connected peers pending Status message.
handshaking_peers: RwLock<HashMap<PeerId, time::Instant>>,
transaction_pool: Arc<TransactionPool>,
transaction_pool: Arc<TransactionPool<B>>,
}
/// Syncing status and statistics
#[derive(Clone)]
pub struct ProtocolStatus {
pub struct ProtocolStatus<B: BlockT> {
/// Sync status.
pub sync: SyncStatus,
pub sync: SyncStatus<B>,
/// Total number of connected peers
pub num_peers: usize,
/// Total number of active peers.
@@ -70,42 +68,49 @@ pub struct ProtocolStatus {
}
/// Peer information
struct Peer {
struct Peer<B: BlockT> {
/// Protocol version
protocol_version: u32,
/// Roles
roles: Role,
/// Peer best block hash
best_hash: HeaderHash,
best_hash: B::Hash,
/// Peer best block number
best_number: BlockNumber,
best_number: <B::Header as HeaderT>::Number,
/// Pending block request if any
block_request: Option<message::BlockRequest>,
block_request: Option<message::BlockRequest<B>>,
/// Request timestamp
request_timestamp: Option<time::Instant>,
/// Holds a set of transactions known to this peer.
known_transactions: HashSet<ExtrinsicHash>,
known_transactions: HashSet<B::Hash>,
/// Holds a set of blocks known to this peer.
known_blocks: HashSet<HeaderHash>,
known_blocks: HashSet<B::Hash>,
/// Request counter,
next_request_id: message::RequestId,
}
#[derive(Debug)]
pub struct PeerInfo {
pub struct PeerInfo<B: BlockT> {
/// Roles
pub roles: Role,
/// Protocol version
pub protocol_version: u32,
/// Peer best block hash
pub best_hash: HeaderHash,
pub best_hash: B::Hash,
/// Peer best block number
pub best_number: BlockNumber,
pub best_number: <B::Header as HeaderT>::Number,
}
impl Protocol {
impl<B: BlockT> Protocol<B> where
B::Header: HeaderT<Number=u64>
{
/// Create a new instance.
pub fn new(config: ProtocolConfig, chain: Arc<Client>, on_demand: Option<Arc<OnDemandService>>, transaction_pool: Arc<TransactionPool>) -> error::Result<Protocol> {
pub fn new(
config: ProtocolConfig,
chain: Arc<Client<B>>,
on_demand: Option<Arc<OnDemandService>>,
transaction_pool: Arc<TransactionPool<B>>
) -> error::Result<Self> {
let info = chain.info()?;
let sync = ChainSync::new(config.roles, &info);
let protocol = Protocol {
@@ -123,7 +128,7 @@ impl Protocol {
}
/// Returns protocol status
pub fn status(&self) -> ProtocolStatus {
pub fn status(&self) -> ProtocolStatus<B> {
let sync = self.sync.read();
let peers = self.peers.read();
ProtocolStatus {
@@ -134,7 +139,7 @@ impl Protocol {
}
pub fn handle_packet(&self, io: &mut SyncIo, peer_id: PeerId, data: &[u8]) {
let message: Message = match serde_json::from_slice(data) {
let message: Message<B> = match serde_json::from_slice(data) {
Ok(m) => m,
Err(e) => {
debug!("Invalid packet from {}: {}", peer_id, e);
@@ -144,9 +149,9 @@ impl Protocol {
};
match message {
Message::Status(s) => self.on_status_message(io, peer_id, s),
Message::BlockRequest(r) => self.on_block_request(io, peer_id, r),
Message::BlockResponse(r) => {
GenericMessage::Status(s) => self.on_status_message(io, peer_id, s),
GenericMessage::BlockRequest(r) => self.on_block_request(io, peer_id, r),
GenericMessage::BlockResponse(r) => {
let request = {
let mut peers = self.peers.write();
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
@@ -171,22 +176,19 @@ impl Protocol {
}
self.on_block_response(io, peer_id, request, r);
},
Message::BlockAnnounce(announce) => {
GenericMessage::BlockAnnounce(announce) => {
self.on_block_announce(io, peer_id, announce);
},
Message::Statement(s) => self.on_statement(io, peer_id, s, blake2_256(data).into()),
Message::CandidateRequest(r) => self.on_candidate_request(io, peer_id, r),
Message::CandidateResponse(r) => self.on_candidate_response(io, peer_id, r),
Message::BftMessage(m) => self.on_bft_message(io, peer_id, m, blake2_256(data).into()),
Message::Transactions(m) => self.on_transactions(io, peer_id, m),
Message::RemoteCallRequest(request) => self.on_remote_call_request(io, peer_id, request),
Message::RemoteCallResponse(response) => self.on_remote_call_response(io, peer_id, response)
GenericMessage::BftMessage(m) => self.on_bft_message(io, peer_id, m, HashingFor::<B>::hash(data)),
GenericMessage::Transactions(m) => self.on_transactions(io, peer_id, m),
GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(io, peer_id, request),
GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(io, peer_id, response)
}
}
pub fn send_message(&self, io: &mut SyncIo, peer_id: PeerId, mut message: Message) {
pub fn send_message(&self, io: &mut SyncIo, peer_id: PeerId, mut message: Message<B>) {
match &mut message {
&mut Message::BlockRequest(ref mut r) => {
&mut GenericMessage::BlockRequest(ref mut r) => {
let mut peers = self.peers.write();
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
r.id = peer.next_request_id;
@@ -204,9 +206,9 @@ impl Protocol {
}
}
pub fn hash_message(message: &Message) -> Hash {
pub fn hash_message(message: &Message<B>) -> B::Hash {
let data = serde_json::to_vec(&message).expect("Serializer is infallible; qed");
blake2_256(&data).into()
HashingFor::<B>::hash(&data)
}
/// Called when a new peer is connected
@@ -232,7 +234,7 @@ impl Protocol {
}
}
fn on_block_request(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest) {
fn on_block_request(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest<B>) {
trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", request.id, peer, request.from, request.to, request.max);
let mut blocks = Vec::new();
let mut id = match request.from {
@@ -255,9 +257,9 @@ impl Protocol {
if blocks.len() >= max{
break;
}
let number = header.number;
let hash = header_hash(&header);
let block_data = message::BlockData {
let number = header.number().clone();
let hash = header.hash();
let block_data = message::generic::BlockData {
hash: hash,
header: if get_header { Some(header) } else { None },
body: if get_body { self.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } else { None },
@@ -276,69 +278,34 @@ impl Protocol {
}
}
}
let response = message::BlockResponse {
let response = message::generic::BlockResponse {
id: request.id,
blocks: blocks,
};
self.send_message(io, peer, Message::BlockResponse(response))
self.send_message(io, peer, GenericMessage::BlockResponse(response))
}
fn on_block_response(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest, response: message::BlockResponse) {
fn on_block_response(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest<B>, response: message::BlockResponse<B>) {
// TODO: validate response
trace!(target: "sync", "BlockResponse {} from {} with {} blocks", response.id, peer, response.blocks.len());
self.sync.write().on_block_data(io, self, peer, request, response);
}
fn on_candidate_request(&self, io: &mut SyncIo, peer: PeerId, request: message::CandidateRequest) {
trace!(target: "sync", "CandidateRequest {} from {} for {}", request.id, peer, request.hash);
self.consensus.lock().on_candidate_request(io, self, peer, request);
}
fn on_candidate_response(&self, io: &mut SyncIo, peer: PeerId, response: message::CandidateResponse) {
trace!(target: "sync", "CandidateResponse {} from {} with {:?} bytes", response.id, peer, response.data.as_ref().map(|d| d.len()));
self.consensus.lock().on_candidate_response(io, self, peer, response);
}
fn on_statement(&self, io: &mut SyncIo, peer: PeerId, statement: message::Statement, hash: Hash) {
trace!(target: "sync", "Statement from {}: {:?}", peer, statement);
self.consensus.lock().on_statement(io, self, peer, statement, hash);
}
fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage, hash: Hash) {
fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage<B>, hash: B::Hash) {
trace!(target: "sync", "BFT message from {}: {:?}", peer, message);
self.consensus.lock().on_bft_message(io, self, peer, message, hash);
}
/// See `ConsensusService` trait.
pub fn send_bft_message(&self, io: &mut SyncIo, message: message::LocalizedBftMessage) {
pub fn send_bft_message(&self, io: &mut SyncIo, message: message::LocalizedBftMessage<B>) {
self.consensus.lock().send_bft_message(io, self, message)
}
/// See `ConsensusService` trait.
pub fn bft_messages(&self, parent_hash: Hash) -> BftMessageStream {
pub fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B> {
self.consensus.lock().bft_messages(parent_hash)
}
/// See `ConsensusService` trait.
pub fn statements(&self) -> StatementStream {
self.consensus.lock().statements()
}
/// See `ConsensusService` trait.
pub fn fetch_candidate(&self, io: &mut SyncIo, hash: &Hash) -> oneshot::Receiver<Vec<u8>> {
self.consensus.lock().fetch_candidate(io, self, hash)
}
/// See `ConsensusService` trait.
pub fn send_statement(&self, io: &mut SyncIo, statement: message::Statement) {
self.consensus.lock().send_statement(io, self, statement)
}
/// See `ConsensusService` trait.
pub fn set_local_candidate(&self, candidate: Option<(Hash, Vec<u8>)>) {
self.consensus.lock().set_local_candidate(candidate)
}
/// Perform time based maintenance.
pub fn tick(&self, io: &mut SyncIo) {
self.maintain_peers(io);
@@ -367,7 +334,7 @@ impl Protocol {
}
}
pub fn peer_info(&self, peer: PeerId) -> Option<PeerInfo> {
pub fn peer_info(&self, peer: PeerId) -> Option<PeerInfo<B>> {
self.peers.read().get(&peer).map(|p| {
PeerInfo {
roles: p.roles,
@@ -379,7 +346,7 @@ impl Protocol {
}
/// Called by peer to report status
fn on_status_message(&self, io: &mut SyncIo, peer_id: PeerId, status: message::Status) {
fn on_status_message(&self, io: &mut SyncIo, peer_id: PeerId, status: message::Status<B>) {
trace!(target: "sync", "New peer {} {:?}", peer_id, status);
if io.is_expired() {
trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id));
@@ -426,7 +393,7 @@ impl Protocol {
}
/// Called when peer sends us new transactions
fn on_transactions(&self, _io: &mut SyncIo, peer_id: PeerId, transactions: message::Transactions) {
fn on_transactions(&self, _io: &mut SyncIo, peer_id: PeerId, transactions: message::Transactions<B::Extrinsic>) {
// Accept transactions only when fully synced
if self.sync.read().status().state != SyncState::Idle {
trace!(target: "sync", "{} Ignoring transactions while syncing", peer_id);
@@ -475,7 +442,7 @@ impl Protocol {
}
}
trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), peer_id);
self.send_message(io, *peer_id, Message::Transactions(to_send));
self.send_message(io, *peer_id, GenericMessage::Transactions(to_send));
}
}
self.transaction_pool.on_broadcasted(propagated_to);
@@ -484,7 +451,7 @@ impl Protocol {
/// Send Status message
fn send_status(&self, io: &mut SyncIo, peer_id: PeerId) {
if let Ok(info) = self.chain.info() {
let status = message::Status {
let status = message::generic::Status {
version: PROTOCOL_VERSION,
genesis_hash: info.chain.genesis_hash,
roles: self.config.roles.into(),
@@ -494,7 +461,7 @@ impl Protocol {
validator_id: None,
parachain_id: None,
};
self.send_message(io, peer_id, Message::Status(status))
self.send_message(io, peer_id, GenericMessage::Status(status))
}
}
@@ -508,9 +475,9 @@ impl Protocol {
self.consensus.lock().restart();
}
pub fn on_block_announce(&self, io: &mut SyncIo, peer_id: PeerId, announce: message::BlockAnnounce) {
pub fn on_block_announce(&self, io: &mut SyncIo, peer_id: PeerId, announce: message::BlockAnnounce<B::Header>) {
let header = announce.header;
let hash: HeaderHash = header.blake2_256().into();
let hash = header.hash();
{
let mut peers = self.peers.write();
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
@@ -520,7 +487,7 @@ impl Protocol {
self.sync.write().on_block_announce(io, self, peer_id, hash, &header);
}
pub fn on_block_imported(&self, io: &mut SyncIo, hash: HeaderHash, header: &Header) {
pub fn on_block_imported(&self, io: &mut SyncIo, hash: B::Hash, header: &B::Header) {
self.sync.write().update_chain_info(&header);
// send out block announcements
let mut peers = self.peers.write();
@@ -528,7 +495,7 @@ impl Protocol {
for (peer_id, ref mut peer) in peers.iter_mut() {
if peer.known_blocks.insert(hash.clone()) {
trace!(target: "sync", "Announcing block {:?} to {}", hash, peer_id);
self.send_message(io, *peer_id, Message::BlockAnnounce(message::BlockAnnounce {
self.send_message(io, *peer_id, GenericMessage::BlockAnnounce(message::BlockAnnounce {
header: header.clone()
}));
}
@@ -537,7 +504,7 @@ impl Protocol {
self.consensus.lock().collect_garbage(Some(&header));
}
fn on_remote_call_request(&self, io: &mut SyncIo, peer_id: PeerId, request: message::RemoteCallRequest) {
fn on_remote_call_request(&self, io: &mut SyncIo, peer_id: PeerId, request: message::RemoteCallRequest<B::Hash>) {
trace!(target: "sync", "Remote request {} from {} ({} at {})", request.id, peer_id, request.method, request.block);
let (value, proof) = match self.chain.execution_proof(&request.block, &request.method, &request.data) {
Ok((value, proof)) => (value, proof),
@@ -548,7 +515,7 @@ impl Protocol {
},
};
self.send_message(io, peer_id, message::Message::RemoteCallResponse(message::RemoteCallResponse {
self.send_message(io, peer_id, GenericMessage::RemoteCallResponse(message::RemoteCallResponse {
id: request.id, value, proof,
}));
}
@@ -558,7 +525,7 @@ impl Protocol {
self.on_demand.as_ref().map(|s| s.on_remote_response(io, peer_id, response));
}
pub fn chain(&self) -> &Client {
pub fn chain(&self) -> &Client<B> {
&*self.chain
}
}
+40 -72
View File
@@ -22,16 +22,15 @@ use futures::sync::{oneshot, mpsc};
use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId,
NetworkConfiguration , NonReservedPeerMode, ErrorKind};
use network_devp2p::{NetworkService};
use primitives::block::{ExtrinsicHash, Header, HeaderHash};
use primitives::Hash;
use core_io::{TimerToken};
use io::NetSyncIo;
use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo};
use config::{ProtocolConfig};
use error::Error;
use chain::Client;
use message::{Statement, LocalizedBftMessage};
use message::LocalizedBftMessage;
use on_demand::OnDemandService;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
/// Polkadot devp2p protocol id
pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot";
@@ -40,10 +39,8 @@ const V0_PACKET_COUNT: u8 = 1;
/// Type that represents fetch completion future.
pub type FetchFuture = oneshot::Receiver<Vec<u8>>;
/// Type that represents statement stream.
pub type StatementStream = mpsc::UnboundedReceiver<Statement>;
/// Type that represents bft messages stream.
pub type BftMessageStream = mpsc::UnboundedReceiver<LocalizedBftMessage>;
pub type BftMessageStream<B> = mpsc::UnboundedReceiver<LocalizedBftMessage<B>>;
const TICK_TOKEN: TimerToken = 0;
const TICK_TIMEOUT: Duration = Duration::from_millis(1000);
@@ -68,60 +65,51 @@ bitflags! {
}
/// Sync status
pub trait SyncProvider: Send + Sync {
pub trait SyncProvider<B: BlockT>: Send + Sync {
/// Get sync status
fn status(&self) -> ProtocolStatus;
fn status(&self) -> ProtocolStatus<B>;
/// Get peers information
fn peers(&self) -> Vec<PeerInfo>;
fn peers(&self) -> Vec<PeerInfo<B>>;
/// Get this node id if available.
fn node_id(&self) -> Option<String>;
}
/// Transaction pool interface
pub trait TransactionPool: Send + Sync {
pub trait TransactionPool<B: BlockT>: Send + Sync {
/// Get transactions from the pool that are ready to be propagated.
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)>;
fn transactions(&self) -> Vec<(B::Hash, B::Extrinsic)>;
/// Import a transction into the pool.
fn import(&self, transaction: &[u8]) -> Option<ExtrinsicHash>;
fn import(&self, transaction: &B::Extrinsic) -> Option<B::Hash>;
/// Notify the pool about transactions broadcast.
fn on_broadcasted(&self, propagations: HashMap<ExtrinsicHash, Vec<String>>);
fn on_broadcasted(&self, propagations: HashMap<B::Hash, Vec<String>>);
}
/// ConsensusService
pub trait ConsensusService: Send + Sync {
/// Get statement stream.
fn statements(&self) -> StatementStream;
/// Send out a statement.
fn send_statement(&self, statement: Statement);
pub trait ConsensusService<B: BlockT>: Send + Sync {
/// Maintain connectivity to given addresses.
fn connect_to_authorities(&self, addresses: &[String]);
/// Fetch candidate.
fn fetch_candidate(&self, hash: &Hash) -> oneshot::Receiver<Vec<u8>>;
/// Note local candidate. Accepts candidate receipt hash and candidate data.
/// Pass `None` to clear the candidate.
fn set_local_candidate(&self, candidate: Option<(Hash, Vec<u8>)>);
/// Get BFT message stream for messages corresponding to consensus on given
/// parent hash.
fn bft_messages(&self, parent_hash: Hash) -> BftMessageStream;
fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B>;
/// Send out a BFT message.
fn send_bft_message(&self, message: LocalizedBftMessage);
fn send_bft_message(&self, message: LocalizedBftMessage<B>);
}
/// Service able to execute closure in the network context.
pub trait ExecuteInContext: Send + Sync {
pub trait ExecuteInContext<B: BlockT>: Send + Sync {
/// Execute closure in network context.
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, closure: F);
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<B>)>(&self, closure: F);
}
/// devp2p Protocol handler
struct ProtocolHandler {
protocol: Protocol,
struct ProtocolHandler<B: BlockT> {
protocol: Protocol<B>,
}
/// Peer connection information
#[derive(Debug)]
pub struct PeerInfo {
pub struct PeerInfo<B: BlockT> {
/// Public node id
pub id: Option<String>,
/// Node client ID
@@ -133,34 +121,34 @@ pub struct PeerInfo {
/// Local endpoint address
pub local_address: String,
/// Dot protocol info.
pub dot_info: Option<ProtocolPeerInfo>,
pub dot_info: Option<ProtocolPeerInfo<B>>,
}
/// Service initialization parameters.
pub struct Params {
pub struct Params<B: BlockT> {
/// Configuration.
pub config: ProtocolConfig,
/// Network layer configuration.
pub network_config: NetworkConfiguration,
/// Polkadot relay chain access point.
pub chain: Arc<Client>,
pub chain: Arc<Client<B>>,
/// On-demand service reference.
pub on_demand: Option<Arc<OnDemandService>>,
/// Transaction pool.
pub transaction_pool: Arc<TransactionPool>,
pub transaction_pool: Arc<TransactionPool<B>>,
}
/// Polkadot network service. Handles network IO and manages connectivity.
pub struct Service {
pub struct Service<B: BlockT + 'static> where B::Header: HeaderT<Number=u64> {
/// Network service
network: NetworkService,
/// Devp2p protocol handler
handler: Arc<ProtocolHandler>,
handler: Arc<ProtocolHandler<B>>,
}
impl Service {
impl<B: BlockT + 'static> Service<B> where B::Header: HeaderT<Number=u64> {
/// Creates and register protocol with the network service
pub fn new(params: Params) -> Result<Arc<Service>, Error> {
pub fn new(params: Params<B>) -> Result<Arc<Service<B>>, Error> {
let service = NetworkService::new(params.network_config.clone(), None)?;
let sync = Arc::new(Service {
network: service,
@@ -173,7 +161,7 @@ impl Service {
}
/// Called when a new block is imported by the client.
pub fn on_block_imported(&self, hash: HeaderHash, header: &Header) {
pub fn on_block_imported(&self, hash: B::Hash, header: &B::Header) {
self.network.with_context(DOT_PROTOCOL_ID, |context| {
self.handler.protocol.on_block_imported(&mut NetSyncIo::new(context), hash, header)
});
@@ -199,32 +187,32 @@ impl Service {
fn stop(&self) {
self.handler.protocol.abort();
self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
self.network.stop();
}
}
impl Drop for Service {
impl<B: BlockT + 'static> Drop for Service<B> where B::Header: HeaderT<Number=u64> {
fn drop(&mut self) {
self.stop();
}
}
impl ExecuteInContext for Service {
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, closure: F) {
impl<B: BlockT + 'static> ExecuteInContext<B> for Service<B> where B::Header: HeaderT<Number=u64> {
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<B>)>(&self, closure: F) {
self.network.with_context(DOT_PROTOCOL_ID, |context| {
closure(&mut NetSyncIo::new(context), &self.handler.protocol)
});
}
}
impl SyncProvider for Service {
impl<B: BlockT + 'static> SyncProvider<B> for Service<B> where B::Header: HeaderT<Number=u64> {
/// Get sync status
fn status(&self) -> ProtocolStatus {
fn status(&self) -> ProtocolStatus<B> {
self.handler.protocol.status()
}
/// Get sync peers
fn peers(&self) -> Vec<PeerInfo> {
fn peers(&self) -> Vec<PeerInfo<B>> {
self.network.with_context_eval(DOT_PROTOCOL_ID, |ctx| {
let peer_ids = self.network.connected_peers();
@@ -252,43 +240,23 @@ impl SyncProvider for Service {
}
/// ConsensusService
impl ConsensusService for Service {
fn statements(&self) -> StatementStream {
self.handler.protocol.statements()
}
impl<B: BlockT + 'static> ConsensusService<B> for Service<B> where B::Header: HeaderT<Number=u64> {
fn connect_to_authorities(&self, _addresses: &[String]) {
//TODO: implement me
}
fn fetch_candidate(&self, hash: &Hash) -> oneshot::Receiver<Vec<u8>> {
self.network.with_context_eval(DOT_PROTOCOL_ID, |context| {
self.handler.protocol.fetch_candidate(&mut NetSyncIo::new(context), hash)
}).expect("DOT Service is registered")
}
fn send_statement(&self, statement: Statement) {
self.network.with_context(DOT_PROTOCOL_ID, |context| {
self.handler.protocol.send_statement(&mut NetSyncIo::new(context), statement);
});
}
fn set_local_candidate(&self, candidate: Option<(Hash, Vec<u8>)>) {
self.handler.protocol.set_local_candidate(candidate)
}
fn bft_messages(&self, parent_hash: Hash) -> BftMessageStream {
fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B> {
self.handler.protocol.bft_messages(parent_hash)
}
fn send_bft_message(&self, message: LocalizedBftMessage) {
fn send_bft_message(&self, message: LocalizedBftMessage<B>) {
self.network.with_context(DOT_PROTOCOL_ID, |context| {
self.handler.protocol.send_bft_message(&mut NetSyncIo::new(context), message);
});
}
}
impl NetworkProtocolHandler for ProtocolHandler {
impl<B: BlockT + 'static> NetworkProtocolHandler for ProtocolHandler<B> where B::Header: HeaderT<Number=u64> {
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
io.register_timer(TICK_TOKEN, TICK_TIMEOUT)
.expect("Error registering sync timer");
@@ -319,7 +287,7 @@ impl NetworkProtocolHandler for ProtocolHandler {
}
/// Trait for managing network
pub trait ManageNetwork : Send + Sync {
pub trait ManageNetwork: Send + Sync {
/// Set to allow unreserved peers to connect
fn accept_unreserved_peers(&self);
/// Set to deny unreserved peers to connect
@@ -335,7 +303,7 @@ pub trait ManageNetwork : Send + Sync {
}
impl ManageNetwork for Service {
impl<B: BlockT + 'static> ManageNetwork for Service<B> where B::Header: HeaderT<Number=u64> {
fn accept_unreserved_peers(&self) {
self.network.set_non_reserved_mode(NonReservedPeerMode::Accept);
}
+57 -54
View File
@@ -19,38 +19,38 @@ use io::SyncIo;
use protocol::Protocol;
use network::PeerId;
use client::{ImportResult, BlockStatus, ClientInfo};
use primitives::block::{HeaderHash, Number as BlockNumber, Header, Id as BlockId};
use blocks::{self, BlockCollection};
use message::{self, Message};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
use message::{self, generic::Message as GenericMessage};
use service::Role;
use super::header_hash;
// Maximum blocks to request in a single packet.
const MAX_BLOCKS_TO_REQUEST: usize = 128;
struct PeerSync {
pub common_hash: HeaderHash,
pub common_number: BlockNumber,
pub best_hash: HeaderHash,
pub best_number: BlockNumber,
pub state: PeerSyncState,
struct PeerSync<B: BlockT> {
pub common_hash: B::Hash,
pub common_number: <B::Header as HeaderT>::Number,
pub best_hash: B::Hash,
pub best_number: <B::Header as HeaderT>::Number,
pub state: PeerSyncState<B>,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum PeerSyncState {
AncestorSearch(BlockNumber),
enum PeerSyncState<B: BlockT> {
AncestorSearch(<B::Header as HeaderT>::Number),
Available,
DownloadingNew(BlockNumber),
DownloadingStale(HeaderHash),
DownloadingNew(<B::Header as HeaderT>::Number),
DownloadingStale(B::Hash),
}
/// Relay chain sync strategy.
pub struct ChainSync {
genesis_hash: HeaderHash,
peers: HashMap<PeerId, PeerSync>,
blocks: BlockCollection,
best_queued_number: BlockNumber,
best_queued_hash: HeaderHash,
pub struct ChainSync<B: BlockT> {
genesis_hash: B::Hash,
peers: HashMap<PeerId, PeerSync<B>>,
blocks: BlockCollection<B>,
best_queued_number: u64,
best_queued_hash: B::Hash,
required_block_attributes: Vec<message::BlockAttribute>,
}
@@ -65,16 +65,18 @@ pub enum SyncState {
/// Syncing status and statistics
#[derive(Clone)]
pub struct Status {
pub struct Status<B: BlockT> {
/// Current global sync state.
pub state: SyncState,
/// Target sync block number.
pub best_seen_block: Option<BlockNumber>,
pub best_seen_block: Option<<B::Header as HeaderT>::Number>,
}
impl ChainSync {
impl<B: BlockT> ChainSync<B> where
B::Header: HeaderT<Number=u64>,
{
/// Create a new instance.
pub fn new(role: Role, info: &ClientInfo) -> ChainSync {
pub fn new(role: Role, info: &ClientInfo<B>) -> Self {
let mut required_block_attributes = vec![
message::BlockAttribute::Header,
message::BlockAttribute::Justification
@@ -93,12 +95,12 @@ impl ChainSync {
}
}
fn best_seen_block(&self) -> Option<BlockNumber> {
fn best_seen_block(&self) -> Option<u64> {
self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number)
}
/// Returns sync status
pub fn status(&self) -> Status {
pub fn status(&self) -> Status<B> {
let best_seen = self.best_seen_block();
let state = match &best_seen {
&Some(n) if n > self.best_queued_number && n - self.best_queued_number > 5 => SyncState::Downloading,
@@ -111,7 +113,7 @@ impl ChainSync {
}
/// Handle new connected peer.
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId) {
if let Some(info) = protocol.peer_info(peer_id) {
match (protocol.chain().block_status(&BlockId::Hash(info.best_hash)), info.best_number) {
(Err(e), _) => {
@@ -165,7 +167,7 @@ impl ChainSync {
}
}
pub fn on_block_data(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, _request: message::BlockRequest, response: message::BlockResponse) {
pub fn on_block_data(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, _request: message::BlockRequest<B>, response: message::BlockResponse<B>) {
let count = response.blocks.len();
let mut imported: usize = 0;
let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
@@ -235,9 +237,9 @@ impl ChainSync {
let block = block.block;
match (block.header, block.justification) {
(Some(header), Some(justification)) => {
let number = header.number;
let hash = header_hash(&header);
let parent = header.parent_hash;
let number = header.number().clone();
let hash = header.hash();
let parent = header.parent_hash().clone();
let is_best = best_seen.as_ref().map_or(false, |n| number >= *n);
// check whether the block is known before importing.
@@ -305,14 +307,14 @@ impl ChainSync {
self.maintain_sync(io, protocol);
}
fn maintain_sync(&mut self, io: &mut SyncIo, protocol: &Protocol) {
fn maintain_sync(&mut self, io: &mut SyncIo, protocol: &Protocol<B>) {
let peers: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
for peer in peers {
self.download_new(io, protocol, peer);
}
}
fn block_imported(&mut self, hash: &HeaderHash, number: BlockNumber) {
fn block_imported(&mut self, hash: &B::Hash, number: u64) {
if number > self.best_queued_number {
self.best_queued_number = number;
self.best_queued_hash = *hash;
@@ -327,28 +329,29 @@ impl ChainSync {
}
}
pub fn update_chain_info(&mut self, best_header: &Header ) {
let hash = header_hash(&best_header);
self.block_imported(&hash, best_header.number)
pub fn update_chain_info(&mut self, best_header: &B::Header) {
let hash = best_header.hash();
self.block_imported(&hash, best_header.number().clone())
}
pub fn on_block_announce(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: HeaderHash, header: &Header) {
pub fn on_block_announce(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, hash: B::Hash, header: &B::Header) {
let number = *header.number();
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
if header.number > peer.best_number {
peer.best_number = header.number;
if number > peer.best_number {
peer.best_number = number;
peer.best_hash = hash;
}
if header.number <= self.best_queued_number && header.number > peer.common_number {
peer.common_number = header.number;
if number <= self.best_queued_number && number > peer.common_number {
peer.common_number = number
}
} else {
return;
}
if !self.is_known_or_already_downloading(protocol, &hash) {
let stale = header.number <= self.best_queued_number;
let stale = number <= self.best_queued_number;
if stale {
if !self.is_known_or_already_downloading(protocol, &header.parent_hash) {
if !self.is_known_or_already_downloading(protocol, header.parent_hash()) {
trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", peer_id, hash, header);
} else {
trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", peer_id, hash, header);
@@ -363,18 +366,18 @@ impl ChainSync {
}
}
fn is_known_or_already_downloading(&self, protocol: &Protocol, hash: &HeaderHash) -> bool {
fn is_known_or_already_downloading(&self, protocol: &Protocol<B>, hash: &B::Hash) -> bool {
self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash))
|| protocol.chain().block_status(&BlockId::Hash(*hash)).ok().map_or(false, |s| s != BlockStatus::Unknown)
}
pub fn peer_disconnected(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
pub fn peer_disconnected(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId) {
self.blocks.clear_peer_download(peer_id);
self.peers.remove(&peer_id);
self.maintain_sync(io, protocol);
}
pub fn restart(&mut self, io: &mut SyncIo, protocol: &Protocol) {
pub fn restart(&mut self, io: &mut SyncIo, protocol: &Protocol<B>) {
self.blocks.clear();
let ids: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
for id in ids {
@@ -399,11 +402,11 @@ impl ChainSync {
}
// Download old block.
fn download_stale(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: &HeaderHash) {
fn download_stale(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, hash: &B::Hash) {
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
match peer.state {
PeerSyncState::Available => {
let request = message::BlockRequest {
let request = message::generic::BlockRequest {
id: 0,
fields: self.required_block_attributes.clone(),
from: message::FromBlock::Hash(*hash),
@@ -412,7 +415,7 @@ impl ChainSync {
max: Some(1),
};
peer.state = PeerSyncState::DownloadingStale(*hash);
protocol.send_message(io, peer_id, Message::BlockRequest(request));
protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request));
},
_ => (),
}
@@ -420,14 +423,14 @@ impl ChainSync {
}
// Issue a request for a peer to download new blocks, if any are available
fn download_new(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
fn download_new(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId) {
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
trace!(target: "sync", "Considering new block download from {}, common block is {}, best is {:?}", peer_id, peer.common_number, peer.best_number);
match peer.state {
PeerSyncState::Available => {
if let Some(range) = self.blocks.needed_blocks(peer_id, MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) {
trace!(target: "sync", "Requesting blocks from {}, ({} to {})", peer_id, range.start, range.end);
let request = message::BlockRequest {
let request = message::generic::BlockRequest {
id: 0,
fields: self.required_block_attributes.clone(),
from: message::FromBlock::Number(range.start),
@@ -436,7 +439,7 @@ impl ChainSync {
max: Some((range.end - range.start) as u32),
};
peer.state = PeerSyncState::DownloadingNew(range.start);
protocol.send_message(io, peer_id, Message::BlockRequest(request));
protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request));
} else {
trace!(target: "sync", "Nothing to request");
}
@@ -446,9 +449,9 @@ impl ChainSync {
}
}
fn request_ancestry(io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, block: BlockNumber) {
fn request_ancestry(io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, block: u64) {
trace!(target: "sync", "Requesting ancestry block #{} from {}", block, peer_id);
let request = message::BlockRequest {
let request = message::generic::BlockRequest {
id: 0,
fields: vec![message::BlockAttribute::Header, message::BlockAttribute::Justification],
from: message::FromBlock::Number(block),
@@ -456,6 +459,6 @@ impl ChainSync {
direction: message::Direction::Ascending,
max: Some(1),
};
protocol.send_message(io, peer_id, Message::BlockRequest(request));
protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request));
}
}
@@ -15,8 +15,9 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use super::*;
use message::*;
use message::{Message, generic};
use futures::Stream;
use test_client::runtime::Block;
#[test]
fn bft_messages_include_those_sent_before_asking_for_stream() {
@@ -28,21 +29,22 @@ fn bft_messages_include_those_sent_before_asking_for_stream() {
let peer = net.peer(0);
let mut io = TestIo::new(&peer.queue, None);
let bft_message = BftMessage::Consensus(SignedConsensusMessage::Vote(SignedConsensusVote {
vote: ConsensusVote::AdvanceRound(0),
let bft_message = generic::BftMessage::Consensus(generic::SignedConsensusMessage::Vote(generic::SignedConsensusVote {
vote: generic::ConsensusVote::AdvanceRound(0),
sender: [0; 32],
signature: Default::default(),
}));
let parent_hash = peer.genesis_hash();
let localized = LocalizedBftMessage {
let localized = ::message::LocalizedBftMessage::<Block> {
message: bft_message,
parent_hash: parent_hash,
};
let message: Message<Block> = generic::Message::BftMessage(localized.clone());
let as_bytes = ::serde_json::to_vec(&Message::BftMessage(localized.clone())).unwrap();
let as_bytes = ::serde_json::to_vec(&message).unwrap();
peer.sync.handle_packet(&mut io, 1, &as_bytes[..]);
let stream = peer.sync.bft_messages(parent_hash);
+18 -19
View File
@@ -23,17 +23,17 @@ use std::sync::Arc;
use parking_lot::RwLock;
use client;
use client::block_builder::BlockBuilder;
use primitives::block::{Id as BlockId, ExtrinsicHash, HeaderHash};
use primitives;
use runtime_primitives::traits::Block as BlockT;
use runtime_primitives::generic::BlockId;
use io::SyncIo;
use protocol::Protocol;
use config::ProtocolConfig;
use service::TransactionPool;
use network::{PeerId, SessionInfo, Error as NetworkError};
use runtime_support::Hashable;
use keyring::Keyring;
use codec::Slicable;
use test_client::{self, TestClient};
use test_client::runtime::{Block, Hash, Transfer, Extrinsic};
pub struct TestIo<'p> {
pub queue: &'p RwLock<VecDeque<TestPacket>>,
@@ -100,8 +100,8 @@ pub struct TestPacket {
}
pub struct Peer {
client: Arc<client::Client<test_client::Backend, test_client::Executor>>,
pub sync: Protocol,
client: Arc<client::Client<test_client::Backend, test_client::Executor, Block>>,
pub sync: Protocol<Block>,
pub queue: RwLock<VecDeque<TestPacket>>,
}
@@ -158,12 +158,12 @@ impl Peer {
fn flush(&self) {
}
fn generate_blocks<F>(&self, count: usize, mut edit_block: F) where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor>) {
fn generate_blocks<F>(&self, count: usize, mut edit_block: F) where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor, Block>) {
for _ in 0 .. count {
let mut builder = self.client.new_block().unwrap();
edit_block(&mut builder);
let block = builder.bake().unwrap();
trace!("Generating {}, (#{})", primitives::block::HeaderHash::from(block.header.blake2_256()), block.header.number);
trace!("Generating {}, (#{})", block.hash(), block.header.number);
self.client.justify_and_import(client::BlockOrigin::File, block).unwrap();
}
}
@@ -172,15 +172,14 @@ impl Peer {
let mut nonce = 0;
if with_tx {
self.generate_blocks(count, |builder| {
let tx = test_client::runtime::Transaction {
from: Keyring::Alice.to_raw_public(),
to: Keyring::Alice.to_raw_public(),
let transfer = Transfer {
from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Alice.to_raw_public().into(),
amount: 1,
nonce: nonce,
nonce,
};
let signature = Keyring::from_raw_public(tx.from.clone()).unwrap().sign(&tx.encode());
let tx = primitives::block::Extrinsic::decode(&mut test_client::runtime::UncheckedTransaction { signature, tx: tx }.encode().as_ref()).unwrap();
builder.push(tx).unwrap();
let signature = Keyring::from_raw_public(transfer.from.0).unwrap().sign(&transfer.encode()).into();
builder.push(Extrinsic { transfer, signature }).unwrap();
nonce = nonce + 1;
});
} else {
@@ -188,7 +187,7 @@ impl Peer {
}
}
pub fn genesis_hash(&self) -> HeaderHash {
pub fn genesis_hash(&self) -> Hash {
let info = self.client.info().expect("In-mem client does not fail");
info.chain.genesis_hash
}
@@ -196,16 +195,16 @@ impl Peer {
struct EmptyTransactionPool;
impl TransactionPool for EmptyTransactionPool {
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)> {
impl TransactionPool<Block> for EmptyTransactionPool {
fn transactions(&self) -> Vec<(Hash, Extrinsic)> {
Vec::new()
}
fn import(&self, _transaction: &[u8]) -> Option<ExtrinsicHash> {
fn import(&self, _transaction: &Extrinsic) -> Option<Hash> {
None
}
fn on_broadcasted(&self, _: HashMap<ExtrinsicHash, Vec<String>>) {}
fn on_broadcasted(&self, _: HashMap<Hash, Vec<String>>) {}
}
pub struct TestNet {
-276
View File
@@ -1,276 +0,0 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Block and header type definitions.
use rstd::fmt;
use rstd::vec::Vec;
#[cfg(feature = "std")]
use bytes;
use Hash;
use codec::{Input, Slicable};
/// Used to refer to a block number.
pub type Number = u64;
/// Hash used to refer to a block hash.
pub type HeaderHash = Hash;
/// Hash used to refer to an extrinsic.
pub type ExtrinsicHash = Hash;
/// Simple generic extrinsic type.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Extrinsic(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Extrinsic {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Extrinsic)
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
/// Execution log (event)
#[derive(PartialEq, Eq, Clone, Default)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Log {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Log)
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
/// The digest of a block, useful for light-clients.
#[derive(Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Digest {
/// All logs that have happened in the block.
pub logs: Vec<Log>,
}
impl Slicable for Digest {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<Log>::decode(input).map(|logs| Digest { logs })
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.logs.using_encoded(f)
}
}
/// Generic types to be specialised later.
pub mod generic {
use super::{Header, Slicable, Input, Vec};
/// A Block - this is generic for later specialisation in particular runtimes.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Block<Transaction: PartialEq + Eq + Clone> {
/// The block header.
pub header: Header,
/// All relay-chain transactions.
pub transactions: Vec<Transaction>,
}
impl<T: PartialEq + Eq + Clone> Slicable for Block<T> where Vec<T>: Slicable {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Block {
header: Slicable::decode(input)?,
transactions: Slicable::decode(input)?,
})
}
fn encode(&self) -> Vec<u8> {
let mut v: Vec<u8> = Vec::new();
v.extend(self.header.encode());
v.extend(self.transactions.encode());
v
}
}
}
/// The body of a block is just a bunch of extrinsics.
pub type Body = Vec<Extrinsic>;
/// The header and body of a concrete, but unspecialised, block. Used by substrate to represent a
/// block some fields of which the runtime alone knows how to interpret (e.g. the transactions).
pub type Block = generic::Block<Extrinsic>;
/// A substrate chain block header.
// TODO: split out into light-client-specific fields and runtime-specific fields.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Header {
/// Block parent's hash.
pub parent_hash: HeaderHash,
/// Block number.
pub number: Number,
/// State root after this transition.
pub state_root: Hash,
/// The root of the trie that represents this block's transactions, indexed by a 32-byte integer.
pub extrinsics_root: Hash,
// TODO...
// /// The root of the trie that represents the receipts from this block's transactions
// pub receipts_root: Hash,
/// The digest of activity on the block.
pub digest: Digest,
}
impl Header {
/// Create a new instance with default fields except `number`, which is given as an argument.
pub fn from_block_number(number: Number) -> Self {
Header {
parent_hash: Default::default(),
number,
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
}
}
}
impl Slicable for Header {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Header {
parent_hash: Slicable::decode(input)?,
number: Slicable::decode(input)?,
state_root: Slicable::decode(input)?,
extrinsics_root: Slicable::decode(input)?,
digest: Slicable::decode(input)?,
})
}
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
self.parent_hash.using_encoded(|s| v.extend(s));
self.number.using_encoded(|s| v.extend(s));
self.state_root.using_encoded(|s| v.extend(s));
self.extrinsics_root.using_encoded(|s| v.extend(s));
self.digest.using_encoded(|s| v.extend(s));
v
}
}
/// Block indentification.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Id {
/// Identify by block header hash.
Hash(HeaderHash),
/// Identify by block number.
Number(Number),
}
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Id::Hash(h) => h.fmt(f),
Id::Number(n) => n.fmt(f),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use codec::Slicable;
use substrate_serializer as ser;
#[test]
fn test_header_encoding() {
let header = Header {
parent_hash: 5.into(),
number: 67,
state_root: 3.into(),
extrinsics_root: 6.into(),
digest: Digest { logs: vec![Log(vec![1]), Log(vec![2])] },
};
assert_eq!(header.encode(), vec![
// parent_hash
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, 5,
// number
67, 0, 0, 0, 0, 0, 0, 0,
// state_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, 3,
// extrinsics_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, 6,
// digest (length, log1, log2)
2, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 2
]);
}
#[test]
fn test_header_serialization() {
let header = Header {
parent_hash: 5.into(),
number: 67,
state_root: 3.into(),
extrinsics_root: 6.into(),
digest: Digest { logs: vec![Log(vec![1])] },
};
assert_eq!(ser::to_string_pretty(&header), r#"{
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005",
"number": 67,
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003",
"extrinsicsRoot": "0x0000000000000000000000000000000000000000000000000000000000000006",
"digest": {
"logs": [
"0x01"
]
}
}"#);
let v = header.encode();
assert_eq!(Header::decode(&mut &v[..]).unwrap(), header);
}
#[test]
fn test_block_encoding() {
let block = Block {
header: Header::from_block_number(12),
transactions: vec![Extrinsic(vec!(4))],
};
assert_eq!(block.encode(), vec![
// parent_hash
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,
// number
12, 0, 0, 0, 0, 0, 0, 0,
// state_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,
// extrinsics_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,
// digest
0, 0, 0, 0,
// transactions (length, tx...)
1, 0, 0, 0, 1, 0, 0, 0, 4
]);
}
}
+2 -2
View File
@@ -66,7 +66,7 @@ mod tests {
#[test]
fn test_h160() {
let tests = vec![
(H160::from(0), "0x0000000000000000000000000000000000000000"),
(Default::default(), "0x0000000000000000000000000000000000000000"),
(H160::from(2), "0x0000000000000000000000000000000000000002"),
(H160::from(15), "0x000000000000000000000000000000000000000f"),
(H160::from(16), "0x0000000000000000000000000000000000000010"),
@@ -84,7 +84,7 @@ mod tests {
#[test]
fn test_h256() {
let tests = vec![
(H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"),
(Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"),
(H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"),
(H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"),
(H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"),
+1 -18
View File
@@ -54,17 +54,6 @@ extern crate substrate_serializer;
#[macro_use]
extern crate pretty_assertions;
// TODO: factor out to separate crate.
#[macro_export]
macro_rules! try_opt {
($e: expr) => {
match $e {
Some(x) => x,
None => return None,
}
}
}
#[macro_export]
macro_rules! map {
($( $name:expr => $value:expr ),*) => (
@@ -82,8 +71,6 @@ pub use hashing::{blake2_256, twox_128, twox_256};
#[cfg(feature = "std")]
pub mod hexdisplay;
pub mod bft;
pub mod block;
pub mod hash;
pub mod sandbox;
pub mod storage;
@@ -92,12 +79,8 @@ pub mod uint;
#[cfg(test)]
mod tests;
pub use self::hash::{H160, H256};
pub use self::hash::{H160, H256, H512};
pub use self::uint::{U256, U512};
pub use block::{Block, Header, Digest};
/// General hash type.
pub type Hash = H256;
/// An identifier for an authority in the consensus algorithm. The same as ed25519::Public.
pub type AuthorityId = [u8; 32];
@@ -10,3 +10,4 @@ jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git" }
jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git" }
log = "0.3"
substrate-rpc = { path = "../rpc", version = "0.1" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
+7 -4
View File
@@ -24,25 +24,28 @@ extern crate jsonrpc_core as rpc;
extern crate jsonrpc_http_server as http;
extern crate jsonrpc_pubsub as pubsub;
extern crate jsonrpc_ws_server as ws;
extern crate substrate_runtime_primitives;
#[macro_use]
extern crate log;
use std::io;
use substrate_runtime_primitives::traits::Block as BlockT;
type Metadata = apis::metadata::Metadata;
type RpcHandler = pubsub::PubSubHandler<Metadata>;
/// Construct rpc `IoHandler`
pub fn rpc_handler<S, C, A, Y>(
pub fn rpc_handler<Block: BlockT, S, C, A, Y>(
state: S,
chain: C,
author: A,
system: Y,
) -> RpcHandler where
S: apis::state::StateApi,
C: apis::chain::ChainApi<Metadata=Metadata>,
A: apis::author::AuthorApi,
Block: 'static,
S: apis::state::StateApi<Block::Hash>,
C: apis::chain::ChainApi<Block::Hash, Block::Header, Metadata=Metadata>,
A: apis::author::AuthorApi<Block::Hash, Block::Extrinsic>,
Y: apis::system::SystemApi,
{
let mut io = pubsub::PubSubHandler::default();
+1
View File
@@ -14,6 +14,7 @@ substrate-client = { path = "../client" }
substrate-executor = { path = "../executor" }
substrate-extrinsic-pool = { path = "../extrinsic-pool" }
substrate-primitives = { path = "../primitives" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
substrate-state-machine = { path = "../state-machine" }
tokio-core = "0.1.12"
+6 -6
View File
@@ -17,7 +17,6 @@
//! Substrate block-author/full-node API.
use std::sync::Arc;
use primitives::block::{Extrinsic, ExtrinsicHash};
use extrinsic_pool::api::{Error, ExtrinsicPool};
pub mod error;
@@ -29,17 +28,18 @@ use self::error::Result;
build_rpc_trait! {
/// Substrate authoring RPC API
pub trait AuthorApi {
pub trait AuthorApi<Hash, Extrinsic> {
/// Submit extrinsic for inclusion in block.
#[rpc(name = "author_submitExtrinsic")]
fn submit_extrinsic(&self, Extrinsic) -> Result<ExtrinsicHash>;
fn submit_extrinsic(&self, Extrinsic) -> Result<Hash>;
}
}
impl<T> AuthorApi for Arc<T> where
T: ExtrinsicPool,
impl<Ex, Hash, T> AuthorApi<Hash, Ex> for Arc<T> where
T: ExtrinsicPool<Ex, Hash>,
T::Error: 'static,
{
fn submit_extrinsic(&self, xt: Extrinsic) -> Result<ExtrinsicHash> {
fn submit_extrinsic(&self, xt: Ex) -> Result<Hash> {
self
.submit(vec![xt])
.map(|mut res| res.pop().expect("One extrinsic passed; one result back; qed"))
+10 -9
View File
@@ -19,11 +19,13 @@ use super::*;
use std::{fmt, sync::Arc};
use extrinsic_pool::api;
use parking_lot::Mutex;
use primitives::block;
type Extrinsic = u64;
type Hash = u64;
#[derive(Default)]
struct DummyTxPool {
submitted: Mutex<Vec<block::Extrinsic>>,
submitted: Mutex<Vec<Extrinsic>>,
}
#[derive(Debug)]
@@ -38,14 +40,14 @@ impl fmt::Display for Error {
}
}
impl api::ExtrinsicPool for DummyTxPool {
impl api::ExtrinsicPool<Extrinsic, Hash> for DummyTxPool {
type Error = Error;
/// Submit extrinsic for inclusion in block.
fn submit(&self, xt: Vec<Extrinsic>) -> ::std::result::Result<Vec<ExtrinsicHash>, Self::Error> {
fn submit(&self, xt: Vec<Extrinsic>) -> ::std::result::Result<Vec<Hash>, Self::Error> {
let mut submitted = self.submitted.lock();
if submitted.len() < 1 {
let hashes = xt.iter().map(|_xt| 1.into()).collect();
let hashes = xt.iter().map(|_xt| 1).collect();
submitted.extend(xt);
Ok(hashes)
} else {
@@ -57,13 +59,12 @@ impl api::ExtrinsicPool for DummyTxPool {
#[test]
fn submit_transaction_should_not_cause_error() {
let p = Arc::new(DummyTxPool::default());
let hash: ExtrinsicHash = 1.into();
assert_matches!(
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])),
Ok(hash)
AuthorApi::submit_extrinsic(&p, 5),
Ok(1)
);
assert!(
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])).is_err()
AuthorApi::submit_extrinsic(&p, 5).is_err()
);
}
+21 -19
View File
@@ -18,7 +18,8 @@
use std::sync::Arc;
use primitives::block;
use runtime_primitives::traits::Block as BlockT;
use runtime_primitives::generic::BlockId;
use client::{self, Client, BlockchainEvents};
use state_machine;
@@ -38,23 +39,23 @@ use self::error::{Result, ResultExt};
build_rpc_trait! {
/// Polkadot blockchain API
pub trait ChainApi {
pub trait ChainApi<Hash, Header> {
type Metadata;
/// Get header of a relay chain block.
#[rpc(name = "chain_getHeader")]
fn header(&self, block::HeaderHash) -> Result<Option<block::Header>>;
fn header(&self, Hash) -> Result<Option<Header>>;
/// Get hash of the head.
#[rpc(name = "chain_getHead")]
fn head(&self) -> Result<block::HeaderHash>;
fn head(&self) -> Result<Hash>;
#[pubsub(name = "chain_newHead")] {
/// Hello subscription
/// New head subscription
#[rpc(name = "subscribe_newHead")]
fn subscribe_new_head(&self, Self::Metadata, pubsub::Subscriber<block::Header>);
fn subscribe_new_head(&self, Self::Metadata, pubsub::Subscriber<Header>);
/// Unsubscribe from hello subscription.
/// Unsubscribe from new head subscription.
#[rpc(name = "unsubscribe_newHead")]
fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>;
}
@@ -62,16 +63,16 @@ build_rpc_trait! {
}
/// Chain API with subscriptions support.
pub struct Chain<B, E> {
pub struct Chain<B, E, Block: BlockT> {
/// Substrate client.
client: Arc<Client<B, E>>,
client: Arc<Client<B, E, Block>>,
/// Current subscriptions.
subscriptions: Subscriptions,
}
impl<B, E> Chain<B, E> {
impl<B, E, Block: BlockT> Chain<B, E, Block> {
/// Create new Chain API RPC handler.
pub fn new(client: Arc<Client<B, E>>, remote: Remote) -> Self {
pub fn new(client: Arc<Client<B, E, Block>>, remote: Remote) -> Self {
Chain {
client,
subscriptions: Subscriptions::new(remote),
@@ -79,22 +80,23 @@ impl<B, E> Chain<B, E> {
}
}
impl<B, E> ChainApi for Chain<B, E> where
B: client::backend::Backend + Send + Sync + 'static,
E: client::CallExecutor + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
impl<B, E, Block> ChainApi<Block::Hash, Block::Header> for Chain<B, E, Block> where
Block: BlockT + 'static,
B: client::backend::Backend<Block> + Send + Sync + 'static,
E: client::CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
{
type Metadata = ::metadata::Metadata;
fn header(&self, hash: block::HeaderHash) -> Result<Option<block::Header>> {
self.client.header(&block::Id::Hash(hash)).chain_err(|| "Blockchain error")
fn header(&self, hash: Block::Hash) -> Result<Option<Block::Header>> {
self.client.header(&BlockId::Hash(hash)).chain_err(|| "Blockchain error")
}
fn head(&self) -> Result<block::HeaderHash> {
fn head(&self) -> Result<Block::Hash> {
Ok(self.client.info().chain_err(|| "Blockchain error")?.chain.best_hash)
}
fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber<block::Header>) {
fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber<Block::Header>) {
self.subscriptions.add(subscriber, |sink| {
let stream = self.client.import_notification_stream()
.filter(|notification| notification.is_new_best)
+4 -3
View File
@@ -18,6 +18,7 @@ use super::*;
use jsonrpc_macros::pubsub;
use client::BlockOrigin;
use test_client::{self, TestClient};
use test_client::runtime::Header;
#[test]
fn should_return_header() {
@@ -30,10 +31,10 @@ fn should_return_header() {
};
assert_matches!(
client.header(client.client.genesis_hash()),
Ok(Some(ref x)) if x == &block::Header {
Ok(Some(ref x)) if x == &Header {
parent_hash: 0.into(),
number: 0,
state_root: "0c81ab6cfac8c8d7201d78cb699b6b79d714462a4ba00abcacce22444babe315".into(),
state_root: "9c70014029b05f780858f654bfcf297ca708b3663d32bc81486193e84a2f2f3d".into(),
extrinsics_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into(),
digest: Default::default(),
}
@@ -69,7 +70,7 @@ fn should_notify_about_latest_block() {
// assert notification send to transport
let (notification, next) = core.run(transport.into_future()).unwrap();
assert_eq!(notification, Some(
r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x72ae67388233893fb4594f13df56d4e654aa8721763bcd0bd4e187fee7b2f349","stateRoot":"0x2e1f2f1c53ffb1767fe1abf4fe5953cc87c7650d4af2d4393d1f72324f2cc5d7"},"subscription":0}}"#.to_owned()
r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x45a44c50cae6ffcc413b65d6b4444a572fa4be2e5d1cd026cc113f9d8f9bc368","stateRoot":"0x987aa0851a133413b42c6d9aa3c91b1dddc2ad5337508ee8815116b11e44c64d"},"subscription":0}}"#.to_owned()
));
// no more notifications on this channel
assert_eq!(core.run(next.into_future()).unwrap().0, None);
+1
View File
@@ -24,6 +24,7 @@ extern crate parking_lot;
extern crate substrate_client as client;
extern crate substrate_extrinsic_pool as extrinsic_pool;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_state_machine as state_machine;
extern crate tokio_core;
+30 -26
View File
@@ -23,7 +23,9 @@ mod tests;
use std::sync::Arc;
use client::{self, Client, CallExecutor};
use primitives::{block, Hash, blake2_256};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::Block as BlockT;
use primitives::storage::{StorageKey, StorageData};
use primitives::hexdisplay::HexDisplay;
use state_machine;
@@ -32,65 +34,67 @@ use self::error::Result;
build_rpc_trait! {
/// Polkadot state API
pub trait StateApi {
/// Returns a storage entry.
pub trait StateApi<Hash> {
/// Returns a storage entry at a specific block's state.
#[rpc(name = "state_getStorageAt")]
fn storage_at(&self, StorageKey, block::HeaderHash) -> Result<StorageData>;
fn storage_at(&self, StorageKey, Hash) -> Result<StorageData>;
/// Call a contract.
/// Call a contract at a block's state.
#[rpc(name = "state_callAt")]
fn call_at(&self, String, Vec<u8>, block::HeaderHash) -> Result<Vec<u8>>;
fn call_at(&self, String, Vec<u8>, Hash) -> Result<Vec<u8>>;
/// Returns the hash of a storage entry.
/// Returns the hash of a storage entry at a block's state.
#[rpc(name = "state_getStorageHashAt")]
fn storage_hash_at(&self, StorageKey, block::HeaderHash) -> Result<Hash>;
fn storage_hash_at(&self, StorageKey, Hash) -> Result<Hash>;
/// Returns the size of a storage entry.
/// Returns the size of a storage entry at a block's state.
#[rpc(name = "state_getStorageSizeAt")]
fn storage_size_at(&self, StorageKey, block::HeaderHash) -> Result<u64>;
fn storage_size_at(&self, StorageKey, Hash) -> Result<u64>;
/// Returns the hash of a storage entry.
/// Returns the hash of a storage entry at the best block.
#[rpc(name = "state_getStorageHash")]
fn storage_hash(&self, StorageKey) -> Result<Hash>;
/// Returns the size of a storage entry.
/// Returns the size of a storage entry at the best block.
#[rpc(name = "state_getStorageSize")]
fn storage_size(&self, StorageKey) -> Result<u64>;
/// Returns a storage entry.
/// Returns a storage entry at the best block.
#[rpc(name = "state_getStorage")]
fn storage(&self, StorageKey) -> Result<StorageData>;
/// Call a contract.
/// Call a contract at the best block.
#[rpc(name = "state_call")]
fn call(&self, String, Vec<u8>) -> Result<Vec<u8>>;
}
}
impl<B, E> StateApi for Arc<Client<B, E>> where
B: client::backend::Backend + Send + Sync + 'static,
E: CallExecutor + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
impl<B, E, Block> StateApi<Block::Hash> for Arc<Client<B, E, Block>> where
Block: BlockT + 'static,
B: client::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
{
fn storage_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<StorageData> {
fn storage_at(&self, key: StorageKey, block: Block::Hash) -> Result<StorageData> {
trace!(target: "rpc", "Querying storage at {:?} for key {}", block, HexDisplay::from(&key.0));
Ok(self.as_ref().storage(&block::Id::Hash(block), &key)?)
Ok(self.as_ref().storage(&BlockId::Hash(block), &key)?)
}
fn call_at(&self, method: String, data: Vec<u8>, block: block::HeaderHash) -> Result<Vec<u8>> {
fn call_at(&self, method: String, data: Vec<u8>, block: Block::Hash) -> Result<Vec<u8>> {
trace!(target: "rpc", "Calling runtime at {:?} for method {} ({})", block, method, HexDisplay::from(&data));
Ok(self.as_ref().executor().call(&block::Id::Hash(block), &method, &data)?.return_data)
Ok(self.as_ref().executor().call(&BlockId::Hash(block), &method, &data)?.return_data)
}
fn storage_hash_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<Hash> {
self.storage_at(key, block).map(|x| blake2_256(&x.0).into())
fn storage_hash_at(&self, key: StorageKey, block: Block::Hash) -> Result<Block::Hash> {
use runtime_primitives::traits::{Hashing, Header as HeaderT};
self.storage_at(key, block).map(|x| <Block::Header as HeaderT>::Hashing::hash(&x.0))
}
fn storage_size_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<u64> {
fn storage_size_at(&self, key: StorageKey, block: Block::Hash) -> Result<u64> {
self.storage_at(key, block).map(|x| x.0.len() as u64)
}
fn storage_hash(&self, key: StorageKey) -> Result<Hash> {
fn storage_hash(&self, key: StorageKey) -> Result<Block::Hash> {
self.storage_hash_at(key, self.as_ref().info()?.chain.best_hash)
}
+1 -1
View File
@@ -13,7 +13,7 @@ environmental = { path = "../environmental", optional = true }
substrate-state-machine = { path = "../state-machine", optional = true }
substrate-primitives = { path = "../primitives", default_features = false }
substrate-codec = { path = "../codec", default_features = false }
triehash = { version = "0.1", optional = true }
triehash = { version = "0.1.2", optional = true }
ed25519 = { path = "../ed25519", optional = true }
[features]
-34
View File
@@ -30,37 +30,3 @@ include!("../with_std.rs");
#[cfg(not(feature = "std"))]
include!("../without_std.rs");
/// Abstraction around hashing
pub trait Hashing {
/// The hash type produced.
type Output;
/// Produce the hash of some byte-slice.
fn hash(s: &[u8]) -> Self::Output;
/// Produce the hash of some codec-encodable value.
fn hash_of<S: codec::Slicable>(s: &S) -> Self::Output {
codec::Slicable::using_encoded(s, Self::hash)
}
/// Produce the patricia-trie root of a mapping from indices to byte slices.
fn enumerated_trie_root(items: &[&[u8]]) -> Self::Output;
/// Acquire the global storage root.
fn storage_root() -> Self::Output;
}
/// Blake2-256 Hashing implementation.
pub struct BlakeTwo256;
impl Hashing for BlakeTwo256 {
type Output = primitives::H256;
fn hash(s: &[u8]) -> Self::Output {
blake2_256(s).into()
}
fn enumerated_trie_root(items: &[&[u8]]) -> Self::Output {
enumerated_trie_root(items).into()
}
fn storage_root() -> Self::Output {
storage_root().into()
}
}
+18 -1
View File
@@ -82,11 +82,28 @@ pub fn storage_root() -> [u8; 32] {
).unwrap_or([0u8; 32])
}
/// "Commit" all existing operations and get the resultant storage root.
/// A trie root formed from the enumerated items.
pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] {
triehash::ordered_trie_root(serialised_values.iter().map(|s| s.to_vec())).0
}
/// A trie root formed from the iterated items.
pub fn trie_root<
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
>(input: I) -> [u8; 32] {
triehash::trie_root(input).0
}
/// A trie root formed from the enumerated items.
pub fn ordered_trie_root<
I: IntoIterator<Item = A>,
A: AsRef<[u8]>
>(input: I) -> [u8; 32] {
triehash::ordered_trie_root(input).0
}
/// Verify a ed25519 signature.
pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
ed25519::verify(sig, msg, pubkey)
@@ -138,6 +138,27 @@ pub fn enumerated_trie_root(values: &[&[u8]]) -> [u8; 32] {
result
}
/// A trie root formed from the iterated items.
pub fn trie_root<
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
>(_input: I) -> [u8; 32] {
unimplemented!()
// TODO Maybe implement (though probably easier/cleaner to have blake2 be the only thing
// implemneted natively and compile the trie logic as wasm).
}
/// A trie root formed from the enumerated items.
pub fn ordered_trie_root<
I: IntoIterator<Item = A>,
A: AsRef<[u8]>
>(_input: I) -> [u8; 32] {
unimplemented!()
// TODO Maybe implement (though probably easier/cleaner to have blake2 be the only thing
// implemneted natively and compile the trie logic as wasm).
}
/// The current relay chain identifier.
pub fn chain_id() -> u64 {
unsafe {
@@ -20,6 +20,7 @@ pub use std::cell;
pub use std::clone;
pub use std::cmp;
pub use std::fmt;
pub use std::hash;
pub use std::iter;
pub use std::marker;
pub use std::mem;
@@ -29,6 +29,7 @@ pub use core::cell;
pub use core::clone;
pub use core::cmp;
pub use core::fmt;
pub use core::hash;
pub use core::intrinsics;
pub use core::iter;
pub use core::marker;
@@ -20,7 +20,6 @@ pub use rstd::prelude::{Vec, Clone, Eq, PartialEq};
#[cfg(feature = "std")]
pub use std::fmt;
pub use rstd::result;
pub use rstd::marker::PhantomData;
#[cfg(feature = "std")]
use serde;
pub use codec::{Slicable, Input};
@@ -47,6 +46,10 @@ pub trait AuxCallable {
type Call: AuxDispatchable + Slicable + Clone + PartialEq + Eq;
}
// dirty hack to work around serde_derive issue
// https://github.com/rust-lang/rust/issues/51331
pub type AuxCallableCallFor<A> = <A as AuxCallable>::Call;
#[cfg(feature = "std")]
pub trait Callable {
type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq;
@@ -56,6 +59,10 @@ pub trait Callable {
type Call: Dispatchable + Slicable + Clone + PartialEq + Eq;
}
// dirty hack to work around serde_derive issue.
// https://github.com/rust-lang/rust/issues/51331
pub type CallableCallFor<C> = <C as Callable>::Call;
#[cfg(feature = "std")]
pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {}
@@ -68,26 +75,43 @@ pub trait Parameter: Slicable + Clone + Eq {}
#[cfg(not(feature = "std"))]
impl<T> Parameter for T where T: Slicable + Clone + Eq {}
/// Declare a struct for this module, then implement dispatch logic to create a pairing of several
/// dispatch traits and enums.
#[macro_export]
macro_rules! decl_module {
(
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$($rest:tt)*
) => {
pub struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>);
// TODO: switching based on std feature is because of an issue in
// serde-derive for when we attempt to derive `Deserialize` on these types,
// in a situation where we've imported `substrate_runtime_support` as another name.
#[cfg(feature = "std")]
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>);
#[cfg(not(feature = "std"))]
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>);
decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>;
$($rest)*
}
};
(
$(#[$attr:meta])*
struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$($rest:tt)*
) => {
struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>);
#[cfg(feature = "std")]
$(#[$attr])*
struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>);
#[cfg(not(feature = "std"))]
$(#[$attr])*
struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>);
decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>;
$($rest)*
@@ -101,6 +125,7 @@ macro_rules! decl_dispatch {
// WITHOUT AUX
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident {
$(
fn $fn_name:ident(
@@ -115,6 +140,7 @@ macro_rules! decl_dispatch {
) => {
__decl_dispatch_module_without_aux! {
impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type;
$(
fn $fn_name( $( $param_name: $param ),* ) -> $result = $id;
@@ -128,6 +154,7 @@ macro_rules! decl_dispatch {
// WITH AUX
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident where aux: $aux_type:ty {
$(
fn $fn_name:ident(aux
@@ -142,6 +169,7 @@ macro_rules! decl_dispatch {
) => {
__decl_dispatch_module_with_aux! {
impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type where aux: $aux_type;
$(
fn $fn_name(aux $(, $param_name: $param )*) -> $result = $id;
@@ -172,6 +200,7 @@ macro_rules! decl_dispatch {
macro_rules! __decl_dispatch_module_without_aux {
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident;
$(
fn $fn_name:ident(
@@ -185,6 +214,7 @@ macro_rules! __decl_dispatch_module_without_aux {
) => {
__decl_dispatch_module_common! {
impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type;
$( fn $fn_name( $( $param_name : $param ),* ) -> $result = $id ; )*
}
@@ -215,6 +245,7 @@ macro_rules! __decl_dispatch_module_without_aux {
macro_rules! __decl_dispatch_module_with_aux {
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident where aux: $aux_type:ty;
$(
fn $fn_name:ident(aux
@@ -228,6 +259,7 @@ macro_rules! __decl_dispatch_module_with_aux {
) => {
__decl_dispatch_module_common! {
impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type;
$( fn $fn_name( $( $param_name : $param ),* ) -> $result = $id ; )*
}
@@ -254,11 +286,12 @@ macro_rules! __decl_dispatch_module_with_aux {
};
}
#[macro_export]
/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum.
#[macro_export]
macro_rules! __decl_dispatch_module_common {
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident;
$(
fn $fn_name:ident(
@@ -270,10 +303,20 @@ macro_rules! __decl_dispatch_module_common {
= $id:expr ;
)*
) => {
#[cfg_attr(feature = "std", derive(Serialize))]
#[allow(missing_docs)]
#[cfg(feature = "std")]
$(#[$attr])*
pub enum $call_type<$trait_instance: $trait_name> {
__PhantomItem($crate::dispatch::PhantomData<$trait_instance>),
__PhantomItem(::std::marker::PhantomData<$trait_instance>),
$(
#[allow(non_camel_case_types)]
$fn_name ( $( $param ),* ),
)*
}
#[cfg(not(feature = "std"))]
$(#[$attr])*
pub enum $call_type<$trait_instance: $trait_name> {
__PhantomItem(::core::marker::PhantomData<$trait_instance>),
$(
#[allow(non_camel_case_types)]
$fn_name ( $( $param ),* ),
@@ -395,6 +438,7 @@ pub trait IsAuxSubType<T: AuxCallable> {
macro_rules! impl_outer_dispatch {
() => ();
(
$(#[$attr:meta])*
pub enum $call_type:ident where aux: $aux:ty {
$(
$camelcase:ident = $id:expr,
@@ -402,12 +446,10 @@ macro_rules! impl_outer_dispatch {
}
$( $rest:tt )*
) => {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[allow(missing_docs)]
$(#[$attr])*
pub enum $call_type {
$(
$camelcase ( <$camelcase as $crate::dispatch::AuxCallable>::Call )
$camelcase ( $crate::dispatch::AuxCallableCallFor<$camelcase> )
,)*
}
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
@@ -436,6 +478,7 @@ macro_rules! impl_outer_dispatch {
impl_outer_dispatch!{ $($rest)* }
};
(
$(#[$attr:meta])*
pub enum $call_type:ident {
$(
$camelcase:ident = $id:expr,
@@ -443,12 +486,10 @@ macro_rules! impl_outer_dispatch {
}
$( $rest:tt )*
) => {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[allow(missing_docs)]
$(#[$attr])*
pub enum $call_type {
$(
$camelcase ( <$camelcase as $crate::dispatch::Callable>::Call )
$camelcase ( $crate::dispatch::CallableCallFor<$camelcase> )
,)*
}
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
@@ -21,14 +21,6 @@
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
#[allow(unused_imports)] // can be removed when fixed: https://github.com/rust-lang/rust/issues/43497
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
pub use serde_derive::*;
extern crate substrate_runtime_std as rstd;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives;
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
hex-literal = "0.1.0"
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../codec", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
@@ -18,6 +19,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
default = ["std"]
std = [
"serde/std",
"serde_derive",
"substrate-codec/std",
"substrate-primitives/std",
"substrate-runtime-std/std",
@@ -25,6 +25,13 @@ extern crate substrate_runtime_std as rstd;
#[macro_use]
extern crate substrate_runtime_support as runtime_support;
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_primitives as primitives;
extern crate substrate_codec as codec;
@@ -36,8 +43,7 @@ use runtime_support::{storage, Parameter};
use runtime_support::dispatch::Result;
use runtime_support::storage::unhashed::StorageVec;
use primitives::traits::RefInto;
use substrate_primitives::bft::MisbehaviorReport;
use primitives::bft::MisbehaviorReport;
pub const AUTHORITY_AT: &'static [u8] = b":auth:";
pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len";
@@ -59,9 +65,13 @@ pub trait Trait: system::Trait {
decl_module! {
pub struct Module<T: Trait>;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux {
fn report_misbehavior(aux, report: MisbehaviorReport) -> Result = 0;
fn report_misbehavior(aux, report: MisbehaviorReport<T::Hash, T::BlockNumber>) -> Result = 0;
}
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum PrivCall {
fn set_code(new: Vec<u8>) -> Result = 0;
fn set_storage(items: Vec<KeyValue>) -> Result = 1;
@@ -89,7 +99,7 @@ impl<T: Trait> Module<T> {
}
/// Report some misbehaviour.
fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport) -> Result {
fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport<T::Hash, T::BlockNumber>) -> Result {
// TODO.
Ok(())
}
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
hex-literal = "0.1.0"
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../../safe-mix", default_features = false}
substrate-keyring = { path = "../../keyring", optional = true }
substrate-codec = { path = "../../codec", default_features = false }
@@ -25,6 +26,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
default = ["std"]
std = [
"serde/std",
"serde_derive",
"safe-mix/std",
"substrate-keyring",
"substrate-codec/std",
+16 -6
View File
@@ -18,7 +18,12 @@
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")] extern crate serde;
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
extern crate integer_sqrt;
extern crate substrate_codec as codec;
@@ -26,7 +31,7 @@ extern crate substrate_primitives;
#[cfg(any(feature = "std", test))] extern crate substrate_keyring as keyring;
#[macro_use] extern crate substrate_runtime_std as rstd;
extern crate substrate_runtime_io as runtime_io;
#[macro_use] extern crate substrate_runtime_support as runtime_support;
#[macro_use] extern crate substrate_runtime_support;
extern crate substrate_runtime_primitives as primitives;
extern crate substrate_runtime_consensus as consensus;
extern crate substrate_runtime_democracy as democracy;
@@ -36,8 +41,8 @@ extern crate substrate_runtime_system as system;
use rstd::prelude::*;
use primitives::traits::{Zero, One, RefInto, As};
use runtime_support::{StorageValue, StorageMap};
use runtime_support::dispatch::Result;
use substrate_runtime_support::{StorageValue, StorageMap};
use substrate_runtime_support::dispatch::Result;
pub mod voting;
@@ -101,6 +106,8 @@ pub trait Trait: democracy::Trait {}
decl_module! {
pub struct Module<T: Trait>;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux {
fn set_approvals(aux, votes: Vec<bool>, index: VoteIndex) -> Result = 0;
fn reap_inactive_voter(aux, signed_index: u32, who: T::AccountId, who_index: u32, assumed_vote_index: VoteIndex) -> Result = 1;
@@ -108,6 +115,8 @@ decl_module! {
fn submit_candidacy(aux, slot: u32) -> Result = 3;
fn present_winner(aux, candidate: T::AccountId, total: T::Balance, index: VoteIndex) -> Result = 4;
}
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum PrivCall {
fn set_desired_seats(count: u32) -> Result = 0;
fn remove_member(who: T::AccountId) -> Result = 1;
@@ -597,10 +606,11 @@ mod tests {
pub use runtime_io::with_externalities;
pub use substrate_primitives::H256;
use primitives::BuildExternalities;
use primitives::traits::{HasPublicAux, Identity};
use primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
use primitives::testing::{Digest, Header};
impl_outer_dispatch! {
#[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)]
pub enum Proposal {
Staking = 0,
Democracy = 1,
@@ -619,7 +629,7 @@ mod tests {
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = runtime_io::BlakeTwo256;
type Hashing = BlakeTwo256;
type Digest = Digest;
type AccountId = u64;
type Header = Header;
@@ -18,20 +18,24 @@
use rstd::prelude::*;
use rstd::borrow::Borrow;
use primitives::traits::{Executable, RefInto};
use runtime_io::{Hashing, print};
use runtime_support::{StorageValue, StorageMap, IsSubType};
use runtime_support::dispatch::Result;
use primitives::traits::{Executable, RefInto, Hashing};
use runtime_io::print;
use substrate_runtime_support::dispatch::Result;
use substrate_runtime_support::{StorageValue, StorageMap, IsSubType};
use {system, democracy};
use super::{Trait, Module as Council};
decl_module! {
pub struct Module<T: Trait>;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux {
fn propose(aux, proposal: Box<T::Proposal>) -> Result = 0;
fn vote(aux, proposal: T::Hash, approve: bool) -> Result = 1;
fn veto(aux, proposal_hash: T::Hash) -> Result = 2;
}
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum PrivCall {
fn set_cooloff_period(blocks: T::BlockNumber) -> Result = 0;
fn set_voting_period(blocks: T::BlockNumber) -> Result = 1;
@@ -214,7 +218,7 @@ impl<T: Trait> Executable for Council<T> {
mod tests {
use super::*;
use ::tests::*;
use runtime_support::Hashable;
use substrate_runtime_support::Hashable;
use democracy::VoteThreshold;
type CouncilVoting = super::Module<Test>;
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
hex-literal = "0.1.0"
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../../safe-mix", default_features = false}
substrate-codec = { path = "../../codec", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false }
@@ -22,6 +23,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
default = ["std"]
std = [
"serde/std",
"serde_derive",
"safe-mix/std",
"substrate-codec/std",
"substrate-primitives/std",

Some files were not shown because too many files have changed in this diff Show More