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 std::sync::Arc;
use client::genesis; use client::genesis;
use codec::Slicable; use demo_primitives::Hash;
use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
SessionConfig, StakingConfig, BuildExternalities}; SessionConfig, StakingConfig, BuildExternalities};
use demo_runtime::{Block, Header, UncheckedExtrinsic};
use futures::{Future, Sink, Stream}; use futures::{Future, Sink, Stream};
struct DummyPool; struct DummyPool;
impl extrinsic_pool::api::ExtrinsicPool for DummyPool { impl extrinsic_pool::api::ExtrinsicPool<UncheckedExtrinsic, Hash> for DummyPool {
type Error = extrinsic_pool::txpool::Error; type Error = extrinsic_pool::txpool::Error;
fn submit(&self, _: Vec<primitives::block::Extrinsic>) fn submit(&self, _: Vec<UncheckedExtrinsic>)
-> Result<Vec<primitives::block::ExtrinsicHash>, Self::Error> -> Result<Vec<Hash>, Self::Error>
{ {
Err("unimplemented".into()) Err("unimplemented".into())
} }
@@ -102,8 +103,8 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
struct GenesisBuilder; struct GenesisBuilder;
impl client::GenesisBuilder for GenesisBuilder { impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (primitives::Header, Vec<(Vec<u8>, Vec<u8>)>) { fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"]; let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"];
let genesis_config = GenesisConfig { let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig { consensus: Some(ConsensusConfig {
@@ -113,7 +114,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
system: None, system: None,
// block_time: 5, // 5 second block time. // block_time: 5, // 5 second block time.
session: Some(SessionConfig { session: Some(SessionConfig {
validators: vec![god_key.clone()], validators: vec![god_key.clone().into()],
session_length: 720, // that's 1 hour per session. session_length: 720, // that's 1 hour per session.
}), }),
staking: Some(StakingConfig { staking: Some(StakingConfig {
@@ -121,7 +122,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
intentions: vec![], intentions: vec![],
transaction_base_fee: 100, transaction_base_fee: 100,
transaction_byte_fee: 1, 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, validator_count: 12,
sessions_per_era: 24, // 24 hours per era. sessions_per_era: 24, // 24 hours per era.
bonding_duration: 90, // 90 days per bond. 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 storage = genesis_config.build_externalities();
let block = genesis::construct_genesis_block(&storage); let block = genesis::construct_genesis_block::<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()) (block.header, storage.into_iter().collect())
} }
} }
@@ -160,7 +161,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
let _rpc_servers = { let _rpc_servers = {
let handler = || { let handler = || {
let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote()); 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 http_address = "127.0.0.1:9933".parse().unwrap();
let ws_address = "127.0.0.1:9944".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 super::Executor;
use substrate_executor::WasmExecutor; use substrate_executor::WasmExecutor;
use codec::{Slicable, Joiner}; use codec::{Slicable, Joiner};
use keyring::Keyring::{self, Alice, Bob}; use keyring::Keyring;
use runtime_support::{Hashable, StorageValue, StorageMap}; use runtime_support::{Hashable, StorageValue, StorageMap};
use state_machine::{CodeExecutor, TestExternalities}; use state_machine::{CodeExecutor, TestExternalities};
use primitives::twox_128; 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 { fn xt() -> UncheckedExtrinsic {
let extrinsic = Extrinsic { let extrinsic = Extrinsic {
signed: Alice.into(), signed: alice(),
index: 0, 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(); .sign(&extrinsic.encode()).into();
UncheckedExtrinsic { extrinsic, signature } UncheckedExtrinsic { extrinsic, signature }
@@ -82,7 +90,7 @@ mod tests {
#[test] #[test]
fn panic_execution_with_foreign_code_gives_error() { fn panic_execution_with_foreign_code_gives_error() {
let mut t: TestExternalities = map![ 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::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<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] twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -97,7 +105,7 @@ mod tests {
#[test] #[test]
fn panic_execution_with_native_equivalent_code_gives_error() { fn panic_execution_with_native_equivalent_code_gives_error() {
let mut t: TestExternalities = map![ 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::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<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] twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -112,7 +120,7 @@ mod tests {
#[test] #[test]
fn successful_execution_with_native_equivalent_code_gives_ok() { fn successful_execution_with_native_equivalent_code_gives_ok() {
let mut t: TestExternalities = map![ 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::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<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] twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -124,15 +132,15 @@ mod tests {
assert!(r.is_ok()); assert!(r.is_ok());
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 42); assert_eq!(Staking::balance(&alice()), 42);
assert_eq!(Staking::balance(&Bob), 69); assert_eq!(Staking::balance(&bob()), 69);
}); });
} }
#[test] #[test]
fn successful_execution_with_foreign_code_gives_ok() { fn successful_execution_with_foreign_code_gives_ok() {
let mut t: TestExternalities = map![ 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::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<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] twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -144,26 +152,26 @@ mod tests {
assert!(r.is_ok()); assert!(r.is_ok());
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 42); assert_eq!(Staking::balance(&alice()), 42);
assert_eq!(Staking::balance(&Bob), 69); assert_eq!(Staking::balance(&bob()), 69);
}); });
} }
fn new_test_ext() -> TestExternalities { fn new_test_ext() -> TestExternalities {
use keyring::Keyring::*; use keyring::Keyring::*;
let three = [3u8; 32]; let three = [3u8; 32].into();
GenesisConfig { GenesisConfig {
consensus: Some(Default::default()), consensus: Some(Default::default()),
system: Some(Default::default()), system: Some(Default::default()),
session: Some(SessionConfig { session: Some(SessionConfig {
session_length: 2, 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 { staking: Some(StakingConfig {
sessions_per_era: 2, sessions_per_era: 2,
current_era: 0, current_era: 0,
balances: vec![(Alice.into(), 111)], balances: vec![(alice(), 111)],
intentions: vec![Alice.into(), Bob.into(), Charlie.into()], intentions: vec![alice(), bob(), Charlie.to_raw_public().into()],
validator_count: 3, validator_count: 3,
bonding_duration: 0, bonding_duration: 0,
transaction_base_fee: 1, transaction_base_fee: 1,
@@ -178,7 +186,7 @@ mod tests {
use triehash::ordered_trie_root; use triehash::ordered_trie_root;
let extrinsics = extrinsics.into_iter().map(|extrinsic| { 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(); .sign(&extrinsic.encode()).into();
UncheckedExtrinsic { extrinsic, signature } UncheckedExtrinsic { extrinsic, signature }
@@ -204,9 +212,9 @@ mod tests {
[69u8; 32].into(), [69u8; 32].into(),
hex!("76b0393b4958d3cb98bb51d9f4edb316af48485142b8721e94c3b52c75ec3243").into(), hex!("76b0393b4958d3cb98bb51d9f4edb316af48485142b8721e94c3b52c75ec3243").into(),
vec![Extrinsic { vec![Extrinsic {
signed: Alice.into(), signed: alice(),
index: 0, 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(), hex!("8ae9828a5988459d35fb428086170dead660176ee0766e89bc1a4b48153d4e88").into(),
vec![ vec![
Extrinsic { Extrinsic {
signed: Bob.into(), signed: bob(),
index: 0, index: 0,
function: Call::Staking(staking::Call::transfer(Alice.into(), 5)), function: Call::Staking(staking::Call::transfer(alice(), 5)),
}, },
Extrinsic { Extrinsic {
signed: Alice.into(), signed: alice(),
index: 1, 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(); Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 41); assert_eq!(Staking::balance(&alice()), 41);
assert_eq!(Staking::balance(&Bob), 69); assert_eq!(Staking::balance(&bob()), 69);
}); });
Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 30); assert_eq!(Staking::balance(&alice()), 30);
assert_eq!(Staking::balance(&Bob), 78); assert_eq!(Staking::balance(&bob()), 78);
}); });
} }
@@ -257,22 +265,22 @@ mod tests {
WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 41); assert_eq!(Staking::balance(&alice()), 41);
assert_eq!(Staking::balance(&Bob), 69); assert_eq!(Staking::balance(&bob()), 69);
}); });
WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 30); assert_eq!(Staking::balance(&alice()), 30);
assert_eq!(Staking::balance(&Bob), 78); assert_eq!(Staking::balance(&bob()), 78);
}); });
} }
#[test] #[test]
fn panic_execution_gives_error() { fn panic_execution_gives_error() {
let mut t: TestExternalities = map![ 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::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<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] twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -288,7 +296,7 @@ mod tests {
#[test] #[test]
fn successful_execution_gives_ok() { fn successful_execution_gives_ok() {
let mut t: TestExternalities = map![ 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::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<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] twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
@@ -301,8 +309,8 @@ mod tests {
assert!(r.is_ok()); assert!(r.is_ok());
runtime_io::with_externalities(&mut t, || { runtime_io::with_externalities(&mut t, || {
assert_eq!(Staking::balance(&Alice), 42); assert_eq!(Staking::balance(&alice()), 42);
assert_eq!(Staking::balance(&Bob), 69); 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 /// 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`. /// 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. /// Balance of an account.
pub type Balance = u64; pub type Balance = u64;
+25 -7
View File
@@ -22,11 +22,18 @@
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
#[macro_use] #[macro_use]
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support;
#[macro_use] #[macro_use]
extern crate substrate_runtime_primitives as runtime_primitives; 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_std as rstd;
extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_consensus as consensus;
extern crate substrate_runtime_council as council; extern crate substrate_runtime_council as council;
@@ -39,10 +46,9 @@ extern crate substrate_runtime_timestamp as timestamp;
extern crate demo_primitives; extern crate demo_primitives;
use rstd::prelude::*; use rstd::prelude::*;
use runtime_io::BlakeTwo256;
use demo_primitives::{AccountId, Balance, BlockNumber, Hash, Index, SessionKey, Signature}; use demo_primitives::{AccountId, Balance, BlockNumber, Hash, Index, SessionKey, Signature};
use runtime_primitives::generic; use runtime_primitives::generic;
use runtime_primitives::traits::{Identity, HasPublicAux}; use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256};
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
pub use runtime_primitives::BuildExternalities; pub use runtime_primitives::BuildExternalities;
@@ -61,7 +67,7 @@ impl system::Trait for Concrete {
type Hashing = BlakeTwo256; type Hashing = BlakeTwo256;
type Digest = generic::Digest<Vec<u8>>; type Digest = generic::Digest<Vec<u8>>;
type AccountId = AccountId; 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. /// System module for this concrete runtime.
@@ -84,8 +90,16 @@ impl timestamp::Trait for Concrete {
/// Timestamp module for this concrete runtime. /// Timestamp module for this concrete runtime.
pub type Timestamp = timestamp::Module<Concrete>; 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 { impl session::Trait for Concrete {
type ConvertAccountIdToSessionKey = Identity; type ConvertAccountIdToSessionKey = SessionKeyConversion;
} }
/// Session module for this concrete runtime. /// Session module for this concrete runtime.
@@ -114,6 +128,8 @@ pub type Council = council::Module<Concrete>;
pub type CouncilVoting = council::voting::Module<Concrete>; pub type CouncilVoting = council::voting::Module<Concrete>;
impl_outer_dispatch! { impl_outer_dispatch! {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux { pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
Consensus = 0, Consensus = 0,
Session = 1, Session = 1,
@@ -124,6 +140,8 @@ impl_outer_dispatch! {
CouncilVoting = 7, CouncilVoting = 7,
} }
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum PrivCall { pub enum PrivCall {
Consensus = 0, Consensus = 0,
Session = 1, Session = 1,
@@ -135,9 +153,9 @@ impl_outer_dispatch! {
} }
/// Block header type as expected by this runtime. /// 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. /// 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. /// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
/// Extrinsic type as expected by this runtime. /// Extrinsic type as expected by this runtime.
+246 -192
View File
@@ -11,19 +11,9 @@ name = "base58"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.0.1" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -37,33 +27,55 @@ dependencies = [
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.2.1" version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.4" version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.2" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "constant_time_eq" name = "constant_time_eq"
version = "0.1.3" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "crunchy" name = "crunchy"
version = "0.1.6" version = "0.1.6"
@@ -73,8 +85,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "demo-primitives" name = "demo-primitives"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"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.27 (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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0", "substrate-runtime-primitives 0.1.0",
@@ -110,20 +122,15 @@ version = "0.1.0"
dependencies = [ dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "elastic-array" name = "elastic-array"
version = "0.9.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -134,15 +141,37 @@ name = "environmental"
version = "0.1.0" version = "0.1.0"
[[package]] [[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" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.64 (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)",
] ]
[[package]] [[package]]
@@ -154,12 +183,23 @@ dependencies = [
"rustc-hex 1.0.0 (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 = "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]] [[package]]
name = "fuchsia-zircon" name = "fuchsia-zircon"
version = "0.3.3" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -183,16 +223,16 @@ dependencies = [
[[package]] [[package]]
name = "hex-literal" name = "hex-literal"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "hex-literal-impl" name = "hex-literal-impl"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "keccak-hash" name = "keccak-hash"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -220,12 +260,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.36" version = "0.2.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -241,9 +281,14 @@ name = "log"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "memory_units" name = "memory_units"
version = "0.3.0" version = "0.3.0"
@@ -264,7 +309,7 @@ name = "num_cpus"
version = "1.8.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@@ -280,9 +325,9 @@ name = "parity-wasm"
version = "0.27.6" version = "0.27.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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]] [[package]]
@@ -290,37 +335,29 @@ name = "parity-wasm"
version = "0.30.0" version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.5.4" version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.2.10" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"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)",
"smallvec 0.6.0 (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)", "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]] [[package]]
name = "proc-macro-hack" name = "proc-macro-hack"
version = "0.4.0" version = "0.4.0"
@@ -334,12 +371,20 @@ name = "proc-macro-hack-impl"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "pwasm-alloc" name = "pwasm-alloc"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"pwasm-libc 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]] [[package]]
@@ -351,15 +396,18 @@ name = "pwasm-utils"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.3.15" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "rand" name = "rand"
@@ -367,7 +415,7 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -386,19 +434,19 @@ name = "rayon"
version = "0.8.2" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"coco 0.1.1 (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 0.2.11 (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.36 (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)", "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]] [[package]]
@@ -408,20 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "rlp" name = "rlp"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (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]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "safe-mix" name = "safe-mix"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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]] [[package]]
@@ -457,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "semver" name = "semver"
version = "0.6.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "serde" name = "serde"
version = "1.0.27" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.27" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.1 (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)",
] ]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -511,8 +549,8 @@ name = "substrate-keyring"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ed25519 0.1.0", "ed25519 0.1.0",
"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)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -520,25 +558,26 @@ name = "substrate-primitives"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (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-codec 0.1.0",
"substrate-runtime-std 0.1.0", "substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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]] [[package]]
name = "substrate-runtime-consensus" name = "substrate-runtime-consensus"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -563,10 +602,11 @@ dependencies = [
name = "substrate-runtime-council" name = "substrate-runtime-council"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
"safe-mix 0.1.0", "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-codec 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -585,9 +625,10 @@ dependencies = [
name = "substrate-runtime-democracy" name = "substrate-runtime-democracy"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0", "substrate-runtime-consensus 0.1.0",
@@ -604,8 +645,8 @@ dependencies = [
name = "substrate-runtime-executive" name = "substrate-runtime-executive"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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-codec 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
"substrate-runtime-primitives 0.1.0", "substrate-runtime-primitives 0.1.0",
@@ -620,12 +661,12 @@ version = "0.1.0"
dependencies = [ dependencies = [
"ed25519 0.1.0", "ed25519 0.1.0",
"environmental 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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-std 0.1.0", "substrate-runtime-std 0.1.0",
"substrate-state-machine 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]] [[package]]
@@ -634,8 +675,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "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)", "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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -647,21 +688,22 @@ dependencies = [
name = "substrate-runtime-sandbox" name = "substrate-runtime-sandbox"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
"substrate-runtime-std 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]] [[package]]
name = "substrate-runtime-session" name = "substrate-runtime-session"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -677,9 +719,10 @@ dependencies = [
name = "substrate-runtime-staking" name = "substrate-runtime-staking"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -700,7 +743,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"pwasm-alloc 0.1.0", "pwasm-alloc 0.1.0",
"pwasm-libc 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]] [[package]]
@@ -708,9 +751,9 @@ name = "substrate-runtime-support"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ed25519 0.1.0", "ed25519 0.1.0",
"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)",
"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.27 (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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -721,9 +764,9 @@ dependencies = [
name = "substrate-runtime-system" name = "substrate-runtime-system"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -736,8 +779,9 @@ dependencies = [
name = "substrate-runtime-timestamp" name = "substrate-runtime-timestamp"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -751,43 +795,39 @@ dependencies = [
name = "substrate-state-machine" name = "substrate-state-machine"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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)",
"substrate-primitives 0.1.0", "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]] [[package]]
name = "syn" name = "syn"
version = "0.11.11" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (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.0.4 (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 = "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)",
] ]
[[package]] [[package]]
name = "tiny-keccak" name = "tiny-keccak"
version = "1.4.0" version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "triehash" name = "triehash"
version = "0.1.0" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"ethcore-bigint 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)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (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]] [[package]]
@@ -803,14 +843,25 @@ name = "uint"
version = "0.1.2" version = "0.1.2"
source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71" source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71"
dependencies = [ 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-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]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.0.4" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -820,10 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "wasmi" name = "wasmi"
version = "0.1.2" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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] [metadata]
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "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 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.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "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 byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" "checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "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 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.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5" "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.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 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 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 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 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 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631" "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 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 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 lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "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.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 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 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 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" "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 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.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 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 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "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-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 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.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 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 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 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 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-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 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 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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" "checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" "checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "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 syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" "checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce"
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "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 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 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 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-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" "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. //! Strongly typed API for full Polkadot client.
use client::backend::{Backend, LocalBackend}; 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 polkadot_executor::Executor as LocalDispatch;
use substrate_executor::{NativeExecutionDispatch, NativeExecutor}; use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
use state_machine::{self, OverlayedChanges}; use state_machine;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; use primitives::{AccountId, Block, Header, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use runtime::{self, Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall, ParachainsCall};
use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result}; use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
/// A checked block ID used for the substrate-client implementation of CheckedBlockId; /// A checked block ID used for the substrate-client implementation of CheckedBlockId;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct CheckedId(pub BlockId); pub struct CheckedId(pub(crate) BlockId);
impl CheckedBlockId for CheckedId { impl CheckedBlockId for CheckedId {
fn block_id(&self) -> &BlockId { fn block_id(&self) -> &BlockId {
@@ -44,14 +44,16 @@ macro_rules! with_runtime {
($client: ident, $at: expr, $exec: expr) => {{ ($client: ident, $at: expr, $exec: expr) => {{
let parent = $at.block_id(); let parent = $at.block_id();
let header = Header { let header = Header {
parent_hash: $client.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?, parent_hash: $client.block_hash_from_id(&parent)?
number: $client.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1, .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(), state_root: Default::default(),
extrinsics_root: Default::default(), extrinsics_root: Default::default(),
digest: 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 changes = Default::default();
let mut ext = state_machine::Ext::new(&mut changes, &state); let mut ext = state_machine::Ext::new(&mut changes, &state);
@@ -63,105 +65,28 @@ macro_rules! with_runtime {
}} }}
} }
/// A polkadot block builder. impl<B: LocalBackend<Block>> BlockBuilder for ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
#[derive(Debug, Clone)] where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
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>
{ {
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> { fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
// Check that this is not an "inherent" extrinsic. self.push(extrinsic).map_err(Into::into)
if extrinsic.signature == Default::default() {
bail!(ErrorKind::PushedInherentTransaction(extrinsic));
} else {
self.apply_extrinsic(extrinsic.clone())?;
self.extrinsics.push(extrinsic);
Ok(())
}
} }
fn bake(mut self) -> Block { /// Bake the block with provided extrinsics.
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state); fn bake(self) -> Result<Block> {
ClientBlockBuilder::bake(self).map_err(Into::into)
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,
}
} }
} }
impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>> impl<B: LocalBackend<Block>> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{ {
type CheckedBlockId = CheckedId; 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> { fn check_id(&self, id: BlockId) -> Result<CheckedId> {
// bail if the code is not the same as the natively linked. // 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.") 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> { fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<bool> {
use substrate_executor::error::ErrorKind as ExecErrorKind; 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 { match res {
Ok(()) => Ok(true), Ok(()) => Ok(true),
Err(err) => match err.kind() { 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)) with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain))
} }
fn build_block(&self, parent: &CheckedId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> { fn build_block(&self, at: &CheckedId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
let parent = parent.block_id(); let mut block_builder = self.new_block_at(at.block_id())?;
let header = Header { for inherent in self.inherent_extrinsics(at, timestamp, new_heads)? {
parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?, block_builder.push(inherent)?;
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)?;
} }
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>>> impl<B: LocalBackend<Block>> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{} {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use keyring::Keyring; use keyring::Keyring;
use codec::Slicable;
use client::{self, LocalCallExecutor}; use client::{self, LocalCallExecutor};
use client::in_mem::Backend as InMemory; use client::in_mem::Backend as InMemory;
use substrate_executor::NativeExecutionDispatch; use substrate_executor::NativeExecutionDispatch;
use substrate_primitives::{self, Header};
use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities}; use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities};
fn validators() -> Vec<AccountId> { fn validators() -> Vec<AccountId> {
vec![
Keyring::One.to_raw_public().into(),
Keyring::Two.to_raw_public().into(),
]
}
fn session_keys() -> Vec<SessionKey> {
vec![ vec![
Keyring::One.to_raw_public(), Keyring::One.to_raw_public(),
Keyring::Two.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; struct GenesisBuilder;
impl client::GenesisBuilder for GenesisBuilder { impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) { fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let genesis_config = GenesisConfig { let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig { consensus: Some(ConsensusConfig {
code: LocalDispatch::native_equivalent().to_vec(), code: LocalDispatch::native_equivalent().to_vec(),
authorities: validators(), authorities: session_keys(),
}), }),
system: None, system: None,
session: Some(SessionConfig { session: Some(SessionConfig {
@@ -309,8 +222,8 @@ mod tests {
}; };
let storage = genesis_config.build_externalities(); let storage = genesis_config.build_externalities();
let block = ::client::genesis::construct_genesis_block(&storage); let block = ::client::genesis::construct_genesis_block::<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()) (block.header, storage.into_iter().collect())
} }
} }
@@ -320,18 +233,36 @@ mod tests {
#[test] #[test]
fn gets_session_and_validator_keys() { fn gets_session_and_validator_keys() {
let client = client(); let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap(); let id = client.check_id(BlockId::number(0)).unwrap();
assert_eq!(client.session_keys(&id).unwrap(), validators()); assert_eq!(client.session_keys(&id).unwrap(), session_keys());
assert_eq!(client.validators(&id).unwrap(), validators()); assert_eq!(client.validators(&id).unwrap(), validators());
} }
#[test] #[test]
fn build_block() { fn build_block_implicit_succeeds() {
let client = client(); 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_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_eq!(block.header.number, 1);
assert!(block.header.extrinsics_root != Default::default()); assert!(block.header.extrinsics_root != Default::default());
@@ -339,14 +270,14 @@ mod tests {
#[test] #[test]
fn fails_to_check_id_for_unknown_block() { 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] #[test]
fn gets_random_seed_with_genesis() { fn gets_random_seed_with_genesis() {
let client = client(); 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()); assert!(client.random_seed(&id).is_ok());
} }
} }
+21 -28
View File
@@ -18,8 +18,8 @@
//! runtime. //! runtime.
extern crate polkadot_executor; extern crate polkadot_executor;
extern crate polkadot_runtime as runtime;
extern crate polkadot_primitives as primitives; extern crate polkadot_primitives as primitives;
extern crate polkadot_runtime as runtime;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
extern crate substrate_client as client; extern crate substrate_client as client;
@@ -37,9 +37,8 @@ extern crate substrate_keyring as keyring;
pub mod full; pub mod full;
pub mod light; pub mod light;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use runtime::{Block, UncheckedExtrinsic};
error_chain! { error_chain! {
errors { errors {
@@ -49,19 +48,9 @@ error_chain! {
display("Unknown runtime code") display("Unknown runtime code")
} }
/// Unknown block ID. /// Unknown block ID.
UnknownBlock(b: BlockId) { UnknownBlock(b: String) {
description("Unknown block") description("Unknown block")
display("Unknown block") display("Unknown block {}", b)
}
/// 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),
} }
/// Some other error. /// Some other error.
// TODO: allow to be specified as associated type of PolkadotApi // 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. /// A checked block identifier.
pub trait CheckedBlockId: Clone + 'static { pub trait CheckedBlockId: Clone + 'static {
/// Yield the underlying block ID. /// Yield the underlying block ID.
fn block_id(&self) -> &BlockId; 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. /// Trait encapsulating the Polkadot API.
/// ///
/// All calls should fail when the exact runtime is unknown. /// All calls should fail when the exact runtime is unknown.
pub trait PolkadotApi { pub trait PolkadotApi {
/// A checked block ID. Used to avoid redundancy of code check. /// A checked block ID. Used to avoid redundancy of code check.
type CheckedBlockId: CheckedBlockId; type CheckedBlockId: CheckedBlockId;
/// The type used to build blocks. /// The block builder for this API type.
type BlockBuilder: BlockBuilder; type BlockBuilder: BlockBuilder;
/// Check whether requests at the given block ID can be served. /// 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. /// and an error if we can't evaluate for some reason.
fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<bool>; fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<bool>;
/// Create a block builder on top of the parent block. /// Build a block on top of the given, with inherent extrinsics pre-pushed.
fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>; 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. /// 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 client::{Client, CallExecutor};
use codec::Slicable; use codec::Slicable;
use state_machine; use state_machine;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use runtime::{Block, UncheckedExtrinsic};
use full::CheckedId; use full::CheckedId;
use {PolkadotApi, RemotePolkadotApi, BlockBuilder, CheckedBlockId, Result, ErrorKind}; use {PolkadotApi, BlockBuilder, RemotePolkadotApi, CheckedBlockId, Result, ErrorKind};
/// Remote polkadot API implementation. /// Light block builder. TODO: make this work (efficiently)
pub struct RemotePolkadotApiWrapper<B: Backend, E: CallExecutor>(pub Arc<Client<B, E>>); #[derive(Clone, Copy)]
/// Block builder for light client.
pub struct LightBlockBuilder; pub struct LightBlockBuilder;
impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E> impl BlockBuilder for LightBlockBuilder {
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> 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 CheckedBlockId = CheckedId;
type BlockBuilder = LightBlockBuilder; type BlockBuilder = LightBlockBuilder;
@@ -86,21 +96,15 @@ impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E>
Err(ErrorKind::UnknownRuntime.into()) 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()) Err(ErrorKind::UnknownRuntime.into())
} }
} }
impl<B: RemoteBackend, E: CallExecutor> RemotePolkadotApi for RemotePolkadotApiWrapper<B, E> impl<B: RemoteBackend<Block>, E: CallExecutor<Block>> RemotePolkadotApi for RemotePolkadotApiWrapper<B, E>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> 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" fdlimit = "0.1"
parking_lot = "0.4" parking_lot = "0.4"
substrate-client = { path = "../../substrate/client" } 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-state-machine = { path = "../../substrate/state-machine" }
substrate-executor = { path = "../../substrate/executor" }
substrate-primitives = { path = "../../substrate/primitives" }
substrate-rpc = { path = "../../substrate/rpc" } substrate-rpc = { path = "../../substrate/rpc" }
substrate-rpc-servers = { path = "../../substrate/rpc-servers" } substrate-rpc-servers = { path = "../../substrate/rpc-servers" }
substrate-network = { path = "../../substrate/network" }
polkadot-primitives = { path = "../primitives" } polkadot-primitives = { path = "../primitives" }
polkadot-executor = { path = "../executor" }
polkadot-runtime = { path = "../runtime" }
polkadot-service = { path = "../service" } polkadot-service = { path = "../service" }
polkadot-transaction-pool = { path = "../transaction-pool" } polkadot-transaction-pool = { path = "../transaction-pool" }
+5 -6
View File
@@ -21,8 +21,7 @@ use futures::stream::Stream;
use service::Service; use service::Service;
use tokio_core::reactor; use tokio_core::reactor;
use network::{SyncState, SyncProvider}; use network::{SyncState, SyncProvider};
use runtime_support::Hashable; use polkadot_primitives::Block;
use primitives::block::HeaderHash;
use state_machine; use state_machine;
use client::{self, BlockchainEvents}; use client::{self, BlockchainEvents};
@@ -31,9 +30,9 @@ const TIMER_INTERVAL_MS: u64 = 5000;
/// Spawn informant on the event loop /// Spawn informant on the event loop
pub fn start<B, E>(service: &Service<B, E>, handle: reactor::Handle) pub fn start<B, E>(service: &Service<B, E>, handle: reactor::Handle)
where where
B: client::backend::Backend + Send + Sync + 'static, B: client::backend::Backend<Block> + Send + Sync + 'static,
E: client::CallExecutor + Send + Sync + 'static, E: client::CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error> 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) let interval = reactor::Interval::new_at(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS), &handle)
.expect("Error creating informant timer"); .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(); let sync_status = network.status();
if let Ok(best_block) = client.best_block_header() { 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) { let status = match (sync_status.sync.state, sync_status.sync.best_seen_block) {
(SyncState::Idle, _) => "Idle".into(), (SyncState::Idle, _) => "Idle".into(),
(SyncState::Downloading, None) => "Syncing".into(), (SyncState::Downloading, None) => "Syncing".into(),
+5 -9
View File
@@ -32,17 +32,12 @@ extern crate ed25519;
extern crate triehash; extern crate triehash;
extern crate parking_lot; extern crate parking_lot;
extern crate substrate_codec as codec;
extern crate substrate_state_machine as state_machine; extern crate substrate_state_machine as state_machine;
extern crate substrate_client as client; extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate substrate_network as network; extern crate substrate_network as network;
extern crate substrate_rpc; extern crate substrate_rpc;
extern crate substrate_rpc_servers as rpc; extern crate substrate_rpc_servers as rpc;
extern crate substrate_runtime_support as runtime_support;
extern crate polkadot_primitives; extern crate polkadot_primitives;
extern crate polkadot_executor;
extern crate polkadot_runtime;
extern crate polkadot_service as service; extern crate polkadot_service as service;
extern crate polkadot_transaction_pool as txpool; extern crate polkadot_transaction_pool as txpool;
@@ -61,6 +56,7 @@ mod informant;
use std::io; use std::io;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use polkadot_primitives::Block;
use futures::sync::mpsc; use futures::sync::mpsc;
use futures::{Sink, Future, Stream}; 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<()> fn run_until_exit<B, E>(mut core: reactor::Core, service: service::Service<B, E>, matches: &clap::ArgMatches, config: service::Configuration) -> error::Result<()>
where where
B: client::backend::Backend + Send + Sync + 'static, B: client::backend::Backend<Block> + Send + Sync + 'static,
E: client::CallExecutor + Send + Sync + 'static, E: client::CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error> client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>
{ {
let exit = { let exit = {
// can't use signal directly here because CtrlC takes only `Fn`. // 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 handler = || {
let chain = rpc::apis::chain::Chain::new(service.client(), core.remote()); let chain = rpc::apis::chain::Chain::new(service.client(), core.remote());
rpc::rpc_handler( rpc::rpc_handler::<Block, _, _, _, _>(
service.client(), service.client(),
chain, chain,
service.transaction_pool(), service.transaction_pool(),
+2 -1
View File
@@ -8,5 +8,6 @@ description = "Abstract collation logic"
futures = "0.1.17" futures = "0.1.17"
substrate-codec = { path = "../../substrate/codec", version = "0.1" } substrate-codec = { path = "../../substrate/codec", version = "0.1" }
substrate-primitives = { path = "../../substrate/primitives", 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-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 futures;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate polkadot_runtime;
extern crate polkadot_primitives; extern crate polkadot_primitives;
use std::collections::{BTreeSet, BTreeMap}; use std::collections::{BTreeSet, BTreeMap};
use futures::{stream, Stream, Future, IntoFuture}; 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. /// Parachain context needed for collation.
/// ///
@@ -62,7 +63,7 @@ pub trait ParachainContext {
fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>( fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>(
&self, &self,
ingress: I, ingress: I,
) -> (parachain::BlockData, polkadot_primitives::AccountId, polkadot_primitives::Signature); ) -> (parachain::BlockData, polkadot_primitives::AccountId, CandidateSignature);
} }
/// Relay chain context needed to collate. /// 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-network = { path = "../../substrate/network" }
substrate-keyring = { path = "../../substrate/keyring" } substrate-keyring = { path = "../../substrate/keyring" }
substrate-client = { path = "../../substrate/client" } 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. //! Errors that can occur during the consensus process.
use polkadot_primitives::AccountId; use primitives::AuthorityId;
error_chain! { error_chain! {
links { links {
@@ -29,7 +29,7 @@ error_chain! {
description("Duty Roster had invalid length"), description("Duty Roster had invalid length"),
display("Invalid duty roster length: expected {}, got {}", expected, got), 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."), description("Local account ID not a validator at this block."),
display("Local account ID ({:?}) not a validator at this block.", id), display("Local account ID ({:?}) not a validator at this block.", id),
} }
@@ -19,11 +19,9 @@
use super::MAX_TRANSACTIONS_SIZE; use super::MAX_TRANSACTIONS_SIZE;
use codec::Slicable; use codec::Slicable;
use polkadot_runtime::Block as PolkadotGenericBlock; use polkadot_runtime::{Block as PolkadotGenericBlock, CheckedBlock};
use polkadot_primitives::Timestamp; use polkadot_primitives::{Block, Hash, BlockNumber, Timestamp};
use polkadot_primitives::parachain::Id as ParaId; use polkadot_primitives::parachain::Id as ParaId;
use primitives::block::{Block as SubstrateBlock, HeaderHash, Number as BlockNumber};
use transaction_pool::PolkadotBlock;
error_chain! { error_chain! {
links { links {
@@ -51,7 +49,7 @@ error_chain! {
description("Proposal included unregistered parachain."), description("Proposal included unregistered parachain."),
display("Proposal included unregistered parachain {:?}", id), display("Proposal included unregistered parachain {:?}", id),
} }
WrongParentHash(expected: HeaderHash, got: HeaderHash) { WrongParentHash(expected: Hash, got: Hash) {
description("Proposal had wrong parent hash."), description("Proposal had wrong parent hash."),
display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got), 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 /// Attempt to evaluate a substrate block as a polkadot block, returning error
/// upon any initial validity checks failing. /// upon any initial validity checks failing.
pub fn evaluate_initial( pub fn evaluate_initial(
proposal: &SubstrateBlock, proposal: &Block,
now: Timestamp, now: Timestamp,
parent_hash: &HeaderHash, parent_hash: &Hash,
parent_number: BlockNumber, parent_number: BlockNumber,
active_parachains: &[ParaId], active_parachains: &[ParaId],
) -> Result<PolkadotBlock> { ) -> Result<CheckedBlock> {
const MAX_TIMESTAMP_DRIFT: Timestamp = 60; const MAX_TIMESTAMP_DRIFT: Timestamp = 60;
let encoded = Slicable::encode(proposal); let encoded = Slicable::encode(proposal);
let proposal = PolkadotGenericBlock::decode(&mut &encoded[..]) 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)?; .ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?;
let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| { 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_collator as collator;
extern crate polkadot_statement_table as table; extern crate polkadot_statement_table as table;
extern crate polkadot_parachain as parachain; extern crate polkadot_parachain as parachain;
extern crate polkadot_primitives;
extern crate polkadot_transaction_pool as transaction_pool; extern crate polkadot_transaction_pool as transaction_pool;
extern crate polkadot_runtime; extern crate polkadot_runtime;
extern crate polkadot_primitives;
extern crate substrate_bft as bft; extern crate substrate_bft as bft;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_network; extern crate substrate_network;
extern crate exit_future; extern crate exit_future;
@@ -68,10 +69,9 @@ use std::time::{Duration, Instant};
use codec::Slicable; use codec::Slicable;
use table::generic::Statement as GenericStatement; use table::generic::Statement as GenericStatement;
use runtime_support::Hashable; use runtime_support::Hashable;
use polkadot_api::{PolkadotApi, BlockBuilder}; use polkadot_api::PolkadotApi;
use polkadot_primitives::{Hash, Timestamp}; use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp};
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic, CandidateReceipt}; use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt};
use primitives::block::{Block as SubstrateBlock, Header as SubstrateHeader, HeaderHash, Id as BlockId, Number as BlockNumber};
use primitives::AuthorityId; use primitives::AuthorityId;
use transaction_pool::{Ready, TransactionPool}; use transaction_pool::{Ready, TransactionPool};
use tokio_core::reactor::{Handle, Timeout, Interval}; use tokio_core::reactor::{Handle, Timeout, Interval};
@@ -105,10 +105,10 @@ pub trait TableRouter: Clone {
/// Future that resolves when candidate data is fetched. /// Future that resolves when candidate data is fetched.
type FetchCandidate: IntoFuture<Item=BlockData,Error=Self::Error>; type FetchCandidate: IntoFuture<Item=BlockData,Error=Self::Error>;
/// Future that resolves when extrinsic candidate data is fetched. /// 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. /// 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. /// Fetch block data for a specific candidate.
fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate; fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate;
@@ -236,7 +236,7 @@ pub struct ProposerFactory<C, N, P> {
pub parachain_empty_duration: Duration, 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 where
C: PolkadotApi, C: PolkadotApi,
N: Network, 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 Proposer = Proposer<C, N::TableRouter, P>;
type Error = Error; 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; use std::time::Duration;
const DELAY_UNTIL: Duration = Duration::from_millis(5000); const DELAY_UNTIL: Duration = Duration::from_millis(5000);
let parent_hash = parent_header.blake2_256().into(); 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 duty_roster = self.client.duty_roster(&checked_id)?;
let random_seed = self.client.random_seed(&checked_id)?; let random_seed = self.client.random_seed(&checked_id)?;
@@ -312,7 +312,7 @@ pub struct Proposer<C: PolkadotApi, R, P> {
handle: Handle, handle: Handle,
local_duty: LocalDuty, local_duty: LocalDuty,
local_key: Arc<ed25519::Pair>, local_key: Arc<ed25519::Pair>,
parent_hash: HeaderHash, parent_hash: Hash,
parent_id: C::CheckedBlockId, parent_id: C::CheckedBlockId,
parent_number: BlockNumber, parent_number: BlockNumber,
random_seed: Hash, random_seed: Hash,
@@ -321,7 +321,7 @@ pub struct Proposer<C: PolkadotApi, R, P> {
transaction_pool: Arc<TransactionPool>, 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 where
C: PolkadotApi, C: PolkadotApi,
R: TableRouter, R: TableRouter,
@@ -330,7 +330,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
type Error = Error; type Error = Error;
type Create = future::Either< type Create = future::Either<
CreateProposal<C, R, P>, CreateProposal<C, R, P>,
future::FutureResult<SubstrateBlock, Error>, future::FutureResult<Block, Error>,
>; >;
type Evaluate = Box<Future<Item=bool, Error=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); 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) { 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. // do initial serialization and structural integrity checks.
let maybe_proposal = evaluation::evaluate_initial( let maybe_proposal = evaluation::evaluate_initial(
proposal, unchecked_proposal,
current_timestamp, current_timestamp,
&self.parent_hash, &self.parent_hash,
self.parent_number, 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. // evaluate whether the block is actually valid.
// TODO: is it better to delay this until the delays are finished? // 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 future = future::result(evaluated).and_then(move |good| {
let end_result = future::ok(good); let end_result = future::ok(good);
if good { if good {
@@ -489,13 +492,13 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
proposer 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 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}; use polkadot_runtime::{Call, Extrinsic, UncheckedExtrinsic, ConsensusCall};
let local_id = self.local_key.public().0.into();
let local_id = self.local_key.public().0;
let mut next_index = { let mut next_index = {
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); 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 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; 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 }; 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. /// Future which resolves upon the creation of a proposal.
pub struct CreateProposal<C: PolkadotApi, R, P: Collators> { pub struct CreateProposal<C: PolkadotApi, R, P: Collators> {
parent_hash: HeaderHash, parent_hash: Hash,
parent_number: BlockNumber, parent_number: BlockNumber,
parent_id: C::CheckedBlockId, parent_id: C::CheckedBlockId,
client: Arc<C>, client: Arc<C>,
@@ -620,14 +624,13 @@ impl<C, R, P> CreateProposal<C, R, P>
R: TableRouter, R: TableRouter,
P: Collators, 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. // TODO: handle case when current timestamp behind that in state.
let timestamp = current_timestamp(); let timestamp = current_timestamp();
let mut block_builder = self.client.build_block( let mut block_builder = self.client.build_block(&self.parent_id, timestamp, candidates)?;
&self.parent_id,
timestamp,
candidates,
)?;
{ {
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); 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 } 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(()) => { Ok(()) => {
pending_size += pending.encoded_size(); pending_size += pending.encoded_size();
} }
@@ -658,14 +661,14 @@ impl<C, R, P> CreateProposal<C, R, P>
self.transaction_pool.remove(&unqueue_invalid, false); 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: [{}]]", info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
polkadot_block.header.number, polkadot_block.header.number,
Hash::from(polkadot_block.header.blake2_256()), Hash::from(polkadot_block.header.hash()),
polkadot_block.header.parent_hash, polkadot_block.header.parent_hash,
polkadot_block.extrinsics.iter() polkadot_block.extrinsics.iter()
.map(|xt| format!("{}", Hash::from(xt.blake2_256()))) .map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
); );
@@ -693,10 +696,10 @@ impl<C, R, P> Future for CreateProposal<C, R, P>
R: TableRouter, R: TableRouter,
P: Collators, P: Collators,
{ {
type Item = SubstrateBlock; type Item = Block;
type Error = Error; type Error = Error;
fn poll(&mut self) -> Poll<SubstrateBlock, Error> { fn poll(&mut self) -> Poll<Block, Error> {
// 1. poll local collation future. // 1. poll local collation future.
match self.collation.poll() { match self.collation.poll() {
Ok(Async::Ready((collation, extrinsic))) => { Ok(Async::Ready((collation, extrinsic))) => {
+45 -57
View File
@@ -29,10 +29,9 @@ use ed25519;
use futures::prelude::*; use futures::prelude::*;
use futures::{future, Canceled}; use futures::{future, Canceled};
use polkadot_api::LocalPolkadotApi; 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 polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt};
use primitives::{Hash, AuthorityId}; use primitives::AuthorityId;
use primitives::block::{Id as BlockId, HeaderHash, Header};
use runtime_support::Hashable; use runtime_support::Hashable;
use substrate_network as net; use substrate_network as net;
use tokio_core::reactor; use tokio_core::reactor;
@@ -45,19 +44,19 @@ const TIMER_DELAY_MS: u64 = 5000;
const TIMER_INTERVAL_MS: u64 = 500; const TIMER_INTERVAL_MS: u64 = 500;
struct BftSink<E> { struct BftSink<E> {
network: Arc<net::ConsensusService>, network: Arc<net::ConsensusService<Block>>,
parent_hash: HeaderHash, parent_hash: Hash,
_e: ::std::marker::PhantomData<E>, _e: ::std::marker::PhantomData<E>,
} }
struct Messages { struct Messages {
network_stream: net::BftMessageStream, network_stream: net::BftMessageStream<Block>,
local_id: AuthorityId, local_id: AuthorityId,
authorities: Vec<AuthorityId>, authorities: Vec<AuthorityId>,
} }
impl Stream for Messages { impl Stream for Messages {
type Item = bft::Communication; type Item = bft::Communication<Block>;
type Error = bft::Error; type Error = bft::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::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 { Ok(Some(match msg.message {
net::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c { net::generic_message::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c {
net::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({ net::generic_message::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({
if &proposal.sender == local_id { return Ok(None) } if &proposal.sender == local_id { return Ok(None) }
let proposal = bft::generic::LocalizedProposal { let proposal = bft::generic::LocalizedProposal {
round_number: proposal.round_number as usize, 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)); trace!(target: "bft", "importing proposal message for round {} from {}", proposal.round_number, Hash::from(proposal.sender));
proposal 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) } if &vote.sender == local_id { return Ok(None) }
let vote = bft::generic::LocalizedVote { let vote = bft::generic::LocalizedVote {
sender: vote.sender, sender: vote.sender,
@@ -114,21 +113,21 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
signer: ed25519::Public(vote.sender), signer: ed25519::Public(vote.sender),
}, },
vote: match vote.vote { vote: match vote.vote {
net::ConsensusVote::Prepare(r, h) => bft::generic::Vote::Prepare(r as usize, h), net::generic_message::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::generic_message::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::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)); trace!(target: "bft", "importing vote {:?} from {}", vote.vote, Hash::from(vote.sender));
vote vote
}), }),
}), }),
net::BftMessage::Auxiliary(a) => { net::generic_message::BftMessage::Auxiliary(a) => {
let justification = bft::UncheckedJustification::from(a); let justification = bft::UncheckedJustification::<Hash>::from(a);
// TODO: get proper error // 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()); .map_err(|_| bft::ErrorKind::InvalidJustification.into());
bft::generic::Communication::Auxiliary(justification?) 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> { 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 // TODO: replace this with the ! type when that's stabilized
type SinkError = E; type SinkError = E;
fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend<bft::Communication, E> { fn start_send(&mut self, message: bft::Communication<Block>) -> ::futures::StartSend<bft::Communication<Block>, E> {
let network_message = net::LocalizedBftMessage { let network_message = net::generic_message::LocalizedBftMessage {
message: match message { message: match message {
bft::generic::Communication::Consensus(c) => net::BftMessage::Consensus(match c { bft::generic::Communication::Consensus(c) => net::generic_message::BftMessage::Consensus(match c {
bft::generic::LocalizedMessage::Propose(proposal) => net::SignedConsensusMessage::Propose(net::SignedConsensusProposal { bft::generic::LocalizedMessage::Propose(proposal) => net::generic_message::SignedConsensusMessage::Propose(net::generic_message::SignedConsensusProposal {
round_number: proposal.round_number as u32, round_number: proposal.round_number as u32,
proposal: proposal.proposal, proposal: proposal.proposal,
digest: proposal.digest, digest: proposal.digest,
@@ -152,17 +151,17 @@ impl<E> Sink for BftSink<E> {
digest_signature: proposal.digest_signature.signature, digest_signature: proposal.digest_signature.signature,
full_signature: proposal.full_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, sender: vote.sender,
signature: vote.signature.signature, signature: vote.signature.signature,
vote: match vote.vote { vote: match vote.vote {
bft::generic::Vote::Prepare(r, h) => net::ConsensusVote::Prepare(r as u32, h), bft::generic::Vote::Prepare(r, h) => net::generic_message::ConsensusVote::Prepare(r as u32, h),
bft::generic::Vote::Commit(r, h) => net::ConsensusVote::Commit(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::ConsensusVote::AdvanceRound(r as u32), 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, 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 { impl super::Network for Network {
type TableRouter = Router; type TableRouter = Router;
@@ -189,20 +188,20 @@ impl super::Network for Network {
fn start_bft<F, C>( fn start_bft<F, C>(
header: &Header, header: &Header,
handle: reactor::Handle, handle: reactor::Handle,
client: &bft::Authorities, client: &bft::Authorities<Block>,
network: Arc<net::ConsensusService>, network: Arc<net::ConsensusService<Block>>,
bft_service: &BftService<F, C>, bft_service: &BftService<Block, F, C>,
) where ) where
F: bft::ProposerFactory + 'static, F: bft::ProposerFactory<Block> + 'static,
C: bft::BlockImport + bft::Authorities + 'static, C: bft::BlockImport<Block> + bft::Authorities<Block> + 'static,
<F as bft::ProposerFactory>::Error: ::std::fmt::Debug, <F as bft::ProposerFactory<Block>>::Error: ::std::fmt::Debug,
<F::Proposer as bft::Proposer>::Error: ::std::fmt::Display + Into<error::Error>, <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) { if bft_service.live_agreement().map_or(false, |h| h == parent_hash) {
return; return;
} }
let authorities = match client.authorities(&BlockId::Hash(parent_hash)) { let authorities = match client.authorities(&BlockId::hash(parent_hash)) {
Ok(authorities) => authorities, Ok(authorities) => authorities,
Err(e) => { Err(e) => {
debug!("Error reading authorities: {:?}", e); debug!("Error reading authorities: {:?}", e);
@@ -235,14 +234,14 @@ impl Service {
pub fn new<A, C>( pub fn new<A, C>(
client: Arc<C>, client: Arc<C>,
api: Arc<A>, api: Arc<A>,
network: Arc<net::ConsensusService>, network: Arc<net::ConsensusService<Block>>,
transaction_pool: Arc<TransactionPool>, transaction_pool: Arc<TransactionPool>,
parachain_empty_duration: Duration, parachain_empty_duration: Duration,
key: ed25519::Pair, key: ed25519::Pair,
) -> Service ) -> Service
where where
A: LocalPolkadotApi + Send + Sync + 'static, 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 (signal, exit) = ::exit_future::signal();
let thread = thread::spawn(move || { let thread = thread::spawn(move || {
@@ -346,36 +345,25 @@ impl ::collation::Collators for NoCollators {
fn note_bad_collator(&self, _collator: AccountId) { } fn note_bad_collator(&self, _collator: AccountId) { }
} }
type FetchCandidateAdapter = future::Map<net::FetchFuture, fn(Vec<u8>) -> BlockData>;
#[derive(Clone)] #[derive(Clone)]
struct Router { struct Router {
network: Arc<net::ConsensusService>, network: Arc<net::ConsensusService<Block>>,
}
impl Router {
fn fetch_candidate_adapter(data: Vec<u8>) -> BlockData {
BlockData(data)
}
} }
impl TableRouter for Router { impl TableRouter for Router {
type Error = Canceled; type Error = Canceled;
type FetchCandidate = FetchCandidateAdapter; type FetchCandidate = future::Empty<BlockData, Self::Error>;
type FetchExtrinsic = future::FutureResult<Extrinsic, Self::Error>; type FetchExtrinsic = future::FutureResult<Extrinsic, Self::Error>;
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, _extrinsic: Extrinsic) { fn local_candidate_data(&self, _hash: Hash, _block_data: BlockData, _extrinsic: Extrinsic) {
let data = block_data.0; // TODO
self.network.set_local_candidate(Some((hash, data)))
} }
fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate { fn fetch_block_data(&self, _candidate: &CandidateReceipt) -> Self::FetchCandidate {
let hash = candidate.hash(); future::empty()
self.network.fetch_candidate(&hash).map(Self::fetch_candidate_adapter)
} }
fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic { fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic {
future::ok(Extrinsic) future::ok(Extrinsic)
} }
} }
@@ -486,7 +486,7 @@ mod tests {
let candidate = CandidateReceipt { let candidate = CandidateReceipt {
parachain_index: para_id, parachain_index: para_id,
collator: [1; 32], collator: [1; 32].into(),
head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]), head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]),
balance_uploads: Vec::new(), balance_uploads: Vec::new(),
egress_queue_roots: Vec::new(), egress_queue_roots: Vec::new(),
@@ -536,7 +536,7 @@ mod tests {
let candidate = CandidateReceipt { let candidate = CandidateReceipt {
parachain_index: para_id, parachain_index: para_id,
collator: [1; 32], collator: [1; 32].into(),
head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]), head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]),
balance_uploads: Vec::new(), balance_uploads: Vec::new(),
egress_queue_roots: 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." description = "Polkadot node implementation in Rust."
[dependencies] [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-executor = { path = "../../substrate/executor" }
substrate-primitives = { path = "../../substrate/primitives" }
polkadot-primitives = { path = "../primitives" }
polkadot-runtime = { path = "../runtime" } polkadot-runtime = { path = "../runtime" }
[dev-dependencies]
substrate-keyring = { path = "../../substrate/keyring" }
-7
View File
@@ -19,12 +19,5 @@
extern crate polkadot_runtime; extern crate polkadot_runtime;
#[macro_use] extern crate substrate_executor; #[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")); 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"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))] #![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_runtime_std as rstd;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_runtime_primitives as runtime_primitives;
@@ -35,27 +29,43 @@ extern crate substrate_serializer;
extern crate substrate_codec as codec; 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; pub mod parachain;
/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody /// Block header type as expected by this runtime.
/// (who matters). Essentially this means that a majority of validators have decided it is pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
/// "correct".
pub const EVERYBODY: AccountId = [255u8; 32];
/// Something that identifies a block. /// Opaque, encoded, unchecked extrinsic.
pub use primitives::block::Id as BlockId; pub type UncheckedExtrinsic = Vec<u8>;
/// The type of digest item. /// A "future-proof" block type for Polkadot. This will be resilient to upgrades in transaction
pub use primitives::block::Log as Log; /// 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. /// An index to a block.
/// 32-bits will allow for 136 years of blocks assuming 1 block per second. /// 32-bits will allow for 136 years of blocks assuming 1 block per second.
/// TODO: switch to u32 /// TODO: switch to u32
pub type BlockNumber = u64; pub type BlockNumber = u64;
/// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost /// Alias to Ed25519 pubkey that identifies an account on the relay chain.
/// certainly continue to be the same as the substrate's `AuthorityId`. pub type AccountId = primitives::hash::H256;
pub type AccountId = primitives::AuthorityId;
/// The Ed25519 pub key of an session that belongs to an authority of the relay chain. This is /// 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". /// 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. /// Indentifier for a chain. 32-bit should be plenty.
pub type ChainId = u32; 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. /// A hash of some data used by the relay chain.
pub type Hash = primitives::H256; 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. /// 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. /// A timestamp: seconds since the unix epoch.
pub type Timestamp = u64; 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 /// 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. /// that 32 bits may be multiplied with a balance in 128 bits without worrying about overflow.
pub type Balance = u128; 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 // You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>. // 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")] #[cfg(feature = "std")]
use primitives::bytes; use primitives::bytes;
use primitives;
use codec::{Input, Slicable}; /// Signature on candidate's block data by a collator.
use rstd::cmp::{PartialOrd, Ord, Ordering}; pub type CandidateSignature = ::runtime_primitives::Ed25519Signature;
use rstd::vec::Vec;
use ::Hash;
/// Unique identifier of a parachain. /// Unique identifier of a parachain.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] #[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); pub struct Id(u32);
impl From<Id> for u32 { impl From<Id> for u32 {
@@ -67,7 +70,6 @@ pub enum Chain {
impl Slicable for Chain { impl Slicable for Chain {
fn decode<I: Input>(input: &mut I) -> Option<Self> { fn decode<I: Input>(input: &mut I) -> Option<Self> {
let disc = input.read_byte()?; let disc = input.read_byte()?;
match disc { match disc {
0 => Some(Chain::Relay), 0 => Some(Chain::Relay),
1 => Some(Chain::Parachain(Slicable::decode(input)?)), 1 => Some(Chain::Parachain(Slicable::decode(input)?)),
@@ -84,7 +86,6 @@ impl Slicable for Chain {
id.using_encoded(|s| v.extend(s)); id.using_encoded(|s| v.extend(s));
} }
} }
v v
} }
@@ -128,7 +129,7 @@ impl Slicable for DutyRoster {
/// Extrinsic data for a parachain. /// Extrinsic data for a parachain.
#[derive(PartialEq, Eq, Clone)] #[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(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Extrinsic; pub struct Extrinsic;
@@ -137,14 +138,14 @@ pub struct Extrinsic;
/// ///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
#[derive(PartialEq, Eq, Clone)] #[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(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Candidate { pub struct Candidate {
/// The ID of the parachain this is a proposal for. /// The ID of the parachain this is a proposal for.
pub parachain_index: Id, pub parachain_index: Id,
/// Collator's signature /// Collator's signature
pub collator_signature: ::Signature, pub collator_signature: CandidateSignature,
/// Unprocessed ingress queue. /// Unprocessed ingress queue.
/// ///
/// Ordered by parachain ID and block number. /// Ordered by parachain ID and block number.
@@ -155,20 +156,20 @@ pub struct Candidate {
/// Candidate receipt type. /// Candidate receipt type.
#[derive(PartialEq, Eq, Clone)] #[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(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct CandidateReceipt { pub struct CandidateReceipt {
/// The ID of the parachain this is a candidate for. /// The ID of the parachain this is a candidate for.
pub parachain_index: Id, pub parachain_index: Id,
/// The collator's relay-chain account ID /// The collator's relay-chain account ID
pub collator: ::AccountId, pub collator: super::AccountId,
/// The head-data /// The head-data
pub head_data: HeadData, pub head_data: HeadData,
/// Balance uploads to the relay chain. /// Balance uploads to the relay chain.
pub balance_uploads: Vec<(::AccountId, u64)>, pub balance_uploads: Vec<(super::AccountId, u64)>,
/// Egress queue roots. /// 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 /// Fees paid from the chain to the relay chain validators
pub fees: u64, pub fees: u64,
} }
@@ -203,8 +204,8 @@ impl CandidateReceipt {
/// Get the blake2_256 hash /// Get the blake2_256 hash
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn hash(&self) -> Hash { pub fn hash(&self) -> Hash {
let encoded = self.encode(); use runtime_primitives::traits::{BlakeTwo256, Hashing};
primitives::hashing::blake2_256(&encoded).into() BlakeTwo256::hash_of(self)
} }
} }
@@ -224,7 +225,7 @@ impl Ord for CandidateReceipt {
/// Parachain ingress queue message. /// Parachain ingress queue message.
#[derive(PartialEq, Eq, Clone)] #[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>); pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Consolidated ingress queue data. /// 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, /// This is just an ordered vector of other parachains' egress queues,
/// obtained according to the routing rules. /// obtained according to the routing rules.
#[derive(Default, PartialEq, Eq, Clone)] #[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>)>); pub struct ConsolidatedIngress(pub Vec<(Id, Vec<Message>)>);
/// Parachain block data. /// Parachain block data.
/// ///
/// contains everything required to validate para-block, may contain block and witness data /// contains everything required to validate para-block, may contain block and witness data
#[derive(PartialEq, Eq, Clone)] #[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>); pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain header raw bytes wrapper type. /// Parachain header raw bytes wrapper type.
#[derive(PartialEq, Eq)] #[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>); pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain head data included in the chain. /// Parachain head data included in the chain.
#[derive(PartialEq, Eq, Clone, PartialOrd, Ord)] #[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>); pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain validation code. /// Parachain validation code.
#[derive(PartialEq, Eq)] #[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>); pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Activitiy bit field /// Activitiy bit field
#[derive(PartialEq, Eq, Clone, Default)] #[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>); pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Activity { 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 = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../safe-mix", default_features = false} safe-mix = { path = "../../safe-mix", default_features = false}
polkadot-primitives = { path = "../primitives", default_features = false }
substrate-codec = { path = "../../substrate/codec" } substrate-codec = { path = "../../substrate/codec" }
substrate-serializer = { path = "../../substrate/serializer" } substrate-serializer = { path = "../../substrate/serializer" }
substrate-runtime-std = { path = "../../substrate/runtime-std" } 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-staking = { path = "../../substrate/runtime/staking" }
substrate-runtime-system = { path = "../../substrate/runtime/system" } substrate-runtime-system = { path = "../../substrate/runtime/system" }
substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" } substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" }
polkadot-primitives = { path = "../primitives" }
[dev-dependencies] [dev-dependencies]
hex-literal = "0.1.0" hex-literal = "0.1.0"
@@ -33,6 +33,7 @@ hex-literal = "0.1.0"
[features] [features]
default = ["std"] default = ["std"]
std = [ std = [
"polkadot-primitives/std",
"substrate-codec/std", "substrate-codec/std",
"substrate-primitives/std", "substrate-primitives/std",
"substrate-runtime-std/std", "substrate-runtime-std/std",
@@ -47,7 +48,6 @@ std = [
"substrate-runtime-staking/std", "substrate-runtime-staking/std",
"substrate-runtime-system/std", "substrate-runtime-system/std",
"substrate-runtime-timestamp/std", "substrate-runtime-timestamp/std",
"polkadot-primitives/std",
"serde_derive", "serde_derive",
"serde/std", "serde/std",
"log", "log",
+168 -23
View File
@@ -18,11 +18,18 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
extern crate serde;
#[macro_use] #[macro_use]
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
#[macro_use] #[macro_use]
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support;
#[macro_use] #[macro_use]
extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_runtime_primitives as runtime_primitives;
@@ -37,7 +44,10 @@ extern crate substrate_serializer;
#[cfg_attr(feature = "std", macro_use)] #[cfg_attr(feature = "std", macro_use)]
extern crate substrate_primitives; extern crate substrate_primitives;
#[macro_use]
extern crate substrate_runtime_std as rstd; extern crate substrate_runtime_std as rstd;
extern crate polkadot_primitives as primitives;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_consensus as consensus;
extern crate substrate_runtime_council as council; 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_staking as staking;
extern crate substrate_runtime_system as system; extern crate substrate_runtime_system as system;
extern crate substrate_runtime_timestamp as timestamp; extern crate substrate_runtime_timestamp as timestamp;
extern crate polkadot_primitives;
mod parachains; mod parachains;
use runtime_io::BlakeTwo256; use rstd::prelude::*;
use polkadot_primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature}; use primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature};
use runtime_primitives::generic; use primitives::parachain::CandidateReceipt;
use runtime_primitives::traits::{Identity, HasPublicAux}; use runtime_primitives::{generic, traits::{HasPublicAux, BlakeTwo256, Convert}};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use runtime_primitives::BuildExternalities; pub use runtime_primitives::BuildExternalities;
@@ -62,13 +71,113 @@ pub use runtime_primitives::BuildExternalities;
pub use consensus::Call as ConsensusCall; pub use consensus::Call as ConsensusCall;
pub use timestamp::Call as TimestampCall; pub use timestamp::Call as TimestampCall;
pub use parachains::Call as ParachainsCall; pub use parachains::Call as ParachainsCall;
pub use primitives::Header;
/// The position of the timestamp set extrinsic. /// The position of the timestamp set extrinsic.
pub const TIMESTAMP_SET_POSITION: u32 = 0; pub const TIMESTAMP_SET_POSITION: u32 = 0;
/// The position of the parachains set extrinsic. /// The position of the parachains set extrinsic.
pub const PARACHAINS_SET_POSITION: u32 = 1; 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. /// Concrete runtime type used to parameterize the various modules.
pub struct Concrete; pub struct Concrete;
@@ -83,7 +192,7 @@ impl system::Trait for Concrete {
type Hashing = BlakeTwo256; type Hashing = BlakeTwo256;
type Digest = generic::Digest<Log>; type Digest = generic::Digest<Log>;
type AccountId = AccountId; type AccountId = AccountId;
type Header = generic::Header<BlockNumber, Hash, Log>; type Header = Header;
} }
/// System module for this concrete runtime. /// System module for this concrete runtime.
pub type System = system::Module<Concrete>; pub type System = system::Module<Concrete>;
@@ -102,8 +211,16 @@ impl timestamp::Trait for Concrete {
/// Timestamp module for this concrete runtime. /// Timestamp module for this concrete runtime.
pub type Timestamp = timestamp::Module<Concrete>; 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 { impl session::Trait for Concrete {
type ConvertAccountIdToSessionKey = Identity; type ConvertAccountIdToSessionKey = SessionKeyConversion;
} }
/// Session module for this concrete runtime. /// Session module for this concrete runtime.
pub type Session = session::Module<Concrete>; pub type Session = session::Module<Concrete>;
@@ -135,6 +252,9 @@ impl parachains::Trait for Concrete {
pub type Parachains = parachains::Module<Concrete>; pub type Parachains = parachains::Module<Concrete>;
impl_outer_dispatch! { 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 { pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
Consensus = 0, Consensus = 0,
Session = 1, Session = 1,
@@ -146,6 +266,9 @@ impl_outer_dispatch! {
Parachains = 8, Parachains = 8,
} }
/// Internal calls.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum PrivCall { pub enum PrivCall {
Consensus = 0, Consensus = 0,
Session = 1, 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. /// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Concrete, Block, Staking, pub type Executive = executive::Executive<Concrete, Block, Staking,
(((((((), Parachains), Council), Democracy), Staking), Session), Timestamp)>; (((((((), 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 { pub mod api {
impl_stubs!( impl_stubs!(
authorities => |()| super::Consensus::authorities(), authorities => |()| super::Consensus::authorities(),
@@ -187,6 +331,7 @@ pub mod api {
apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic),
execute_block => |block| super::Executive::execute_block(block), execute_block => |block| super::Executive::execute_block(block),
finalise_block => |()| super::Executive::finalise_block(), finalise_block => |()| super::Executive::finalise_block(),
inherent_extrinsics => |(timestamp, heads)| super::inherent_extrinsics(timestamp, heads),
validator_count => |()| super::Session::validator_count(), validator_count => |()| super::Session::validator_count(),
validators => |()| super::Session::validators() validators => |()| super::Session::validators()
); );
@@ -290,9 +435,9 @@ mod tests {
}); });
let raw = block.encode(); let raw = block.encode();
let decoded_substrate = primitives::block::Block::decode(&mut &raw[..]).unwrap(); let decoded_primitive = ::primitives::Block::decode(&mut &raw[..]).unwrap();
let encoded_substrate = decoded_substrate.encode(); let encoded_primitive = decoded_primitive.encode();
let decoded = Block::decode(&mut &encoded_substrate[..]).unwrap(); let decoded = Block::decode(&mut &encoded_primitive[..]).unwrap();
assert_eq!(block, decoded); assert_eq!(block, decoded);
} }
@@ -301,11 +446,11 @@ mod tests {
fn serialize_unchecked() { fn serialize_unchecked() {
let tx = UncheckedExtrinsic { let tx = UncheckedExtrinsic {
extrinsic: Extrinsic { extrinsic: Extrinsic {
signed: [1; 32], signed: [1; 32].into(),
index: 999, index: 999,
function: Call::Timestamp(TimestampCall::set(135135)), function: Call::Timestamp(TimestampCall::set(135135)),
}, },
signature: primitives::hash::H512([0; 64]).into(), signature: runtime_primitives::Ed25519Signature(primitives::hash::H512([0; 64])).into(),
}; };
// 71000000 // 71000000
// 0101010101010101010101010101010101010101010101010101010101010101 // 0101010101010101010101010101010101010101010101010101010101010101
@@ -322,7 +467,7 @@ mod tests {
#[test] #[test]
fn serialize_checked() { fn serialize_checked() {
let xt = Extrinsic { let xt = Extrinsic {
signed: hex!["0d71d1a9cad6f2ab773435a7dec1bac019994d05d1dd5eb3108211dcf25c9d1e"], signed: hex!["0d71d1a9cad6f2ab773435a7dec1bac019994d05d1dd5eb3108211dcf25c9d1e"].into(),
index: 0, index: 0,
function: Call::CouncilVoting(council::voting::Call::propose(Box::new( function: Call::CouncilVoting(council::voting::Call::propose(Box::new(
PrivCall::Consensus(consensus::PrivCall::set_code( 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. //! Main parachains logic. For now this is just the determination of which validators do what.
use polkadot_primitives; use primitives;
use rstd::prelude::*; use rstd::prelude::*;
use codec::{Slicable, Joiner}; use codec::{Slicable, Joiner};
use runtime_support::Hashable;
use runtime_primitives::traits::{Executable, RefInto, MaybeEmpty}; 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 {system, session};
use runtime_support::{StorageValue, StorageMap}; use substrate_runtime_support::{Hashable, StorageValue, StorageMap};
use runtime_support::dispatch::Result; use substrate_runtime_support::dispatch::Result;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
use rstd::marker::PhantomData; use rstd::marker::PhantomData;
@@ -34,7 +33,7 @@ use rstd::marker::PhantomData;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
use {runtime_io, runtime_primitives}; 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. /// The position of the set_heads call in the block.
const SET_POSITION: u32; const SET_POSITION: u32;
@@ -42,7 +41,11 @@ pub trait Trait: system::Trait<Hash = polkadot_primitives::Hash> + session::Trai
} }
decl_module! { decl_module! {
/// Parachains module.
pub struct Module<T: Trait>; 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 { pub enum Call where aux: <T as Trait>::PublicAux {
// provide candidate receipts for parachains, in ascending order by id. // provide candidate receipts for parachains, in ascending order by id.
fn set_heads(aux, heads: Vec<CandidateReceipt>) -> Result = 0; fn set_heads(aux, heads: Vec<CandidateReceipt>) -> Result = 0;
@@ -227,7 +230,7 @@ mod tests {
use runtime_io::with_externalities; use runtime_io::with_externalities;
use substrate_primitives::H256; use substrate_primitives::H256;
use runtime_primitives::BuildExternalities; use runtime_primitives::BuildExternalities;
use runtime_primitives::traits::{HasPublicAux, Identity}; use runtime_primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
use runtime_primitives::testing::{Digest, Header}; use runtime_primitives::testing::{Digest, Header};
use consensus; use consensus;
@@ -243,7 +246,7 @@ mod tests {
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
type Hashing = runtime_io::BlakeTwo256; type Hashing = BlakeTwo256;
type Digest = Digest; type Digest = Digest;
type AccountId = u64; type AccountId = u64;
type Header = Header; type Header = Header;
+246 -192
View File
@@ -11,19 +11,9 @@ name = "base58"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.0.1" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -37,33 +27,55 @@ dependencies = [
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.2.1" version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.4" version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.2" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "constant_time_eq" name = "constant_time_eq"
version = "0.1.3" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "crunchy" name = "crunchy"
version = "0.1.6" version = "0.1.6"
@@ -75,20 +87,15 @@ version = "0.1.0"
dependencies = [ dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "elastic-array" name = "elastic-array"
version = "0.9.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -99,15 +106,37 @@ name = "environmental"
version = "0.1.0" version = "0.1.0"
[[package]] [[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" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.64 (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)",
] ]
[[package]] [[package]]
@@ -119,12 +148,23 @@ dependencies = [
"rustc-hex 1.0.0 (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 = "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]] [[package]]
name = "fuchsia-zircon" name = "fuchsia-zircon"
version = "0.3.3" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -148,16 +188,16 @@ dependencies = [
[[package]] [[package]]
name = "hex-literal" name = "hex-literal"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "hex-literal-impl" name = "hex-literal-impl"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "keccak-hash" name = "keccak-hash"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -185,12 +225,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.36" version = "0.2.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -206,9 +246,14 @@ name = "log"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "memory_units" name = "memory_units"
version = "0.3.0" version = "0.3.0"
@@ -229,7 +274,7 @@ name = "num_cpus"
version = "1.8.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@@ -245,9 +290,9 @@ name = "parity-wasm"
version = "0.27.6" version = "0.27.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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]] [[package]]
@@ -255,43 +300,35 @@ name = "parity-wasm"
version = "0.30.0" version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.5.4" version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.2.10" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"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)",
"smallvec 0.6.0 (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)", "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]] [[package]]
name = "polkadot-primitives" name = "polkadot-primitives"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"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.27 (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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0", "substrate-runtime-primitives 0.1.0",
@@ -334,12 +371,20 @@ name = "proc-macro-hack-impl"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "pwasm-alloc" name = "pwasm-alloc"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"pwasm-libc 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]] [[package]]
@@ -351,15 +396,18 @@ name = "pwasm-utils"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.3.15" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "rand" name = "rand"
@@ -367,7 +415,7 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -386,19 +434,19 @@ name = "rayon"
version = "0.8.2" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"coco 0.1.1 (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 0.2.11 (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.36 (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)", "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]] [[package]]
@@ -408,20 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "rlp" name = "rlp"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (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]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
name = "safe-mix" name = "safe-mix"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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]] [[package]]
@@ -457,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "semver" name = "semver"
version = "0.6.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "serde" name = "serde"
version = "1.0.27" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.27" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.1 (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)",
] ]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -511,8 +549,8 @@ name = "substrate-keyring"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ed25519 0.1.0", "ed25519 0.1.0",
"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)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -520,25 +558,26 @@ name = "substrate-primitives"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (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-codec 0.1.0",
"substrate-runtime-std 0.1.0", "substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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]] [[package]]
name = "substrate-runtime-consensus" name = "substrate-runtime-consensus"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -563,10 +602,11 @@ dependencies = [
name = "substrate-runtime-council" name = "substrate-runtime-council"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
"safe-mix 0.1.0", "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-codec 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -585,9 +625,10 @@ dependencies = [
name = "substrate-runtime-democracy" name = "substrate-runtime-democracy"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0", "substrate-runtime-consensus 0.1.0",
@@ -604,8 +645,8 @@ dependencies = [
name = "substrate-runtime-executive" name = "substrate-runtime-executive"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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-codec 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
"substrate-runtime-primitives 0.1.0", "substrate-runtime-primitives 0.1.0",
@@ -620,12 +661,12 @@ version = "0.1.0"
dependencies = [ dependencies = [
"ed25519 0.1.0", "ed25519 0.1.0",
"environmental 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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-std 0.1.0", "substrate-runtime-std 0.1.0",
"substrate-state-machine 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]] [[package]]
@@ -634,8 +675,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "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)", "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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -647,21 +688,22 @@ dependencies = [
name = "substrate-runtime-sandbox" name = "substrate-runtime-sandbox"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
"substrate-runtime-std 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]] [[package]]
name = "substrate-runtime-session" name = "substrate-runtime-session"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -677,9 +719,10 @@ dependencies = [
name = "substrate-runtime-staking" name = "substrate-runtime-staking"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-keyring 0.1.0", "substrate-keyring 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
@@ -700,7 +743,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"pwasm-alloc 0.1.0", "pwasm-alloc 0.1.0",
"pwasm-libc 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]] [[package]]
@@ -708,9 +751,9 @@ name = "substrate-runtime-support"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ed25519 0.1.0", "ed25519 0.1.0",
"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)",
"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.27 (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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -721,9 +764,9 @@ dependencies = [
name = "substrate-runtime-system" name = "substrate-runtime-system"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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", "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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -736,8 +779,9 @@ dependencies = [
name = "substrate-runtime-timestamp" name = "substrate-runtime-timestamp"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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-codec 0.1.0",
"substrate-primitives 0.1.0", "substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0", "substrate-runtime-io 0.1.0",
@@ -751,43 +795,39 @@ dependencies = [
name = "substrate-state-machine" name = "substrate-state-machine"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)",
"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)",
"substrate-primitives 0.1.0", "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]] [[package]]
name = "syn" name = "syn"
version = "0.11.11" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (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.0.4 (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 = "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)",
] ]
[[package]] [[package]]
name = "tiny-keccak" name = "tiny-keccak"
version = "1.4.0" version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "triehash" name = "triehash"
version = "0.1.0" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"ethcore-bigint 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)",
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (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]] [[package]]
@@ -803,14 +843,25 @@ name = "uint"
version = "0.1.2" version = "0.1.2"
source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71" source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71"
dependencies = [ 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-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]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.0.4" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@@ -820,10 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "wasmi" name = "wasmi"
version = "0.1.2" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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] [metadata]
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "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 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.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "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 byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" "checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "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 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.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5" "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.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 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 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 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 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 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631" "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 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 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 lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "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.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 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 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 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" "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 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.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 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 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "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-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 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.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 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 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 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 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-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 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 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 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" "checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" "checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "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 syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" "checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce"
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "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 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 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 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-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" "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] [dependencies]
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" } 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 } safe-mix = { path = "../../../safe-mix", default-features = false }
substrate-codec = { path = "../../../substrate/codec", default-features = false } substrate-codec = { path = "../../../substrate/codec", default-features = false }
substrate-primitives = { path = "../../../substrate/primitives", 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-staking = { path = "../../../substrate/runtime/staking", default-features = false }
substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false } substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false }
substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false } substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false }
polkadot-primitives = { path = "../../primitives", default-features = false }
[features] [features]
default = [] default = []
std = [ std = [
"polkadot-primitives/std",
"safe-mix/std", "safe-mix/std",
"substrate-codec/std", "substrate-codec/std",
"substrate-primitives/std", "substrate-primitives/std",
@@ -43,7 +44,6 @@ std = [
"substrate-runtime-staking/std", "substrate-runtime-staking/std",
"substrate-runtime-system/std", "substrate-runtime-system/std",
"substrate-runtime-timestamp/std", "substrate-runtime-timestamp/std",
"polkadot-primitives/std",
] ]
[profile.release] [profile.release]
+58 -48
View File
@@ -19,6 +19,7 @@
extern crate futures; extern crate futures;
extern crate ed25519; extern crate ed25519;
extern crate exit_future;
extern crate parking_lot; extern crate parking_lot;
extern crate tokio_timer; extern crate tokio_timer;
extern crate polkadot_primitives; extern crate polkadot_primitives;
@@ -28,17 +29,16 @@ extern crate polkadot_api;
extern crate polkadot_consensus as consensus; extern crate polkadot_consensus as consensus;
extern crate polkadot_transaction_pool as transaction_pool; extern crate polkadot_transaction_pool as transaction_pool;
extern crate polkadot_keystore as keystore; extern crate polkadot_keystore as keystore;
extern crate substrate_client as client;
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_network as network; extern crate substrate_network as network;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_client_db as client_db;
extern crate substrate_executor; extern crate substrate_executor;
extern crate substrate_state_machine as state_machine; extern crate substrate_state_machine as state_machine;
extern crate exit_future;
extern crate tokio_core; extern crate tokio_core;
extern crate substrate_client as client;
extern crate substrate_client_db as client_db;
#[macro_use] #[macro_use]
extern crate error_chain; extern crate error_chain;
@@ -56,13 +56,13 @@ use std::thread;
use futures::prelude::*; use futures::prelude::*;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
use codec::Slicable; use codec::Slicable;
use primitives::block::{Id as BlockId, ExtrinsicHash, HeaderHash, Header}; use primitives::AuthorityId;
use primitives::{AuthorityId};
use transaction_pool::TransactionPool; use transaction_pool::TransactionPool;
use substrate_executor::NativeExecutor; use substrate_executor::NativeExecutor;
use polkadot_executor::Executor as LocalDispatch; use polkadot_executor::Executor as LocalDispatch;
use keystore::Store as Keystore; use keystore::Store as Keystore;
use polkadot_api::PolkadotApi; use polkadot_api::PolkadotApi;
use polkadot_primitives::{Block, BlockId, Hash, Header};
use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig, use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
SessionConfig, StakingConfig, BuildExternalities}; SessionConfig, StakingConfig, BuildExternalities};
use client::backend::Backend; use client::backend::Backend;
@@ -78,8 +78,8 @@ type CodeExecutor = NativeExecutor<LocalDispatch>;
/// Polkadot service. /// Polkadot service.
pub struct Service<B, E> { pub struct Service<B, E> {
thread: Option<thread::JoinHandle<()>>, thread: Option<thread::JoinHandle<()>>,
client: Arc<Client<B, E>>, client: Arc<Client<B, E, Block>>,
network: Arc<network::Service>, network: Arc<network::Service<Block>>,
transaction_pool: Arc<TransactionPool>, transaction_pool: Arc<TransactionPool>,
signal: Option<Signal>, signal: Option<Signal>,
_consensus: Option<consensus::Service>, _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 { struct TransactionPoolAdapter<B, E, A> where A: Send + Sync, E: Send + Sync {
pool: Arc<TransactionPool>, pool: Arc<TransactionPool>,
client: Arc<Client<B, E>>, client: Arc<Client<B, E, Block>>,
api: Arc<A>, 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 where
B: Backend + Send + Sync, B: Backend<Block> + Send + Sync,
E: client::CallExecutor + Send + Sync, E: client::CallExecutor<Block> + Send + Sync,
client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>, client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>,
A: PolkadotApi + Send + Sync, 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() { let best_block = match self.client.info() {
Ok(info) => info.chain.best_hash, Ok(info) => info.chain.best_hash,
Err(e) => { 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); let ready = transaction_pool::Ready::create(id, &*self.api);
self.pool.cull_and_get_pending(ready, |pending| pending self.pool.cull_and_get_pending(ready, |pending| pending
.map(|t| { .map(|t| {
let hash = ::primitives::Hash::from(&t.hash()[..]); let hash = t.hash().clone();
let tx = codec::Slicable::encode(t.as_transaction()); (hash, t.primitive_extrinsic())
(hash, tx)
}) })
.collect() .collect()
) )
} }
fn import(&self, transaction: &[u8]) -> Option<ExtrinsicHash> { fn import(&self, transaction: &Vec<u8>) -> Option<Hash> {
if let Some(uxt) = codec::Slicable::decode(&mut &transaction[..]) { let encoded = transaction.encode();
if let Some(uxt) = codec::Slicable::decode(&mut &encoded[..]) {
match self.pool.import_unchecked_extrinsic(uxt) { match self.pool.import_unchecked_extrinsic(uxt) {
Ok(xt) => Some(*xt.hash()), Ok(xt) => Some(*xt.hash()),
Err(e) => match *e.kind() { 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) self.pool.on_broadcasted(propagations)
} }
} }
@@ -165,12 +169,12 @@ fn poc_2_testnet_config() -> ChainConfig {
}), }),
system: None, system: None,
session: Some(SessionConfig { 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. session_length: 720, // that's 1 hour per session.
}), }),
staking: Some(StakingConfig { staking: Some(StakingConfig {
current_era: 0, current_era: 0,
intentions: initial_authorities.clone(), intentions: initial_authorities.iter().cloned().map(Into::into).collect(),
transaction_base_fee: 100, transaction_base_fee: 100,
transaction_byte_fee: 1, transaction_byte_fee: 1,
balances: endowed_accounts.iter().map(|&k|(k, 1u128 << 60)).collect(), 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 { fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
let endowed_accounts = vec![ let endowed_accounts = vec![
ed25519::Pair::from_seed(b"Alice ").public().into(), ed25519::Pair::from_seed(b"Alice ").public().0.into(),
ed25519::Pair::from_seed(b"Bob ").public().into(), ed25519::Pair::from_seed(b"Bob ").public().0.into(),
ed25519::Pair::from_seed(b"Charlie ").public().into(), ed25519::Pair::from_seed(b"Charlie ").public().0.into(),
ed25519::Pair::from_seed(b"Dave ").public().into(), ed25519::Pair::from_seed(b"Dave ").public().0.into(),
ed25519::Pair::from_seed(b"Eve ").public().into(), ed25519::Pair::from_seed(b"Eve ").public().0.into(),
ed25519::Pair::from_seed(b"Ferdie ").public().into(), ed25519::Pair::from_seed(b"Ferdie ").public().0.into(),
]; ];
let genesis_config = GenesisConfig { let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig { consensus: Some(ConsensusConfig {
@@ -224,12 +228,12 @@ fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
}), }),
system: None, system: None,
session: Some(SessionConfig { session: Some(SessionConfig {
validators: initial_authorities.clone(), validators: initial_authorities.iter().cloned().map(Into::into).collect(),
session_length: 10, session_length: 10,
}), }),
staking: Some(StakingConfig { staking: Some(StakingConfig {
current_era: 0, current_era: 0,
intentions: initial_authorities.clone(), intentions: initial_authorities.iter().cloned().map(Into::into).collect(),
transaction_base_fee: 1, transaction_base_fee: 1,
transaction_byte_fee: 0, transaction_byte_fee: 0,
balances: endowed_accounts.iter().map(|&k|(k, (1u128 << 60))).collect(), 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, minimum_deposit: 10,
}), }),
council: Some(CouncilConfig { 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, candidacy_bond: 10,
voter_bond: 2, voter_bond: 2,
present_slash_per_voter: 1, present_slash_per_voter: 1,
@@ -280,16 +284,23 @@ struct GenesisBuilder {
config: GenesisConfig, config: GenesisConfig,
} }
impl client::GenesisBuilder for GenesisBuilder { impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) { fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let storage = self.config.build_externalities(); let storage = self.config.build_externalities();
let block = genesis::construct_genesis_block(&storage); let block = genesis::construct_genesis_block::<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()) (block.header, storage.into_iter().collect())
} }
} }
/// Creates light client and register protocol with the network service /// 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| { Service::new(move |_, executor, genesis_builder: GenesisBuilder| {
let client_backend = client::light::new_light_backend(); let client_backend = client::light::new_light_backend();
let fetch_checker = Arc::new(client::light::new_fetch_checker(client_backend.clone(), executor)); 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 /// 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; let is_validator = (config.roles & Role::VALIDATOR) == Role::VALIDATOR;
Service::new(|db_settings, executor, genesis_builder: GenesisBuilder| Service::new(|db_settings, executor, genesis_builder: GenesisBuilder|
Ok((Arc::new(client_db::new_client(db_settings, executor, genesis_builder)?), None)), 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> impl<B, E> Service<B, E>
where where
B: Backend + Send + Sync + 'static, B: Backend<Block> + Send + Sync + 'static,
E: CallExecutor + Send + Sync + 'static, E: CallExecutor<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{ {
/// Creates and register protocol with the network service /// 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> 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, client_db::DatabaseSettings,
CodeExecutor, CodeExecutor,
GenesisBuilder, 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( G: Fn(
Arc<Client<B, E>>, Arc<Client<B, E, Block>>,
) -> Arc<A>, ) -> Arc<A>,
C: Fn( C: Fn(
Arc<Client<B, E>>, Arc<Client<B, E, Block>>,
Arc<network::Service>, Arc<network::Service<Block>>,
Arc<TransactionPool>, Arc<TransactionPool>,
&Keystore &Keystore
) -> Result<Option<consensus::Service>, error::Error>, ) -> 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>), on_demand: on_demand.clone().map(|d| d as Arc<network::OnDemandService>),
transaction_pool: transaction_pool_adapter, transaction_pool: transaction_pool_adapter,
}; };
let network = network::Service::new(network_params)?; let network = network::Service::new(network_params)?;
let barrier = ::std::sync::Arc::new(Barrier::new(2)); let barrier = ::std::sync::Arc::new(Barrier::new(2));
on_demand.map(|on_demand| on_demand.set_service_link(Arc::downgrade(&network))); 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. /// Get shared client instance.
pub fn client(&self) -> Arc<Client<B, E>> { pub fn client(&self) -> Arc<Client<B, E, Block>> {
self.client.clone() self.client.clone()
} }
/// Get shared network instance. /// Get shared network instance.
pub fn network(&self) -> Arc<network::Service> { pub fn network(&self) -> Arc<network::Service<Block>> {
self.network.clone() self.network.clone()
} }
@@ -484,11 +494,11 @@ impl<B, E> Service<B, E>
} }
/// Produce a task which prunes any finalized transactions from the pool. /// 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 where
A: PolkadotApi, A: PolkadotApi,
{ {
match api.check_id(BlockId::Hash(hash)) { match api.check_id(BlockId::hash(hash)) {
Ok(id) => { Ok(id) => {
let ready = transaction_pool::Ready::create(id, api); let ready = transaction_pool::Ready::create(id, api);
pool.cull(None, ready); pool.cull(None, ready);
@@ -21,8 +21,8 @@ pub mod generic;
pub use generic::Table; pub use generic::Table;
use primitives::parachain::{Id, CandidateReceipt}; use primitives::parachain::{Id, CandidateReceipt, CandidateSignature as Signature};
use primitives::{SessionKey, Hash, Signature}; use primitives::{SessionKey, Hash};
/// Statements about candidates on the network. /// Statements about candidates on the network.
pub type Statement = generic::Statement<CandidateReceipt, Hash>; pub type Statement = generic::Statement<CandidateReceipt, Hash>;
+38 -107
View File
@@ -40,106 +40,23 @@ use std::{
use codec::Slicable; use codec::Slicable;
use extrinsic_pool::{Pool, txpool::{self, Readiness, scoring::{Change, Choice}}}; use extrinsic_pool::{Pool, txpool::{self, Readiness, scoring::{Change, Choice}}};
use extrinsic_pool::api::ExtrinsicPool;
use polkadot_api::PolkadotApi; use polkadot_api::PolkadotApi;
use primitives::parachain::CandidateReceipt; use primitives::{AccountId, Hash, UncheckedExtrinsic as FutureProofUncheckedExtrinsic};
use primitives::{AccountId, Timestamp, Hash}; use runtime::UncheckedExtrinsic;
use runtime::{Block, UncheckedExtrinsic, TimestampCall, ParachainsCall, Call}; use substrate_runtime_primitives::traits::{Bounded, Checkable, BlakeTwo256, Hashing};
use substrate_primitives::block::{Extrinsic, ExtrinsicHash};
use substrate_primitives::hexdisplay::HexDisplay;
use substrate_runtime_primitives::traits::{Bounded, Checkable};
pub use extrinsic_pool::txpool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps}; pub use extrinsic_pool::txpool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps};
pub use error::{Error, ErrorKind, Result}; pub use error::{Error, ErrorKind, Result};
/// Useful functions for working with Polkadot blocks. /// Type alias for convenience.
pub struct PolkadotBlock { pub type CheckedExtrinsic = <UncheckedExtrinsic as Checkable>::Checked;
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
}
}
/// A verified transaction which should be includable and non-inherent. /// A verified transaction which should be includable and non-inherent.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VerifiedTransaction { pub struct VerifiedTransaction {
inner: <UncheckedExtrinsic as Checkable>::Checked, inner: CheckedExtrinsic,
hash: ExtrinsicHash, hash: Hash,
encoded_size: usize, encoded_size: usize,
} }
@@ -150,10 +67,10 @@ impl VerifiedTransaction {
bail!(ErrorKind::IsInherent(xt)) bail!(ErrorKind::IsInherent(xt))
} }
let message = codec::Slicable::encode(&xt); let message = Slicable::encode(&xt);
match xt.check() { match xt.check() {
Ok(xt) => { Ok(xt) => {
let hash = substrate_primitives::hashing::blake2_256(&message); let hash = BlakeTwo256::hash(&message);
Ok(VerifiedTransaction { Ok(VerifiedTransaction {
inner: xt, inner: xt,
hash: hash.into(), hash: hash.into(),
@@ -169,8 +86,14 @@ impl VerifiedTransaction {
self.as_ref().as_unchecked() 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. /// 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 self.inner
} }
@@ -190,8 +113,8 @@ impl VerifiedTransaction {
} }
} }
impl AsRef< <UncheckedExtrinsic as Checkable>::Checked > for VerifiedTransaction { impl AsRef<CheckedExtrinsic> for VerifiedTransaction {
fn as_ref(&self) -> &<UncheckedExtrinsic as Checkable>::Checked { fn as_ref(&self) -> &CheckedExtrinsic {
&self.inner &self.inner
} }
} }
@@ -303,15 +226,12 @@ impl<'a, T: 'a + PolkadotApi> txpool::Ready<VerifiedTransaction> for Ready<'a, T
pub struct Verifier; pub struct Verifier;
impl txpool::Verifier<Extrinsic> for Verifier { impl txpool::Verifier<UncheckedExtrinsic> for Verifier {
type VerifiedTransaction = VerifiedTransaction; type VerifiedTransaction = VerifiedTransaction;
type Error = Error; type Error = Error;
fn verify_transaction(&self, xt: Extrinsic) -> Result<Self::VerifiedTransaction> { fn verify_transaction(&self, uxt: UncheckedExtrinsic) -> Result<Self::VerifiedTransaction> {
info!("Extrinsic submitted: {}", HexDisplay::from(&xt.0)); info!("Extrinsic Submitted: {:?}", uxt);
let uxt = xt.using_encoded(|ref mut s| UncheckedExtrinsic::decode(s))
.ok_or_else(|| ErrorKind::InvalidExtrinsicFormat)?;
info!("Correctly formatted: {:?}", uxt);
VerifiedTransaction::create(uxt) VerifiedTransaction::create(uxt)
} }
} }
@@ -320,7 +240,7 @@ impl txpool::Verifier<Extrinsic> for Verifier {
/// ///
/// Wraps a `extrinsic_pool::Pool`. /// Wraps a `extrinsic_pool::Pool`.
pub struct TransactionPool { pub struct TransactionPool {
inner: Pool<Verifier, Scoring, Error>, inner: Pool<UncheckedExtrinsic, Hash, Verifier, Scoring, Error>,
} }
impl TransactionPool { impl TransactionPool {
@@ -337,14 +257,25 @@ impl TransactionPool {
} }
impl Deref for TransactionPool { impl Deref for TransactionPool {
type Target = Pool<Verifier, Scoring, Error>; type Target = Pool<UncheckedExtrinsic, Hash, Verifier, Scoring, Error>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.inner &self.inner
} }
} }
#[cfg(test)] impl ExtrinsicPool<FutureProofUncheckedExtrinsic, Hash> for TransactionPool {
mod tests { 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-codec = { path = "../codec" }
substrate-primitives = { path = "../primitives" } substrate-primitives = { path = "../primitives" }
substrate-runtime-support = { path = "../runtime-support" } substrate-runtime-support = { path = "../runtime-support" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
ed25519 = { path = "../ed25519" } ed25519 = { path = "../ed25519" }
tokio-timer = "0.1.2" tokio-timer = "0.1.2"
parking_lot = "0.4" parking_lot = "0.4"
+3 -3
View File
@@ -18,10 +18,10 @@
error_chain! { error_chain! {
errors { errors {
/// Missing state at block with given Id. /// Missing state at block with given descriptor.
StateUnavailable(b: ::primitives::block::Id) { StateUnavailable(b: String) {
description("State missing at given block."), description("State missing at given block."),
display("State unavailable at block {:?}", b), display("State unavailable at block {}", b),
} }
/// I/O terminated unexpectedly /// I/O terminated unexpectedly
+169 -142
View File
@@ -22,6 +22,7 @@ pub mod generic;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate ed25519; extern crate ed25519;
extern crate tokio_timer; extern crate tokio_timer;
extern crate parking_lot; extern crate parking_lot;
@@ -41,9 +42,9 @@ use std::sync::atomic::{AtomicBool, Ordering};
use codec::Slicable; use codec::Slicable;
use ed25519::LocalizedSignature; use ed25519::LocalizedSignature;
use runtime_support::Hashable; use runtime_primitives::generic::BlockId;
use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification}; use runtime_primitives::traits::{Block, Header};
use primitives::block::{Block, Id as BlockId, Header, HeaderHash}; use runtime_primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification};
use primitives::AuthorityId; use primitives::AuthorityId;
use futures::{task, Async, Stream, Sink, Future, IntoFuture}; use futures::{task, Async, Stream, Sink, Future, IntoFuture};
@@ -56,27 +57,27 @@ pub use error::{Error, ErrorKind};
/// Messages over the proposal. /// Messages over the proposal.
/// Each message carries an associated round number. /// 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. /// Localized message type.
pub type LocalizedMessage = generic::LocalizedMessage< pub type LocalizedMessage<B> = generic::LocalizedMessage<
Block, B,
HeaderHash, <B as Block>::Hash,
AuthorityId, AuthorityId,
LocalizedSignature LocalizedSignature
>; >;
/// Justification of some hash. /// Justification of some hash.
pub type Justification = generic::Justification<HeaderHash, LocalizedSignature>; pub type Justification<H> = generic::Justification<H, LocalizedSignature>;
/// Justification of a prepare message. /// Justification of a prepare message.
pub type PrepareJustification = generic::PrepareJustification<HeaderHash, LocalizedSignature>; pub type PrepareJustification<H> = generic::PrepareJustification<H, LocalizedSignature>;
/// Unchecked justification. /// Unchecked justification.
pub type UncheckedJustification = generic::UncheckedJustification<HeaderHash, LocalizedSignature>; pub type UncheckedJustification<H> = generic::UncheckedJustification<H, LocalizedSignature>;
impl From<PrimitiveJustification> for UncheckedJustification { impl<H> From<PrimitiveJustification<H>> for UncheckedJustification<H> {
fn from(just: PrimitiveJustification) -> Self { fn from(just: PrimitiveJustification<H>) -> Self {
UncheckedJustification { UncheckedJustification {
round_number: just.round_number as usize, round_number: just.round_number as usize,
digest: just.hash, digest: just.hash,
@@ -88,46 +89,46 @@ impl From<PrimitiveJustification> for UncheckedJustification {
} }
} }
impl From<UncheckedJustification> for PrimitiveJustification { impl<H> Into<PrimitiveJustification<H>> for UncheckedJustification<H> {
fn from(just: UncheckedJustification) -> Self { fn into(self) -> PrimitiveJustification<H> {
PrimitiveJustification { PrimitiveJustification {
round_number: just.round_number as u32, round_number: self.round_number as u32,
hash: just.digest, hash: self.digest,
signatures: just.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(), signatures: self.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(),
} }
} }
} }
/// Result of a committed round of BFT /// 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. /// 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. /// 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. /// Proposer factory. Can be used to create a proposer instance.
pub trait ProposerFactory { pub trait ProposerFactory<B: Block> {
/// The proposer type this creates. /// The proposer type this creates.
type Proposer: Proposer; type Proposer: Proposer<B>;
/// Error which can occur upon creation. /// Error which can occur upon creation.
type Error: From<Error>; type Error: From<Error>;
/// Initialize the proposal logic on top of a specific header. /// Initialize the proposal logic on top of a specific header.
// TODO: provide state context explicitly? // 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. /// Logic for a proposer.
/// ///
/// This will encapsulate creation and evaluation of proposals at a specific /// This will encapsulate creation and evaluation of proposals at a specific
/// block. /// block.
pub trait Proposer { pub trait Proposer<B: Block> {
/// Error type which can occur when proposing or evaluating. /// Error type which can occur when proposing or evaluating.
type Error: From<Error> + From<InputStreamConcluded> + 'static; type Error: From<Error> + From<InputStreamConcluded> + 'static;
/// Future that resolves to a created proposal. /// Future that resolves to a committed proposal.
type Create: IntoFuture<Item=Block,Error=Self::Error>; type Create: IntoFuture<Item=B,Error=Self::Error>;
/// Future that resolves when a proposal is evaluated. /// Future that resolves when a proposal is evaluated.
type Evaluate: IntoFuture<Item=bool,Error=Self::Error>; type Evaluate: IntoFuture<Item=bool,Error=Self::Error>;
@@ -135,10 +136,10 @@ pub trait Proposer {
fn propose(&self) -> Self::Create; fn propose(&self) -> Self::Create;
/// Evaluate proposal. True means valid. /// Evaluate proposal. True means valid.
fn evaluate(&self, proposal: &Block) -> Self::Evaluate; fn evaluate(&self, proposal: &B) -> Self::Evaluate;
/// Import witnessed misbehavior. /// 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 /// Determine the proposer for a given round. This should be a deterministic function
/// with consistent results across all authorities. /// with consistent results across all authorities.
@@ -146,33 +147,37 @@ pub trait Proposer {
} }
/// Block import trait. /// Block import trait.
pub trait BlockImport { pub trait BlockImport<B: Block> {
/// Import a block alongside its corresponding justification. /// 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. /// Trait for getting the authorities at a given block.
pub trait Authorities { pub trait Authorities<B: Block> {
/// Get the authorities at the given 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. /// Instance of BFT agreement.
struct BftInstance<P> { struct BftInstance<B: Block, P> {
key: Arc<ed25519::Pair>, key: Arc<ed25519::Pair>,
authorities: Vec<AuthorityId>, authorities: Vec<AuthorityId>,
parent_hash: HeaderHash, parent_hash: B::Hash,
timer: Timer, timer: Timer,
round_timeout_multiplier: u64, round_timeout_multiplier: u64,
proposer: P, 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 Error = P::Error;
type AuthorityId = AuthorityId; type AuthorityId = AuthorityId;
type Digest = HeaderHash; type Digest = B::Hash;
type Signature = LocalizedSignature; type Signature = LocalizedSignature;
type Candidate = Block; type Candidate = B;
type RoundTimeout = Box<Future<Item=(),Error=Self::Error> + Send>; type RoundTimeout = Box<Future<Item=(),Error=Self::Error> + Send>;
type CreateProposal = <P::Create as IntoFuture>::Future; type CreateProposal = <P::Create as IntoFuture>::Future;
type EvaluateProposal = <P::Evaluate 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() self.proposer.propose().into_future()
} }
fn candidate_digest(&self, proposal: &Block) -> HeaderHash { fn candidate_digest(&self, proposal: &B) -> B::Hash {
proposal.header.blake2_256().into() 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()) 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[..]) 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() 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) /// A future that resolves either when canceled (witnessing a block from the network at same height)
/// or when agreement completes. /// or when agreement completes.
pub struct BftFuture<P, I, InStream, OutSink> where pub struct BftFuture<B, P, I, InStream, OutSink> where
P: Proposer, B: Block + Clone + Eq,
InStream: Stream<Item=Communication, Error=P::Error>, B::Hash: ::std::hash::Hash,
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>, 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>, cancel: Arc<AtomicBool>,
send_task: Option<oneshot::Sender<task::Task>>, send_task: Option<oneshot::Sender<task::Task>>,
import: Arc<I>, import: Arc<I>,
} }
impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> where impl<B, P, I, InStream, OutSink> Future for BftFuture<B, P, I, InStream, OutSink> where
P: Proposer, B: Block + Clone + Eq,
B::Hash: ::std::hash::Hash,
P: Proposer<B>,
P::Error: ::std::fmt::Display, P::Error: ::std::fmt::Display,
I: BlockImport, I: BlockImport<B>,
InStream: Stream<Item=Communication, Error=P::Error>, InStream: Stream<Item=Communication<B>, Error=P::Error>,
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>, OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
{ {
type Item = (); type Item = ();
type Error = (); 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. // we will get the block from the network later.
if let Some(justified_block) = committed.candidate { if let Some(justified_block) = committed.candidate {
info!(target: "bft", "Importing block #{} ({}) directly from BFT consensus", 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) 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 impl<B, P, I, InStream, OutSink> Drop for BftFuture<B, P, I, InStream, OutSink> where
P: Proposer, B: Block + Clone + Eq,
InStream: Stream<Item=Communication, Error=P::Error>, B::Hash: ::std::hash::Hash,
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>, P: Proposer<B>,
InStream: Stream<Item=Communication<B>, Error=P::Error>,
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
{ {
fn drop(&mut self) { fn drop(&mut self) {
// TODO: have a trait member to pass misbehavior reports into. // 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 /// The BftService kicks off the agreement process on top of any blocks it
/// is notified of. /// is notified of.
pub struct BftService<P, I> { pub struct BftService<B: Block, P, I> {
client: Arc<I>, client: Arc<I>,
live_agreement: Mutex<Option<(HeaderHash, AgreementHandle)>>, live_agreement: Mutex<Option<(B::Hash, AgreementHandle)>>,
timer: Timer, timer: Timer,
round_timeout_multiplier: u64, round_timeout_multiplier: u64,
key: Arc<ed25519::Pair>, // TODO: key changing over time. key: Arc<ed25519::Pair>, // TODO: key changing over time.
factory: P, factory: P,
} }
impl<P, I> BftService<P, I> impl<B, P, I> BftService<B, P, I>
where where
P: ProposerFactory, B: Block + Clone + Eq,
<P::Proposer as Proposer>::Error: ::std::fmt::Display, B::Hash: ::std::hash::Hash,
I: BlockImport + Authorities, P: ProposerFactory<B>,
<P::Proposer as Proposer<B>>::Error: ::std::fmt::Display,
I: BlockImport<B> + Authorities<B>,
{ {
/// Create a new service instance. /// 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 { BftService {
client: client, client: client,
live_agreement: Mutex::new(None), 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 /// 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. /// 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. /// 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) pub fn build_upon<InStream, OutSink>(&self, header: &B::Header, input: InStream, output: OutSink)
-> Result<Option<BftFuture<<P as ProposerFactory>::Proposer, I, InStream, OutSink>>, P::Error> where -> Result<Option<BftFuture<B, <P as ProposerFactory<B>>::Proposer, I, InStream, OutSink>>, P::Error> where
InStream: Stream<Item=Communication, Error=<<P as ProposerFactory>::Proposer as Proposer>::Error>, InStream: Stream<Item=Communication<B>, Error=<<P as ProposerFactory<B>>::Proposer as Proposer<B>>::Error>,
OutSink: Sink<SinkItem=Communication, SinkError=<<P as ProposerFactory>::Proposer as Proposer>::Error>, OutSink: Sink<SinkItem=Communication<B>, SinkError=<<P as ProposerFactory<B>>::Proposer as Proposer<B>>::Error>,
{ {
let hash = header.blake2_256().into(); let hash = header.hash();
if self.live_agreement.lock().as_ref().map_or(false, |&(h, _)| h == hash) { if self.live_agreement.lock().as_ref().map_or(false, |&(ref h, _)| h == &hash) {
return Ok(None); 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 n = authorities.len();
let max_faulty = max_faulty_of(n); let max_faulty = max_faulty_of(n);
@@ -368,7 +381,7 @@ impl<P, I> BftService<P, I>
let bft_instance = BftInstance { let bft_instance = BftInstance {
proposer, proposer,
parent_hash: hash, parent_hash: hash.clone(),
round_timeout_multiplier: self.round_timeout_multiplier, round_timeout_multiplier: self.round_timeout_multiplier,
timer: self.timer.clone(), timer: self.timer.clone(),
key: self.key.clone(), key: self.key.clone(),
@@ -409,8 +422,8 @@ impl<P, I> BftService<P, I>
} }
/// Get current agreement parent hash if any. /// Get current agreement parent hash if any.
pub fn live_agreement(&self) -> Option<HeaderHash> { pub fn live_agreement(&self) -> Option<B::Hash> {
self.live_agreement.lock().as_ref().map(|&(h, _)| h.clone()) 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) n - max_faulty_of(n)
} }
fn check_justification_signed_message(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification) fn check_justification_signed_message<H>(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification<H>)
-> Result<Justification, UncheckedJustification> -> Result<Justification<H>, UncheckedJustification<H>>
{ {
// TODO: return additional error information. // TODO: return additional error information.
just.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| { 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. /// Provide all valid authorities.
/// ///
/// On failure, returns the justification back. /// On failure, returns the justification back.
pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification) pub fn check_justification<B: Block>(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification<B::Hash>)
-> Result<Justification, UncheckedJustification> -> Result<Justification<B::Hash>, UncheckedJustification<B::Hash>>
{ {
let message = Slicable::encode(&PrimitiveMessage { let message = Slicable::encode(&PrimitiveMessage::<B, _> {
parent, 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) check_justification_signed_message(authorities, &message[..], just)
@@ -462,12 +475,12 @@ pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just
/// Provide all valid authorities. /// Provide all valid authorities.
/// ///
/// On failure, returns the justification back. /// On failure, returns the justification back.
pub fn check_prepare_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification) pub fn check_prepare_justification<B: Block>(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification<B::Hash>)
-> Result<PrepareJustification, UncheckedJustification> -> Result<PrepareJustification<B::Hash>, UncheckedJustification<B::Hash>>
{ {
let message = Slicable::encode(&PrimitiveMessage { let message = Slicable::encode(&PrimitiveMessage::<B, _> {
parent, 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) 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. /// Check proposal message signatures and authority.
/// Provide all valid authorities. /// Provide all valid authorities.
pub fn check_proposal( pub fn check_proposal<B: Block + Clone>(
authorities: &[AuthorityId], authorities: &[AuthorityId],
parent_hash: &HeaderHash, parent_hash: &B::Hash,
propose: &::generic::LocalizedProposal<Block, HeaderHash, AuthorityId, LocalizedSignature>) propose: &::generic::LocalizedProposal<B, B::Hash, AuthorityId, LocalizedSignature>)
-> Result<(), Error> -> Result<(), Error>
{ {
if !authorities.contains(&propose.sender) { 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_header = PrimitiveAction::ProposeHeader(propose.round_number as u32, propose.digest.clone());
let action_propose = PrimitiveAction::Propose(propose.round_number as u32, propose.proposal.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::<B>(action_header, parent_hash, &propose.digest_signature)?;
check_action(action_propose, parent_hash, &propose.full_signature) check_action::<B>(action_propose, parent_hash, &propose.full_signature)
} }
/// Check vote message signatures and authority. /// Check vote message signatures and authority.
/// Provide all valid authorities. /// Provide all valid authorities.
pub fn check_vote( pub fn check_vote<B: Block>(
authorities: &[AuthorityId], authorities: &[AuthorityId],
parent_hash: &HeaderHash, parent_hash: &B::Hash,
vote: &::generic::LocalizedVote<HeaderHash, AuthorityId, LocalizedSignature>) vote: &::generic::LocalizedVote<B::Hash, AuthorityId, LocalizedSignature>)
-> Result<(), Error> -> Result<(), Error>
{ {
if !authorities.contains(&vote.sender) { if !authorities.contains(&vote.sender) {
@@ -504,14 +517,14 @@ pub fn check_vote(
} }
let action = match vote.vote { let action = match vote.vote {
::generic::Vote::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h), ::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()),
::generic::Vote::Commit(r, h) => PrimitiveAction::Commit(r as u32, h), ::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()),
::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32), ::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 { let primitive = PrimitiveMessage {
parent: parent_hash.clone(), parent: parent_hash.clone(),
action, action,
@@ -526,12 +539,12 @@ fn check_action(action: PrimitiveAction, parent_hash: &HeaderHash, sig: &Localiz
} }
/// Sign a BFT message with the given key. /// 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 signer = key.public();
let sign_action = |action| { let sign_action = |action: PrimitiveAction<B, B::Hash>| {
let primitive = PrimitiveMessage { let primitive = PrimitiveMessage {
parent: parent_hash, parent: parent_hash.clone(),
action, action,
}; };
@@ -544,7 +557,7 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
match message { match message {
::generic::Message::Propose(r, proposal) => { ::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_header = PrimitiveAction::ProposeHeader(r as u32, header_hash.clone());
let action_propose = PrimitiveAction::Propose(r as u32, proposal.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) => { ::generic::Message::Vote(vote) => {
let action = match vote { let action = match vote {
::generic::Vote::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h), ::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()),
::generic::Vote::Commit(r, h) => PrimitiveAction::Commit(r as u32, h), ::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()),
::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32), ::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 { mod tests {
use super::*; use super::*;
use std::collections::HashSet; 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::tokio_core::reactor::{Core};
use self::keyring::Keyring; use self::keyring::Keyring;
use futures::stream; use futures::stream;
@@ -586,19 +600,21 @@ mod tests {
extern crate substrate_keyring as keyring; extern crate substrate_keyring as keyring;
extern crate tokio_core; extern crate tokio_core;
type TestBlock = GenericTestBlock<()>;
struct FakeClient { struct FakeClient {
authorities: Vec<AuthorityId>, authorities: Vec<AuthorityId>,
imported_heights: Mutex<HashSet<block::Number>> imported_heights: Mutex<HashSet<u64>>
} }
impl BlockImport for FakeClient { impl BlockImport<TestBlock> for FakeClient {
fn import_block(&self, block: Block, _justification: Justification) { fn import_block(&self, block: TestBlock, _justification: Justification<H256>) {
assert!(self.imported_heights.lock().insert(block.header.number)) assert!(self.imported_heights.lock().insert(block.header.number))
} }
} }
impl Authorities for FakeClient { impl Authorities<TestBlock> for FakeClient {
fn authorities(&self, _at: &BlockId) -> Result<Vec<AuthorityId>, Error> { fn authorities(&self, _at: &BlockId<TestBlock>) -> Result<Vec<AuthorityId>, Error> {
Ok(self.authorities.clone()) Ok(self.authorities.clone())
} }
} }
@@ -607,10 +623,10 @@ mod tests {
struct Output<E>(::std::marker::PhantomData<E>); struct Output<E>(::std::marker::PhantomData<E>);
impl<E> Sink for Output<E> { impl<E> Sink for Output<E> {
type SinkItem = Communication; type SinkItem = Communication<TestBlock>;
type SinkError = E; 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) Ok(::futures::AsyncSink::Ready)
} }
@@ -620,34 +636,35 @@ mod tests {
} }
struct DummyFactory; struct DummyFactory;
struct DummyProposer(block::Number); struct DummyProposer(u64);
impl ProposerFactory for DummyFactory { impl ProposerFactory<TestBlock> for DummyFactory {
type Proposer = DummyProposer; type Proposer = DummyProposer;
type Error = Error; 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)) Ok(DummyProposer(parent_header.number + 1))
} }
} }
impl Proposer for DummyProposer { impl Proposer<TestBlock> for DummyProposer {
type Error = Error; type Error = Error;
type Create = Result<Block, Error>; type Create = Result<TestBlock, Error>;
type Evaluate = Result<bool, Error>; type Evaluate = Result<bool, Error>;
fn propose(&self) -> Result<Block, Error> { fn propose(&self) -> Result<TestBlock, Error> {
Ok(Block {
header: Header::from_block_number(self.0), Ok(TestBlock {
transactions: Default::default() 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) 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 { fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId {
authorities[round_number % authorities.len()].clone() authorities[round_number % authorities.len()].clone()
@@ -655,7 +672,7 @@ mod tests {
} }
fn make_service(client: FakeClient) fn make_service(client: FakeClient)
-> BftService<DummyFactory, FakeClient> -> BftService<TestBlock, DummyFactory, FakeClient>
{ {
BftService { BftService {
client: Arc::new(client), client: Arc::new(client),
@@ -667,13 +684,23 @@ mod tests {
} }
} }
fn sign_vote(vote: ::generic::Vote<HeaderHash>, key: &ed25519::Pair, parent_hash: HeaderHash) -> LocalizedSignature { fn sign_vote(vote: ::generic::Vote<H256>, key: &ed25519::Pair, parent_hash: H256) -> LocalizedSignature {
match sign_message(vote.into(), key, parent_hash) { match sign_message::<TestBlock>(vote.into(), key, parent_hash) {
::generic::LocalizedMessage::Vote(vote) => vote.signature, ::generic::LocalizedMessage::Vote(vote) => vote.signature,
_ => panic!("signing vote leads to signed vote"), _ => 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] #[test]
fn future_gets_preempted() { fn future_gets_preempted() {
let client = FakeClient { let client = FakeClient {
@@ -690,12 +717,12 @@ mod tests {
let service = make_service(client); let service = make_service(client);
let first = Header::from_block_number(2); let first = from_block_number(2);
let first_hash = first.blake2_256().into(); 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; 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(); let bft = service.build_upon(&first, stream::empty(), Output(Default::default())).unwrap();
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash); assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash);
@@ -749,7 +776,7 @@ mod tests {
}).collect(), }).collect(),
}; };
assert!(check_justification(&authorities, parent_hash, unchecked).is_ok()); assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_ok());
let unchecked = UncheckedJustification { let unchecked = UncheckedJustification {
digest: hash, digest: hash,
@@ -759,7 +786,7 @@ mod tests {
}).collect(), }).collect(),
}; };
assert!(check_justification(&authorities, parent_hash, unchecked).is_err()); assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
// not enough signatures. // not enough signatures.
let unchecked = UncheckedJustification { let unchecked = UncheckedJustification {
@@ -770,7 +797,7 @@ mod tests {
}).collect(), }).collect(),
}; };
assert!(check_justification(&authorities, parent_hash, unchecked).is_err()); assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
// wrong hash. // wrong hash.
let unchecked = UncheckedJustification { let unchecked = UncheckedJustification {
@@ -781,7 +808,7 @@ mod tests {
}).collect(), }).collect(),
}; };
assert!(check_justification(&authorities, parent_hash, unchecked).is_err()); assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
} }
#[test] #[test]
@@ -793,9 +820,9 @@ mod tests {
Keyring::Eve.to_raw_public(), Keyring::Eve.to_raw_public(),
]; ];
let block = Block { let block = TestBlock {
header: Header::from_block_number(1), header: from_block_number(1),
transactions: Default::default() extrinsics: Default::default()
}; };
let proposal = sign_message(::generic::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);; let proposal = sign_message(::generic::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);;
@@ -812,7 +839,7 @@ mod tests {
} }
// Not an authority // 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 { if let ::generic::LocalizedMessage::Propose(proposal) = proposal {
assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err()); assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err());
} else { } else {
@@ -822,28 +849,28 @@ mod tests {
#[test] #[test]
fn vote_check_works() { fn vote_check_works() {
let parent_hash = Default::default(); let parent_hash: H256 = Default::default();
let hash = [0xff; 32].into(); let hash: H256 = [0xff; 32].into();
let authorities = vec![ let authorities = vec![
Keyring::Alice.to_raw_public(), Keyring::Alice.to_raw_public(),
Keyring::Eve.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 { 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(); let mut invalid_sender = vote.clone();
invalid_sender.signature.signer = Keyring::Eve.into(); 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 { } else {
assert!(false); assert!(false);
} }
// Not an authority // 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 { 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 { } else {
assert!(false); assert!(false);
} }
+1
View File
@@ -17,6 +17,7 @@ substrate-executor = { path = "../executor" }
substrate-primitives = { path = "../primitives" } substrate-primitives = { path = "../primitives" }
substrate-runtime-io = { path = "../runtime-io" } substrate-runtime-io = { path = "../runtime-io" }
substrate-runtime-support = { path = "../runtime-support" } substrate-runtime-support = { path = "../runtime-support" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
substrate-state-machine = { path = "../state-machine" } substrate-state-machine = { path = "../state-machine" }
substrate-keyring = { path = "../../substrate/keyring" } 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" } patricia-trie = { git = "https://github.com/paritytech/parity.git" }
memorydb = { git = "https://github.com/paritytech/parity.git" } memorydb = { git = "https://github.com/paritytech/parity.git" }
substrate-primitives = { path = "../../../substrate/primitives" } substrate-primitives = { path = "../../../substrate/primitives" }
substrate-runtime-primitives = { path = "../../../substrate/runtime/primitives" }
substrate-client = { path = "../../../substrate/client" } substrate-client = { path = "../../../substrate/client" }
substrate-state-machine = { path = "../../../substrate/state-machine" } substrate-state-machine = { path = "../../../substrate/state-machine" }
substrate-runtime-support = { path = "../../../substrate/runtime-support" } 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_state_machine as state_machine;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
#[macro_use] #[macro_use]
@@ -47,9 +48,9 @@ use kvdb::{KeyValueDB, DBTransaction};
use memorydb::MemoryDB; use memorydb::MemoryDB;
use parking_lot::RwLock; use parking_lot::RwLock;
use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut}; use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut};
use primitives::blake2_256; use runtime_primitives::generic::BlockId;
use primitives::block::{self, Id as BlockId, HeaderHash}; use runtime_primitives::bft::Justification;
use runtime_support::Hashable; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, Hashing, HashingFor, Zero};
use state_machine::backend::Backend as StateBackend; use state_machine::backend::Backend as StateBackend;
use state_machine::CodeExecutor; use state_machine::CodeExecutor;
@@ -62,14 +63,17 @@ pub struct DatabaseSettings {
} }
/// Create an instance of db-backed client. /// Create an instance of db-backed client.
pub fn new_client<E, F>( pub fn new_client<E, F, Block>(
settings: DatabaseSettings, settings: DatabaseSettings,
executor: E, executor: E,
genesis_builder: F, 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 where
Block: BlockT,
<Block::Header as HeaderT>::Number: As<u32>,
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
E: CodeExecutor, E: CodeExecutor,
F: client::GenesisBuilder, F: client::GenesisBuilder<Block>,
{ {
let backend = Arc::new(Backend::new(&settings)?); let backend = Arc::new(Backend::new(&settings)?);
let executor = client::LocalCallExecutor::new(backend.clone(), executor); let executor = client::LocalCallExecutor::new(backend.clone(), executor);
@@ -90,24 +94,26 @@ mod meta {
pub const BEST_BLOCK: &[u8; 4] = b"best"; pub const BEST_BLOCK: &[u8; 4] = b"best";
} }
struct PendingBlock { struct PendingBlock<Block: BlockT> {
header: block::Header, header: Block::Header,
justification: Option<primitives::bft::Justification>, justification: Option<Justification<Block::Hash>>,
body: Option<block::Body>, body: Option<Vec<Block::Extrinsic>>,
is_best: bool, is_best: bool,
} }
#[derive(Clone)] #[derive(Clone)]
struct Meta { struct Meta<N, H> {
best_hash: HeaderHash, best_hash: H,
best_number: block::Number, best_number: N,
genesis_hash: HeaderHash, genesis_hash: H,
} }
type BlockKey = [u8; 4]; type BlockKey = [u8; 4];
// Little endian // 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 >> 24) as u8,
((n >> 16) & 0xff) as u8, ((n >> 16) & 0xff) as u8,
@@ -127,13 +133,13 @@ fn db_err(err: kvdb::Error) -> client::error::Error {
} }
/// Block database /// Block database
pub struct BlockchainDb { pub struct BlockchainDb<Block: BlockT> {
db: Arc<KeyValueDB>, db: Arc<KeyValueDB>,
meta: RwLock<Meta>, meta: RwLock<Meta<<Block::Header as HeaderT>::Number, Block::Hash>>,
} }
impl BlockchainDb { impl<Block: BlockT> BlockchainDb<Block> where <Block::Header as HeaderT>::Number: As<u32> {
fn id(&self, id: BlockId) -> Result<Option<BlockKey>, client::error::Error> { fn id(&self, id: BlockId<Block>) -> Result<Option<BlockKey>, client::error::Error> {
match id { match id {
BlockId::Hash(h) => { BlockId::Hash(h) => {
{ {
@@ -142,7 +148,7 @@ impl BlockchainDb {
return Ok(Some(number_to_db_key(meta.best_number))); 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]; let mut key: [u8; 4] = [0; 4];
key.copy_from_slice(&v); key.copy_from_slice(&v);
key 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| let (best_hash, best_number) = if let Some(Some(header)) = db.get(columns::META, meta::BEST_BLOCK).and_then(|id|
match 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), None => Ok(None),
}).map_err(db_err)? }).map_err(db_err)?
{ {
let hash = header.blake2_256().into(); let hash = header.hash();
debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number); debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number());
(hash, header.number) (hash, header.number().clone())
} else { } 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)? let genesis_hash = db.get(columns::HEADER, &number_to_db_key(<Block::Header as HeaderT>::Number::zero())).map_err(db_err)?
.map(|b| blake2_256(&b)).unwrap_or_default().into(); .map(|b| HashingFor::<Block>::hash(&b)).unwrap_or_default().into();
Ok(BlockchainDb { Ok(BlockchainDb {
db, 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| self.id(id).and_then(|key|
match key { match key {
Some(key) => self.db.get(column, &key).map_err(db_err), 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 { if is_best {
let mut meta = self.meta.write(); let mut meta = self.meta.write();
if number == 0 { if number == Zero::zero() {
meta.genesis_hash = hash; meta.genesis_hash = hash;
} }
meta.best_number = number; meta.best_number = number;
@@ -198,10 +204,10 @@ impl BlockchainDb {
} }
} }
impl client::blockchain::Backend for BlockchainDb { impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> where <Block::Header as HeaderT>::Number: As<u32> {
fn header(&self, id: BlockId) -> Result<Option<block::Header>, client::error::Error> { fn header(&self, id: BlockId<Block>) -> Result<Option<Block::Header>, client::error::Error> {
match self.read_db(id, columns::HEADER)? { 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)), Some(header) => Ok(Some(header)),
None => return Err(client::error::ErrorKind::Backend("Error decoding header".into()).into()), 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)? { 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)), Some(body) => Ok(Some(body)),
None => return Err(client::error::ErrorKind::Backend("Error decoding body".into()).into()), 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)? { 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)), Some(justification) => Ok(Some(justification)),
None => return Err(client::error::ErrorKind::Backend("Error decoding justification".into()).into()), 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(); let meta = self.meta.read();
Ok(client::blockchain::Info { Ok(client::blockchain::Info {
best_hash: meta.best_hash, 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 { let exists = match id {
BlockId::Hash(_) => self.id(id)?.is_some(), BlockId::Hash(_) => self.id(id)?.is_some(),
BlockId::Number(n) => n <= self.meta.read().best_number, 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| 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 /// Database transaction
pub struct BlockImportOperation { pub struct BlockImportOperation<Block: BlockT> {
old_state: DbState, old_state: DbState,
updates: MemoryDB, 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; type State = DbState;
fn state(&self) -> Result<Option<&Self::State>, client::error::Error> { fn state(&self) -> Result<Option<&Self::State>, client::error::Error> {
Ok(Some(&self.old_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_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"); assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
self.pending_block = Some(PendingBlock { self.pending_block = Some(PendingBlock {
header, 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. /// 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. /// Otherwise, trie nodes are kept only from the most recent block.
pub struct Backend { pub struct Backend<Block: BlockT> {
db: Arc<KeyValueDB>, db: Arc<KeyValueDB>,
blockchain: BlockchainDb, blockchain: BlockchainDb<Block>,
archive: bool, archive: bool,
} }
impl Backend { impl<Block: BlockT> Backend<Block> where <Block::Header as HeaderT>::Number: As<u32> {
/// Create a new instance of database backend. /// 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)); let mut db_config = DatabaseConfig::with_columns(Some(columns::NUM_COLUMNS));
db_config.memory_budget = config.cache_size; db_config.memory_budget = config.cache_size;
db_config.wal = true; db_config.wal = true;
@@ -442,13 +448,13 @@ impl Backend {
} }
#[cfg(test)] #[cfg(test)]
fn new_test() -> Backend { fn new_test() -> Self {
let db = Arc::new(::kvdb_memorydb::create(columns::NUM_COLUMNS)); let db = Arc::new(::kvdb_memorydb::create(columns::NUM_COLUMNS));
Backend::from_kvdb(db as Arc<_>, false).expect("failed to create test-db") 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())?; let blockchain = BlockchainDb::new(db.clone())?;
Ok(Backend { Ok(Backend {
@@ -459,12 +465,15 @@ impl Backend {
} }
} }
impl client::backend::Backend for Backend { impl<Block: BlockT> client::backend::Backend<Block> for Backend<Block> where
type BlockImportOperation = BlockImportOperation; <Block::Header as HeaderT>::Number: As<u32>,
type Blockchain = BlockchainDb; Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
{
type BlockImportOperation = BlockImportOperation<Block>;
type Blockchain = BlockchainDb<Block>;
type State = DbState; 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)?; let state = self.state_at(block)?;
Ok(BlockImportOperation { Ok(BlockImportOperation {
pending_block: None, 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> { fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> Result<(), client::error::Error> {
let mut transaction = DBTransaction::new(); let mut transaction = DBTransaction::new();
if let Some(pending_block) = operation.pending_block { if let Some(pending_block) = operation.pending_block {
let hash: block::HeaderHash = pending_block.header.blake2_256().into(); let hash = pending_block.header.hash();
let number = pending_block.header.number;; let number = pending_block.header.number().clone();
let key = number_to_db_key(pending_block.header.number); let key = number_to_db_key(pending_block.header.number().clone());
transaction.put(columns::HEADER, &key, &pending_block.header.encode()); transaction.put(columns::HEADER, &key, &pending_block.header.encode());
if let Some(body) = pending_block.body { if let Some(body) = pending_block.body {
transaction.put(columns::BODY, &key, &body.encode()); transaction.put(columns::BODY, &key, &body.encode());
@@ -486,7 +495,7 @@ impl client::backend::Backend for Backend {
if let Some(justification) = pending_block.justification { if let Some(justification) = pending_block.justification {
transaction.put(columns::JUSTIFICATION, &key, &justification.encode()); 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 { if pending_block.is_best {
transaction.put(columns::META, meta::BEST_BLOCK, &key); transaction.put(columns::META, meta::BEST_BLOCK, &key);
} }
@@ -504,11 +513,11 @@ impl client::backend::Backend for Backend {
Ok(()) Ok(())
} }
fn blockchain(&self) -> &BlockchainDb { fn blockchain(&self) -> &BlockchainDb<Block> {
&self.blockchain &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; use client::blockchain::Backend as BcBackend;
// special case for genesis initialization // 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| { self.blockchain.header(block).and_then(|maybe_hdr| maybe_hdr.map(|hdr| {
let root: [u8; 32] = hdr.state_root().clone().into();
DbState { DbState {
db: self.db.clone(), 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)] #[cfg(test)]
mod tests { mod tests {
@@ -543,10 +556,13 @@ mod tests {
use client::backend::Backend as BTrait; use client::backend::Backend as BTrait;
use client::backend::BlockImportOperation as Op; use client::backend::BlockImportOperation as Op;
use client::blockchain::Backend as BCTrait; use client::blockchain::Backend as BCTrait;
use runtime_primitives::testing::{Header, Block as RawBlock};
type Block = RawBlock<u64>;
#[test] #[test]
fn block_hash_inserted_correctly() { fn block_hash_inserted_correctly() {
let db = Backend::new_test(); let db = Backend::<Block>::new_test();
for i in 0..10 { for i in 0..10 {
assert!(db.blockchain().hash(i).unwrap().is_none()); assert!(db.blockchain().hash(i).unwrap().is_none());
@@ -558,7 +574,7 @@ mod tests {
}; };
let mut op = db.begin_operation(id).unwrap(); let mut op = db.begin_operation(id).unwrap();
let header = block::Header { let header = Header {
number: i, number: i,
parent_hash: Default::default(), parent_hash: Default::default(),
state_root: Default::default(), state_root: Default::default(),
@@ -581,10 +597,10 @@ mod tests {
#[test] #[test]
fn set_state_data() { 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 op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
let mut header = block::Header { let mut header = Header {
number: 0, number: 0,
parent_hash: Default::default(), parent_hash: Default::default(),
state_root: Default::default(), state_root: Default::default(),
@@ -623,7 +639,7 @@ mod tests {
{ {
let mut op = db.begin_operation(BlockId::Number(0)).unwrap(); let mut op = db.begin_operation(BlockId::Number(0)).unwrap();
let mut header = block::Header { let mut header = Header {
number: 1, number: 1,
parent_hash: Default::default(), parent_hash: Default::default(),
state_root: Default::default(), state_root: Default::default(),
@@ -660,11 +676,11 @@ mod tests {
#[test] #[test]
fn delete_only_when_negative_rc() { fn delete_only_when_negative_rc() {
let key; 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 op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
let mut header = block::Header { let mut header = Header {
number: 0, number: 0,
parent_hash: Default::default(), parent_hash: Default::default(),
state_root: Default::default(), state_root: Default::default(),
@@ -697,7 +713,7 @@ mod tests {
{ {
let mut op = db.begin_operation(BlockId::Number(0)).unwrap(); let mut op = db.begin_operation(BlockId::Number(0)).unwrap();
let mut header = block::Header { let mut header = Header {
number: 1, number: 1,
parent_hash: Default::default(), parent_hash: Default::default(),
state_root: Default::default(), state_root: Default::default(),
@@ -729,7 +745,7 @@ mod tests {
{ {
let mut op = db.begin_operation(BlockId::Number(1)).unwrap(); let mut op = db.begin_operation(BlockId::Number(1)).unwrap();
let mut header = block::Header { let mut header = Header {
number: 1, number: 1,
parent_hash: Default::default(), parent_hash: Default::default(),
state_root: Default::default(), state_root: Default::default(),
+19 -11
View File
@@ -18,18 +18,26 @@
use state_machine::backend::Backend as StateBackend; use state_machine::backend::Backend as StateBackend;
use error; use error;
use primitives::block::{self, Id as BlockId}; use runtime_primitives::bft::Justification;
use primitives; use runtime_primitives::traits::Block as BlockT;
use runtime_primitives::generic::BlockId;
/// Block insertion operation. Keeps hold if the inserted block state and data. /// Block insertion operation. Keeps hold if the inserted block state and data.
pub trait BlockImportOperation { pub trait BlockImportOperation<Block: BlockT> {
/// Associated state backend type. /// Associated state backend type.
type State: StateBackend; type State: StateBackend;
/// Returns pending state. Returns None for backends with locally-unavailable state data. /// Returns pending state. Returns None for backends with locally-unavailable state data.
fn state(&self) -> error::Result<Option<&Self::State>>; fn state(&self) -> error::Result<Option<&Self::State>>;
/// Append block data to the transaction. /// 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. /// Inject storage data into the database.
fn update_storage(&mut self, update: <Self::State as StateBackend>::Transaction) -> error::Result<()>; fn update_storage(&mut self, update: <Self::State as StateBackend>::Transaction) -> error::Result<()>;
/// Inject storage data into the database replacing any existing data. /// 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` /// 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. /// 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. /// Associated block insertion operation type.
type BlockImportOperation: BlockImportOperation; type BlockImportOperation: BlockImportOperation<Block>;
/// Associated blockchain backend type. /// Associated blockchain backend type.
type Blockchain: ::blockchain::Backend; type Blockchain: ::blockchain::Backend<Block>;
/// Associated state backend type. /// Associated state backend type.
type State: StateBackend; type State: StateBackend;
/// Begin a new block insertion transaction with given parent block id. /// Begin a new block insertion transaction with given parent block id.
/// When constructing the genesis, this is called with all-zero hash. /// 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. /// Commit block insertion.
fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>; fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>;
/// Returns reference to blockchain backend. /// Returns reference to blockchain backend.
fn blockchain(&self) -> &Self::Blockchain; fn blockchain(&self) -> &Self::Blockchain;
/// Returns state backend with post-state of given block. /// 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. /// 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. /// 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. //! Utility struct to build a block.
use std::vec::Vec; use std::vec::Vec;
use codec::{Joiner, Slicable}; use codec::Slicable;
use state_machine; use state_machine;
use primitives::{Header, Block}; use runtime_primitives::traits::{Header as HeaderT, Hashing as HashingT, Block as BlockT, One, HashingFor};
use primitives::block::{Id as BlockId, Extrinsic}; use runtime_primitives::generic::BlockId;
use {backend, error, Client, CallExecutor}; use {backend, error, Client, CallExecutor};
use triehash::ordered_trie_root;
/// Utility for building new (valid) blocks from a stream of transactions. /// Utility for building new (valid) blocks from a stream of extrinsics.
pub struct BlockBuilder<B, E> where pub struct BlockBuilder<B, E, Block> where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor + Clone, E: CallExecutor<Block> + Clone,
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>, Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
{ {
header: Header, header: <Block as BlockT>::Header,
transactions: Vec<Extrinsic>, extrinsics: Vec<<Block as BlockT>::Extrinsic>,
executor: E, executor: E,
state: B::State, state: B::State,
changes: state_machine::OverlayedChanges, changes: state_machine::OverlayedChanges,
} }
impl<B, E> BlockBuilder<B, E> where impl<B, E, Block> BlockBuilder<B, E, Block> where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor + Clone, E: CallExecutor<Block> + Clone,
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>, 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. /// 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)) 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 /// Create a new instance of builder from the given client using a particular block's ID to
/// build upon. /// 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 { Ok(BlockBuilder {
header: Header { header,
number: client.block_number_from_id(block_id)?.ok_or(error::ErrorKind::UnknownBlock(*block_id))? + 1, extrinsics: Vec::new(),
parent_hash: client.block_hash_from_id(block_id)?.ok_or(error::ErrorKind::UnknownBlock(*block_id))?, executor,
state_root: Default::default(), state,
extrinsics_root: Default::default(), changes,
digest: Default::default(),
},
transactions: Default::default(),
executor: client.executor().clone(),
state: client.state_at(block_id)?,
changes: Default::default(),
}) })
} }
/// 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 /// 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). /// the error. Otherwise, it will return a mutable reference to self (in order to chain).
pub fn push(&mut self, tx: Extrinsic) -> error::Result<()> { pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> error::Result<()> {
let (output, _) = self.executor.call_at_state( match self.executor.call_at_state(&self.state, &mut self.changes, "apply_extrinsic", &xt.encode()) {
&self.state, Ok(_) => {
&mut self.changes, self.extrinsics.push(xt);
"execute_transaction", Ok(())
&vec![].and(&self.header).and(&tx))?; }
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime so must be valid"); Err(e) => {
self.transactions.push(tx); self.changes.discard_prospective();
Ok(()) 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> { 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( let (output, _) = self.executor.call_at_state(
&self.state, &self.state,
&mut self.changes, &mut self.changes,
"finalise_block", "finalise_block",
&self.header.encode())?; &[],
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime so must be valid"); )?;
Ok(Block { self.header = <<Block as BlockT>::Header as Slicable>::decode(&mut &output[..])
header: self.header, .expect("Header came straight out of runtime so must be valid");
transactions: self.transactions,
}) 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 //! Polkadot blockchain trait
use primitives::block::{self, Id as BlockId}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use primitives; use runtime_primitives::generic::BlockId;
use runtime_primitives::bft::Justification;
use error::Result; use error::Result;
/// Blockchain database backend. Does not perform any validation. /// 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. /// 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. /// 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. /// 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. /// Get blockchain info.
fn info(&self) -> Result<Info>; fn info(&self) -> Result<Info<Block>>;
/// Get block status. /// 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. /// 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 /// Block import outcome
@@ -50,13 +52,13 @@ pub enum ImportResult<E> {
/// Blockchain info /// Blockchain info
#[derive(Debug)] #[derive(Debug)]
pub struct Info { pub struct Info<Block: BlockT> {
/// Best block hash. /// Best block hash.
pub best_hash: block::HeaderHash, pub best_hash: <<Block as BlockT>::Header as HeaderT>::Hash,
/// Best block number. /// Best block number.
pub best_number: block::Number, pub best_number: <<Block as BlockT>::Header as HeaderT>::Number,
/// Genesis block hash. /// Genesis block hash.
pub genesis_hash: block::HeaderHash, pub genesis_hash: <<Block as BlockT>::Header as HeaderT>::Hash,
} }
/// Block status. /// Block status.
+26 -21
View File
@@ -16,10 +16,10 @@
use std::sync::Arc; use std::sync::Arc;
use futures::{IntoFuture, Future}; 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::{self, OverlayedChanges, Backend as StateBackend, CodeExecutor};
use state_machine::backend::InMemory as InMemoryStateBackend; use state_machine::backend::InMemory as InMemoryStateBackend;
use triehash::trie_root;
use backend; use backend;
use blockchain::Backend as ChainBackend; use blockchain::Backend as ChainBackend;
@@ -36,14 +36,14 @@ pub struct CallResult {
} }
/// Method call executor. /// Method call executor.
pub trait CallExecutor { pub trait CallExecutor<B: BlockT> {
/// Externalities error type. /// Externalities error type.
type Error: state_machine::Error; type Error: state_machine::Error;
/// Execute a call to a contract on top of state in a block of given hash. /// Execute a call to a contract on top of state in a block of given hash.
/// ///
/// No changes are made. /// 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. /// 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 where
B: backend::LocalBackend, B: backend::LocalBackend<Block>,
E: CodeExecutor, 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; 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 mut changes = OverlayedChanges::default();
let (return_data, _) = self.call_at_state(&self.backend.state_at(*id)?, &mut changes, method, call_data)?; let (return_data, _) = self.call_at_state(&self.backend.state_at(*id)?, &mut changes, method, call_data)?;
Ok(CallResult{ return_data, changes }) 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 where
B: backend::RemoteBackend, B: backend::RemoteBackend<Block>,
F: Fetcher, F: Fetcher<Block>,
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 = error::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 { let block_hash = match *id {
BlockId::Hash(hash) => hash, BlockId::Hash(hash) => hash,
BlockId::Number(number) => self.backend.blockchain().hash(number)? 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 { self.fetcher.remote_call(RemoteCallRequest {
@@ -141,22 +143,25 @@ impl<B, F> CallExecutor for RemoteCallExecutor<B, F>
} }
/// Check remote execution proof. /// 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 where
B: backend::RemoteBackend, B: backend::RemoteBackend<Block>,
E: CodeExecutor, 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_result, remote_proof) = remote_proof;
let remote_state = state_from_execution_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 = backend.blockchain().header(BlockId::Hash(request.block))?;
let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(BlockId::Hash(request.block)))?; let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", request.block)))?;
let local_state_root = local_header.state_root; 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()); return Err(error::ErrorKind::InvalidExecutionProof.into());
} }
+123 -115
View File
@@ -19,11 +19,11 @@
use std::sync::Arc; use std::sync::Arc;
use futures::sync::mpsc; use futures::sync::mpsc;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use primitives::{self, block, AuthorityId}; use primitives::AuthorityId;
use primitives::block::{Id as BlockId, HeaderHash}; 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 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 state_machine::{self, Ext, OverlayedChanges, Backend as StateBackend, CodeExecutor};
use backend::{self, BlockImportOperation}; use backend::{self, BlockImportOperation};
@@ -32,45 +32,45 @@ use call_executor::{CallExecutor, LocalCallExecutor};
use {error, in_mem, block_builder, runtime_io, bft}; use {error, in_mem, block_builder, runtime_io, bft};
/// Type that implements `futures::Stream` of block import events. /// 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. /// Polkadot Client genesis block builder.
pub trait GenesisBuilder { pub trait GenesisBuilder<B: BlockT> {
/// Build genesis block. /// 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 /// Polkadot Client
pub struct Client<B, E> { pub struct Client<B, E, Block> where Block: BlockT {
backend: Arc<B>, backend: Arc<B>,
executor: E, executor: E,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification>>>, import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification<Block>>>>,
import_lock: Mutex<()>, 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. /// A source of blockchain evenets.
pub trait BlockchainEvents { pub trait BlockchainEvents<Block: BlockT> {
/// Get block import event stream. /// Get block import event stream.
fn import_notification_stream(&self) -> BlockchainEventStream; fn import_notification_stream(&self) -> mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
} }
/// Chain head information. /// Chain head information.
pub trait ChainHead { pub trait ChainHead<Block: BlockT> {
/// Get best block header. /// 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 /// Client info
// TODO: split queue info from chain info and amalgamate into single struct. // TODO: split queue info from chain info and amalgamate into single struct.
#[derive(Debug)] #[derive(Debug)]
pub struct ClientInfo { pub struct ClientInfo<Block: BlockT> {
/// Best block hash. /// Best block hash.
pub chain: ChainInfo, pub chain: ChainInfo<Block>,
/// Best block number in the queue. /// 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. /// Best queued block hash.
pub best_queued_hash: Option<block::HeaderHash>, pub best_queued_hash: Option<Block::Hash>,
} }
/// Block import result. /// Block import result.
@@ -120,49 +120,51 @@ pub enum BlockOrigin {
/// Summary of an imported block /// Summary of an imported block
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BlockImportNotification { pub struct BlockImportNotification<Block: BlockT> {
/// Imported block header hash. /// Imported block header hash.
pub hash: block::HeaderHash, pub hash: Block::Hash,
/// Imported block origin. /// Imported block origin.
pub origin: BlockOrigin, pub origin: BlockOrigin,
/// Imported block header. /// Imported block header.
pub header: block::Header, pub header: Block::Header,
/// Is this the new best block. /// Is this the new best block.
pub is_new_best: bool, pub is_new_best: bool,
} }
/// A header paired with a justification which has already been checked. /// A header paired with a justification which has already been checked.
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct JustifiedHeader { pub struct JustifiedHeader<Block: BlockT> {
header: block::Header, header: <Block as BlockT>::Header,
justification: bft::Justification, justification: ::bft::Justification<Block::Hash>,
} }
impl JustifiedHeader { impl<Block: BlockT> JustifiedHeader<Block> {
/// Deconstruct the justified header into parts. /// 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) (self.header, self.justification)
} }
} }
/// Create an instance of in-memory client. /// Create an instance of in-memory client.
pub fn new_in_mem<E, F>( pub fn new_in_mem<E, F, Block>(
executor: E, executor: E,
genesis_builder: F 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 where
E: CodeExecutor, E: CodeExecutor,
F: GenesisBuilder, F: GenesisBuilder<Block>,
Block: BlockT,
{ {
let backend = Arc::new(in_mem::Backend::new()); let backend = Arc::new(in_mem::Backend::new());
let executor = LocalCallExecutor::new(backend.clone(), executor); let executor = LocalCallExecutor::new(backend.clone(), executor);
Client::new(backend, executor, genesis_builder) Client::new(backend, executor, genesis_builder)
} }
impl<B, E> Client<B, E> where impl<B, E, Block: BlockT> Client<B, E, Block> where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor, E: CallExecutor<Block>,
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>,
{ {
/// Creates new Polkadot Client with given blockchain and code executor. /// Creates new Polkadot Client with given blockchain and code executor.
pub fn new<F>( pub fn new<F>(
@@ -171,12 +173,12 @@ impl<B, E> Client<B, E> where
genesis_builder: F, genesis_builder: F,
) -> error::Result<Self> ) -> error::Result<Self>
where 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"); trace!("Empty database, writing genesis block");
let (genesis_header, genesis_store) = genesis_builder.build(); 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.reset_storage(genesis_store.into_iter())?;
op.set_block_data(genesis_header, Some(vec![]), None, true)?; op.set_block_data(genesis_header, Some(vec![]), None, true)?;
backend.commit_operation(op)?; 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. /// 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) 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. /// 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)? Ok(StorageData(self.state_at(id)?
.storage(&key.0)? .storage(&key.0)?
.ok_or_else(|| error::ErrorKind::NoValueForKey(key.0.clone()))? .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. /// 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) self.storage(id, &StorageKey(b":code".to_vec())).map(|data| data.0)
} }
/// Get the set of authorities at a given block. /// 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",&[]) self.executor.call(id, "authorities",&[])
.and_then(|r| Vec::<AuthorityId>::decode(&mut &r.return_data[..]) .and_then(|r| Vec::<AuthorityId>::decode(&mut &r.return_data[..])
.ok_or(error::ErrorKind::AuthLenInvalid.into())) .ok_or(error::ErrorKind::AuthLenInvalid.into()))
@@ -229,7 +231,7 @@ impl<B, E> Client<B, E> where
/// AND returning execution proof. /// AND returning execution proof.
/// ///
/// No changes are made. /// 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; use call_executor::state_to_execution_proof;
let result = self.executor.call(id, method, call_data); 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. /// Set up the native execution environment to call into a native runtime code.
pub fn using_environment_at<F: FnOnce() -> T, T>( pub fn using_environment_at<F: FnOnce() -> T, T>(
&self, &self,
id: &BlockId, id: &BlockId<Block>,
overlay: &mut OverlayedChanges, overlay: &mut OverlayedChanges,
f: F f: F
) -> error::Result<T> { ) -> 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. /// 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) block_builder::BlockBuilder::new(self)
} }
/// Create a new block, built on top of `parent`. /// 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) block_builder::BlockBuilder::at_block(parent, &self)
} }
/// Check a header's justification. /// Check a header's justification.
pub fn check_justification( pub fn check_justification(
&self, &self,
header: block::Header, header: <Block as BlockT>::Header,
justification: bft::UncheckedJustification, justification: ::bft::UncheckedJustification<Block::Hash>,
) -> error::Result<JustifiedHeader> { ) -> error::Result<JustifiedHeader<Block>> {
let authorities = self.authorities_at(&BlockId::Hash(header.parent_hash))?; let parent_hash = header.parent_hash().clone();
let just = bft::check_justification(&authorities[..], header.parent_hash, justification) let authorities = self.authorities_at(&BlockId::Hash(parent_hash))?;
.map_err(|_| error::ErrorKind::BadJustification(BlockId::Hash(header.blake2_256().into())))?; let just = ::bft::check_justification::<Block>(&authorities[..], parent_hash, justification)
.map_err(|_|
error::ErrorKind::BadJustification(
format!("{}", header.hash())
)
)?;
Ok(JustifiedHeader { Ok(JustifiedHeader {
header, header,
justification: just, justification: just,
@@ -284,16 +291,16 @@ impl<B, E> Client<B, E> where
pub fn import_block( pub fn import_block(
&self, &self,
origin: BlockOrigin, origin: BlockOrigin,
header: JustifiedHeader, header: JustifiedHeader<Block>,
body: Option<block::Body>, body: Option<Vec<<Block as BlockT>::Extrinsic>>,
) -> error::Result<ImportResult> { ) -> error::Result<ImportResult> {
let (header, justification) = header.into_inner(); 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::InChain => {},
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), 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(); let _import_lock = self.import_lock.lock();
*self.importing_block.write() = Some(hash); *self.importing_block.write() = Some(hash);
let result = self.execute_and_import_block(origin, hash, header, justification, body); 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( fn execute_and_import_block(
&self, &self,
origin: BlockOrigin, origin: BlockOrigin,
hash: HeaderHash, hash: Block::Hash,
header: block::Header, header: Block::Header,
justification: bft::Justification, justification: bft::Justification<Block::Hash>,
body: Option<block::Body>, body: Option<Vec<Block::Extrinsic>>,
) -> error::Result<ImportResult> { ) -> error::Result<ImportResult> {
let parent_hash = header.parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(hash))? { match self.backend.blockchain().status(BlockId::Hash(hash))? {
blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain), blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain),
blockchain::BlockStatus::Unknown => {}, 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()? { let storage_update = match transaction.state()? {
Some(transaction_state) => { Some(transaction_state) => {
let mut overlay = Default::default(); let mut overlay = Default::default();
@@ -322,7 +330,7 @@ impl<B, E> Client<B, E> where
transaction_state, transaction_state,
&mut overlay, &mut overlay,
"execute_block", "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) Some(storage_update)
@@ -330,15 +338,15 @@ impl<B, E> Client<B, E> where
None => None, None => None,
}; };
let is_new_best = header.number == self.backend.blockchain().info()?.best_number + 1; 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); 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)?; transaction.set_block_data(header.clone(), body, Some(justification.uncheck().into()), is_new_best)?;
if let Some(storage_update) = storage_update { if let Some(storage_update) = storage_update {
transaction.update_storage(storage_update)?; transaction.update_storage(storage_update)?;
} }
self.backend.commit_operation(transaction)?; self.backend.commit_operation(transaction)?;
if origin == BlockOrigin::NetworkBroadcast || origin == BlockOrigin::Own || origin == BlockOrigin::ConsensusBroadcast { if origin == BlockOrigin::NetworkBroadcast || origin == BlockOrigin::Own || origin == BlockOrigin::ConsensusBroadcast {
let notification = BlockImportNotification { let notification = BlockImportNotification::<Block> {
hash: hash, hash: hash,
origin: origin, origin: origin,
header: header, header: header,
@@ -351,7 +359,7 @@ impl<B, E> Client<B, E> where
} }
/// Get blockchain info. /// 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)))?; let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?;
Ok(ClientInfo { Ok(ClientInfo {
chain: info, chain: info,
@@ -361,7 +369,7 @@ impl<B, E> Client<B, E> where
} }
/// Get block status. /// 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 // TODO: more efficient implementation
if let BlockId::Hash(ref h) = id { if let BlockId::Hash(ref h) = id {
if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { 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. /// 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) self.backend.blockchain().hash(block_number)
} }
/// Convert an arbitrary block ID into a block hash. /// 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 { match *id {
BlockId::Hash(h) => Ok(Some(h)), BlockId::Hash(h) => Ok(Some(h)),
BlockId::Number(n) => self.block_hash(n), 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. /// 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 { 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)), BlockId::Number(n) => Ok(Some(n)),
} }
} }
/// Get block header by id. /// 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) self.backend.blockchain().header(*id)
} }
/// Get block body by 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) self.backend.blockchain().body(*id)
} }
/// Get block justification set by 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) self.backend.blockchain().justification(*id)
} }
/// Get best block header. /// 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)))?; 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")) 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 where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor, E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error> 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 { let justified_header = JustifiedHeader {
header: block.header, header: header,
justification, 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 where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor, E: CallExecutor<Block>,
error::Error: From<<B::State as state_machine::backend::Backend>::Error> Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error>,
{ {
fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, bft::Error> { fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, bft::Error> {
self.authorities_at(at).map_err(|_| bft::ErrorKind::StateUnavailable(*at).into()) 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 where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor, E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error> error::Error: From<<B::State as state_machine::backend::Backend>::Error>
{ {
/// Get block import event stream. /// 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(); let (sink, stream) = mpsc::unbounded();
self.import_notification_sinks.lock().push(sink); self.import_notification_sinks.lock().push(sink);
stream stream
} }
} }
impl<B, E> ChainHead for Client<B, E> impl<B, E, Block> ChainHead<Block> for Client<B, E, Block>
where where
B: backend::Backend, B: backend::Backend<Block>,
E: CallExecutor, E: CallExecutor<Block>,
Block: BlockT,
error::Error: From<<B::State as state_machine::backend::Backend>::Error> 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) Client::best_block_header(self)
} }
} }
@@ -474,20 +490,18 @@ mod tests {
use super::*; use super::*;
use codec::Slicable; use codec::Slicable;
use keyring::Keyring; use keyring::Keyring;
use primitives::block::Extrinsic as PrimitiveExtrinsic;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::client::BlockOrigin; use test_client::client::BlockOrigin;
use test_client::runtime as test_runtime; use test_client::runtime as test_runtime;
use test_client::runtime::{UncheckedTransaction, Transaction}; use test_client::runtime::{Transfer, Extrinsic};
#[test] #[test]
fn client_initialises_from_genesis_ok() { fn client_initialises_from_genesis_ok() {
let client = test_client::new(); let client = test_client::new();
let genesis_hash = client.block_hash(0).unwrap().unwrap(); 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().into())).unwrap(), 1000);
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().into())).unwrap(), 0);
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public())).unwrap(), 0);
} }
#[test] #[test]
@@ -511,17 +525,11 @@ mod tests {
client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
assert_eq!(client.info().unwrap().chain.best_number, 1); 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 sign_tx(tx: Transfer) -> Extrinsic {
fn signed(self) -> PrimitiveExtrinsic; let signature = Keyring::from_raw_public(tx.from.0.clone()).unwrap().sign(&tx.encode()).into();
} Extrinsic { transfer: tx, signature }
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()
}
} }
#[test] #[test]
@@ -530,18 +538,18 @@ mod tests {
let mut builder = client.new_block().unwrap(); let mut builder = client.new_block().unwrap();
builder.push(Transaction { builder.push(sign_tx(Transfer {
from: Keyring::Alice.to_raw_public(), from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Ferdie.to_raw_public(), to: Keyring::Ferdie.to_raw_public().into(),
amount: 42, amount: 42,
nonce: 0 nonce: 0,
}.signed()).unwrap(); })).unwrap();
client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
assert_eq!(client.info().unwrap().chain.best_number, 1); 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!(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::Alice.to_raw_public().into())).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::Ferdie.to_raw_public().into())).unwrap(), 42);
} }
} }
+6 -6
View File
@@ -29,9 +29,9 @@ error_chain! {
} }
/// Unknown block. /// Unknown block.
UnknownBlock(h: ::primitives::block::Id) { UnknownBlock(h: String) {
description("unknown block"), description("unknown block"),
display("UnknownBlock: {}", h), display("UnknownBlock: {}", &*h),
} }
/// Execution error. /// Execution error.
@@ -77,9 +77,9 @@ error_chain! {
} }
/// Bad justification for header. /// Bad justification for header.
BadJustification(h: ::primitives::block::Id) { BadJustification(h: String) {
description("bad justification for header"), description("bad justification for header"),
display("bad justification for header: {}", h), display("bad justification for header: {}", &*h),
} }
/// Not available on light client. /// 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 { impl From<state_machine::backend::Void> for Error {
fn from(_e: state_machine::backend::Void) -> Self { fn from(e: state_machine::backend::Void) -> Self {
unreachable!() match e {}
} }
} }
+48 -39
View File
@@ -17,54 +17,56 @@
//! Tool for creating the genesis block. //! Tool for creating the genesis block.
use std::collections::HashMap; use std::collections::HashMap;
use primitives::{Block, Header}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing as HashingT, Zero};
use triehash::trie_root;
/// Create a genesis block, given the initial storage. /// Create a genesis block, given the initial storage.
pub fn construct_genesis_block(storage: &HashMap<Vec<u8>, Vec<u8>>) -> Block { pub fn construct_genesis_block<
let state_root = trie_root(storage.clone().into_iter()).0.into(); Block: BlockT
let header = Header { > (
parent_hash: Default::default(), storage: &HashMap<Vec<u8>, Vec<u8>>
number: 0, ) -> Block {
state_root, let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashingT>::trie_root(storage.clone().into_iter());
extrinsics_root: trie_root(vec![].into_iter()).0.into(), let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashingT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>());
digest: Default::default(), Block::new(
}; <<Block as BlockT>::Header as HeaderT>::new(
Block { Zero::zero(),
header, extrinsics_root,
transactions: vec![], state_root,
} Default::default(),
Default::default()
),
Default::default()
)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use codec::{Slicable, Joiner}; use codec::{Slicable, Joiner};
use runtime_support::Hashable;
use keyring::Keyring; use keyring::Keyring;
use executor::WasmExecutor; use executor::WasmExecutor;
use state_machine::{execute, OverlayedChanges}; use state_machine::{execute, OverlayedChanges};
use state_machine::backend::InMemory; use state_machine::backend::InMemory;
use test_client; use test_client;
use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
use test_client::runtime::{Hash, Block, BlockNumber, Header, Digest, Transaction, use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic};
UncheckedTransaction};
use ed25519::{Public, Pair}; 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")); 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; use triehash::ordered_trie_root;
let transactions = txs.into_iter().map(|tx| { let transactions = txs.into_iter().map(|tx| {
let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from)).unwrap()) let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from.0)).unwrap())
.sign(&tx.encode()); .sign(&tx.encode()).into();
UncheckedTransaction { tx, signature } Extrinsic { transfer: tx, signature }
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
let extrinsics_root = ordered_trie_root(transactions.iter().map(Slicable::encode)).0.into(); let extrinsics_root = ordered_trie_root(transactions.iter().map(Slicable::encode)).0.into();
println!("root before: {:?}", extrinsics_root);
let mut header = Header { let mut header = Header {
parent_hash, parent_hash,
number, number,
@@ -72,19 +74,25 @@ mod tests {
extrinsics_root, extrinsics_root,
digest: Digest { logs: vec![], }, digest: Digest { logs: vec![], },
}; };
let hash = header.blake2_256(); let hash = header.hash();
let mut overlay = OverlayedChanges::default(); let mut overlay = OverlayedChanges::default();
execute(
backend,
&mut overlay,
&Executor::new(),
"initialise_block",
&header.encode(),
).unwrap();
for tx in transactions.iter() { for tx in transactions.iter() {
let (ret_data, _) = execute( execute(
backend, backend,
&mut overlay, &mut overlay,
&Executor::new(), &Executor::new(),
"execute_transaction", "apply_extrinsic",
&vec![].and(&header).and(tx) &tx.encode(),
).unwrap(); ).unwrap();
header = Header::decode(&mut &ret_data[..]).unwrap();
} }
let (ret_data, _) = execute( let (ret_data, _) = execute(
@@ -92,11 +100,12 @@ mod tests {
&mut overlay, &mut overlay,
&Executor::new(), &Executor::new(),
"finalise_block", "finalise_block",
&vec![].and(&header) &[]
).unwrap(); ).unwrap();
header = Header::decode(&mut &ret_data[..]).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) { fn block1(genesis_hash: Hash, backend: &InMemory) -> (Vec<u8>, Hash) {
@@ -105,9 +114,9 @@ mod tests {
1, 1,
genesis_hash, genesis_hash,
hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(),
vec![Transaction { vec![Transfer {
from: Keyring::One.to_raw_public(), from: Keyring::One.to_raw_public().into(),
to: Keyring::Two.to_raw_public(), to: Keyring::Two.to_raw_public().into(),
amount: 69, amount: 69,
nonce: 0, nonce: 0,
}] }]
@@ -119,8 +128,8 @@ mod tests {
let mut storage = GenesisConfig::new_simple( let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000 vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
).genesis_map(); ).genesis_map();
let block = construct_genesis_block(&storage); let block = construct_genesis_block::<Block>(&storage);
let genesis_hash = block.header.blake2_256().into(); let genesis_hash = block.header.hash();
storage.extend(additional_storage_with_genesis(&block).into_iter()); storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage); let backend = InMemory::from(storage);
@@ -141,8 +150,8 @@ mod tests {
let mut storage = GenesisConfig::new_simple( let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000 vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
).genesis_map(); ).genesis_map();
let block = construct_genesis_block(&storage); let block = construct_genesis_block::<Block>(&storage);
let genesis_hash = block.header.blake2_256().into(); let genesis_hash = block.header.hash();
storage.extend(additional_storage_with_genesis(&block).into_iter()); storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage); let backend = InMemory::from(storage);
@@ -164,8 +173,8 @@ mod tests {
let mut storage = GenesisConfig::new_simple( let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 68 vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 68
).genesis_map(); ).genesis_map();
let block = construct_genesis_block(&storage); let block = construct_genesis_block::<Block>(&storage);
let genesis_hash = block.header.blake2_256().into(); let genesis_hash = block.header.hash();
storage.extend(additional_storage_with_genesis(&block).into_iter()); storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage); let backend = InMemory::from(storage);
+144 -86
View File
@@ -20,95 +20,136 @@ use std::collections::HashMap;
use parking_lot::RwLock; use parking_lot::RwLock;
use error; use error;
use backend; use backend;
use runtime_support::Hashable; use runtime_primitives::generic::BlockId;
use primitives; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero};
use primitives::block::{self, Id as BlockId, HeaderHash}; use runtime_primitives::bft::Justification;
use blockchain::{self, BlockStatus}; use blockchain::{self, BlockStatus};
use state_machine::backend::{Backend as StateBackend, InMemory}; use state_machine::backend::{Backend as StateBackend, InMemory};
struct PendingBlock { struct PendingBlock<B: BlockT> {
block: Block, block: StoredBlock<B>,
is_best: bool, is_best: bool,
} }
#[derive(PartialEq, Eq, Clone)] #[derive(PartialEq, Eq, Clone)]
struct Block { enum StoredBlock<B: BlockT> {
header: block::Header, Header(B::Header, Option<Justification<B::Hash>>),
justification: Option<primitives::bft::Justification>, Full(B, Option<Justification<B::Hash>>),
body: Option<block::Body>, }
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)] #[derive(Clone)]
struct BlockchainStorage { struct BlockchainStorage<Block: BlockT> {
blocks: HashMap<HeaderHash, Block>, blocks: HashMap<Block::Hash, StoredBlock<Block>>,
hashes: HashMap<block::Number, HeaderHash>, hashes: HashMap<<<Block as BlockT>::Header as HeaderT>::Number, Block::Hash>,
best_hash: HeaderHash, best_hash: Block::Hash,
best_number: block::Number, best_number: <<Block as BlockT>::Header as HeaderT>::Number,
genesis_hash: HeaderHash, genesis_hash: Block::Hash,
} }
/// In-memory blockchain. Supports concurrent reads. /// In-memory blockchain. Supports concurrent reads.
pub struct Blockchain { pub struct Blockchain<Block: BlockT> {
storage: RwLock<BlockchainStorage>, storage: RwLock<BlockchainStorage<Block>>,
} }
impl Clone for Blockchain { impl<Block: BlockT + Clone> Clone for Blockchain<Block> {
fn clone(&self) -> Blockchain { fn clone(&self) -> Self {
Blockchain { Blockchain {
storage: RwLock::new(self.storage.read().clone()), storage: RwLock::new(self.storage.read().clone()),
} }
} }
} }
impl Blockchain { impl<Block: BlockT> Blockchain<Block> {
/// 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(),
})
}
}
/// Get header hash of given 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 { match id {
BlockId::Hash(h) => Some(h), BlockId::Hash(h) => Some(h),
BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(), BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(),
} }
} }
/// Insert block. /// Create new in-memory blockchain storage.
pub fn insert(&self, hash: HeaderHash, header: block::Header, justification: Option<primitives::bft::Justification>, body: Option<block::Body>, is_new_best: bool) { pub fn new() -> Self {
let number = header.number; Blockchain {
let mut storage = self.storage.write(); storage: RwLock::new(
storage.blocks.insert(hash, Block { BlockchainStorage {
header: header, blocks: HashMap::new(),
body: body, hashes: HashMap::new(),
justification: justification, best_hash: Default::default(),
}); best_number: Zero::zero(),
storage.hashes.insert(number, hash); genesis_hash: Default::default(),
if is_new_best { })
storage.best_hash = hash;
storage.best_number = number;
} }
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; storage.genesis_hash = hash;
} }
} }
/// Compare this blockchain with another in-mem blockchain /// 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 self.canon_equals_to(other) && self.storage.read().blocks == other.storage.read().blocks
} }
/// Compare canonical chain to other canonical chain. /// 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 this = self.storage.read();
let other = other.storage.read(); let other = other.storage.read();
this.hashes == other.hashes this.hashes == other.hashes
@@ -118,20 +159,27 @@ impl Blockchain {
} }
} }
impl blockchain::Backend for Blockchain { impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> { 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()))) 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>> { 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.body.clone()))) 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>> { 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.clone()))) 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(); let storage = self.storage.read();
Ok(blockchain::Info { Ok(blockchain::Info {
best_hash: storage.best_hash, 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)) { match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) {
true => Ok(BlockStatus::InChain), true => Ok(BlockStatus::InChain),
false => Ok(BlockStatus::Unknown), 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))) Ok(self.id(BlockId::Number(number)))
} }
} }
/// In-memory operation. /// In-memory operation.
pub struct BlockImportOperation { pub struct BlockImportOperation<Block: BlockT> {
pending_block: Option<PendingBlock>, pending_block: Option<PendingBlock<Block>>,
old_state: InMemory, old_state: InMemory,
new_state: Option<InMemory>, new_state: Option<InMemory>,
} }
impl backend::BlockImportOperation for BlockImportOperation { impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperation<Block> {
type State = InMemory; type State = InMemory;
fn state(&self) -> error::Result<Option<&Self::State>> { fn state(&self) -> error::Result<Option<&Self::State>> {
Ok(Some(&self.old_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"); assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
self.pending_block = Some(PendingBlock { self.pending_block = Some(PendingBlock {
block: Block { block: StoredBlock::new(header, body, justification),
header: header,
body: body,
justification: justification,
},
is_best: is_new_best, is_best: is_new_best,
}); });
Ok(()) Ok(())
@@ -191,14 +241,18 @@ impl backend::BlockImportOperation for BlockImportOperation {
} }
/// In-memory backend. Keeps all states and blocks in memory. Useful for testing. /// In-memory backend. Keeps all states and blocks in memory. Useful for testing.
pub struct Backend { pub struct Backend<Block> where
states: RwLock<HashMap<block::HeaderHash, InMemory>>, Block: BlockT,
blockchain: Blockchain, {
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. /// Create a new instance of in-mem backend.
pub fn new() -> Backend { pub fn new() -> Backend<Block> {
Backend { Backend {
states: RwLock::new(HashMap::new()), states: RwLock::new(HashMap::new()),
blockchain: Blockchain::new(), blockchain: Blockchain::new(),
@@ -206,14 +260,16 @@ impl Backend {
} }
} }
impl backend::Backend for Backend { impl<Block> backend::Backend<Block> for Backend<Block> where
type BlockImportOperation = BlockImportOperation; Block: BlockT,
type Blockchain = Blockchain; {
type BlockImportOperation = BlockImportOperation<Block>;
type Blockchain = Blockchain<Block>;
type State = InMemory; 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 { 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)?, _ => self.state_at(block)?,
}; };
@@ -226,24 +282,26 @@ impl backend::Backend for Backend {
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> { fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
if let Some(pending_block) = operation.pending_block { if let Some(pending_block) = operation.pending_block {
let hash = pending_block.block.header.blake2_256().into();
let old_state = &operation.old_state; 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.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(()) Ok(())
} }
fn blockchain(&self) -> &Blockchain { fn blockchain(&self) -> &Self::Blockchain {
&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()) { match self.blockchain.id(block).and_then(|id| self.states.read().get(&id).cloned()) {
Some(state) => Ok(state), 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_primitives as primitives;
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_state_machine as state_machine; extern crate substrate_state_machine as state_machine;
#[cfg(test)] extern crate substrate_keyring as keyring; #[cfg(test)] extern crate substrate_keyring as keyring;
#[cfg(test)] extern crate substrate_test_client as test_client; #[cfg(test)] extern crate substrate_test_client as test_client;
+60 -56
View File
@@ -19,11 +19,11 @@
use std::sync::Arc; use std::sync::Arc;
use futures::future::IntoFuture; 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::CodeExecutor;
use state_machine::backend::Backend as StateBackend; 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 blockchain::{self, BlockStatus};
use backend; use backend;
use call_executor::{CallResult, RemoteCallExecutor, check_execution_proof}; use call_executor::{CallResult, RemoteCallExecutor, check_execution_proof};
@@ -32,9 +32,9 @@ use error;
use in_mem::Blockchain as InMemBlockchain; use in_mem::Blockchain as InMemBlockchain;
/// Remote call request. /// Remote call request.
pub struct RemoteCallRequest { pub struct RemoteCallRequest<H> {
/// Call at state of given block. /// Call at state of block referenced by given header hash.
pub block: HeaderHash, pub block: H,
/// Method to call. /// Method to call.
pub method: String, pub method: String,
/// Call data. /// Call data.
@@ -43,62 +43,62 @@ pub struct RemoteCallRequest {
/// Light client data fetcher. Implementations of this trait must check if remote data /// Light client data fetcher. Implementations of this trait must check if remote data
/// is correct (see FetchedDataChecker) and return already checked 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. /// Remote call result future.
type RemoteCallResult: IntoFuture<Item=CallResult, Error=error::Error>; type RemoteCallResult: IntoFuture<Item=CallResult, Error=error::Error>;
/// Fetch remote call result. /// 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. /// Light client remote data checker.
pub trait FetchChecker: Send + Sync { pub trait FetchChecker<B: BlockT>: Send + Sync {
/// Check remote method execution proof. /// 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. /// Light client backend.
pub struct Backend { pub struct Backend<B: BlockT> {
blockchain: Blockchain, blockchain: Blockchain<B>,
} }
/// Light client blockchain. /// Light client blockchain.
pub struct Blockchain { pub struct Blockchain<B: BlockT> {
storage: InMemBlockchain, storage: InMemBlockchain<B>,
} }
/// Block (header and justification) import operation. /// Block (header and justification) import operation.
pub struct BlockImportOperation { pub struct BlockImportOperation<B: BlockT> {
pending_block: Option<PendingBlock>, pending_block: Option<PendingBlock<B>>,
} }
/// On-demand state. /// On-demand state.
#[derive(Clone)] #[derive(Clone)]
pub struct OnDemandState { pub struct OnDemandState<H> {
/// Hash of the block, state is valid for. /// Hash of the block, state is valid for.
_block: HeaderHash, _block: H,
} }
/// Remote data checker. /// Remote data checker.
pub struct LightDataChecker<E> { pub struct LightDataChecker<E, B: BlockT> {
/// Backend reference. /// Backend reference.
backend: Arc<Backend>, backend: Arc<Backend<B>>,
/// Executor. /// Executor.
executor: E, executor: E,
} }
struct PendingBlock { struct PendingBlock<B: BlockT> {
header: block::Header, header: B::Header,
justification: Option<primitives::bft::Justification>, justification: Option<Justification<B::Hash>>,
is_best: bool, is_best: bool,
} }
impl backend::Backend for Backend { impl<B: BlockT> backend::Backend<B> for Backend<B> {
type BlockImportOperation = BlockImportOperation; type BlockImportOperation = BlockImportOperation<B>;
type Blockchain = Blockchain; type Blockchain = Blockchain<B>;
type State = OnDemandState; 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 { Ok(BlockImportOperation {
pending_block: None, pending_block: None,
}) })
@@ -106,34 +106,34 @@ impl backend::Backend for Backend {
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> { fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
if let Some(pending_block) = operation.pending_block { 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); self.blockchain.storage.insert(hash, pending_block.header, pending_block.justification, None, pending_block.is_best);
} }
Ok(()) Ok(())
} }
fn blockchain(&self) -> &Blockchain { fn blockchain(&self) -> &Blockchain<B> {
&self.blockchain &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 { 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 { impl<B: BlockT> backend::BlockImportOperation<B> for BlockImportOperation<B> {
type State = OnDemandState; type State = OnDemandState<B::Hash>;
fn state(&self) -> error::Result<Option<&Self::State>> { fn state(&self) -> error::Result<Option<&Self::State>> {
// None means 'locally-stateless' backend // None means 'locally-stateless' backend
Ok(None) 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"); assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
self.pending_block = Some(PendingBlock { self.pending_block = Some(PendingBlock {
header, header,
@@ -154,34 +154,34 @@ impl backend::BlockImportOperation for BlockImportOperation {
} }
} }
impl blockchain::Backend for Blockchain { impl<B: BlockT> blockchain::Backend<B> for Blockchain<B> {
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> { fn header(&self, id: BlockId<B>) -> error::Result<Option<B::Header>> {
self.storage.header(id) 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 // TODO [light]: fetch from remote node
Ok(None) 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) self.storage.justification(id)
} }
fn info(&self) -> error::Result<blockchain::Info> { fn info(&self) -> error::Result<blockchain::Info<B>> {
self.storage.info() self.storage.info()
} }
fn status(&self, id: BlockId) -> error::Result<BlockStatus> { fn status(&self, id: BlockId<B>) -> error::Result<BlockStatus> {
self.storage.status(id) 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) self.storage.hash(number)
} }
} }
impl StateBackend for OnDemandState { impl<H: Clone> StateBackend for OnDemandState<H> {
type Error = error::Error; type Error = error::Error;
type Transaction = (); type Transaction = ();
@@ -191,7 +191,8 @@ impl StateBackend for OnDemandState {
} }
fn storage_root<I>(&self, _delta: I) -> ([u8; 32], Self::Transaction) 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], ()) ([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 where
E: CodeExecutor, 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) check_execution_proof(&*self.backend, &self.executor, request, remote_proof)
} }
} }
/// Create an instance of light client backend. /// 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 storage = InMemBlockchain::new();
let blockchain = Blockchain { storage }; let blockchain = Blockchain { storage };
Arc::new(Backend { blockchain }) Arc::new(Backend { blockchain })
} }
/// Create an instance of light client. /// Create an instance of light client.
pub fn new_light<F, B>( pub fn new_light<F, B, Block>(
backend: Arc<Backend>, backend: Arc<Backend<Block>>,
fetcher: Arc<F>, fetcher: Arc<F>,
genesis_builder: B, genesis_builder: B,
) -> error::Result<Client<Backend, RemoteCallExecutor<Backend, F>>> ) -> error::Result<Client<Backend<Block>, RemoteCallExecutor<Backend<Block>, F>, Block>>
where where
F: Fetcher, F: Fetcher<Block>,
B: GenesisBuilder, B: GenesisBuilder<Block>,
Block: BlockT,
{ {
let executor = RemoteCallExecutor::new(backend.clone(), fetcher); let executor = RemoteCallExecutor::new(backend.clone(), fetcher);
Client::new(backend, executor, genesis_builder) Client::new(backend, executor, genesis_builder)
} }
/// Create an instance of fetch data checker. /// Create an instance of fetch data checker.
pub fn new_fetch_checker<E>( pub fn new_fetch_checker<E, Block>(
backend: Arc<Backend>, backend: Arc<Backend<Block>>,
executor: E, executor: E,
) -> LightDataChecker<E> ) -> LightDataChecker<E, Block>
where where
E: CodeExecutor, E: CodeExecutor,
Block: BlockT,
{ {
LightDataChecker { backend, executor } LightDataChecker { backend, executor }
} }
@@ -8,5 +8,4 @@ error-chain = "0.11"
futures = "0.1" futures = "0.1"
log = "0.3" log = "0.3"
parking_lot = "0.4" parking_lot = "0.4"
substrate-primitives = { path = "../primitives" }
transaction-pool = "1.12" transaction-pool = "1.12"
+8 -10
View File
@@ -16,12 +16,9 @@
//! External API for extrinsic pool. //! External API for extrinsic pool.
use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use txpool::{self, VerifiedTransaction}; use txpool::{self, VerifiedTransaction};
use primitives::{
Hash,
block::{Extrinsic, ExtrinsicHash},
};
/// Extrinsic pool error. /// Extrinsic pool error.
pub trait Error: ::std::error::Error + Send + Sized { pub trait Error: ::std::error::Error + Send + Sized {
@@ -38,18 +35,19 @@ impl Error for txpool::Error {
} }
/// Extrinsic pool. /// Extrinsic pool.
pub trait ExtrinsicPool: Send + Sync + 'static { pub trait ExtrinsicPool<Ex, Hash>: Send + Sync + 'static {
/// Error type /// Error type
type Error: Error; type Error: Error;
/// Submit a collection of extrinsics to the pool. /// 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. // Blanket implementation for anything that `Derefs` to the pool.
impl<V, S, E, T> ExtrinsicPool for T where impl<Ex, Hash, V, S, E, T> ExtrinsicPool<Ex, Hash> for T where
T: Deref<Target=super::Pool<V, S, E>> + Send + Sync + 'static, Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
V: txpool::Verifier<Extrinsic>, T: Deref<Target=super::Pool<Ex, Hash, V, S, E>> + Send + Sync + 'static,
V: txpool::Verifier<Ex>,
S: txpool::Scoring<V::VerifiedTransaction>, S: txpool::Scoring<V::VerifiedTransaction>,
V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>, V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>,
E: From<V::Error>, E: From<V::Error>,
@@ -58,7 +56,7 @@ impl<V, S, E, T> ExtrinsicPool for T where
{ {
type Error = E; 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()) self.deref().submit(xt).map(|result| result.into_iter().map(|xt| *xt.hash()).collect())
} }
} }
@@ -20,7 +20,6 @@
extern crate futures; extern crate futures;
extern crate parking_lot; extern crate parking_lot;
extern crate substrate_primitives as primitives;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
@@ -16,29 +16,29 @@
use std::{ use std::{
sync::Arc, sync::Arc,
fmt,
collections::HashMap, collections::HashMap,
}; };
use primitives::Hash;
use txpool; use txpool;
use watcher; use watcher;
#[derive(Default)] #[derive(Default)]
pub struct Listener { pub struct Listener<H: ::std::hash::Hash + Eq> {
watchers: HashMap<Hash, watcher::Sender> watchers: HashMap<H, watcher::Sender<H>>
} }
impl Listener { impl<H: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default> Listener<H> {
pub fn create_watcher<T: txpool::VerifiedTransaction<Hash=Hash>>(&mut self, xt: Arc<T>) -> watcher::Watcher { 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); let sender = self.watchers.entry(*xt.hash()).or_insert_with(watcher::Sender::default);
sender.new_watcher() 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)); 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) { let clean = if let Some(h) = self.watchers.get_mut(hash) {
fun(h); fun(h);
h.is_done() 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>>) { fn added(&mut self, tx: &Arc<T>, old: Option<&Arc<T>>) {
if let Some(old) = old { if let Some(old) = old {
let hash = tx.hash(); 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>) { fn mined(&mut self, tx: &Arc<T>) {
// TODO [ToDr] latest block number? // TODO [ToDr] latest block number?
let header_hash = 1.into(); let header_hash = Default::default();
self.fire(tx.hash(), |watcher| watcher.finalised(header_hash)) self.fire(tx.hash(), |watcher| watcher.finalised(header_hash))
} }
} }
+11 -9
View File
@@ -16,6 +16,7 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt,
marker::PhantomData, marker::PhantomData,
sync::{Arc, Weak}, sync::{Arc, Weak},
}; };
@@ -23,28 +24,29 @@ use std::{
use futures::sync::mpsc; use futures::sync::mpsc;
use parking_lot::{RwLock, Mutex}; use parking_lot::{RwLock, Mutex};
use txpool; use txpool;
use primitives::{Hash, block::Extrinsic};
use listener::Listener; use listener::Listener;
use watcher::Watcher; use watcher::Watcher;
/// Extrinsics pool. /// Extrinsics pool.
pub struct Pool<V, S, E> where pub struct Pool<Ex, Hash, V, S, E> where
V: txpool::Verifier<Extrinsic>, Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex,
V: txpool::Verifier<Ex>,
S: txpool::Scoring<V::VerifiedTransaction>, S: txpool::Scoring<V::VerifiedTransaction>,
{ {
_error: Mutex<PhantomData<E>>, _error: Mutex<PhantomData<E>>,
pool: RwLock<txpool::Pool< pool: RwLock<txpool::Pool<
V::VerifiedTransaction, V::VerifiedTransaction,
S, S,
Listener, Listener<Hash>,
>>, >>,
verifier: V, verifier: V,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<Weak<V::VerifiedTransaction>>>>, import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<Weak<V::VerifiedTransaction>>>>,
} }
impl<V, S, E> Pool<V, S, E> where impl<Ex, Hash, V, S, E> Pool<Ex, Hash, V, S, E> where
V: txpool::Verifier<Extrinsic>, Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
V: txpool::Verifier<Ex>,
S: txpool::Scoring<V::VerifiedTransaction>, S: txpool::Scoring<V::VerifiedTransaction>,
V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>, V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>,
E: From<V::Error>, 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 /// 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 xts
.into_iter() .into_iter()
.map(|xt| self.verifier.verify_transaction(xt)) .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. /// 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"); let xt = self.submit(vec![xt])?.pop().expect("One extrinsic passed; one result returned; qed");
Ok(self.pool.write().listener_mut().create_watcher(xt)) 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. /// 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 pub fn cull_and_get_pending<R, F, T>(&self, ready: R, f: F) -> T where
R: txpool::Ready<V::VerifiedTransaction> + Clone, 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(); let mut pool = self.pool.write();
pool.cull(None, ready.clone()); pool.cull(None, ready.clone());
@@ -15,17 +15,14 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>. // along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use futures::sync::mpsc; use futures::sync::mpsc;
use primitives::{
block::{HeaderHash, ExtrinsicHash}
};
/// Possible extrinsic status events /// Possible extrinsic status events
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Status { pub enum Status<H> {
/// Extrinsic has been finalised in block with given hash. /// 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. /// 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. /// The extrinsic has been broadcast to the given peers.
Broadcast(Vec<String>), Broadcast(Vec<String>),
/// Extrinsic has been dropped from the pool because of the limit. /// 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. /// Represents a stream of status updates for particular extrinsic.
#[derive(Debug)] #[derive(Debug)]
pub struct Watcher { pub struct Watcher<H> {
receiver: mpsc::UnboundedReceiver<Status>, receiver: mpsc::UnboundedReceiver<Status<H>>,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct Sender { pub(crate) struct Sender<H> {
receivers: Vec<mpsc::UnboundedSender<Status>>, receivers: Vec<mpsc::UnboundedSender<Status<H>>>,
finalised: bool, finalised: bool,
} }
impl Sender { impl<H: Clone> Sender<H> {
/// Add a new watcher to this sender object. /// 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(); let (tx, receiver) = mpsc::unbounded();
self.receivers.push(tx); self.receivers.push(tx);
Watcher { Watcher {
@@ -57,12 +54,12 @@ impl Sender {
} }
/// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. /// 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)) self.send(Status::Usurped(hash))
} }
/// Extrinsic has been finalised in block with given 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.send(Status::Finalised(hash));
self.finalised = true; self.finalised = true;
} }
@@ -82,7 +79,7 @@ impl Sender {
self.finalised || self.receivers.is_empty() 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()) self.receivers.retain(|sender| sender.unbounded_send(status.clone()).is_ok())
} }
} }
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
substrate-codec = { path = "../codec", default-features = false } substrate-codec = { path = "../codec", default-features = false }
substrate-primitives = { path = "../primitives", 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 } substrate-runtime-io = { path = "../runtime-io", default-features = false }
[dev-dependencies] [dev-dependencies]
@@ -14,4 +15,4 @@ substrate-keyring = { path = "../keyring" }
[features] [features]
default = ["std"] 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_codec as codec;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_primitives as runtime_primitives;
#[cfg(test)] #[cfg(test)]
extern crate substrate_bft; extern crate substrate_bft;
@@ -29,23 +30,27 @@ extern crate substrate_keyring as keyring;
use codec::Slicable; use codec::Slicable;
use primitives::{AuthorityId, Signature}; 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. // check a message signature. returns true if signed by that authority.
fn check_message_sig(message: Message, signature: &Signature, from: &AuthorityId) -> bool { fn check_message_sig<B: Slicable, H: Slicable>(
let msg = message.encode(); message: Message<B, H>,
signature: &Signature,
from: &AuthorityId
) -> bool {
let msg: Vec<u8> = message.encode();
runtime_io::ed25519_verify(&signature.0, &msg, from) 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 { Message {
parent, parent,
action: Action::Prepare(round_number, hash), 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 { Message {
parent, parent,
action: Action::Commit(round_number, hash), 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 /// Doesn't check that the header hash in question is
/// valid or whether the misbehaving authority was part of /// valid or whether the misbehaving authority was part of
/// the set at that block. /// the set at that block.
pub fn evaluate_misbehavior( pub fn evaluate_misbehavior<B: Slicable, H: Slicable + Copy>(
misbehaved: &AuthorityId, misbehaved: &AuthorityId,
parent_hash: HeaderHash, parent_hash: H,
kind: &MisbehaviorKind, kind: &MisbehaviorKind<H>,
) -> bool { ) -> bool {
match *kind { match *kind {
MisbehaviorKind::BftDoublePrepare(round, (h_1, ref s_1), (h_2, ref s_2)) => { MisbehaviorKind::BftDoublePrepare(round, (h_1, ref s_1), (h_2, ref s_2)) => {
s_1 != s_2 && s_1 != s_2 &&
check_message_sig(prepare(parent_hash, round, h_1), s_1, misbehaved) && check_message_sig::<B, H>(prepare::<B, H>(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_2), s_2, misbehaved)
} }
MisbehaviorKind::BftDoubleCommit(round, (h_1, ref s_1), (h_2, ref s_2)) => { MisbehaviorKind::BftDoubleCommit(round, (h_1, ref s_1), (h_2, ref s_2)) => {
s_1 != s_2 && s_1 != s_2 &&
check_message_sig(commit(parent_hash, round, h_1), s_1, misbehaved) && check_message_sig::<B, H>(commit::<B, H>(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_2), s_2, misbehaved)
} }
} }
} }
@@ -84,8 +89,12 @@ mod tests {
use keyring::ed25519; use keyring::ed25519;
use keyring::Keyring; use keyring::Keyring;
fn sign_prepare(key: &ed25519::Pair, round: u32, hash: HeaderHash, parent_hash: HeaderHash) -> (HeaderHash, Signature) { use runtime_primitives::testing::{H256, Block as RawBlock};
let msg = substrate_bft::sign_message(
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)), generic::Message::Vote(generic::Vote::Prepare(round as _, hash)),
key, key,
parent_hash parent_hash
@@ -97,8 +106,8 @@ mod tests {
} }
} }
fn sign_commit(key: &ed25519::Pair, round: u32, hash: HeaderHash, parent_hash: HeaderHash) -> (HeaderHash, Signature) { fn sign_commit(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
let msg = substrate_bft::sign_message( let msg = substrate_bft::sign_message::<Block>(
generic::Message::Vote(generic::Vote::Commit(round as _, hash)), generic::Message::Vote(generic::Vote::Commit(round as _, hash)),
key, key,
parent_hash parent_hash
@@ -117,7 +126,7 @@ mod tests {
let hash_1 = [0; 32].into(); let hash_1 = [0; 32].into();
let hash_2 = [1; 32].into(); let hash_2 = [1; 32].into();
assert!(evaluate_misbehavior( assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0, &key.public().0,
parent_hash, parent_hash,
&MisbehaviorKind::BftDoublePrepare( &MisbehaviorKind::BftDoublePrepare(
@@ -129,7 +138,7 @@ mod tests {
// same signature twice is not misbehavior. // same signature twice is not misbehavior.
let signed = sign_prepare(&key, 1, hash_1, parent_hash); let signed = sign_prepare(&key, 1, hash_1, parent_hash);
assert!(evaluate_misbehavior( assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0, &key.public().0,
parent_hash, parent_hash,
&MisbehaviorKind::BftDoublePrepare( &MisbehaviorKind::BftDoublePrepare(
@@ -140,7 +149,7 @@ mod tests {
) == false); ) == false);
// misbehavior has wrong target. // misbehavior has wrong target.
assert!(evaluate_misbehavior( assert!(evaluate_misbehavior::<Block, H256>(
&Keyring::Two.to_raw_public(), &Keyring::Two.to_raw_public(),
parent_hash, parent_hash,
&MisbehaviorKind::BftDoublePrepare( &MisbehaviorKind::BftDoublePrepare(
@@ -158,7 +167,7 @@ mod tests {
let hash_1 = [0; 32].into(); let hash_1 = [0; 32].into();
let hash_2 = [1; 32].into(); let hash_2 = [1; 32].into();
assert!(evaluate_misbehavior( assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0, &key.public().0,
parent_hash, parent_hash,
&MisbehaviorKind::BftDoubleCommit( &MisbehaviorKind::BftDoubleCommit(
@@ -170,7 +179,7 @@ mod tests {
// same signature twice is not misbehavior. // same signature twice is not misbehavior.
let signed = sign_commit(&key, 1, hash_1, parent_hash); let signed = sign_commit(&key, 1, hash_1, parent_hash);
assert!(evaluate_misbehavior( assert!(evaluate_misbehavior::<Block, H256>(
&key.public().0, &key.public().0,
parent_hash, parent_hash,
&MisbehaviorKind::BftDoubleCommit( &MisbehaviorKind::BftDoubleCommit(
@@ -181,7 +190,7 @@ mod tests {
) == false); ) == false);
// misbehavior has wrong target. // misbehavior has wrong target.
assert!(evaluate_misbehavior( assert!(evaluate_misbehavior::<Block, H256>(
&Keyring::Two.to_raw_public(), &Keyring::Two.to_raw_public(),
parent_hash, parent_hash,
&MisbehaviorKind::BftDoubleCommit( &MisbehaviorKind::BftDoubleCommit(
+1
View File
@@ -27,6 +27,7 @@ substrate-client = { path = "../../substrate/client" }
substrate-state-machine = { path = "../../substrate/state-machine" } substrate-state-machine = { path = "../../substrate/state-machine" }
substrate-serializer = { path = "../../substrate/serializer" } substrate-serializer = { path = "../../substrate/serializer" }
substrate-runtime-support = { path = "../../substrate/runtime-support" } substrate-runtime-support = { path = "../../substrate/runtime-support" }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
substrate-bft = { path = "../../substrate/bft" } substrate-bft = { path = "../../substrate/bft" }
[dev-dependencies] [dev-dependencies]
+28 -25
View File
@@ -20,47 +20,47 @@ use std::ops::Range;
use std::collections::{HashMap, BTreeMap}; use std::collections::{HashMap, BTreeMap};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use network::PeerId; use network::PeerId;
use primitives::block::Number as BlockNumber; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use message; use message;
const MAX_PARALLEL_DOWNLOADS: u32 = 1; const MAX_PARALLEL_DOWNLOADS: u32 = 1;
/// Block data with origin. /// Block data with origin.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlockData { pub struct BlockData<B: BlockT> {
pub block: message::BlockData, pub block: message::BlockData<B>,
pub origin: PeerId, pub origin: PeerId,
} }
#[derive(Debug)] #[derive(Debug)]
enum BlockRangeState { enum BlockRangeState<B: BlockT> {
Downloading { Downloading {
len: BlockNumber, len: u64,
downloading: u32, downloading: u32,
}, },
Complete(Vec<BlockData>), Complete(Vec<BlockData<B>>),
} }
impl BlockRangeState { impl<B: BlockT> BlockRangeState<B> where B::Header: HeaderT<Number=u64> {
pub fn len(&self) -> BlockNumber { pub fn len(&self) -> u64 {
match *self { match *self {
BlockRangeState::Downloading { len, .. } => len, 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. /// A collection of blocks being downloaded.
#[derive(Default)] #[derive(Default)]
pub struct BlockCollection { pub struct BlockCollection<B: BlockT> {
/// Downloaded blocks. /// Downloaded blocks.
blocks: BTreeMap<BlockNumber, BlockRangeState>, blocks: BTreeMap<u64, BlockRangeState<B>>,
peer_requests: HashMap<PeerId, BlockNumber>, peer_requests: HashMap<PeerId, u64>,
} }
impl BlockCollection { impl<B: BlockT> BlockCollection<B> where B::Header: HeaderT<Number=u64> {
/// Create a new instance. /// Create a new instance.
pub fn new() -> BlockCollection { pub fn new() -> Self {
BlockCollection { BlockCollection {
blocks: BTreeMap::new(), blocks: BTreeMap::new(),
peer_requests: HashMap::new(), peer_requests: HashMap::new(),
@@ -74,7 +74,7 @@ impl BlockCollection {
} }
/// Insert a set of blocks into collection. /// 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() { if blocks.is_empty() {
return; 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. /// 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 // First block number that we need to download
let first_different = common + 1; let first_different = common + 1;
let count = count as BlockNumber; let count = count as u64;
let (mut range, downloading) = { let (mut range, downloading) = {
let mut downloading_iter = self.blocks.iter().peekable(); let mut downloading_iter = self.blocks.iter().peekable();
let mut prev: Option<(&BlockNumber, &BlockRangeState)> = None; let mut prev: Option<(&u64, &BlockRangeState<B>)> = None;
loop { loop {
let next = downloading_iter.next(); let next = downloading_iter.next();
break match &(prev, 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. /// 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 drained = Vec::new();
let mut ranges = Vec::new(); let mut ranges = Vec::new();
{ {
@@ -145,7 +145,7 @@ impl BlockCollection {
for (start, range_data) in &mut self.blocks { for (start, range_data) in &mut self.blocks {
match range_data { match range_data {
&mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => { &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()); let mut blocks = mem::replace(blocks, Vec::new());
drained.append(&mut blocks); drained.append(&mut blocks);
ranges.push(*start); ranges.push(*start);
@@ -191,16 +191,19 @@ impl BlockCollection {
mod test { mod test {
use super::{BlockCollection, BlockData}; use super::{BlockCollection, BlockData};
use message; 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.blocks.is_empty() &&
bc.peer_requests.is_empty() bc.peer_requests.is_empty()
} }
fn generate_blocks(n: usize) -> Vec<message::BlockData> { fn generate_blocks(n: usize) -> Vec<message::BlockData<Block>> {
(0 .. n).map(|_| message::BlockData { (0 .. n).map(|_| message::generic::BlockData {
hash: HeaderHash::random(), hash: H256::random(),
header: None, header: None,
body: None, body: None,
message_queue: 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::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus, BlockOrigin, CallExecutor};
use client::error::Error; use client::error::Error;
use state_machine; use state_machine;
use primitives::block::{self, Id as BlockId}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use primitives::bft::Justification; 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. /// 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. /// Get blockchain info.
fn info(&self) -> Result<ClientInfo, Error>; fn info(&self) -> Result<ClientInfo<Block>, Error>;
/// Get block status. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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 impl<B, E, Block> Client<Block> for PolkadotClient<B, E, Block> where
B: client::backend::Backend + Send + Sync + 'static, B: client::backend::Backend<Block> + Send + Sync + 'static,
E: CallExecutor + Send + Sync + 'static, E: CallExecutor<Block> + Send + Sync + 'static,
Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>, { 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. // TODO: defer justification check.
let justified_header = self.check_justification(header, justification.into())?; let justified_header = self.check_justification(header, justification.into())?;
let origin = if is_best { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync }; 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> { fn info(&self) -> Result<ClientInfo<Block>, Error> {
(self as &PolkadotClient<B, E>).info() (self as &PolkadotClient<B, E, Block>).info()
} }
fn block_status(&self, id: &BlockId) -> Result<BlockStatus, Error> { fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error> {
(self as &PolkadotClient<B, E>).block_status(id) (self as &PolkadotClient<B, E, Block>).block_status(id)
} }
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> {
(self as &PolkadotClient<B, E>).block_hash(block_number) (self as &PolkadotClient<B, E, Block>).block_hash(block_number)
} }
fn header(&self, id: &BlockId) -> Result<Option<block::Header>, Error> { fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error> {
(self as &PolkadotClient<B, E>).header(id) (self as &PolkadotClient<B, E, Block>).header(id)
} }
fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error> { fn body(&self, id: &BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, Error> {
(self as &PolkadotClient<B, E>).body(id) (self as &PolkadotClient<B, E, Block>).body(id)
} }
fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error> { fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, Error> {
(self as &PolkadotClient<B, E>).justification(id) (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> { fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error> {
(self as &PolkadotClient<B, E>).execution_proof(&BlockId::Hash(block.clone()), method, data) (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. //! Consensus related bits of the network service.
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use futures::sync::{oneshot, mpsc}; use futures::sync::mpsc;
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
use io::SyncIo; use io::SyncIo;
use protocol::Protocol; use protocol::Protocol;
use network::PeerId; use network::PeerId;
use primitives::{Hash, block::Id as BlockId, block::Header}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use message::{self, Message}; use runtime_primitives::generic::BlockId;
use runtime_support::Hashable; use message::{self, generic::Message as GenericMessage};
// TODO: Add additional spam/DoS attack protection. // TODO: Add additional spam/DoS attack protection.
const MESSAGE_LIFETIME: Duration = Duration::from_secs(600); const MESSAGE_LIFETIME: Duration = Duration::from_secs(600);
struct CandidateRequest { struct PeerConsensus<H> {
id: message::RequestId, known_messages: HashSet<H>,
completion: oneshot::Sender<Vec<u8>>,
}
struct PeerConsensus {
candidate_fetch: Option<CandidateRequest>,
candidate_available: Option<Hash>,
known_messages: HashSet<Hash>,
} }
/// Consensus network protocol handler. Manages statements and candidate requests. /// Consensus network protocol handler. Manages statements and candidate requests.
pub struct Consensus { pub struct Consensus<B: BlockT> {
peers: HashMap<PeerId, PeerConsensus>, peers: HashMap<PeerId, PeerConsensus<B::Hash>>,
our_candidate: Option<(Hash, Vec<u8>)>, bft_message_sink: Option<(mpsc::UnboundedSender<message::LocalizedBftMessage<B>>, B::Hash)>,
statement_sink: Option<mpsc::UnboundedSender<message::Statement>>, messages: Vec<(B::Hash, Instant, message::Message<B>)>,
bft_message_sink: Option<(mpsc::UnboundedSender<message::LocalizedBftMessage>, Hash)>, message_hashes: HashSet<B::Hash>,
messages: Vec<(Hash, Instant, message::Message)>,
message_hashes: HashSet<Hash>,
} }
impl Consensus { impl<B: BlockT> Consensus<B> where B::Header: HeaderT<Number=u64> {
/// Create a new instance. /// Create a new instance.
pub fn new() -> Consensus { pub fn new() -> Self {
Consensus { Consensus {
peers: HashMap::new(), peers: HashMap::new(),
our_candidate: None,
statement_sink: None,
bft_message_sink: None, bft_message_sink: None,
messages: Default::default(), messages: Default::default(),
message_hashes: Default::default(), message_hashes: Default::default(),
@@ -65,12 +54,11 @@ impl Consensus {
/// Closes all notification streams. /// Closes all notification streams.
pub fn restart(&mut self) { pub fn restart(&mut self) {
self.statement_sink = None;
self.bft_message_sink = None; self.bft_message_sink = None;
} }
/// Handle new connected peer. /// 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) { if roles.iter().any(|r| *r == message::Role::Validator) {
trace!(target:"sync", "Registering validator {}", peer_id); trace!(target:"sync", "Registering validator {}", peer_id);
// Send out all known messages. // Send out all known messages.
@@ -81,14 +69,12 @@ impl Consensus {
protocol.send_message(io, peer_id, message.clone()); protocol.send_message(io, peer_id, message.clone());
} }
self.peers.insert(peer_id, PeerConsensus { self.peers.insert(peer_id, PeerConsensus {
candidate_fetch: None,
candidate_available: None,
known_messages, 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() { for (id, ref mut peer) in self.peers.iter_mut() {
if peer.known_messages.insert(hash.clone()) { if peer.known_messages.insert(hash.clone()) {
protocol.send_message(io, *id, message.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) { if self.message_hashes.insert(hash) {
self.messages.push((hash, Instant::now(), message)); 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) { 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 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) {
if self.message_hashes.contains(&hash) { if self.message_hashes.contains(&hash) {
trace!(target:"sync", "Ignored already known BFT message from {}", peer_id); trace!(target:"sync", "Ignored already known BFT message from {}", peer_id);
return; return;
@@ -149,7 +100,7 @@ impl Consensus {
return; return;
}, },
(Ok(info), Ok(Some(header))) => { (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); trace!(target:"sync", "Ignored ancient BFT message from {}, hash={}", peer_id, message.parent_hash);
return; return;
} }
@@ -174,18 +125,18 @@ impl Consensus {
return; return;
} }
let message = Message::BftMessage(message); let message = GenericMessage::BftMessage(message);
self.register_message(hash.clone(), message.clone()); self.register_message(hash.clone(), message.clone());
// Propagate to other peers. // Propagate to other peers.
self.propagate(io, protocol, message, hash); 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(); let (sink, stream) = mpsc::unbounded();
for &(_, _, ref message) in self.messages.iter() { for &(_, _, ref message) in self.messages.iter() {
let bft_message = match *message { let bft_message = match *message {
Message::BftMessage(ref msg) => msg, GenericMessage::BftMessage(ref msg) => msg,
_ => continue, _ => continue,
}; };
@@ -198,90 +149,20 @@ impl Consensus {
stream stream
} }
pub fn fetch_candidate(&mut self, io: &mut SyncIo, protocol: &Protocol, hash: &Hash) -> oneshot::Receiver<Vec<u8>> { pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, message: message::LocalizedBftMessage<B>) {
// 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) {
// Broadcast message to all validators. // Broadcast message to all validators.
trace!(target:"sync", "Broadcasting BFT message {:?}", message); trace!(target:"sync", "Broadcasting BFT message {:?}", message);
let message = Message::BftMessage(message); let message = GenericMessage::BftMessage(message);
let hash = Protocol::hash_message(&message); let hash = Protocol::hash_message(&message);
self.register_message(hash.clone(), message.clone()); self.register_message(hash.clone(), message.clone());
self.propagate(io, protocol, message, hash); self.propagate(io, protocol, message, hash);
} }
pub fn set_local_candidate(&mut self, candidate: Option<(Hash, Vec<u8>)>) { pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol<B>, peer_id: PeerId) {
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) {
self.peers.remove(&peer_id); 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 hashes = &mut self.message_hashes;
let before = self.messages.len(); let before = self.messages.len();
let now = Instant::now(); let now = Instant::now();
@@ -289,8 +170,7 @@ impl Consensus {
if timestamp >= now - MESSAGE_LIFETIME && if timestamp >= now - MESSAGE_LIFETIME &&
best_header.map_or(true, |header| best_header.map_or(true, |header|
match *message { match *message {
Message::BftMessage(ref msg) => msg.parent_hash != header.parent_hash, GenericMessage::BftMessage(ref msg) => &msg.parent_hash != header.parent_hash(),
Message::Statement(ref msg) => msg.parent_hash != header.parent_hash,
_ => true, _ => true,
}) })
{ {
@@ -311,32 +191,33 @@ impl Consensus {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use primitives::Hash; use runtime_primitives::bft::Justification;
use primitives::bft::Justification; use runtime_primitives::testing::{H256, Header, Block as RawBlock};
use primitives::block::{HeaderHash, Header};
use std::time::Instant; use std::time::Instant;
use message::{self, Message}; use message::{self, generic::Message as GenericMessage};
use super::{Consensus, MESSAGE_LIFETIME}; use super::{Consensus, MESSAGE_LIFETIME};
type Block = RawBlock<u64>;
#[test] #[test]
fn collects_garbage() { fn collects_garbage() {
let prev_hash = HeaderHash::random(); let prev_hash = H256::random();
let best_hash = HeaderHash::random(); let best_hash = H256::random();
let mut consensus = Consensus::new(); let mut consensus = Consensus::<Block>::new();
let now = Instant::now(); let now = Instant::now();
let m1_hash = Hash::random(); let m1_hash = H256::random();
let m2_hash = Hash::random(); let m2_hash = H256::random();
let m1 = Message::BftMessage(message::LocalizedBftMessage { let m1 = GenericMessage::BftMessage(message::LocalizedBftMessage {
parent_hash: prev_hash, parent_hash: prev_hash,
message: message::BftMessage::Auxiliary(Justification { message: message::generic::BftMessage::Auxiliary(Justification {
round_number: 0, round_number: 0,
hash: Default::default(), hash: Default::default(),
signatures: Default::default(), signatures: Default::default(),
}), }),
}); });
let m2 = Message::BftMessage(message::LocalizedBftMessage { let m2 = GenericMessage::BftMessage(message::LocalizedBftMessage {
parent_hash: best_hash, parent_hash: best_hash,
message: message::BftMessage::Auxiliary(Justification { message: message::generic::BftMessage::Auxiliary(Justification {
round_number: 0, round_number: 0,
hash: Default::default(), hash: Default::default(),
signatures: Default::default(), signatures: Default::default(),
@@ -353,7 +234,14 @@ mod tests {
assert_eq!(consensus.message_hashes.len(), 2); assert_eq!(consensus.message_hashes.len(), 2);
// random header, nothing should be cleared // 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)); consensus.collect_garbage(Some(&header));
assert_eq!(consensus.messages.len(), 2); assert_eq!(consensus.messages.len(), 2);
assert_eq!(consensus.message_hashes.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_serializer as ser;
extern crate substrate_client as client; extern crate substrate_client as client;
extern crate substrate_runtime_support as runtime_support; extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_bft; extern crate substrate_bft;
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
@@ -59,19 +60,12 @@ pub mod error;
#[cfg(test)] mod test; #[cfg(test)] mod test;
pub use service::{Service, FetchFuture, StatementStream, ConsensusService, BftMessageStream, pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream,
TransactionPool, Params, ManageNetwork, SyncProvider}; TransactionPool, Params, ManageNetwork, SyncProvider};
pub use protocol::{ProtocolStatus}; pub use protocol::{ProtocolStatus};
pub use sync::{Status as SyncStatus, SyncState}; pub use sync::{Status as SyncStatus, SyncState};
pub use network::{NonReservedPeerMode, NetworkConfiguration}; pub use network::{NonReservedPeerMode, NetworkConfiguration, ConnectionFilter, ConnectionDirection};
pub use network_devp2p::{ConnectionFilter, ConnectionDirection}; pub use message::{generic as generic_message, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal};
pub use message::{Statement, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal};
pub use error::Error; pub use error::Error;
pub use config::{Role, ProtocolConfig}; pub use config::{Role, ProtocolConfig};
pub use on_demand::{OnDemand, OnDemandService, Response as OnDemandResponse}; 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. //! Network packet message types. These get serialized and put into the lower level protocol payload.
use primitives::{AuthorityId, Hash}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body, Block};
use primitives::bft::Justification;
use service::Role as RoleFlags; use service::Role as RoleFlags;
use ed25519;
pub use self::generic::{BlockAnnounce, RemoteCallRequest, ConsensusVote, SignedConsensusVote, FromBlock};
pub type RequestId = u64; 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. /// Configured node role.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] #[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. /// Bits of block data and associated artefacts to request.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
pub enum BlockAttribute { pub enum BlockAttribute {
/// Include block header. /// Include block header.
Header, Header,
@@ -88,33 +148,6 @@ pub enum BlockAttribute {
Justification, 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)] #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Block enumeration direction. /// Block enumeration direction.
pub enum Direction { pub enum Direction {
@@ -124,219 +157,6 @@ pub enum Direction {
Descending, 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)] #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
/// Remote call response. /// Remote call response.
pub struct RemoteCallResponse { pub struct RemoteCallResponse {
@@ -347,3 +167,192 @@ pub struct RemoteCallResponse {
/// Execution proof. /// Execution proof.
pub proof: Vec<Vec<u8>>, 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 message;
use network::PeerId; use network::PeerId;
use service; use service;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
/// Remote request timeout. /// Remote request timeout.
const REQUEST_TIMEOUT: Duration = Duration::from_secs(15); 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. /// On-demand requests service. Dispatches requests to appropriate peers.
pub struct OnDemand<E: service::ExecuteInContext> { pub struct OnDemand<B: BlockT, E: service::ExecuteInContext<B>> {
core: Mutex<OnDemandCore<E>>, core: Mutex<OnDemandCore<B, E>>,
checker: Arc<FetchChecker>, checker: Arc<FetchChecker<B>>,
} }
/// On-demand response. /// On-demand response.
@@ -61,19 +62,19 @@ pub struct Response {
} }
#[derive(Default)] #[derive(Default)]
struct OnDemandCore<E: service::ExecuteInContext> { struct OnDemandCore<B: BlockT, E: service::ExecuteInContext<B>> {
service: Weak<E>, service: Weak<E>,
next_request_id: u64, next_request_id: u64,
pending_requests: VecDeque<Request>, pending_requests: VecDeque<Request<B::Hash>>,
active_peers: LinkedHashMap<PeerId, Request>, active_peers: LinkedHashMap<PeerId, Request<B::Hash>>,
idle_peers: VecDeque<PeerId>, idle_peers: VecDeque<PeerId>,
} }
struct Request { struct Request<H> {
id: u64, id: u64,
timestamp: Instant, timestamp: Instant,
sender: Sender<client::CallResult>, sender: Sender<client::CallResult>,
request: RemoteCallRequest, request: RemoteCallRequest<H>,
} }
impl Future for Response { 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. /// Creates new on-demand service.
pub fn new(checker: Arc<FetchChecker>) -> Self { pub fn new(checker: Arc<FetchChecker<B>>) -> Self {
OnDemand { OnDemand {
checker, checker,
core: Mutex::new(OnDemandCore { 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. /// 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 (sender, receiver) = channel();
let result = Response { let result = Response {
receiver: receiver, 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) { fn on_connect(&self, peer: PeerId, role: service::Role) {
if !role.intersects(service::Role::FULL | service::Role::COLLATOR | service::Role::VALIDATOR) { // TODO: correct? if !role.intersects(service::Role::FULL | service::Role::COLLATOR | service::Role::VALIDATOR) { // TODO: correct?
return; 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; type RemoteCallResult = Response;
fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult { fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Self::RemoteCallResult {
self.remote_call(request) 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) { pub fn add_peer(&mut self, peer: PeerId) {
self.idle_peers.push_back(peer); 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; let request_id = self.next_request_id;
self.next_request_id += 1; 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) { match self.active_peers.entry(peer) {
Entry::Occupied(entry) => match entry.get().id == id { Entry::Occupied(entry) => match entry.get().id == id {
true => { true => {
@@ -263,7 +279,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
data: request.request.call_data.clone(), 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); self.active_peers.insert(peer, request);
} }
@@ -286,16 +302,17 @@ mod tests {
use service::{Role, ExecuteInContext}; use service::{Role, ExecuteInContext};
use test::TestIo; use test::TestIo;
use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService}; use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService};
use test_client::runtime::{Block, Hash};
struct DummyExecutor; struct DummyExecutor;
struct DummyFetchChecker { ok: bool } struct DummyFetchChecker { ok: bool }
impl ExecuteInContext for DummyExecutor { impl ExecuteInContext<Block> for DummyExecutor {
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, _closure: F) {} fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<Block>)>(&self, _closure: F) {}
} }
impl FetchChecker for DummyFetchChecker { impl FetchChecker<Block> for DummyFetchChecker {
fn check_execution_proof(&self, _request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> client::error::Result<client::CallResult> { fn check_execution_proof(&self, _request: &RemoteCallRequest<Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> client::error::Result<client::CallResult> {
match self.ok { match self.ok {
true => Ok(client::CallResult { true => Ok(client::CallResult {
return_data: remote_proof.0, 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 executor = Arc::new(DummyExecutor);
let service = Arc::new(OnDemand::new(Arc::new(DummyFetchChecker { ok }))); let service = Arc::new(OnDemand::new(Arc::new(DummyFetchChecker { ok })));
service.set_service_link(Arc::downgrade(&executor)); service.set_service_link(Arc::downgrade(&executor));
(executor, service) (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(); let core = on_demand.core.lock();
core.idle_peers.len() + core.active_peers.len() 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 { on_demand.on_remote_response(network, peer, message::RemoteCallResponse {
id: id, id: id,
value: vec![1], value: vec![1],
+68 -101
View File
@@ -19,23 +19,21 @@ use std::{mem, cmp};
use std::sync::Arc; use std::sync::Arc;
use std::time; use std::time;
use parking_lot::{RwLock, Mutex}; use parking_lot::{RwLock, Mutex};
use futures::sync::oneshot;
use serde_json; use serde_json;
use primitives::block::{HeaderHash, ExtrinsicHash, Number as BlockNumber, Header, Id as BlockId}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing, HashingFor};
use primitives::{Hash, blake2_256}; use runtime_primitives::generic::BlockId;
use runtime_support::Hashable;
use network::PeerId; use network::PeerId;
use message::{self, Message}; use message::{self, Message};
use message::generic::Message as GenericMessage;
use sync::{ChainSync, Status as SyncStatus, SyncState}; use sync::{ChainSync, Status as SyncStatus, SyncState};
use consensus::Consensus; use consensus::Consensus;
use service::{Role, TransactionPool, StatementStream, BftMessageStream}; use service::{Role, TransactionPool, BftMessageStream};
use config::ProtocolConfig; use config::ProtocolConfig;
use chain::Client; use chain::Client;
use on_demand::OnDemandService; use on_demand::OnDemandService;
use io::SyncIo; use io::SyncIo;
use error; use error;
use super::header_hash;
const REQUEST_TIMEOUT_SEC: u64 = 40; const REQUEST_TIMEOUT_SEC: u64 = 40;
const PROTOCOL_VERSION: u32 = 0; const PROTOCOL_VERSION: u32 = 0;
@@ -44,25 +42,25 @@ const PROTOCOL_VERSION: u32 = 0;
const MAX_BLOCK_DATA_RESPONSE: u32 = 128; const MAX_BLOCK_DATA_RESPONSE: u32 = 128;
// Lock must always be taken in order declared here. // Lock must always be taken in order declared here.
pub struct Protocol { pub struct Protocol<B: BlockT> {
config: ProtocolConfig, config: ProtocolConfig,
chain: Arc<Client>, chain: Arc<Client<B>>,
on_demand: Option<Arc<OnDemandService>>, on_demand: Option<Arc<OnDemandService>>,
genesis_hash: HeaderHash, genesis_hash: B::Hash,
sync: RwLock<ChainSync>, sync: RwLock<ChainSync<B>>,
consensus: Mutex<Consensus>, consensus: Mutex<Consensus<B>>,
// All connected peers // All connected peers
peers: RwLock<HashMap<PeerId, Peer>>, peers: RwLock<HashMap<PeerId, Peer<B>>>,
// Connected peers pending Status message. // Connected peers pending Status message.
handshaking_peers: RwLock<HashMap<PeerId, time::Instant>>, handshaking_peers: RwLock<HashMap<PeerId, time::Instant>>,
transaction_pool: Arc<TransactionPool>, transaction_pool: Arc<TransactionPool<B>>,
} }
/// Syncing status and statistics /// Syncing status and statistics
#[derive(Clone)] #[derive(Clone)]
pub struct ProtocolStatus { pub struct ProtocolStatus<B: BlockT> {
/// Sync status. /// Sync status.
pub sync: SyncStatus, pub sync: SyncStatus<B>,
/// Total number of connected peers /// Total number of connected peers
pub num_peers: usize, pub num_peers: usize,
/// Total number of active peers. /// Total number of active peers.
@@ -70,42 +68,49 @@ pub struct ProtocolStatus {
} }
/// Peer information /// Peer information
struct Peer { struct Peer<B: BlockT> {
/// Protocol version /// Protocol version
protocol_version: u32, protocol_version: u32,
/// Roles /// Roles
roles: Role, roles: Role,
/// Peer best block hash /// Peer best block hash
best_hash: HeaderHash, best_hash: B::Hash,
/// Peer best block number /// Peer best block number
best_number: BlockNumber, best_number: <B::Header as HeaderT>::Number,
/// Pending block request if any /// Pending block request if any
block_request: Option<message::BlockRequest>, block_request: Option<message::BlockRequest<B>>,
/// Request timestamp /// Request timestamp
request_timestamp: Option<time::Instant>, request_timestamp: Option<time::Instant>,
/// Holds a set of transactions known to this peer. /// 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. /// Holds a set of blocks known to this peer.
known_blocks: HashSet<HeaderHash>, known_blocks: HashSet<B::Hash>,
/// Request counter, /// Request counter,
next_request_id: message::RequestId, next_request_id: message::RequestId,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct PeerInfo { pub struct PeerInfo<B: BlockT> {
/// Roles /// Roles
pub roles: Role, pub roles: Role,
/// Protocol version /// Protocol version
pub protocol_version: u32, pub protocol_version: u32,
/// Peer best block hash /// Peer best block hash
pub best_hash: HeaderHash, pub best_hash: B::Hash,
/// Peer best block number /// 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. /// 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 info = chain.info()?;
let sync = ChainSync::new(config.roles, &info); let sync = ChainSync::new(config.roles, &info);
let protocol = Protocol { let protocol = Protocol {
@@ -123,7 +128,7 @@ impl Protocol {
} }
/// Returns protocol status /// Returns protocol status
pub fn status(&self) -> ProtocolStatus { pub fn status(&self) -> ProtocolStatus<B> {
let sync = self.sync.read(); let sync = self.sync.read();
let peers = self.peers.read(); let peers = self.peers.read();
ProtocolStatus { ProtocolStatus {
@@ -134,7 +139,7 @@ impl Protocol {
} }
pub fn handle_packet(&self, io: &mut SyncIo, peer_id: PeerId, data: &[u8]) { 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, Ok(m) => m,
Err(e) => { Err(e) => {
debug!("Invalid packet from {}: {}", peer_id, e); debug!("Invalid packet from {}: {}", peer_id, e);
@@ -144,9 +149,9 @@ impl Protocol {
}; };
match message { match message {
Message::Status(s) => self.on_status_message(io, peer_id, s), GenericMessage::Status(s) => self.on_status_message(io, peer_id, s),
Message::BlockRequest(r) => self.on_block_request(io, peer_id, r), GenericMessage::BlockRequest(r) => self.on_block_request(io, peer_id, r),
Message::BlockResponse(r) => { GenericMessage::BlockResponse(r) => {
let request = { let request = {
let mut peers = self.peers.write(); let mut peers = self.peers.write();
if let Some(ref mut peer) = peers.get_mut(&peer_id) { 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); self.on_block_response(io, peer_id, request, r);
}, },
Message::BlockAnnounce(announce) => { GenericMessage::BlockAnnounce(announce) => {
self.on_block_announce(io, peer_id, announce); self.on_block_announce(io, peer_id, announce);
}, },
Message::Statement(s) => self.on_statement(io, peer_id, s, blake2_256(data).into()), GenericMessage::BftMessage(m) => self.on_bft_message(io, peer_id, m, HashingFor::<B>::hash(data)),
Message::CandidateRequest(r) => self.on_candidate_request(io, peer_id, r), GenericMessage::Transactions(m) => self.on_transactions(io, peer_id, m),
Message::CandidateResponse(r) => self.on_candidate_response(io, peer_id, r), GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(io, peer_id, request),
Message::BftMessage(m) => self.on_bft_message(io, peer_id, m, blake2_256(data).into()), GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(io, peer_id, response)
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)
} }
} }
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 { match &mut message {
&mut Message::BlockRequest(ref mut r) => { &mut GenericMessage::BlockRequest(ref mut r) => {
let mut peers = self.peers.write(); let mut peers = self.peers.write();
if let Some(ref mut peer) = peers.get_mut(&peer_id) { if let Some(ref mut peer) = peers.get_mut(&peer_id) {
r.id = peer.next_request_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"); 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 /// 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); trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", request.id, peer, request.from, request.to, request.max);
let mut blocks = Vec::new(); let mut blocks = Vec::new();
let mut id = match request.from { let mut id = match request.from {
@@ -255,9 +257,9 @@ impl Protocol {
if blocks.len() >= max{ if blocks.len() >= max{
break; break;
} }
let number = header.number; let number = header.number().clone();
let hash = header_hash(&header); let hash = header.hash();
let block_data = message::BlockData { let block_data = message::generic::BlockData {
hash: hash, hash: hash,
header: if get_header { Some(header) } else { None }, header: if get_header { Some(header) } else { None },
body: if get_body { self.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } 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, id: request.id,
blocks: blocks, 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 // TODO: validate response
trace!(target: "sync", "BlockResponse {} from {} with {} blocks", response.id, peer, response.blocks.len()); trace!(target: "sync", "BlockResponse {} from {} with {} blocks", response.id, peer, response.blocks.len());
self.sync.write().on_block_data(io, self, peer, request, response); self.sync.write().on_block_data(io, self, peer, request, response);
} }
fn on_candidate_request(&self, io: &mut SyncIo, peer: PeerId, request: message::CandidateRequest) { fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage<B>, hash: B::Hash) {
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) {
trace!(target: "sync", "BFT message from {}: {:?}", peer, message); trace!(target: "sync", "BFT message from {}: {:?}", peer, message);
self.consensus.lock().on_bft_message(io, self, peer, message, hash); self.consensus.lock().on_bft_message(io, self, peer, message, hash);
} }
/// See `ConsensusService` trait. /// 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) self.consensus.lock().send_bft_message(io, self, message)
} }
/// See `ConsensusService` trait. /// 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) 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. /// Perform time based maintenance.
pub fn tick(&self, io: &mut SyncIo) { pub fn tick(&self, io: &mut SyncIo) {
self.maintain_peers(io); 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| { self.peers.read().get(&peer).map(|p| {
PeerInfo { PeerInfo {
roles: p.roles, roles: p.roles,
@@ -379,7 +346,7 @@ impl Protocol {
} }
/// Called by peer to report status /// 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); trace!(target: "sync", "New peer {} {:?}", peer_id, status);
if io.is_expired() { if io.is_expired() {
trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); 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 /// 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 // Accept transactions only when fully synced
if self.sync.read().status().state != SyncState::Idle { if self.sync.read().status().state != SyncState::Idle {
trace!(target: "sync", "{} Ignoring transactions while syncing", peer_id); 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); 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); self.transaction_pool.on_broadcasted(propagated_to);
@@ -484,7 +451,7 @@ impl Protocol {
/// Send Status message /// Send Status message
fn send_status(&self, io: &mut SyncIo, peer_id: PeerId) { fn send_status(&self, io: &mut SyncIo, peer_id: PeerId) {
if let Ok(info) = self.chain.info() { if let Ok(info) = self.chain.info() {
let status = message::Status { let status = message::generic::Status {
version: PROTOCOL_VERSION, version: PROTOCOL_VERSION,
genesis_hash: info.chain.genesis_hash, genesis_hash: info.chain.genesis_hash,
roles: self.config.roles.into(), roles: self.config.roles.into(),
@@ -494,7 +461,7 @@ impl Protocol {
validator_id: None, validator_id: None,
parachain_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(); 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 header = announce.header;
let hash: HeaderHash = header.blake2_256().into(); let hash = header.hash();
{ {
let mut peers = self.peers.write(); let mut peers = self.peers.write();
if let Some(ref mut peer) = peers.get_mut(&peer_id) { 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); 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); self.sync.write().update_chain_info(&header);
// send out block announcements // send out block announcements
let mut peers = self.peers.write(); let mut peers = self.peers.write();
@@ -528,7 +495,7 @@ impl Protocol {
for (peer_id, ref mut peer) in peers.iter_mut() { for (peer_id, ref mut peer) in peers.iter_mut() {
if peer.known_blocks.insert(hash.clone()) { if peer.known_blocks.insert(hash.clone()) {
trace!(target: "sync", "Announcing block {:?} to {}", hash, peer_id); 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() header: header.clone()
})); }));
} }
@@ -537,7 +504,7 @@ impl Protocol {
self.consensus.lock().collect_garbage(Some(&header)); 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); 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) { let (value, proof) = match self.chain.execution_proof(&request.block, &request.method, &request.data) {
Ok((value, proof)) => (value, proof), 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, 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)); 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 &*self.chain
} }
} }
+40 -72
View File
@@ -22,16 +22,15 @@ use futures::sync::{oneshot, mpsc};
use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId, use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId,
NetworkConfiguration , NonReservedPeerMode, ErrorKind}; NetworkConfiguration , NonReservedPeerMode, ErrorKind};
use network_devp2p::{NetworkService}; use network_devp2p::{NetworkService};
use primitives::block::{ExtrinsicHash, Header, HeaderHash};
use primitives::Hash;
use core_io::{TimerToken}; use core_io::{TimerToken};
use io::NetSyncIo; use io::NetSyncIo;
use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo}; use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo};
use config::{ProtocolConfig}; use config::{ProtocolConfig};
use error::Error; use error::Error;
use chain::Client; use chain::Client;
use message::{Statement, LocalizedBftMessage}; use message::LocalizedBftMessage;
use on_demand::OnDemandService; use on_demand::OnDemandService;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
/// Polkadot devp2p protocol id /// Polkadot devp2p protocol id
pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot"; pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot";
@@ -40,10 +39,8 @@ const V0_PACKET_COUNT: u8 = 1;
/// Type that represents fetch completion future. /// Type that represents fetch completion future.
pub type FetchFuture = oneshot::Receiver<Vec<u8>>; pub type FetchFuture = oneshot::Receiver<Vec<u8>>;
/// Type that represents statement stream.
pub type StatementStream = mpsc::UnboundedReceiver<Statement>;
/// Type that represents bft messages stream. /// 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_TOKEN: TimerToken = 0;
const TICK_TIMEOUT: Duration = Duration::from_millis(1000); const TICK_TIMEOUT: Duration = Duration::from_millis(1000);
@@ -68,60 +65,51 @@ bitflags! {
} }
/// Sync status /// Sync status
pub trait SyncProvider: Send + Sync { pub trait SyncProvider<B: BlockT>: Send + Sync {
/// Get sync status /// Get sync status
fn status(&self) -> ProtocolStatus; fn status(&self) -> ProtocolStatus<B>;
/// Get peers information /// Get peers information
fn peers(&self) -> Vec<PeerInfo>; fn peers(&self) -> Vec<PeerInfo<B>>;
/// Get this node id if available. /// Get this node id if available.
fn node_id(&self) -> Option<String>; fn node_id(&self) -> Option<String>;
} }
/// Transaction pool interface /// 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. /// 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. /// 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. /// 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 /// ConsensusService
pub trait ConsensusService: Send + Sync { pub trait ConsensusService<B: BlockT>: Send + Sync {
/// Get statement stream.
fn statements(&self) -> StatementStream;
/// Send out a statement.
fn send_statement(&self, statement: Statement);
/// Maintain connectivity to given addresses. /// Maintain connectivity to given addresses.
fn connect_to_authorities(&self, addresses: &[String]); 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 /// Get BFT message stream for messages corresponding to consensus on given
/// parent hash. /// 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. /// 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. /// 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. /// 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 /// devp2p Protocol handler
struct ProtocolHandler { struct ProtocolHandler<B: BlockT> {
protocol: Protocol, protocol: Protocol<B>,
} }
/// Peer connection information /// Peer connection information
#[derive(Debug)] #[derive(Debug)]
pub struct PeerInfo { pub struct PeerInfo<B: BlockT> {
/// Public node id /// Public node id
pub id: Option<String>, pub id: Option<String>,
/// Node client ID /// Node client ID
@@ -133,34 +121,34 @@ pub struct PeerInfo {
/// Local endpoint address /// Local endpoint address
pub local_address: String, pub local_address: String,
/// Dot protocol info. /// Dot protocol info.
pub dot_info: Option<ProtocolPeerInfo>, pub dot_info: Option<ProtocolPeerInfo<B>>,
} }
/// Service initialization parameters. /// Service initialization parameters.
pub struct Params { pub struct Params<B: BlockT> {
/// Configuration. /// Configuration.
pub config: ProtocolConfig, pub config: ProtocolConfig,
/// Network layer configuration. /// Network layer configuration.
pub network_config: NetworkConfiguration, pub network_config: NetworkConfiguration,
/// Polkadot relay chain access point. /// Polkadot relay chain access point.
pub chain: Arc<Client>, pub chain: Arc<Client<B>>,
/// On-demand service reference. /// On-demand service reference.
pub on_demand: Option<Arc<OnDemandService>>, pub on_demand: Option<Arc<OnDemandService>>,
/// Transaction pool. /// Transaction pool.
pub transaction_pool: Arc<TransactionPool>, pub transaction_pool: Arc<TransactionPool<B>>,
} }
/// Polkadot network service. Handles network IO and manages connectivity. /// 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 service
network: NetworkService, network: NetworkService,
/// Devp2p protocol handler /// 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 /// 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 service = NetworkService::new(params.network_config.clone(), None)?;
let sync = Arc::new(Service { let sync = Arc::new(Service {
network: service, network: service,
@@ -173,7 +161,7 @@ impl Service {
} }
/// Called when a new block is imported by the client. /// 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.network.with_context(DOT_PROTOCOL_ID, |context| {
self.handler.protocol.on_block_imported(&mut NetSyncIo::new(context), hash, header) self.handler.protocol.on_block_imported(&mut NetSyncIo::new(context), hash, header)
}); });
@@ -199,32 +187,32 @@ impl Service {
fn stop(&self) { fn stop(&self) {
self.handler.protocol.abort(); 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) { fn drop(&mut self) {
self.stop(); self.stop();
} }
} }
impl ExecuteInContext for Service { impl<B: BlockT + 'static> ExecuteInContext<B> for Service<B> where B::Header: HeaderT<Number=u64> {
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) {
self.network.with_context(DOT_PROTOCOL_ID, |context| { self.network.with_context(DOT_PROTOCOL_ID, |context| {
closure(&mut NetSyncIo::new(context), &self.handler.protocol) 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 /// Get sync status
fn status(&self) -> ProtocolStatus { fn status(&self) -> ProtocolStatus<B> {
self.handler.protocol.status() self.handler.protocol.status()
} }
/// Get sync peers /// Get sync peers
fn peers(&self) -> Vec<PeerInfo> { fn peers(&self) -> Vec<PeerInfo<B>> {
self.network.with_context_eval(DOT_PROTOCOL_ID, |ctx| { self.network.with_context_eval(DOT_PROTOCOL_ID, |ctx| {
let peer_ids = self.network.connected_peers(); let peer_ids = self.network.connected_peers();
@@ -252,43 +240,23 @@ impl SyncProvider for Service {
} }
/// ConsensusService /// ConsensusService
impl ConsensusService for Service { impl<B: BlockT + 'static> ConsensusService<B> for Service<B> where B::Header: HeaderT<Number=u64> {
fn statements(&self) -> StatementStream {
self.handler.protocol.statements()
}
fn connect_to_authorities(&self, _addresses: &[String]) { fn connect_to_authorities(&self, _addresses: &[String]) {
//TODO: implement me //TODO: implement me
} }
fn fetch_candidate(&self, hash: &Hash) -> oneshot::Receiver<Vec<u8>> { fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B> {
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 {
self.handler.protocol.bft_messages(parent_hash) 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.network.with_context(DOT_PROTOCOL_ID, |context| {
self.handler.protocol.send_bft_message(&mut NetSyncIo::new(context), message); 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) { fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
io.register_timer(TICK_TOKEN, TICK_TIMEOUT) io.register_timer(TICK_TOKEN, TICK_TIMEOUT)
.expect("Error registering sync timer"); .expect("Error registering sync timer");
@@ -319,7 +287,7 @@ impl NetworkProtocolHandler for ProtocolHandler {
} }
/// Trait for managing network /// Trait for managing network
pub trait ManageNetwork : Send + Sync { pub trait ManageNetwork: Send + Sync {
/// Set to allow unreserved peers to connect /// Set to allow unreserved peers to connect
fn accept_unreserved_peers(&self); fn accept_unreserved_peers(&self);
/// Set to deny unreserved peers to connect /// 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) { fn accept_unreserved_peers(&self) {
self.network.set_non_reserved_mode(NonReservedPeerMode::Accept); self.network.set_non_reserved_mode(NonReservedPeerMode::Accept);
} }
+57 -54
View File
@@ -19,38 +19,38 @@ use io::SyncIo;
use protocol::Protocol; use protocol::Protocol;
use network::PeerId; use network::PeerId;
use client::{ImportResult, BlockStatus, ClientInfo}; use client::{ImportResult, BlockStatus, ClientInfo};
use primitives::block::{HeaderHash, Number as BlockNumber, Header, Id as BlockId};
use blocks::{self, BlockCollection}; 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 service::Role;
use super::header_hash;
// Maximum blocks to request in a single packet. // Maximum blocks to request in a single packet.
const MAX_BLOCKS_TO_REQUEST: usize = 128; const MAX_BLOCKS_TO_REQUEST: usize = 128;
struct PeerSync { struct PeerSync<B: BlockT> {
pub common_hash: HeaderHash, pub common_hash: B::Hash,
pub common_number: BlockNumber, pub common_number: <B::Header as HeaderT>::Number,
pub best_hash: HeaderHash, pub best_hash: B::Hash,
pub best_number: BlockNumber, pub best_number: <B::Header as HeaderT>::Number,
pub state: PeerSyncState, pub state: PeerSyncState<B>,
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum PeerSyncState { enum PeerSyncState<B: BlockT> {
AncestorSearch(BlockNumber), AncestorSearch(<B::Header as HeaderT>::Number),
Available, Available,
DownloadingNew(BlockNumber), DownloadingNew(<B::Header as HeaderT>::Number),
DownloadingStale(HeaderHash), DownloadingStale(B::Hash),
} }
/// Relay chain sync strategy. /// Relay chain sync strategy.
pub struct ChainSync { pub struct ChainSync<B: BlockT> {
genesis_hash: HeaderHash, genesis_hash: B::Hash,
peers: HashMap<PeerId, PeerSync>, peers: HashMap<PeerId, PeerSync<B>>,
blocks: BlockCollection, blocks: BlockCollection<B>,
best_queued_number: BlockNumber, best_queued_number: u64,
best_queued_hash: HeaderHash, best_queued_hash: B::Hash,
required_block_attributes: Vec<message::BlockAttribute>, required_block_attributes: Vec<message::BlockAttribute>,
} }
@@ -65,16 +65,18 @@ pub enum SyncState {
/// Syncing status and statistics /// Syncing status and statistics
#[derive(Clone)] #[derive(Clone)]
pub struct Status { pub struct Status<B: BlockT> {
/// Current global sync state. /// Current global sync state.
pub state: SyncState, pub state: SyncState,
/// Target sync block number. /// 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. /// 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![ let mut required_block_attributes = vec![
message::BlockAttribute::Header, message::BlockAttribute::Header,
message::BlockAttribute::Justification 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) self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number)
} }
/// Returns sync status /// Returns sync status
pub fn status(&self) -> Status { pub fn status(&self) -> Status<B> {
let best_seen = self.best_seen_block(); let best_seen = self.best_seen_block();
let state = match &best_seen { let state = match &best_seen {
&Some(n) if n > self.best_queued_number && n - self.best_queued_number > 5 => SyncState::Downloading, &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. /// 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) { if let Some(info) = protocol.peer_info(peer_id) {
match (protocol.chain().block_status(&BlockId::Hash(info.best_hash)), info.best_number) { match (protocol.chain().block_status(&BlockId::Hash(info.best_hash)), info.best_number) {
(Err(e), _) => { (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 count = response.blocks.len();
let mut imported: usize = 0; let mut imported: usize = 0;
let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { 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; let block = block.block;
match (block.header, block.justification) { match (block.header, block.justification) {
(Some(header), Some(justification)) => { (Some(header), Some(justification)) => {
let number = header.number; let number = header.number().clone();
let hash = header_hash(&header); let hash = header.hash();
let parent = header.parent_hash; let parent = header.parent_hash().clone();
let is_best = best_seen.as_ref().map_or(false, |n| number >= *n); let is_best = best_seen.as_ref().map_or(false, |n| number >= *n);
// check whether the block is known before importing. // check whether the block is known before importing.
@@ -305,14 +307,14 @@ impl ChainSync {
self.maintain_sync(io, protocol); 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(); let peers: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
for peer in peers { for peer in peers {
self.download_new(io, protocol, peer); 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 { if number > self.best_queued_number {
self.best_queued_number = number; self.best_queued_number = number;
self.best_queued_hash = *hash; self.best_queued_hash = *hash;
@@ -327,28 +329,29 @@ impl ChainSync {
} }
} }
pub fn update_chain_info(&mut self, best_header: &Header ) { pub fn update_chain_info(&mut self, best_header: &B::Header) {
let hash = header_hash(&best_header); let hash = best_header.hash();
self.block_imported(&hash, best_header.number) 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 let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
if header.number > peer.best_number { if number > peer.best_number {
peer.best_number = header.number; peer.best_number = number;
peer.best_hash = hash; peer.best_hash = hash;
} }
if header.number <= self.best_queued_number && header.number > peer.common_number { if number <= self.best_queued_number && number > peer.common_number {
peer.common_number = header.number; peer.common_number = number
} }
} else { } else {
return; return;
} }
if !self.is_known_or_already_downloading(protocol, &hash) { 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 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); trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", peer_id, hash, header);
} else { } else {
trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", peer_id, hash, header); 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)) 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) || 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.blocks.clear_peer_download(peer_id);
self.peers.remove(&peer_id); self.peers.remove(&peer_id);
self.maintain_sync(io, protocol); 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(); self.blocks.clear();
let ids: Vec<PeerId> = self.peers.keys().map(|p| *p).collect(); let ids: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
for id in ids { for id in ids {
@@ -399,11 +402,11 @@ impl ChainSync {
} }
// Download old block. // 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) { if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
match peer.state { match peer.state {
PeerSyncState::Available => { PeerSyncState::Available => {
let request = message::BlockRequest { let request = message::generic::BlockRequest {
id: 0, id: 0,
fields: self.required_block_attributes.clone(), fields: self.required_block_attributes.clone(),
from: message::FromBlock::Hash(*hash), from: message::FromBlock::Hash(*hash),
@@ -412,7 +415,7 @@ impl ChainSync {
max: Some(1), max: Some(1),
}; };
peer.state = PeerSyncState::DownloadingStale(*hash); 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 // 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) { 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); trace!(target: "sync", "Considering new block download from {}, common block is {}, best is {:?}", peer_id, peer.common_number, peer.best_number);
match peer.state { match peer.state {
PeerSyncState::Available => { PeerSyncState::Available => {
if let Some(range) = self.blocks.needed_blocks(peer_id, MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) { 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); trace!(target: "sync", "Requesting blocks from {}, ({} to {})", peer_id, range.start, range.end);
let request = message::BlockRequest { let request = message::generic::BlockRequest {
id: 0, id: 0,
fields: self.required_block_attributes.clone(), fields: self.required_block_attributes.clone(),
from: message::FromBlock::Number(range.start), from: message::FromBlock::Number(range.start),
@@ -436,7 +439,7 @@ impl ChainSync {
max: Some((range.end - range.start) as u32), max: Some((range.end - range.start) as u32),
}; };
peer.state = PeerSyncState::DownloadingNew(range.start); 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 { } else {
trace!(target: "sync", "Nothing to request"); 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); trace!(target: "sync", "Requesting ancestry block #{} from {}", block, peer_id);
let request = message::BlockRequest { let request = message::generic::BlockRequest {
id: 0, id: 0,
fields: vec![message::BlockAttribute::Header, message::BlockAttribute::Justification], fields: vec![message::BlockAttribute::Header, message::BlockAttribute::Justification],
from: message::FromBlock::Number(block), from: message::FromBlock::Number(block),
@@ -456,6 +459,6 @@ impl ChainSync {
direction: message::Direction::Ascending, direction: message::Direction::Ascending,
max: Some(1), 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/>. // along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use super::*; use super::*;
use message::*; use message::{Message, generic};
use futures::Stream; use futures::Stream;
use test_client::runtime::Block;
#[test] #[test]
fn bft_messages_include_those_sent_before_asking_for_stream() { 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 peer = net.peer(0);
let mut io = TestIo::new(&peer.queue, None); let mut io = TestIo::new(&peer.queue, None);
let bft_message = BftMessage::Consensus(SignedConsensusMessage::Vote(SignedConsensusVote { let bft_message = generic::BftMessage::Consensus(generic::SignedConsensusMessage::Vote(generic::SignedConsensusVote {
vote: ConsensusVote::AdvanceRound(0), vote: generic::ConsensusVote::AdvanceRound(0),
sender: [0; 32], sender: [0; 32],
signature: Default::default(), signature: Default::default(),
})); }));
let parent_hash = peer.genesis_hash(); let parent_hash = peer.genesis_hash();
let localized = LocalizedBftMessage { let localized = ::message::LocalizedBftMessage::<Block> {
message: bft_message, message: bft_message,
parent_hash: parent_hash, 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[..]); peer.sync.handle_packet(&mut io, 1, &as_bytes[..]);
let stream = peer.sync.bft_messages(parent_hash); 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 parking_lot::RwLock;
use client; use client;
use client::block_builder::BlockBuilder; use client::block_builder::BlockBuilder;
use primitives::block::{Id as BlockId, ExtrinsicHash, HeaderHash}; use runtime_primitives::traits::Block as BlockT;
use primitives; use runtime_primitives::generic::BlockId;
use io::SyncIo; use io::SyncIo;
use protocol::Protocol; use protocol::Protocol;
use config::ProtocolConfig; use config::ProtocolConfig;
use service::TransactionPool; use service::TransactionPool;
use network::{PeerId, SessionInfo, Error as NetworkError}; use network::{PeerId, SessionInfo, Error as NetworkError};
use runtime_support::Hashable;
use keyring::Keyring; use keyring::Keyring;
use codec::Slicable; use codec::Slicable;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::runtime::{Block, Hash, Transfer, Extrinsic};
pub struct TestIo<'p> { pub struct TestIo<'p> {
pub queue: &'p RwLock<VecDeque<TestPacket>>, pub queue: &'p RwLock<VecDeque<TestPacket>>,
@@ -100,8 +100,8 @@ pub struct TestPacket {
} }
pub struct Peer { pub struct Peer {
client: Arc<client::Client<test_client::Backend, test_client::Executor>>, client: Arc<client::Client<test_client::Backend, test_client::Executor, Block>>,
pub sync: Protocol, pub sync: Protocol<Block>,
pub queue: RwLock<VecDeque<TestPacket>>, pub queue: RwLock<VecDeque<TestPacket>>,
} }
@@ -158,12 +158,12 @@ impl Peer {
fn flush(&self) { 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 { for _ in 0 .. count {
let mut builder = self.client.new_block().unwrap(); let mut builder = self.client.new_block().unwrap();
edit_block(&mut builder); edit_block(&mut builder);
let block = builder.bake().unwrap(); 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(); self.client.justify_and_import(client::BlockOrigin::File, block).unwrap();
} }
} }
@@ -172,15 +172,14 @@ impl Peer {
let mut nonce = 0; let mut nonce = 0;
if with_tx { if with_tx {
self.generate_blocks(count, |builder| { self.generate_blocks(count, |builder| {
let tx = test_client::runtime::Transaction { let transfer = Transfer {
from: Keyring::Alice.to_raw_public(), from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Alice.to_raw_public(), to: Keyring::Alice.to_raw_public().into(),
amount: 1, amount: 1,
nonce: nonce, nonce,
}; };
let signature = Keyring::from_raw_public(tx.from.clone()).unwrap().sign(&tx.encode()); let signature = Keyring::from_raw_public(transfer.from.0).unwrap().sign(&transfer.encode()).into();
let tx = primitives::block::Extrinsic::decode(&mut test_client::runtime::UncheckedTransaction { signature, tx: tx }.encode().as_ref()).unwrap(); builder.push(Extrinsic { transfer, signature }).unwrap();
builder.push(tx).unwrap();
nonce = nonce + 1; nonce = nonce + 1;
}); });
} else { } 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"); let info = self.client.info().expect("In-mem client does not fail");
info.chain.genesis_hash info.chain.genesis_hash
} }
@@ -196,16 +195,16 @@ impl Peer {
struct EmptyTransactionPool; struct EmptyTransactionPool;
impl TransactionPool for EmptyTransactionPool { impl TransactionPool<Block> for EmptyTransactionPool {
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)> { fn transactions(&self) -> Vec<(Hash, Extrinsic)> {
Vec::new() Vec::new()
} }
fn import(&self, _transaction: &[u8]) -> Option<ExtrinsicHash> { fn import(&self, _transaction: &Extrinsic) -> Option<Hash> {
None None
} }
fn on_broadcasted(&self, _: HashMap<ExtrinsicHash, Vec<String>>) {} fn on_broadcasted(&self, _: HashMap<Hash, Vec<String>>) {}
} }
pub struct TestNet { 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] #[test]
fn test_h160() { fn test_h160() {
let tests = vec![ let tests = vec![
(H160::from(0), "0x0000000000000000000000000000000000000000"), (Default::default(), "0x0000000000000000000000000000000000000000"),
(H160::from(2), "0x0000000000000000000000000000000000000002"), (H160::from(2), "0x0000000000000000000000000000000000000002"),
(H160::from(15), "0x000000000000000000000000000000000000000f"), (H160::from(15), "0x000000000000000000000000000000000000000f"),
(H160::from(16), "0x0000000000000000000000000000000000000010"), (H160::from(16), "0x0000000000000000000000000000000000000010"),
@@ -84,7 +84,7 @@ mod tests {
#[test] #[test]
fn test_h256() { fn test_h256() {
let tests = vec![ let tests = vec![
(H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), (Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"),
(H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"),
(H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"),
(H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"),
+1 -18
View File
@@ -54,17 +54,6 @@ extern crate substrate_serializer;
#[macro_use] #[macro_use]
extern crate pretty_assertions; 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_export]
macro_rules! map { macro_rules! map {
($( $name:expr => $value:expr ),*) => ( ($( $name:expr => $value:expr ),*) => (
@@ -82,8 +71,6 @@ pub use hashing::{blake2_256, twox_128, twox_256};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod hexdisplay; pub mod hexdisplay;
pub mod bft;
pub mod block;
pub mod hash; pub mod hash;
pub mod sandbox; pub mod sandbox;
pub mod storage; pub mod storage;
@@ -92,12 +79,8 @@ pub mod uint;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub use self::hash::{H160, H256}; pub use self::hash::{H160, H256, H512};
pub use self::uint::{U256, U512}; 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. /// An identifier for an authority in the consensus algorithm. The same as ed25519::Public.
pub type AuthorityId = [u8; 32]; 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" } jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git" }
log = "0.3" log = "0.3"
substrate-rpc = { path = "../rpc", version = "0.1" } 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_http_server as http;
extern crate jsonrpc_pubsub as pubsub; extern crate jsonrpc_pubsub as pubsub;
extern crate jsonrpc_ws_server as ws; extern crate jsonrpc_ws_server as ws;
extern crate substrate_runtime_primitives;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
use std::io; use std::io;
use substrate_runtime_primitives::traits::Block as BlockT;
type Metadata = apis::metadata::Metadata; type Metadata = apis::metadata::Metadata;
type RpcHandler = pubsub::PubSubHandler<Metadata>; type RpcHandler = pubsub::PubSubHandler<Metadata>;
/// Construct rpc `IoHandler` /// Construct rpc `IoHandler`
pub fn rpc_handler<S, C, A, Y>( pub fn rpc_handler<Block: BlockT, S, C, A, Y>(
state: S, state: S,
chain: C, chain: C,
author: A, author: A,
system: Y, system: Y,
) -> RpcHandler where ) -> RpcHandler where
S: apis::state::StateApi, Block: 'static,
C: apis::chain::ChainApi<Metadata=Metadata>, S: apis::state::StateApi<Block::Hash>,
A: apis::author::AuthorApi, C: apis::chain::ChainApi<Block::Hash, Block::Header, Metadata=Metadata>,
A: apis::author::AuthorApi<Block::Hash, Block::Extrinsic>,
Y: apis::system::SystemApi, Y: apis::system::SystemApi,
{ {
let mut io = pubsub::PubSubHandler::default(); let mut io = pubsub::PubSubHandler::default();
+1
View File
@@ -14,6 +14,7 @@ substrate-client = { path = "../client" }
substrate-executor = { path = "../executor" } substrate-executor = { path = "../executor" }
substrate-extrinsic-pool = { path = "../extrinsic-pool" } substrate-extrinsic-pool = { path = "../extrinsic-pool" }
substrate-primitives = { path = "../primitives" } substrate-primitives = { path = "../primitives" }
substrate-runtime-primitives = { path = "../runtime/primitives" }
substrate-state-machine = { path = "../state-machine" } substrate-state-machine = { path = "../state-machine" }
tokio-core = "0.1.12" tokio-core = "0.1.12"
+6 -6
View File
@@ -17,7 +17,6 @@
//! Substrate block-author/full-node API. //! Substrate block-author/full-node API.
use std::sync::Arc; use std::sync::Arc;
use primitives::block::{Extrinsic, ExtrinsicHash};
use extrinsic_pool::api::{Error, ExtrinsicPool}; use extrinsic_pool::api::{Error, ExtrinsicPool};
pub mod error; pub mod error;
@@ -29,17 +28,18 @@ use self::error::Result;
build_rpc_trait! { build_rpc_trait! {
/// Substrate authoring RPC API /// Substrate authoring RPC API
pub trait AuthorApi { pub trait AuthorApi<Hash, Extrinsic> {
/// Submit extrinsic for inclusion in block. /// Submit extrinsic for inclusion in block.
#[rpc(name = "author_submitExtrinsic")] #[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 impl<Ex, Hash, T> AuthorApi<Hash, Ex> for Arc<T> where
T: ExtrinsicPool, T: ExtrinsicPool<Ex, Hash>,
T::Error: 'static,
{ {
fn submit_extrinsic(&self, xt: Extrinsic) -> Result<ExtrinsicHash> { fn submit_extrinsic(&self, xt: Ex) -> Result<Hash> {
self self
.submit(vec![xt]) .submit(vec![xt])
.map(|mut res| res.pop().expect("One extrinsic passed; one result back; qed")) .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 std::{fmt, sync::Arc};
use extrinsic_pool::api; use extrinsic_pool::api;
use parking_lot::Mutex; use parking_lot::Mutex;
use primitives::block;
type Extrinsic = u64;
type Hash = u64;
#[derive(Default)] #[derive(Default)]
struct DummyTxPool { struct DummyTxPool {
submitted: Mutex<Vec<block::Extrinsic>>, submitted: Mutex<Vec<Extrinsic>>,
} }
#[derive(Debug)] #[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; type Error = Error;
/// Submit extrinsic for inclusion in block. /// 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(); let mut submitted = self.submitted.lock();
if submitted.len() < 1 { if submitted.len() < 1 {
let hashes = xt.iter().map(|_xt| 1.into()).collect(); let hashes = xt.iter().map(|_xt| 1).collect();
submitted.extend(xt); submitted.extend(xt);
Ok(hashes) Ok(hashes)
} else { } else {
@@ -57,13 +59,12 @@ impl api::ExtrinsicPool for DummyTxPool {
#[test] #[test]
fn submit_transaction_should_not_cause_error() { fn submit_transaction_should_not_cause_error() {
let p = Arc::new(DummyTxPool::default()); let p = Arc::new(DummyTxPool::default());
let hash: ExtrinsicHash = 1.into();
assert_matches!( assert_matches!(
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])), AuthorApi::submit_extrinsic(&p, 5),
Ok(hash) Ok(1)
); );
assert!( 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 std::sync::Arc;
use primitives::block; use runtime_primitives::traits::Block as BlockT;
use runtime_primitives::generic::BlockId;
use client::{self, Client, BlockchainEvents}; use client::{self, Client, BlockchainEvents};
use state_machine; use state_machine;
@@ -38,23 +39,23 @@ use self::error::{Result, ResultExt};
build_rpc_trait! { build_rpc_trait! {
/// Polkadot blockchain API /// Polkadot blockchain API
pub trait ChainApi { pub trait ChainApi<Hash, Header> {
type Metadata; type Metadata;
/// Get header of a relay chain block. /// Get header of a relay chain block.
#[rpc(name = "chain_getHeader")] #[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. /// Get hash of the head.
#[rpc(name = "chain_getHead")] #[rpc(name = "chain_getHead")]
fn head(&self) -> Result<block::HeaderHash>; fn head(&self) -> Result<Hash>;
#[pubsub(name = "chain_newHead")] { #[pubsub(name = "chain_newHead")] {
/// Hello subscription /// New head subscription
#[rpc(name = "subscribe_newHead")] #[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")] #[rpc(name = "unsubscribe_newHead")]
fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>; fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>;
} }
@@ -62,16 +63,16 @@ build_rpc_trait! {
} }
/// Chain API with subscriptions support. /// Chain API with subscriptions support.
pub struct Chain<B, E> { pub struct Chain<B, E, Block: BlockT> {
/// Substrate client. /// Substrate client.
client: Arc<Client<B, E>>, client: Arc<Client<B, E, Block>>,
/// Current subscriptions. /// Current subscriptions.
subscriptions: Subscriptions, subscriptions: Subscriptions,
} }
impl<B, E> Chain<B, E> { impl<B, E, Block: BlockT> Chain<B, E, Block> {
/// Create new Chain API RPC handler. /// 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 { Chain {
client, client,
subscriptions: Subscriptions::new(remote), subscriptions: Subscriptions::new(remote),
@@ -79,22 +80,23 @@ impl<B, E> Chain<B, E> {
} }
} }
impl<B, E> ChainApi for Chain<B, E> where impl<B, E, Block> ChainApi<Block::Hash, Block::Header> for Chain<B, E, Block> where
B: client::backend::Backend + Send + Sync + 'static, Block: BlockT + 'static,
E: client::CallExecutor + Send + Sync + 'static, B: client::backend::Backend<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>, 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; type Metadata = ::metadata::Metadata;
fn header(&self, hash: block::HeaderHash) -> Result<Option<block::Header>> { fn header(&self, hash: Block::Hash) -> Result<Option<Block::Header>> {
self.client.header(&block::Id::Hash(hash)).chain_err(|| "Blockchain error") 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) 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| { self.subscriptions.add(subscriber, |sink| {
let stream = self.client.import_notification_stream() let stream = self.client.import_notification_stream()
.filter(|notification| notification.is_new_best) .filter(|notification| notification.is_new_best)
+4 -3
View File
@@ -18,6 +18,7 @@ use super::*;
use jsonrpc_macros::pubsub; use jsonrpc_macros::pubsub;
use client::BlockOrigin; use client::BlockOrigin;
use test_client::{self, TestClient}; use test_client::{self, TestClient};
use test_client::runtime::Header;
#[test] #[test]
fn should_return_header() { fn should_return_header() {
@@ -30,10 +31,10 @@ fn should_return_header() {
}; };
assert_matches!( assert_matches!(
client.header(client.client.genesis_hash()), 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(), parent_hash: 0.into(),
number: 0, number: 0,
state_root: "0c81ab6cfac8c8d7201d78cb699b6b79d714462a4ba00abcacce22444babe315".into(), state_root: "9c70014029b05f780858f654bfcf297ca708b3663d32bc81486193e84a2f2f3d".into(),
extrinsics_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into(), extrinsics_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into(),
digest: Default::default(), digest: Default::default(),
} }
@@ -69,7 +70,7 @@ fn should_notify_about_latest_block() {
// assert notification send to transport // assert notification send to transport
let (notification, next) = core.run(transport.into_future()).unwrap(); let (notification, next) = core.run(transport.into_future()).unwrap();
assert_eq!(notification, Some( 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 // no more notifications on this channel
assert_eq!(core.run(next.into_future()).unwrap().0, None); 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_client as client;
extern crate substrate_extrinsic_pool as extrinsic_pool; extern crate substrate_extrinsic_pool as extrinsic_pool;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_state_machine as state_machine; extern crate substrate_state_machine as state_machine;
extern crate tokio_core; extern crate tokio_core;
+30 -26
View File
@@ -23,7 +23,9 @@ mod tests;
use std::sync::Arc; use std::sync::Arc;
use client::{self, Client, CallExecutor}; 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::storage::{StorageKey, StorageData};
use primitives::hexdisplay::HexDisplay; use primitives::hexdisplay::HexDisplay;
use state_machine; use state_machine;
@@ -32,65 +34,67 @@ use self::error::Result;
build_rpc_trait! { build_rpc_trait! {
/// Polkadot state API /// Polkadot state API
pub trait StateApi { pub trait StateApi<Hash> {
/// Returns a storage entry. /// Returns a storage entry at a specific block's state.
#[rpc(name = "state_getStorageAt")] #[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")] #[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")] #[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")] #[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")] #[rpc(name = "state_getStorageHash")]
fn storage_hash(&self, StorageKey) -> Result<Hash>; 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")] #[rpc(name = "state_getStorageSize")]
fn storage_size(&self, StorageKey) -> Result<u64>; fn storage_size(&self, StorageKey) -> Result<u64>;
/// Returns a storage entry. /// Returns a storage entry at the best block.
#[rpc(name = "state_getStorage")] #[rpc(name = "state_getStorage")]
fn storage(&self, StorageKey) -> Result<StorageData>; fn storage(&self, StorageKey) -> Result<StorageData>;
/// Call a contract. /// Call a contract at the best block.
#[rpc(name = "state_call")] #[rpc(name = "state_call")]
fn call(&self, String, Vec<u8>) -> Result<Vec<u8>>; fn call(&self, String, Vec<u8>) -> Result<Vec<u8>>;
} }
} }
impl<B, E> StateApi for Arc<Client<B, E>> where impl<B, E, Block> StateApi<Block::Hash> for Arc<Client<B, E, Block>> where
B: client::backend::Backend + Send + Sync + 'static, Block: BlockT + 'static,
E: CallExecutor + Send + Sync + 'static, B: client::backend::Backend<Block> + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>, 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)); 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)); 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> { fn storage_hash_at(&self, key: StorageKey, block: Block::Hash) -> Result<Block::Hash> {
self.storage_at(key, block).map(|x| blake2_256(&x.0).into()) 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) 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) 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-state-machine = { path = "../state-machine", optional = true }
substrate-primitives = { path = "../primitives", default_features = false } substrate-primitives = { path = "../primitives", default_features = false }
substrate-codec = { path = "../codec", 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 } ed25519 = { path = "../ed25519", optional = true }
[features] [features]
-34
View File
@@ -30,37 +30,3 @@ include!("../with_std.rs");
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
include!("../without_std.rs"); 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]) ).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] { pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] {
triehash::ordered_trie_root(serialised_values.iter().map(|s| s.to_vec())).0 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. /// Verify a ed25519 signature.
pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
ed25519::verify(sig, msg, pubkey) ed25519::verify(sig, msg, pubkey)
@@ -138,6 +138,27 @@ pub fn enumerated_trie_root(values: &[&[u8]]) -> [u8; 32] {
result 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. /// The current relay chain identifier.
pub fn chain_id() -> u64 { pub fn chain_id() -> u64 {
unsafe { unsafe {
@@ -20,6 +20,7 @@ pub use std::cell;
pub use std::clone; pub use std::clone;
pub use std::cmp; pub use std::cmp;
pub use std::fmt; pub use std::fmt;
pub use std::hash;
pub use std::iter; pub use std::iter;
pub use std::marker; pub use std::marker;
pub use std::mem; pub use std::mem;
@@ -29,6 +29,7 @@ pub use core::cell;
pub use core::clone; pub use core::clone;
pub use core::cmp; pub use core::cmp;
pub use core::fmt; pub use core::fmt;
pub use core::hash;
pub use core::intrinsics; pub use core::intrinsics;
pub use core::iter; pub use core::iter;
pub use core::marker; pub use core::marker;
@@ -20,7 +20,6 @@ pub use rstd::prelude::{Vec, Clone, Eq, PartialEq};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::fmt; pub use std::fmt;
pub use rstd::result; pub use rstd::result;
pub use rstd::marker::PhantomData;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use serde; use serde;
pub use codec::{Slicable, Input}; pub use codec::{Slicable, Input};
@@ -47,6 +46,10 @@ pub trait AuxCallable {
type Call: AuxDispatchable + Slicable + Clone + PartialEq + Eq; 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")] #[cfg(feature = "std")]
pub trait Callable { pub trait Callable {
type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq; type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq;
@@ -56,6 +59,10 @@ pub trait Callable {
type Call: Dispatchable + Slicable + Clone + PartialEq + Eq; 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")] #[cfg(feature = "std")]
pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {} pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {}
@@ -68,26 +75,43 @@ pub trait Parameter: Slicable + Clone + Eq {}
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
impl<T> Parameter for T where T: Slicable + Clone + Eq {} 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 /// Declare a struct for this module, then implement dispatch logic to create a pairing of several
/// dispatch traits and enums. /// dispatch traits and enums.
#[macro_export] #[macro_export]
macro_rules! decl_module { macro_rules! decl_module {
( (
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>; pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$($rest:tt)* $($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! { decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>; impl for $mod_type<$trait_instance: $trait_name>;
$($rest)* $($rest)*
} }
}; };
( (
$(#[$attr:meta])*
struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>; struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$($rest:tt)* $($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! { decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>; impl for $mod_type<$trait_instance: $trait_name>;
$($rest)* $($rest)*
@@ -101,6 +125,7 @@ macro_rules! decl_dispatch {
// WITHOUT AUX // WITHOUT AUX
( (
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident { pub enum $call_type:ident {
$( $(
fn $fn_name:ident( fn $fn_name:ident(
@@ -115,6 +140,7 @@ macro_rules! decl_dispatch {
) => { ) => {
__decl_dispatch_module_without_aux! { __decl_dispatch_module_without_aux! {
impl for $mod_type<$trait_instance: $trait_name>; impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type; pub enum $call_type;
$( $(
fn $fn_name( $( $param_name: $param ),* ) -> $result = $id; fn $fn_name( $( $param_name: $param ),* ) -> $result = $id;
@@ -128,6 +154,7 @@ macro_rules! decl_dispatch {
// WITH AUX // WITH AUX
( (
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident where aux: $aux_type:ty { pub enum $call_type:ident where aux: $aux_type:ty {
$( $(
fn $fn_name:ident(aux fn $fn_name:ident(aux
@@ -142,6 +169,7 @@ macro_rules! decl_dispatch {
) => { ) => {
__decl_dispatch_module_with_aux! { __decl_dispatch_module_with_aux! {
impl for $mod_type<$trait_instance: $trait_name>; impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type where aux: $aux_type; pub enum $call_type where aux: $aux_type;
$( $(
fn $fn_name(aux $(, $param_name: $param )*) -> $result = $id; fn $fn_name(aux $(, $param_name: $param )*) -> $result = $id;
@@ -172,6 +200,7 @@ macro_rules! decl_dispatch {
macro_rules! __decl_dispatch_module_without_aux { macro_rules! __decl_dispatch_module_without_aux {
( (
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident; pub enum $call_type:ident;
$( $(
fn $fn_name:ident( fn $fn_name:ident(
@@ -185,6 +214,7 @@ macro_rules! __decl_dispatch_module_without_aux {
) => { ) => {
__decl_dispatch_module_common! { __decl_dispatch_module_common! {
impl for $mod_type<$trait_instance: $trait_name>; impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type; pub enum $call_type;
$( fn $fn_name( $( $param_name : $param ),* ) -> $result = $id ; )* $( 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 { macro_rules! __decl_dispatch_module_with_aux {
( (
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident where aux: $aux_type:ty; pub enum $call_type:ident where aux: $aux_type:ty;
$( $(
fn $fn_name:ident(aux fn $fn_name:ident(aux
@@ -228,6 +259,7 @@ macro_rules! __decl_dispatch_module_with_aux {
) => { ) => {
__decl_dispatch_module_common! { __decl_dispatch_module_common! {
impl for $mod_type<$trait_instance: $trait_name>; impl for $mod_type<$trait_instance: $trait_name>;
$(#[$attr])*
pub enum $call_type; pub enum $call_type;
$( fn $fn_name( $( $param_name : $param ),* ) -> $result = $id ; )* $( 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. /// Implement a single dispatch modules to create a pairing of a dispatch trait and enum.
#[macro_export]
macro_rules! __decl_dispatch_module_common { macro_rules! __decl_dispatch_module_common {
( (
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$(#[$attr:meta])*
pub enum $call_type:ident; pub enum $call_type:ident;
$( $(
fn $fn_name:ident( fn $fn_name:ident(
@@ -270,10 +303,20 @@ macro_rules! __decl_dispatch_module_common {
= $id:expr ; = $id:expr ;
)* )*
) => { ) => {
#[cfg_attr(feature = "std", derive(Serialize))] #[cfg(feature = "std")]
#[allow(missing_docs)] $(#[$attr])*
pub enum $call_type<$trait_instance: $trait_name> { 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)] #[allow(non_camel_case_types)]
$fn_name ( $( $param ),* ), $fn_name ( $( $param ),* ),
@@ -395,6 +438,7 @@ pub trait IsAuxSubType<T: AuxCallable> {
macro_rules! impl_outer_dispatch { macro_rules! impl_outer_dispatch {
() => (); () => ();
( (
$(#[$attr:meta])*
pub enum $call_type:ident where aux: $aux:ty { pub enum $call_type:ident where aux: $aux:ty {
$( $(
$camelcase:ident = $id:expr, $camelcase:ident = $id:expr,
@@ -402,12 +446,10 @@ macro_rules! impl_outer_dispatch {
} }
$( $rest:tt )* $( $rest:tt )*
) => { ) => {
#[derive(Clone, PartialEq, Eq)] $(#[$attr])*
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[allow(missing_docs)]
pub enum $call_type { pub enum $call_type {
$( $(
$camelcase ( <$camelcase as $crate::dispatch::AuxCallable>::Call ) $camelcase ( $crate::dispatch::AuxCallableCallFor<$camelcase> )
,)* ,)*
} }
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* } impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
@@ -436,6 +478,7 @@ macro_rules! impl_outer_dispatch {
impl_outer_dispatch!{ $($rest)* } impl_outer_dispatch!{ $($rest)* }
}; };
( (
$(#[$attr:meta])*
pub enum $call_type:ident { pub enum $call_type:ident {
$( $(
$camelcase:ident = $id:expr, $camelcase:ident = $id:expr,
@@ -443,12 +486,10 @@ macro_rules! impl_outer_dispatch {
} }
$( $rest:tt )* $( $rest:tt )*
) => { ) => {
#[derive(Clone, PartialEq, Eq)] $(#[$attr])*
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[allow(missing_docs)]
pub enum $call_type { pub enum $call_type {
$( $(
$camelcase ( <$camelcase as $crate::dispatch::Callable>::Call ) $camelcase ( $crate::dispatch::CallableCallFor<$camelcase> )
,)* ,)*
} }
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* } impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
@@ -21,14 +21,6 @@
#[cfg(feature = "std")] #[cfg(feature = "std")]
extern crate serde; 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_std as rstd;
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives; extern crate substrate_primitives as primitives;
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
hex-literal = "0.1.0" hex-literal = "0.1.0"
serde = { version = "1.0", default_features = false } serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../codec", default_features = false } substrate-codec = { path = "../../codec", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false } substrate-primitives = { path = "../../primitives", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", 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"] default = ["std"]
std = [ std = [
"serde/std", "serde/std",
"serde_derive",
"substrate-codec/std", "substrate-codec/std",
"substrate-primitives/std", "substrate-primitives/std",
"substrate-runtime-std/std", "substrate-runtime-std/std",
@@ -25,6 +25,13 @@ extern crate substrate_runtime_std as rstd;
#[macro_use] #[macro_use]
extern crate substrate_runtime_support as runtime_support; 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_io as runtime_io;
extern crate substrate_runtime_primitives as primitives; extern crate substrate_runtime_primitives as primitives;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
@@ -36,8 +43,7 @@ use runtime_support::{storage, Parameter};
use runtime_support::dispatch::Result; use runtime_support::dispatch::Result;
use runtime_support::storage::unhashed::StorageVec; use runtime_support::storage::unhashed::StorageVec;
use primitives::traits::RefInto; use primitives::traits::RefInto;
use substrate_primitives::bft::MisbehaviorReport; use primitives::bft::MisbehaviorReport;
pub const AUTHORITY_AT: &'static [u8] = b":auth:"; pub const AUTHORITY_AT: &'static [u8] = b":auth:";
pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len"; pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len";
@@ -59,9 +65,13 @@ pub trait Trait: system::Trait {
decl_module! { decl_module! {
pub struct Module<T: Trait>; pub struct Module<T: Trait>;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux { 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 { pub enum PrivCall {
fn set_code(new: Vec<u8>) -> Result = 0; fn set_code(new: Vec<u8>) -> Result = 0;
fn set_storage(items: Vec<KeyValue>) -> Result = 1; fn set_storage(items: Vec<KeyValue>) -> Result = 1;
@@ -89,7 +99,7 @@ impl<T: Trait> Module<T> {
} }
/// Report some misbehaviour. /// 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. // TODO.
Ok(()) Ok(())
} }
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
hex-literal = "0.1.0" hex-literal = "0.1.0"
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" } integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
serde = { version = "1.0", default_features = false } serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../../safe-mix", default_features = false} safe-mix = { path = "../../../safe-mix", default_features = false}
substrate-keyring = { path = "../../keyring", optional = true } substrate-keyring = { path = "../../keyring", optional = true }
substrate-codec = { path = "../../codec", default_features = false } substrate-codec = { path = "../../codec", default_features = false }
@@ -25,6 +26,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
default = ["std"] default = ["std"]
std = [ std = [
"serde/std", "serde/std",
"serde_derive",
"safe-mix/std", "safe-mix/std",
"substrate-keyring", "substrate-keyring",
"substrate-codec/std", "substrate-codec/std",
+16 -6
View File
@@ -18,7 +18,12 @@
#![cfg_attr(not(feature = "std"), no_std)] #![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 integer_sqrt;
extern crate substrate_codec as codec; 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; #[cfg(any(feature = "std", test))] extern crate substrate_keyring as keyring;
#[macro_use] extern crate substrate_runtime_std as rstd; #[macro_use] extern crate substrate_runtime_std as rstd;
extern crate substrate_runtime_io as runtime_io; 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_primitives as primitives;
extern crate substrate_runtime_consensus as consensus; extern crate substrate_runtime_consensus as consensus;
extern crate substrate_runtime_democracy as democracy; extern crate substrate_runtime_democracy as democracy;
@@ -36,8 +41,8 @@ extern crate substrate_runtime_system as system;
use rstd::prelude::*; use rstd::prelude::*;
use primitives::traits::{Zero, One, RefInto, As}; use primitives::traits::{Zero, One, RefInto, As};
use runtime_support::{StorageValue, StorageMap}; use substrate_runtime_support::{StorageValue, StorageMap};
use runtime_support::dispatch::Result; use substrate_runtime_support::dispatch::Result;
pub mod voting; pub mod voting;
@@ -101,6 +106,8 @@ pub trait Trait: democracy::Trait {}
decl_module! { decl_module! {
pub struct Module<T: Trait>; pub struct Module<T: Trait>;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux { pub enum Call where aux: T::PublicAux {
fn set_approvals(aux, votes: Vec<bool>, index: VoteIndex) -> Result = 0; 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; 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 submit_candidacy(aux, slot: u32) -> Result = 3;
fn present_winner(aux, candidate: T::AccountId, total: T::Balance, index: VoteIndex) -> Result = 4; fn present_winner(aux, candidate: T::AccountId, total: T::Balance, index: VoteIndex) -> Result = 4;
} }
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum PrivCall { pub enum PrivCall {
fn set_desired_seats(count: u32) -> Result = 0; fn set_desired_seats(count: u32) -> Result = 0;
fn remove_member(who: T::AccountId) -> Result = 1; fn remove_member(who: T::AccountId) -> Result = 1;
@@ -597,10 +606,11 @@ mod tests {
pub use runtime_io::with_externalities; pub use runtime_io::with_externalities;
pub use substrate_primitives::H256; pub use substrate_primitives::H256;
use primitives::BuildExternalities; use primitives::BuildExternalities;
use primitives::traits::{HasPublicAux, Identity}; use primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
use primitives::testing::{Digest, Header}; use primitives::testing::{Digest, Header};
impl_outer_dispatch! { impl_outer_dispatch! {
#[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)]
pub enum Proposal { pub enum Proposal {
Staking = 0, Staking = 0,
Democracy = 1, Democracy = 1,
@@ -619,7 +629,7 @@ mod tests {
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
type Hashing = runtime_io::BlakeTwo256; type Hashing = BlakeTwo256;
type Digest = Digest; type Digest = Digest;
type AccountId = u64; type AccountId = u64;
type Header = Header; type Header = Header;
@@ -18,20 +18,24 @@
use rstd::prelude::*; use rstd::prelude::*;
use rstd::borrow::Borrow; use rstd::borrow::Borrow;
use primitives::traits::{Executable, RefInto}; use primitives::traits::{Executable, RefInto, Hashing};
use runtime_io::{Hashing, print}; use runtime_io::print;
use runtime_support::{StorageValue, StorageMap, IsSubType}; use substrate_runtime_support::dispatch::Result;
use runtime_support::dispatch::Result; use substrate_runtime_support::{StorageValue, StorageMap, IsSubType};
use {system, democracy}; use {system, democracy};
use super::{Trait, Module as Council}; use super::{Trait, Module as Council};
decl_module! { decl_module! {
pub struct Module<T: Trait>; pub struct Module<T: Trait>;
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Call where aux: T::PublicAux { pub enum Call where aux: T::PublicAux {
fn propose(aux, proposal: Box<T::Proposal>) -> Result = 0; fn propose(aux, proposal: Box<T::Proposal>) -> Result = 0;
fn vote(aux, proposal: T::Hash, approve: bool) -> Result = 1; fn vote(aux, proposal: T::Hash, approve: bool) -> Result = 1;
fn veto(aux, proposal_hash: T::Hash) -> Result = 2; fn veto(aux, proposal_hash: T::Hash) -> Result = 2;
} }
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum PrivCall { pub enum PrivCall {
fn set_cooloff_period(blocks: T::BlockNumber) -> Result = 0; fn set_cooloff_period(blocks: T::BlockNumber) -> Result = 0;
fn set_voting_period(blocks: T::BlockNumber) -> Result = 1; fn set_voting_period(blocks: T::BlockNumber) -> Result = 1;
@@ -214,7 +218,7 @@ impl<T: Trait> Executable for Council<T> {
mod tests { mod tests {
use super::*; use super::*;
use ::tests::*; use ::tests::*;
use runtime_support::Hashable; use substrate_runtime_support::Hashable;
use democracy::VoteThreshold; use democracy::VoteThreshold;
type CouncilVoting = super::Module<Test>; type CouncilVoting = super::Module<Test>;
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
hex-literal = "0.1.0" hex-literal = "0.1.0"
serde = { version = "1.0", default_features = false } serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../../safe-mix", default_features = false} safe-mix = { path = "../../../safe-mix", default_features = false}
substrate-codec = { path = "../../codec", default_features = false } substrate-codec = { path = "../../codec", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false } substrate-primitives = { path = "../../primitives", default_features = false }
@@ -22,6 +23,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
default = ["std"] default = ["std"]
std = [ std = [
"serde/std", "serde/std",
"serde_derive",
"safe-mix/std", "safe-mix/std",
"substrate-codec/std", "substrate-codec/std",
"substrate-primitives/std", "substrate-primitives/std",

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