mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 17:18:03 +00:00
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:
committed by
Robert Habermeier
parent
4e844760a3
commit
b94cf078af
Generated
+700
-556
File diff suppressed because it is too large
Load Diff
@@ -49,17 +49,18 @@ pub mod error;
|
||||
|
||||
use std::sync::Arc;
|
||||
use client::genesis;
|
||||
use codec::Slicable;
|
||||
use demo_primitives::Hash;
|
||||
use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
|
||||
SessionConfig, StakingConfig, BuildExternalities};
|
||||
use demo_runtime::{Block, Header, UncheckedExtrinsic};
|
||||
use futures::{Future, Sink, Stream};
|
||||
|
||||
struct DummyPool;
|
||||
impl extrinsic_pool::api::ExtrinsicPool for DummyPool {
|
||||
impl extrinsic_pool::api::ExtrinsicPool<UncheckedExtrinsic, Hash> for DummyPool {
|
||||
type Error = extrinsic_pool::txpool::Error;
|
||||
|
||||
fn submit(&self, _: Vec<primitives::block::Extrinsic>)
|
||||
-> Result<Vec<primitives::block::ExtrinsicHash>, Self::Error>
|
||||
fn submit(&self, _: Vec<UncheckedExtrinsic>)
|
||||
-> Result<Vec<Hash>, Self::Error>
|
||||
{
|
||||
Err("unimplemented".into())
|
||||
}
|
||||
@@ -102,8 +103,8 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
|
||||
struct GenesisBuilder;
|
||||
|
||||
impl client::GenesisBuilder for GenesisBuilder {
|
||||
fn build(self) -> (primitives::Header, Vec<(Vec<u8>, Vec<u8>)>) {
|
||||
impl client::GenesisBuilder<Block> for GenesisBuilder {
|
||||
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
|
||||
let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"];
|
||||
let genesis_config = GenesisConfig {
|
||||
consensus: Some(ConsensusConfig {
|
||||
@@ -113,7 +114,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
system: None,
|
||||
// block_time: 5, // 5 second block time.
|
||||
session: Some(SessionConfig {
|
||||
validators: vec![god_key.clone()],
|
||||
validators: vec![god_key.clone().into()],
|
||||
session_length: 720, // that's 1 hour per session.
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
@@ -121,7 +122,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
intentions: vec![],
|
||||
transaction_base_fee: 100,
|
||||
transaction_byte_fee: 1,
|
||||
balances: vec![(god_key.clone(), 1u64 << 63)].into_iter().collect(),
|
||||
balances: vec![(god_key.clone().into(), 1u64 << 63)].into_iter().collect(),
|
||||
validator_count: 12,
|
||||
sessions_per_era: 24, // 24 hours per era.
|
||||
bonding_duration: 90, // 90 days per bond.
|
||||
@@ -149,8 +150,8 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
};
|
||||
|
||||
let storage = genesis_config.build_externalities();
|
||||
let block = genesis::construct_genesis_block(&storage);
|
||||
(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
|
||||
let block = genesis::construct_genesis_block::<Block>(&storage);
|
||||
(block.header, storage.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
let _rpc_servers = {
|
||||
let handler = || {
|
||||
let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote());
|
||||
rpc::rpc_handler(client.clone(), chain, Arc::new(DummyPool), DummySystem)
|
||||
rpc::rpc_handler::<Block, _, _, _, _>(client.clone(), chain, Arc::new(DummyPool), DummySystem)
|
||||
};
|
||||
let http_address = "127.0.0.1:9933".parse().unwrap();
|
||||
let ws_address = "127.0.0.1:9944".parse().unwrap();
|
||||
|
||||
@@ -42,7 +42,7 @@ mod tests {
|
||||
use super::Executor;
|
||||
use substrate_executor::WasmExecutor;
|
||||
use codec::{Slicable, Joiner};
|
||||
use keyring::Keyring::{self, Alice, Bob};
|
||||
use keyring::Keyring;
|
||||
use runtime_support::{Hashable, StorageValue, StorageMap};
|
||||
use state_machine::{CodeExecutor, TestExternalities};
|
||||
use primitives::twox_128;
|
||||
@@ -63,13 +63,21 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
fn alice() -> Hash {
|
||||
Keyring::Alice.to_raw_public().into()
|
||||
}
|
||||
|
||||
fn bob() -> Hash {
|
||||
Keyring::Bob.to_raw_public().into()
|
||||
}
|
||||
|
||||
fn xt() -> UncheckedExtrinsic {
|
||||
let extrinsic = Extrinsic {
|
||||
signed: Alice.into(),
|
||||
signed: alice(),
|
||||
index: 0,
|
||||
function: Call::Staking(staking::Call::transfer::<Concrete>(Bob.into(), 69)),
|
||||
function: Call::Staking(staking::Call::transfer::<Concrete>(bob(), 69)),
|
||||
};
|
||||
let signature = Keyring::from_raw_public(extrinsic.signed).unwrap()
|
||||
let signature = Keyring::from_raw_public(extrinsic.signed.0).unwrap()
|
||||
.sign(&extrinsic.encode()).into();
|
||||
|
||||
UncheckedExtrinsic { extrinsic, signature }
|
||||
@@ -82,7 +90,7 @@ mod tests {
|
||||
#[test]
|
||||
fn panic_execution_with_foreign_code_gives_error() {
|
||||
let mut t: TestExternalities = map![
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
@@ -97,7 +105,7 @@ mod tests {
|
||||
#[test]
|
||||
fn panic_execution_with_native_equivalent_code_gives_error() {
|
||||
let mut t: TestExternalities = map![
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
@@ -112,7 +120,7 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
let mut t: TestExternalities = map![
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
@@ -124,15 +132,15 @@ mod tests {
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 42);
|
||||
assert_eq!(Staking::balance(&Bob), 69);
|
||||
assert_eq!(Staking::balance(&alice()), 42);
|
||||
assert_eq!(Staking::balance(&bob()), 69);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn successful_execution_with_foreign_code_gives_ok() {
|
||||
let mut t: TestExternalities = map![
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
@@ -144,26 +152,26 @@ mod tests {
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 42);
|
||||
assert_eq!(Staking::balance(&Bob), 69);
|
||||
assert_eq!(Staking::balance(&alice()), 42);
|
||||
assert_eq!(Staking::balance(&bob()), 69);
|
||||
});
|
||||
}
|
||||
|
||||
fn new_test_ext() -> TestExternalities {
|
||||
use keyring::Keyring::*;
|
||||
let three = [3u8; 32];
|
||||
let three = [3u8; 32].into();
|
||||
GenesisConfig {
|
||||
consensus: Some(Default::default()),
|
||||
system: Some(Default::default()),
|
||||
session: Some(SessionConfig {
|
||||
session_length: 2,
|
||||
validators: vec![One.into(), Two.into(), three],
|
||||
validators: vec![One.to_raw_public().into(), Two.to_raw_public().into(), three],
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
sessions_per_era: 2,
|
||||
current_era: 0,
|
||||
balances: vec![(Alice.into(), 111)],
|
||||
intentions: vec![Alice.into(), Bob.into(), Charlie.into()],
|
||||
balances: vec![(alice(), 111)],
|
||||
intentions: vec![alice(), bob(), Charlie.to_raw_public().into()],
|
||||
validator_count: 3,
|
||||
bonding_duration: 0,
|
||||
transaction_base_fee: 1,
|
||||
@@ -178,7 +186,7 @@ mod tests {
|
||||
use triehash::ordered_trie_root;
|
||||
|
||||
let extrinsics = extrinsics.into_iter().map(|extrinsic| {
|
||||
let signature = Pair::from(Keyring::from_public(Public::from_raw(extrinsic.signed)).unwrap())
|
||||
let signature = Pair::from(Keyring::from_public(Public::from_raw(extrinsic.signed.0)).unwrap())
|
||||
.sign(&extrinsic.encode()).into();
|
||||
|
||||
UncheckedExtrinsic { extrinsic, signature }
|
||||
@@ -204,9 +212,9 @@ mod tests {
|
||||
[69u8; 32].into(),
|
||||
hex!("76b0393b4958d3cb98bb51d9f4edb316af48485142b8721e94c3b52c75ec3243").into(),
|
||||
vec![Extrinsic {
|
||||
signed: Alice.into(),
|
||||
signed: alice(),
|
||||
index: 0,
|
||||
function: Call::Staking(staking::Call::transfer(Bob.into(), 69)),
|
||||
function: Call::Staking(staking::Call::transfer(bob(), 69)),
|
||||
}]
|
||||
)
|
||||
}
|
||||
@@ -218,14 +226,14 @@ mod tests {
|
||||
hex!("8ae9828a5988459d35fb428086170dead660176ee0766e89bc1a4b48153d4e88").into(),
|
||||
vec![
|
||||
Extrinsic {
|
||||
signed: Bob.into(),
|
||||
signed: bob(),
|
||||
index: 0,
|
||||
function: Call::Staking(staking::Call::transfer(Alice.into(), 5)),
|
||||
function: Call::Staking(staking::Call::transfer(alice(), 5)),
|
||||
},
|
||||
Extrinsic {
|
||||
signed: Alice.into(),
|
||||
signed: alice(),
|
||||
index: 1,
|
||||
function: Call::Staking(staking::Call::transfer(Bob.into(), 15)),
|
||||
function: Call::Staking(staking::Call::transfer(bob(), 15)),
|
||||
}
|
||||
]
|
||||
)
|
||||
@@ -238,15 +246,15 @@ mod tests {
|
||||
Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 41);
|
||||
assert_eq!(Staking::balance(&Bob), 69);
|
||||
assert_eq!(Staking::balance(&alice()), 41);
|
||||
assert_eq!(Staking::balance(&bob()), 69);
|
||||
});
|
||||
|
||||
Executor::new().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 30);
|
||||
assert_eq!(Staking::balance(&Bob), 78);
|
||||
assert_eq!(Staking::balance(&alice()), 30);
|
||||
assert_eq!(Staking::balance(&bob()), 78);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -257,22 +265,22 @@ mod tests {
|
||||
WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 41);
|
||||
assert_eq!(Staking::balance(&Bob), 69);
|
||||
assert_eq!(Staking::balance(&alice()), 41);
|
||||
assert_eq!(Staking::balance(&bob()), 69);
|
||||
});
|
||||
|
||||
WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 30);
|
||||
assert_eq!(Staking::balance(&Bob), 78);
|
||||
assert_eq!(Staking::balance(&alice()), 30);
|
||||
assert_eq!(Staking::balance(&bob()), 78);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panic_execution_gives_error() {
|
||||
let mut t: TestExternalities = map![
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
|
||||
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
@@ -288,7 +296,7 @@ mod tests {
|
||||
#[test]
|
||||
fn successful_execution_gives_ok() {
|
||||
let mut t: TestExternalities = map![
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(*Alice)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
|
||||
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
@@ -301,8 +309,8 @@ mod tests {
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Staking::balance(&Alice), 42);
|
||||
assert_eq!(Staking::balance(&Bob), 69);
|
||||
assert_eq!(Staking::balance(&alice()), 42);
|
||||
assert_eq!(Staking::balance(&bob()), 69);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ pub type BlockNumber = u64;
|
||||
|
||||
/// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost
|
||||
/// certainly continue to be the same as the substrate's `AuthorityId`.
|
||||
pub type AccountId = primitives::AuthorityId;
|
||||
pub type AccountId = ::primitives::H256;
|
||||
|
||||
/// Balance of an account.
|
||||
pub type Balance = u64;
|
||||
|
||||
@@ -22,11 +22,18 @@
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_support;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
extern crate substrate_runtime_std as rstd;
|
||||
extern crate substrate_runtime_consensus as consensus;
|
||||
extern crate substrate_runtime_council as council;
|
||||
@@ -39,10 +46,9 @@ extern crate substrate_runtime_timestamp as timestamp;
|
||||
extern crate demo_primitives;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use runtime_io::BlakeTwo256;
|
||||
use demo_primitives::{AccountId, Balance, BlockNumber, Hash, Index, SessionKey, Signature};
|
||||
use runtime_primitives::generic;
|
||||
use runtime_primitives::traits::{Identity, HasPublicAux};
|
||||
use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256};
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub use runtime_primitives::BuildExternalities;
|
||||
@@ -61,7 +67,7 @@ impl system::Trait for Concrete {
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = generic::Digest<Vec<u8>>;
|
||||
type AccountId = AccountId;
|
||||
type Header = generic::Header<BlockNumber, Hash, Vec<u8>>;
|
||||
type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
|
||||
}
|
||||
|
||||
/// System module for this concrete runtime.
|
||||
@@ -84,8 +90,16 @@ impl timestamp::Trait for Concrete {
|
||||
/// Timestamp module for this concrete runtime.
|
||||
pub type Timestamp = timestamp::Module<Concrete>;
|
||||
|
||||
/// Session key conversion.
|
||||
pub struct SessionKeyConversion;
|
||||
impl Convert<AccountId, SessionKey> for SessionKeyConversion {
|
||||
fn convert(a: AccountId) -> SessionKey {
|
||||
a.0
|
||||
}
|
||||
}
|
||||
|
||||
impl session::Trait for Concrete {
|
||||
type ConvertAccountIdToSessionKey = Identity;
|
||||
type ConvertAccountIdToSessionKey = SessionKeyConversion;
|
||||
}
|
||||
|
||||
/// Session module for this concrete runtime.
|
||||
@@ -114,6 +128,8 @@ pub type Council = council::Module<Concrete>;
|
||||
pub type CouncilVoting = council::voting::Module<Concrete>;
|
||||
|
||||
impl_outer_dispatch! {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
|
||||
Consensus = 0,
|
||||
Session = 1,
|
||||
@@ -124,6 +140,8 @@ impl_outer_dispatch! {
|
||||
CouncilVoting = 7,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
Consensus = 0,
|
||||
Session = 1,
|
||||
@@ -135,9 +153,9 @@ impl_outer_dispatch! {
|
||||
}
|
||||
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, Hash, Vec<u8>>;
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
|
||||
/// Block type as expected by this runtime.
|
||||
pub type Block = generic::Block<BlockNumber, Hash, Vec<u8>, AccountId, Index, Call, Signature>;
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
|
||||
/// Extrinsic type as expected by this runtime.
|
||||
|
||||
Generated
+246
-192
@@ -11,19 +11,9 @@ name = "base58"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bigint"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -37,33 +27,55 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.1"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.4"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "coco"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.1.6"
|
||||
@@ -73,8 +85,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "demo-primitives"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-primitives 0.1.0",
|
||||
@@ -110,20 +122,15 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-primitives 0.1.0",
|
||||
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "elastic-array"
|
||||
version = "0.9.0"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -134,15 +141,37 @@ name = "environmental"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-bigint"
|
||||
name = "ethbloom"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-types-serialize"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -154,12 +183,23 @@ dependencies = [
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -183,16 +223,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal-impl"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -205,12 +245,12 @@ source = "git+https://github.com/paritytech/integer-sqrt-rs.git#886e9cb983c46498
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -220,12 +260,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.36"
|
||||
version = "0.2.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -241,9 +281,14 @@ name = "log"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.3.0"
|
||||
@@ -264,7 +309,7 @@ name = "num_cpus"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -280,9 +325,9 @@ name = "parity-wasm"
|
||||
version = "0.27.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -290,37 +335,29 @@ name = "parity-wasm"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.2.10"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plain_hasher"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.4.0"
|
||||
@@ -334,12 +371,20 @@ name = "proc-macro-hack-impl"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pwasm-alloc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pwasm-libc 0.1.0",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -351,15 +396,18 @@ name = "pwasm-utils"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
@@ -367,7 +415,7 @@ version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -377,7 +425,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -386,19 +434,19 @@ name = "rayon"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.3.0"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -408,20 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -437,17 +484,17 @@ source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "safe-mix"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -457,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.6.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -470,31 +517,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.27"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.27"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -511,8 +549,8 @@ name = "substrate-keyring"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ed25519 0.1.0",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -520,25 +558,26 @@ name = "substrate-primitives"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
|
||||
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
|
||||
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-consensus"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -563,10 +602,11 @@ dependencies = [
|
||||
name = "substrate-runtime-council"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-keyring 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -585,9 +625,10 @@ dependencies = [
|
||||
name = "substrate-runtime-democracy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-consensus 0.1.0",
|
||||
@@ -604,8 +645,8 @@ dependencies = [
|
||||
name = "substrate-runtime-executive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
"substrate-runtime-primitives 0.1.0",
|
||||
@@ -620,12 +661,12 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"ed25519 0.1.0",
|
||||
"environmental 0.1.0",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"substrate-state-machine 0.1.0",
|
||||
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -634,8 +675,8 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -647,21 +688,22 @@ dependencies = [
|
||||
name = "substrate-runtime-sandbox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-session"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-keyring 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -677,9 +719,10 @@ dependencies = [
|
||||
name = "substrate-runtime-staking"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-keyring 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -700,7 +743,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"pwasm-alloc 0.1.0",
|
||||
"pwasm-libc 0.1.0",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -708,9 +751,9 @@ name = "substrate-runtime-support"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ed25519 0.1.0",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -721,9 +764,9 @@ dependencies = [
|
||||
name = "substrate-runtime-system"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -736,8 +779,9 @@ dependencies = [
|
||||
name = "substrate-runtime-timestamp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -751,43 +795,39 @@ dependencies = [
|
||||
name = "substrate-state-machine"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-primitives 0.1.0",
|
||||
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triehash"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -803,14 +843,25 @@ name = "uint"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -820,10 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasmi"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -850,32 +901,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
[metadata]
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
|
||||
"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
|
||||
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
|
||||
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
|
||||
"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
|
||||
"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
||||
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
|
||||
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
|
||||
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
|
||||
"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
|
||||
"checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
|
||||
"checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6"
|
||||
"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002"
|
||||
"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
|
||||
"checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
|
||||
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
|
||||
"checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb"
|
||||
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631"
|
||||
"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
|
||||
"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a"
|
||||
"checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "<none>"
|
||||
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
|
||||
"checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
|
||||
"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
|
||||
"checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206"
|
||||
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
|
||||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
|
||||
@@ -883,39 +938,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd"
|
||||
"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe"
|
||||
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
|
||||
"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8"
|
||||
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
|
||||
"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
|
||||
"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
|
||||
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
|
||||
"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892"
|
||||
"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46"
|
||||
"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
|
||||
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
||||
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
|
||||
"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
|
||||
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
|
||||
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
|
||||
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
|
||||
"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9"
|
||||
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
|
||||
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
|
||||
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
|
||||
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
|
||||
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
|
||||
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
|
||||
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
|
||||
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
|
||||
"checksum serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
|
||||
"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
|
||||
"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7"
|
||||
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0"
|
||||
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
|
||||
"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
|
||||
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
|
||||
"checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce"
|
||||
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435"
|
||||
"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
|
||||
"checksum wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26b20dbeb7caee04597a5d2c93e2b3e64872c6ea2af732d7ad49dbec44067c35"
|
||||
"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
@@ -17,20 +17,20 @@
|
||||
//! Strongly typed API for full Polkadot client.
|
||||
|
||||
use client::backend::{Backend, LocalBackend};
|
||||
use client::{self, Client, LocalCallExecutor};
|
||||
use client::block_builder::BlockBuilder as ClientBlockBuilder;
|
||||
use client::{Client, LocalCallExecutor};
|
||||
use polkadot_executor::Executor as LocalDispatch;
|
||||
use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
|
||||
use state_machine::{self, OverlayedChanges};
|
||||
use state_machine;
|
||||
|
||||
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
|
||||
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
|
||||
use runtime::{self, Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall, ParachainsCall};
|
||||
use primitives::{AccountId, Block, Header, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
|
||||
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
|
||||
|
||||
use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
|
||||
|
||||
/// A checked block ID used for the substrate-client implementation of CheckedBlockId;
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CheckedId(pub BlockId);
|
||||
pub struct CheckedId(pub(crate) BlockId);
|
||||
|
||||
impl CheckedBlockId for CheckedId {
|
||||
fn block_id(&self) -> &BlockId {
|
||||
@@ -44,14 +44,16 @@ macro_rules! with_runtime {
|
||||
($client: ident, $at: expr, $exec: expr) => {{
|
||||
let parent = $at.block_id();
|
||||
let header = Header {
|
||||
parent_hash: $client.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?,
|
||||
number: $client.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1,
|
||||
parent_hash: $client.block_hash_from_id(&parent)?
|
||||
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
|
||||
number: $client.block_number_from_id(&parent)?
|
||||
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))? + 1,
|
||||
state_root: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
digest: Default::default(),
|
||||
};
|
||||
|
||||
$client.state_at(parent).map_err(Error::from).and_then(|state| {
|
||||
$client.state_at(&parent).map_err(Error::from).and_then(|state| {
|
||||
let mut changes = Default::default();
|
||||
let mut ext = state_machine::Ext::new(&mut changes, &state);
|
||||
|
||||
@@ -63,105 +65,28 @@ macro_rules! with_runtime {
|
||||
}}
|
||||
}
|
||||
|
||||
/// A polkadot block builder.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClientBlockBuilder<S> {
|
||||
parent: BlockId,
|
||||
changes: OverlayedChanges,
|
||||
state: S,
|
||||
header: Header,
|
||||
timestamp: Timestamp,
|
||||
extrinsics: Vec<UncheckedExtrinsic>,
|
||||
}
|
||||
|
||||
impl<S: state_machine::Backend> ClientBlockBuilder<S>
|
||||
where S::Error: Into<client::error::Error>
|
||||
{
|
||||
// initialises a block, ready to allow extrinsics to be applied.
|
||||
fn initialise_block(&mut self) -> Result<()> {
|
||||
let result = {
|
||||
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
|
||||
let h = self.header.clone();
|
||||
|
||||
::substrate_executor::with_native_environment(
|
||||
&mut ext,
|
||||
|| runtime::Executive::initialise_block(&h),
|
||||
).map_err(Into::into)
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
self.changes.commit_prospective();
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
self.changes.discard_prospective();
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// executes a extrinsic, inherent or otherwise, without appending to the list.
|
||||
fn apply_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
|
||||
let result = {
|
||||
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
|
||||
|
||||
::substrate_executor::with_native_environment(
|
||||
&mut ext,
|
||||
move || runtime::Executive::apply_extrinsic(extrinsic),
|
||||
).map_err(Into::into)
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
self.changes.commit_prospective();
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
self.changes.discard_prospective();
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: state_machine::Backend> BlockBuilder for ClientBlockBuilder<S>
|
||||
where S::Error: Into<client::error::Error>
|
||||
impl<B: LocalBackend<Block>> BlockBuilder for ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
|
||||
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
|
||||
// Check that this is not an "inherent" extrinsic.
|
||||
if extrinsic.signature == Default::default() {
|
||||
bail!(ErrorKind::PushedInherentTransaction(extrinsic));
|
||||
} else {
|
||||
self.apply_extrinsic(extrinsic.clone())?;
|
||||
self.extrinsics.push(extrinsic);
|
||||
Ok(())
|
||||
}
|
||||
self.push(extrinsic).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn bake(mut self) -> Block {
|
||||
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
|
||||
|
||||
let final_header = ::substrate_executor::with_native_environment(
|
||||
&mut ext,
|
||||
move || runtime::Executive::finalise_block()
|
||||
).expect("all inherent extrinsics pushed; all other extrinsics executed correctly; qed");
|
||||
Block {
|
||||
header: final_header,
|
||||
extrinsics: self.extrinsics,
|
||||
}
|
||||
/// Bake the block with provided extrinsics.
|
||||
fn bake(self) -> Result<Block> {
|
||||
ClientBlockBuilder::bake(self).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>>
|
||||
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
|
||||
impl<B: LocalBackend<Block>> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
|
||||
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
type CheckedBlockId = CheckedId;
|
||||
type BlockBuilder = ClientBlockBuilder<B::State>;
|
||||
type BlockBuilder = ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>;
|
||||
|
||||
fn check_id(&self, id: BlockId) -> Result<CheckedId> {
|
||||
// bail if the code is not the same as the natively linked.
|
||||
if self.code_at(&id)? != LocalDispatch::native_equivalent() {
|
||||
if self.code_at(&id.into())? != LocalDispatch::native_equivalent() {
|
||||
bail!("This node is out of date. Block authoring may not work correctly. Bailing.")
|
||||
}
|
||||
|
||||
@@ -190,8 +115,16 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu
|
||||
|
||||
fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<bool> {
|
||||
use substrate_executor::error::ErrorKind as ExecErrorKind;
|
||||
use codec::Slicable;
|
||||
use runtime::Block as RuntimeBlock;
|
||||
|
||||
let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(block));
|
||||
let encoded = block.encode();
|
||||
let runtime_block = match RuntimeBlock::decode(&mut &encoded[..]) {
|
||||
Some(x) => x,
|
||||
None => return Ok(false),
|
||||
};
|
||||
|
||||
let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(runtime_block));
|
||||
match res {
|
||||
Ok(()) => Ok(true),
|
||||
Err(err) => match err.kind() {
|
||||
@@ -217,85 +150,65 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu
|
||||
with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain))
|
||||
}
|
||||
|
||||
fn build_block(&self, parent: &CheckedId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
|
||||
let parent = parent.block_id();
|
||||
let header = Header {
|
||||
parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?,
|
||||
number: self.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1,
|
||||
state_root: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
digest: Default::default(),
|
||||
};
|
||||
|
||||
let extrinsics = vec![
|
||||
UncheckedExtrinsic {
|
||||
extrinsic: Extrinsic {
|
||||
signed: Default::default(),
|
||||
index: Default::default(),
|
||||
function: Call::Timestamp(TimestampCall::set(timestamp)),
|
||||
},
|
||||
signature: Default::default(),
|
||||
},
|
||||
UncheckedExtrinsic {
|
||||
extrinsic: Extrinsic {
|
||||
signed: Default::default(),
|
||||
index: Default::default(),
|
||||
function: Call::Parachains(ParachainsCall::set_heads(parachains)),
|
||||
},
|
||||
signature: Default::default(),
|
||||
}
|
||||
];
|
||||
|
||||
let mut builder = ClientBlockBuilder {
|
||||
parent: *parent,
|
||||
changes: OverlayedChanges::default(),
|
||||
state: self.state_at(parent)?,
|
||||
header,
|
||||
timestamp,
|
||||
extrinsics: extrinsics.clone(),
|
||||
};
|
||||
|
||||
builder.initialise_block()?;
|
||||
|
||||
for inherent in extrinsics {
|
||||
builder.apply_extrinsic(inherent)?;
|
||||
fn build_block(&self, at: &CheckedId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
|
||||
let mut block_builder = self.new_block_at(at.block_id())?;
|
||||
for inherent in self.inherent_extrinsics(at, timestamp, new_heads)? {
|
||||
block_builder.push(inherent)?;
|
||||
}
|
||||
|
||||
Ok(builder)
|
||||
Ok(block_builder)
|
||||
}
|
||||
|
||||
fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Vec<UncheckedExtrinsic>> {
|
||||
use codec::Slicable;
|
||||
|
||||
with_runtime!(self, at, || {
|
||||
let extrinsics = ::runtime::inherent_extrinsics(timestamp, new_heads);
|
||||
extrinsics.into_iter()
|
||||
.map(|x| x.encode()) // get encoded representation
|
||||
.map(|x| Slicable::decode(&mut &x[..])) // get byte-vec equivalent to extrinsic
|
||||
.map(|x| x.expect("UncheckedExtrinsic has encoded representation equivalent to Vec<u8>; qed"))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: LocalBackend> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>>
|
||||
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
|
||||
impl<B: LocalBackend<Block>> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
|
||||
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use keyring::Keyring;
|
||||
use codec::Slicable;
|
||||
use client::{self, LocalCallExecutor};
|
||||
use client::in_mem::Backend as InMemory;
|
||||
use substrate_executor::NativeExecutionDispatch;
|
||||
use substrate_primitives::{self, Header};
|
||||
use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities};
|
||||
|
||||
fn validators() -> Vec<AccountId> {
|
||||
vec![
|
||||
Keyring::One.to_raw_public().into(),
|
||||
Keyring::Two.to_raw_public().into(),
|
||||
]
|
||||
}
|
||||
|
||||
fn session_keys() -> Vec<SessionKey> {
|
||||
vec![
|
||||
Keyring::One.to_raw_public(),
|
||||
Keyring::Two.to_raw_public(),
|
||||
]
|
||||
}
|
||||
|
||||
fn client() -> Client<InMemory, LocalCallExecutor<InMemory, NativeExecutor<LocalDispatch>>> {
|
||||
fn client() -> Client<InMemory<Block>, LocalCallExecutor<InMemory<Block>, NativeExecutor<LocalDispatch>>, Block> {
|
||||
struct GenesisBuilder;
|
||||
|
||||
impl client::GenesisBuilder for GenesisBuilder {
|
||||
impl client::GenesisBuilder<Block> for GenesisBuilder {
|
||||
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
|
||||
let genesis_config = GenesisConfig {
|
||||
consensus: Some(ConsensusConfig {
|
||||
code: LocalDispatch::native_equivalent().to_vec(),
|
||||
authorities: validators(),
|
||||
authorities: session_keys(),
|
||||
}),
|
||||
system: None,
|
||||
session: Some(SessionConfig {
|
||||
@@ -309,8 +222,8 @@ mod tests {
|
||||
};
|
||||
|
||||
let storage = genesis_config.build_externalities();
|
||||
let block = ::client::genesis::construct_genesis_block(&storage);
|
||||
(substrate_primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
|
||||
let block = ::client::genesis::construct_genesis_block::<Block>(&storage);
|
||||
(block.header, storage.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,18 +233,36 @@ mod tests {
|
||||
#[test]
|
||||
fn gets_session_and_validator_keys() {
|
||||
let client = client();
|
||||
let id = client.check_id(BlockId::Number(0)).unwrap();
|
||||
assert_eq!(client.session_keys(&id).unwrap(), validators());
|
||||
let id = client.check_id(BlockId::number(0)).unwrap();
|
||||
assert_eq!(client.session_keys(&id).unwrap(), session_keys());
|
||||
assert_eq!(client.validators(&id).unwrap(), validators());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_block() {
|
||||
fn build_block_implicit_succeeds() {
|
||||
let client = client();
|
||||
|
||||
let id = client.check_id(BlockId::Number(0)).unwrap();
|
||||
let id = client.check_id(BlockId::number(0)).unwrap();
|
||||
let block_builder = client.build_block(&id, 1_000_000, Vec::new()).unwrap();
|
||||
let block = block_builder.bake();
|
||||
let block = block_builder.bake().unwrap();
|
||||
|
||||
assert_eq!(block.header.number, 1);
|
||||
assert!(block.header.extrinsics_root != Default::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_block_with_inherent_succeeds() {
|
||||
let client = client();
|
||||
|
||||
let id = client.check_id(BlockId::number(0)).unwrap();
|
||||
let inherent = client.inherent_extrinsics(&id, 1_000_000, Vec::new()).unwrap();
|
||||
|
||||
let mut block_builder = client.new_block_at(id.block_id()).unwrap();
|
||||
for extrinsic in inherent {
|
||||
block_builder.push(extrinsic).unwrap();
|
||||
}
|
||||
|
||||
let block = block_builder.bake().unwrap();
|
||||
|
||||
assert_eq!(block.header.number, 1);
|
||||
assert!(block.header.extrinsics_root != Default::default());
|
||||
@@ -339,14 +270,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn fails_to_check_id_for_unknown_block() {
|
||||
assert!(client().check_id(BlockId::Number(100)).is_err());
|
||||
assert!(client().check_id(BlockId::number(100)).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gets_random_seed_with_genesis() {
|
||||
let client = client();
|
||||
|
||||
let id = client.check_id(BlockId::Number(0)).unwrap();
|
||||
let id = client.check_id(BlockId::number(0)).unwrap();
|
||||
assert!(client.random_seed(&id).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//! runtime.
|
||||
|
||||
extern crate polkadot_executor;
|
||||
extern crate polkadot_runtime as runtime;
|
||||
extern crate polkadot_primitives as primitives;
|
||||
extern crate polkadot_runtime as runtime;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_client as client;
|
||||
@@ -37,9 +37,8 @@ extern crate substrate_keyring as keyring;
|
||||
pub mod full;
|
||||
pub mod light;
|
||||
|
||||
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
|
||||
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
|
||||
use runtime::{Block, UncheckedExtrinsic};
|
||||
use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
|
||||
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
|
||||
|
||||
error_chain! {
|
||||
errors {
|
||||
@@ -49,19 +48,9 @@ error_chain! {
|
||||
display("Unknown runtime code")
|
||||
}
|
||||
/// Unknown block ID.
|
||||
UnknownBlock(b: BlockId) {
|
||||
UnknownBlock(b: String) {
|
||||
description("Unknown block")
|
||||
display("Unknown block")
|
||||
}
|
||||
/// Attempted to push an inherent extrinsic manually.
|
||||
PushedInherentTransaction(xt: UncheckedExtrinsic) {
|
||||
description("Attempted to push an inherent extrinsic to a block."),
|
||||
display("Pushed inherent extrinsic to a block: {:?}", xt),
|
||||
}
|
||||
/// Badly-formed extrinsic.
|
||||
BadlyFormedTransaction(xt: UncheckedExtrinsic) {
|
||||
description("Attempted to push a badly-formed extrinsic to a block."),
|
||||
display("Pushed badly-formed extrinsic to a block: {:?}", xt),
|
||||
display("Unknown block {}", b)
|
||||
}
|
||||
/// Some other error.
|
||||
// TODO: allow to be specified as associated type of PolkadotApi
|
||||
@@ -85,28 +74,28 @@ impl From<client::error::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for blocks.
|
||||
pub trait BlockBuilder: Sized {
|
||||
/// Push a non-inherent extrinsic.
|
||||
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
|
||||
|
||||
/// Finalise the block.
|
||||
fn bake(self) -> Block;
|
||||
}
|
||||
|
||||
/// A checked block identifier.
|
||||
pub trait CheckedBlockId: Clone + 'static {
|
||||
/// Yield the underlying block ID.
|
||||
fn block_id(&self) -> &BlockId;
|
||||
}
|
||||
|
||||
/// Build new blocks.
|
||||
pub trait BlockBuilder {
|
||||
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
|
||||
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
|
||||
|
||||
/// Bake the block with provided extrinsics.
|
||||
fn bake(self) -> Result<Block>;
|
||||
}
|
||||
|
||||
/// Trait encapsulating the Polkadot API.
|
||||
///
|
||||
/// All calls should fail when the exact runtime is unknown.
|
||||
pub trait PolkadotApi {
|
||||
/// A checked block ID. Used to avoid redundancy of code check.
|
||||
type CheckedBlockId: CheckedBlockId;
|
||||
/// The type used to build blocks.
|
||||
/// The block builder for this API type.
|
||||
type BlockBuilder: BlockBuilder;
|
||||
|
||||
/// Check whether requests at the given block ID can be served.
|
||||
@@ -146,8 +135,12 @@ pub trait PolkadotApi {
|
||||
/// and an error if we can't evaluate for some reason.
|
||||
fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<bool>;
|
||||
|
||||
/// Create a block builder on top of the parent block.
|
||||
fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>;
|
||||
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
|
||||
fn build_block(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>;
|
||||
|
||||
/// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given.
|
||||
/// This may vary by runtime and will fail if a runtime doesn't follow the same API.
|
||||
fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Vec<UncheckedExtrinsic>>;
|
||||
}
|
||||
|
||||
/// Mark for all Polkadot API implementations, that are making use of state data, stored locally.
|
||||
|
||||
@@ -21,20 +21,30 @@ use client::backend::{Backend, RemoteBackend};
|
||||
use client::{Client, CallExecutor};
|
||||
use codec::Slicable;
|
||||
use state_machine;
|
||||
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
|
||||
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
|
||||
use runtime::{Block, UncheckedExtrinsic};
|
||||
use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
|
||||
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
|
||||
use full::CheckedId;
|
||||
use {PolkadotApi, RemotePolkadotApi, BlockBuilder, CheckedBlockId, Result, ErrorKind};
|
||||
use {PolkadotApi, BlockBuilder, RemotePolkadotApi, CheckedBlockId, Result, ErrorKind};
|
||||
|
||||
/// Remote polkadot API implementation.
|
||||
pub struct RemotePolkadotApiWrapper<B: Backend, E: CallExecutor>(pub Arc<Client<B, E>>);
|
||||
|
||||
/// Block builder for light client.
|
||||
/// Light block builder. TODO: make this work (efficiently)
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LightBlockBuilder;
|
||||
|
||||
impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E>
|
||||
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
|
||||
impl BlockBuilder for LightBlockBuilder {
|
||||
fn push_extrinsic(&mut self, _xt: UncheckedExtrinsic) -> Result<()> {
|
||||
Err(ErrorKind::UnknownRuntime.into())
|
||||
}
|
||||
|
||||
fn bake(self) -> Result<Block> {
|
||||
Err(ErrorKind::UnknownRuntime.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Remote polkadot API implementation.
|
||||
pub struct RemotePolkadotApiWrapper<B: Backend<Block>, E: CallExecutor<Block>>(pub Arc<Client<B, E, Block>>);
|
||||
|
||||
impl<B: Backend<Block>, E: CallExecutor<Block>> PolkadotApi for RemotePolkadotApiWrapper<B, E>
|
||||
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
type CheckedBlockId = CheckedId;
|
||||
type BlockBuilder = LightBlockBuilder;
|
||||
@@ -86,21 +96,15 @@ impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E>
|
||||
Err(ErrorKind::UnknownRuntime.into())
|
||||
}
|
||||
|
||||
fn build_block(&self, _parent: &CheckedId, _timestamp: Timestamp, _parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
|
||||
fn build_block(&self, _at: &Self::CheckedBlockId, _timestamp: Timestamp, _new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
|
||||
Err(ErrorKind::UnknownRuntime.into())
|
||||
}
|
||||
|
||||
fn inherent_extrinsics(&self, _at: &Self::CheckedBlockId, _timestamp: Timestamp, _new_heads: Vec<CandidateReceipt>) -> Result<Vec<Vec<u8>>> {
|
||||
Err(ErrorKind::UnknownRuntime.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: RemoteBackend, E: CallExecutor> RemotePolkadotApi for RemotePolkadotApiWrapper<B, E>
|
||||
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
|
||||
impl<B: RemoteBackend<Block>, E: CallExecutor<Block>> RemotePolkadotApi for RemotePolkadotApiWrapper<B, E>
|
||||
where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{}
|
||||
|
||||
impl BlockBuilder for LightBlockBuilder {
|
||||
fn push_extrinsic(&mut self, _extrinsic: UncheckedExtrinsic) -> Result<()> {
|
||||
Err(ErrorKind::UnknownRuntime.into())
|
||||
}
|
||||
|
||||
fn bake(self) -> Block {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,10 @@ ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
|
||||
fdlimit = "0.1"
|
||||
parking_lot = "0.4"
|
||||
substrate-client = { path = "../../substrate/client" }
|
||||
substrate-network = { path = "../../substrate/network" }
|
||||
substrate-codec = { path = "../../substrate/codec" }
|
||||
substrate-runtime-support = { path = "../../substrate/runtime-support" }
|
||||
substrate-state-machine = { path = "../../substrate/state-machine" }
|
||||
substrate-executor = { path = "../../substrate/executor" }
|
||||
substrate-primitives = { path = "../../substrate/primitives" }
|
||||
substrate-rpc = { path = "../../substrate/rpc" }
|
||||
substrate-rpc-servers = { path = "../../substrate/rpc-servers" }
|
||||
substrate-network = { path = "../../substrate/network" }
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
polkadot-executor = { path = "../executor" }
|
||||
polkadot-runtime = { path = "../runtime" }
|
||||
polkadot-service = { path = "../service" }
|
||||
polkadot-transaction-pool = { path = "../transaction-pool" }
|
||||
|
||||
@@ -21,8 +21,7 @@ use futures::stream::Stream;
|
||||
use service::Service;
|
||||
use tokio_core::reactor;
|
||||
use network::{SyncState, SyncProvider};
|
||||
use runtime_support::Hashable;
|
||||
use primitives::block::HeaderHash;
|
||||
use polkadot_primitives::Block;
|
||||
use state_machine;
|
||||
use client::{self, BlockchainEvents};
|
||||
|
||||
@@ -31,9 +30,9 @@ const TIMER_INTERVAL_MS: u64 = 5000;
|
||||
/// Spawn informant on the event loop
|
||||
pub fn start<B, E>(service: &Service<B, E>, handle: reactor::Handle)
|
||||
where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: client::CallExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>
|
||||
B: client::backend::Backend<Block> + Send + Sync + 'static,
|
||||
E: client::CallExecutor<Block> + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
let interval = reactor::Interval::new_at(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS), &handle)
|
||||
.expect("Error creating informant timer");
|
||||
@@ -45,7 +44,7 @@ pub fn start<B, E>(service: &Service<B, E>, handle: reactor::Handle)
|
||||
let sync_status = network.status();
|
||||
|
||||
if let Ok(best_block) = client.best_block_header() {
|
||||
let hash: HeaderHash = best_block.blake2_256().into();
|
||||
let hash = best_block.hash();
|
||||
let status = match (sync_status.sync.state, sync_status.sync.best_seen_block) {
|
||||
(SyncState::Idle, _) => "Idle".into(),
|
||||
(SyncState::Downloading, None) => "Syncing".into(),
|
||||
|
||||
@@ -32,17 +32,12 @@ extern crate ed25519;
|
||||
extern crate triehash;
|
||||
extern crate parking_lot;
|
||||
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
extern crate substrate_client as client;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_network as network;
|
||||
extern crate substrate_rpc;
|
||||
extern crate substrate_rpc_servers as rpc;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate polkadot_primitives;
|
||||
extern crate polkadot_executor;
|
||||
extern crate polkadot_runtime;
|
||||
extern crate polkadot_service as service;
|
||||
extern crate polkadot_transaction_pool as txpool;
|
||||
|
||||
@@ -61,6 +56,7 @@ mod informant;
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use polkadot_primitives::Block;
|
||||
|
||||
use futures::sync::mpsc;
|
||||
use futures::{Sink, Future, Stream};
|
||||
@@ -188,9 +184,9 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
|
||||
fn run_until_exit<B, E>(mut core: reactor::Core, service: service::Service<B, E>, matches: &clap::ArgMatches, config: service::Configuration) -> error::Result<()>
|
||||
where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: client::CallExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>
|
||||
B: client::backend::Backend<Block> + Send + Sync + 'static,
|
||||
E: client::CallExecutor<Block> + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
let exit = {
|
||||
// can't use signal directly here because CtrlC takes only `Fn`.
|
||||
@@ -210,7 +206,7 @@ fn run_until_exit<B, E>(mut core: reactor::Core, service: service::Service<B, E>
|
||||
|
||||
let handler = || {
|
||||
let chain = rpc::apis::chain::Chain::new(service.client(), core.remote());
|
||||
rpc::rpc_handler(
|
||||
rpc::rpc_handler::<Block, _, _, _, _>(
|
||||
service.client(),
|
||||
chain,
|
||||
service.transaction_pool(),
|
||||
|
||||
@@ -8,5 +8,6 @@ description = "Abstract collation logic"
|
||||
futures = "0.1.17"
|
||||
substrate-codec = { path = "../../substrate/codec", version = "0.1" }
|
||||
substrate-primitives = { path = "../../substrate/primitives", version = "0.1" }
|
||||
polkadot-primitives = { path = "../primitives", version = "0.1" }
|
||||
polkadot-runtime = { path = "../runtime", version = "0.1" }
|
||||
polkadot-parachain = { path = "../parachain", version = "0.1" }
|
||||
polkadot-primitives = { path = "../primitives", version = "0.1" }
|
||||
|
||||
@@ -47,12 +47,13 @@
|
||||
extern crate futures;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate polkadot_runtime;
|
||||
extern crate polkadot_primitives;
|
||||
|
||||
use std::collections::{BTreeSet, BTreeMap};
|
||||
|
||||
use futures::{stream, Stream, Future, IntoFuture};
|
||||
use polkadot_primitives::parachain::{self, ConsolidatedIngress, Message, Id as ParaId};
|
||||
use polkadot_primitives::parachain::{self, CandidateSignature, ConsolidatedIngress, Message, Id as ParaId};
|
||||
|
||||
/// Parachain context needed for collation.
|
||||
///
|
||||
@@ -62,7 +63,7 @@ pub trait ParachainContext {
|
||||
fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>(
|
||||
&self,
|
||||
ingress: I,
|
||||
) -> (parachain::BlockData, polkadot_primitives::AccountId, polkadot_primitives::Signature);
|
||||
) -> (parachain::BlockData, polkadot_primitives::AccountId, CandidateSignature);
|
||||
}
|
||||
|
||||
/// Relay chain context needed to collate.
|
||||
|
||||
@@ -25,3 +25,4 @@ substrate-runtime-support = { path = "../../substrate/runtime-support" }
|
||||
substrate-network = { path = "../../substrate/network" }
|
||||
substrate-keyring = { path = "../../substrate/keyring" }
|
||||
substrate-client = { path = "../../substrate/client" }
|
||||
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Errors that can occur during the consensus process.
|
||||
|
||||
use polkadot_primitives::AccountId;
|
||||
use primitives::AuthorityId;
|
||||
|
||||
error_chain! {
|
||||
links {
|
||||
@@ -29,7 +29,7 @@ error_chain! {
|
||||
description("Duty Roster had invalid length"),
|
||||
display("Invalid duty roster length: expected {}, got {}", expected, got),
|
||||
}
|
||||
NotValidator(id: AccountId) {
|
||||
NotValidator(id: AuthorityId) {
|
||||
description("Local account ID not a validator at this block."),
|
||||
display("Local account ID ({:?}) not a validator at this block.", id),
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
use super::MAX_TRANSACTIONS_SIZE;
|
||||
|
||||
use codec::Slicable;
|
||||
use polkadot_runtime::Block as PolkadotGenericBlock;
|
||||
use polkadot_primitives::Timestamp;
|
||||
use polkadot_runtime::{Block as PolkadotGenericBlock, CheckedBlock};
|
||||
use polkadot_primitives::{Block, Hash, BlockNumber, Timestamp};
|
||||
use polkadot_primitives::parachain::Id as ParaId;
|
||||
use primitives::block::{Block as SubstrateBlock, HeaderHash, Number as BlockNumber};
|
||||
use transaction_pool::PolkadotBlock;
|
||||
|
||||
error_chain! {
|
||||
links {
|
||||
@@ -51,7 +49,7 @@ error_chain! {
|
||||
description("Proposal included unregistered parachain."),
|
||||
display("Proposal included unregistered parachain {:?}", id),
|
||||
}
|
||||
WrongParentHash(expected: HeaderHash, got: HeaderHash) {
|
||||
WrongParentHash(expected: Hash, got: Hash) {
|
||||
description("Proposal had wrong parent hash."),
|
||||
display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got),
|
||||
}
|
||||
@@ -72,17 +70,17 @@ error_chain! {
|
||||
/// Attempt to evaluate a substrate block as a polkadot block, returning error
|
||||
/// upon any initial validity checks failing.
|
||||
pub fn evaluate_initial(
|
||||
proposal: &SubstrateBlock,
|
||||
proposal: &Block,
|
||||
now: Timestamp,
|
||||
parent_hash: &HeaderHash,
|
||||
parent_hash: &Hash,
|
||||
parent_number: BlockNumber,
|
||||
active_parachains: &[ParaId],
|
||||
) -> Result<PolkadotBlock> {
|
||||
) -> Result<CheckedBlock> {
|
||||
const MAX_TIMESTAMP_DRIFT: Timestamp = 60;
|
||||
|
||||
let encoded = Slicable::encode(proposal);
|
||||
let proposal = PolkadotGenericBlock::decode(&mut &encoded[..])
|
||||
.and_then(|b| PolkadotBlock::from(b).ok())
|
||||
.and_then(|b| CheckedBlock::new(b).ok())
|
||||
.ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?;
|
||||
|
||||
let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| {
|
||||
|
||||
@@ -35,14 +35,15 @@ extern crate polkadot_api;
|
||||
extern crate polkadot_collator as collator;
|
||||
extern crate polkadot_statement_table as table;
|
||||
extern crate polkadot_parachain as parachain;
|
||||
extern crate polkadot_primitives;
|
||||
extern crate polkadot_transaction_pool as transaction_pool;
|
||||
extern crate polkadot_runtime;
|
||||
extern crate polkadot_primitives;
|
||||
|
||||
extern crate substrate_bft as bft;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate substrate_network;
|
||||
|
||||
extern crate exit_future;
|
||||
@@ -68,10 +69,9 @@ use std::time::{Duration, Instant};
|
||||
use codec::Slicable;
|
||||
use table::generic::Statement as GenericStatement;
|
||||
use runtime_support::Hashable;
|
||||
use polkadot_api::{PolkadotApi, BlockBuilder};
|
||||
use polkadot_primitives::{Hash, Timestamp};
|
||||
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic, CandidateReceipt};
|
||||
use primitives::block::{Block as SubstrateBlock, Header as SubstrateHeader, HeaderHash, Id as BlockId, Number as BlockNumber};
|
||||
use polkadot_api::PolkadotApi;
|
||||
use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp};
|
||||
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt};
|
||||
use primitives::AuthorityId;
|
||||
use transaction_pool::{Ready, TransactionPool};
|
||||
use tokio_core::reactor::{Handle, Timeout, Interval};
|
||||
@@ -105,10 +105,10 @@ pub trait TableRouter: Clone {
|
||||
/// Future that resolves when candidate data is fetched.
|
||||
type FetchCandidate: IntoFuture<Item=BlockData,Error=Self::Error>;
|
||||
/// Future that resolves when extrinsic candidate data is fetched.
|
||||
type FetchExtrinsic: IntoFuture<Item=Extrinsic,Error=Self::Error>;
|
||||
type FetchExtrinsic: IntoFuture<Item=ParachainExtrinsic,Error=Self::Error>;
|
||||
|
||||
/// Note local candidate data, making it available on the network to other validators.
|
||||
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, extrinsic: Extrinsic);
|
||||
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, extrinsic: ParachainExtrinsic);
|
||||
|
||||
/// Fetch block data for a specific candidate.
|
||||
fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate;
|
||||
@@ -236,7 +236,7 @@ pub struct ProposerFactory<C, N, P> {
|
||||
pub parachain_empty_duration: Duration,
|
||||
}
|
||||
|
||||
impl<C, N, P> bft::ProposerFactory for ProposerFactory<C, N, P>
|
||||
impl<C, N, P> bft::ProposerFactory<Block> for ProposerFactory<C, N, P>
|
||||
where
|
||||
C: PolkadotApi,
|
||||
N: Network,
|
||||
@@ -245,14 +245,14 @@ impl<C, N, P> bft::ProposerFactory for ProposerFactory<C, N, P>
|
||||
type Proposer = Proposer<C, N::TableRouter, P>;
|
||||
type Error = Error;
|
||||
|
||||
fn init(&self, parent_header: &SubstrateHeader, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Error> {
|
||||
fn init(&self, parent_header: &Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Error> {
|
||||
use std::time::Duration;
|
||||
|
||||
const DELAY_UNTIL: Duration = Duration::from_millis(5000);
|
||||
|
||||
let parent_hash = parent_header.blake2_256().into();
|
||||
|
||||
let checked_id = self.client.check_id(BlockId::Hash(parent_hash))?;
|
||||
let checked_id = self.client.check_id(BlockId::hash(parent_hash))?;
|
||||
let duty_roster = self.client.duty_roster(&checked_id)?;
|
||||
let random_seed = self.client.random_seed(&checked_id)?;
|
||||
|
||||
@@ -312,7 +312,7 @@ pub struct Proposer<C: PolkadotApi, R, P> {
|
||||
handle: Handle,
|
||||
local_duty: LocalDuty,
|
||||
local_key: Arc<ed25519::Pair>,
|
||||
parent_hash: HeaderHash,
|
||||
parent_hash: Hash,
|
||||
parent_id: C::CheckedBlockId,
|
||||
parent_number: BlockNumber,
|
||||
random_seed: Hash,
|
||||
@@ -321,7 +321,7 @@ pub struct Proposer<C: PolkadotApi, R, P> {
|
||||
transaction_pool: Arc<TransactionPool>,
|
||||
}
|
||||
|
||||
impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
impl<C, R, P> bft::Proposer<Block> for Proposer<C, R, P>
|
||||
where
|
||||
C: PolkadotApi,
|
||||
R: TableRouter,
|
||||
@@ -330,7 +330,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
type Error = Error;
|
||||
type Create = future::Either<
|
||||
CreateProposal<C, R, P>,
|
||||
future::FutureResult<SubstrateBlock, Error>,
|
||||
future::FutureResult<Block, Error>,
|
||||
>;
|
||||
type Evaluate = Box<Future<Item=bool, Error=Error>>;
|
||||
|
||||
@@ -385,7 +385,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
})
|
||||
}
|
||||
|
||||
fn evaluate(&self, proposal: &SubstrateBlock) -> Self::Evaluate {
|
||||
fn evaluate(&self, unchecked_proposal: &Block) -> Self::Evaluate {
|
||||
debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash);
|
||||
|
||||
let active_parachains = match self.client.active_parachains(&self.parent_id) {
|
||||
@@ -397,7 +397,7 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
|
||||
// do initial serialization and structural integrity checks.
|
||||
let maybe_proposal = evaluation::evaluate_initial(
|
||||
proposal,
|
||||
unchecked_proposal,
|
||||
current_timestamp,
|
||||
&self.parent_hash,
|
||||
self.parent_number,
|
||||
@@ -461,7 +461,10 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
|
||||
// evaluate whether the block is actually valid.
|
||||
// TODO: is it better to delay this until the delays are finished?
|
||||
let evaluated = self.client.evaluate_block(&self.parent_id, proposal.into()).map_err(Into::into);
|
||||
let evaluated = self.client
|
||||
.evaluate_block(&self.parent_id, unchecked_proposal.clone())
|
||||
.map_err(Into::into);
|
||||
|
||||
let future = future::result(evaluated).and_then(move |good| {
|
||||
let end_result = future::ok(good);
|
||||
if good {
|
||||
@@ -489,13 +492,13 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
proposer
|
||||
}
|
||||
|
||||
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior)>) {
|
||||
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior<Hash>)>) {
|
||||
use bft::generic::Misbehavior as GenericMisbehavior;
|
||||
use primitives::bft::{MisbehaviorKind, MisbehaviorReport};
|
||||
use runtime_primitives::bft::{MisbehaviorKind, MisbehaviorReport};
|
||||
use runtime_primitives::MaybeUnsigned;
|
||||
use polkadot_runtime::{Call, Extrinsic, UncheckedExtrinsic, ConsensusCall};
|
||||
|
||||
|
||||
let local_id = self.local_key.public().0;
|
||||
let local_id = self.local_key.public().0.into();
|
||||
let mut next_index = {
|
||||
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client);
|
||||
let cur_index = self.transaction_pool.cull_and_get_pending(readiness_evaluator, |pending| pending
|
||||
@@ -536,10 +539,11 @@ impl<C, R, P> bft::Proposer for Proposer<C, R, P>
|
||||
|
||||
next_index += 1;
|
||||
|
||||
let signature = self.local_key.sign(&extrinsic.encode()).into();
|
||||
let signature = MaybeUnsigned(self.local_key.sign(&extrinsic.encode()).into());
|
||||
let uxt = UncheckedExtrinsic { extrinsic, signature };
|
||||
|
||||
self.transaction_pool.import_unchecked_extrinsic(uxt).expect("locally signed extrinsic is valid; qed");
|
||||
self.transaction_pool.import_unchecked_extrinsic(uxt)
|
||||
.expect("locally signed extrinsic is valid; qed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,7 +607,7 @@ impl ProposalTiming {
|
||||
|
||||
/// Future which resolves upon the creation of a proposal.
|
||||
pub struct CreateProposal<C: PolkadotApi, R, P: Collators> {
|
||||
parent_hash: HeaderHash,
|
||||
parent_hash: Hash,
|
||||
parent_number: BlockNumber,
|
||||
parent_id: C::CheckedBlockId,
|
||||
client: Arc<C>,
|
||||
@@ -620,14 +624,13 @@ impl<C, R, P> CreateProposal<C, R, P>
|
||||
R: TableRouter,
|
||||
P: Collators,
|
||||
{
|
||||
fn propose_with(&self, candidates: Vec<CandidateReceipt>) -> Result<SubstrateBlock, Error> {
|
||||
fn propose_with(&self, candidates: Vec<CandidateReceipt>) -> Result<Block, Error> {
|
||||
use polkadot_api::BlockBuilder;
|
||||
use runtime_primitives::traits::{Hashing, BlakeTwo256};
|
||||
|
||||
// TODO: handle case when current timestamp behind that in state.
|
||||
let timestamp = current_timestamp();
|
||||
let mut block_builder = self.client.build_block(
|
||||
&self.parent_id,
|
||||
timestamp,
|
||||
candidates,
|
||||
)?;
|
||||
let mut block_builder = self.client.build_block(&self.parent_id, timestamp, candidates)?;
|
||||
|
||||
{
|
||||
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client);
|
||||
@@ -643,7 +646,7 @@ impl<C, R, P> CreateProposal<C, R, P>
|
||||
|
||||
if pending_size + pending.encoded_size() >= MAX_TRANSACTIONS_SIZE { break }
|
||||
|
||||
match block_builder.push_extrinsic(pending.as_transaction().clone()) {
|
||||
match block_builder.push_extrinsic(pending.primitive_extrinsic()) {
|
||||
Ok(()) => {
|
||||
pending_size += pending.encoded_size();
|
||||
}
|
||||
@@ -658,14 +661,14 @@ impl<C, R, P> CreateProposal<C, R, P>
|
||||
self.transaction_pool.remove(&unqueue_invalid, false);
|
||||
}
|
||||
|
||||
let polkadot_block = block_builder.bake();
|
||||
let polkadot_block = block_builder.bake()?;
|
||||
|
||||
info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
|
||||
polkadot_block.header.number,
|
||||
Hash::from(polkadot_block.header.blake2_256()),
|
||||
Hash::from(polkadot_block.header.hash()),
|
||||
polkadot_block.header.parent_hash,
|
||||
polkadot_block.extrinsics.iter()
|
||||
.map(|xt| format!("{}", Hash::from(xt.blake2_256())))
|
||||
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
@@ -693,10 +696,10 @@ impl<C, R, P> Future for CreateProposal<C, R, P>
|
||||
R: TableRouter,
|
||||
P: Collators,
|
||||
{
|
||||
type Item = SubstrateBlock;
|
||||
type Item = Block;
|
||||
type Error = Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<SubstrateBlock, Error> {
|
||||
fn poll(&mut self) -> Poll<Block, Error> {
|
||||
// 1. poll local collation future.
|
||||
match self.collation.poll() {
|
||||
Ok(Async::Ready((collation, extrinsic))) => {
|
||||
|
||||
@@ -29,10 +29,9 @@ use ed25519;
|
||||
use futures::prelude::*;
|
||||
use futures::{future, Canceled};
|
||||
use polkadot_api::LocalPolkadotApi;
|
||||
use polkadot_primitives::AccountId;
|
||||
use polkadot_primitives::{BlockId, Block, Header, Hash, AccountId};
|
||||
use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt};
|
||||
use primitives::{Hash, AuthorityId};
|
||||
use primitives::block::{Id as BlockId, HeaderHash, Header};
|
||||
use primitives::AuthorityId;
|
||||
use runtime_support::Hashable;
|
||||
use substrate_network as net;
|
||||
use tokio_core::reactor;
|
||||
@@ -45,19 +44,19 @@ const TIMER_DELAY_MS: u64 = 5000;
|
||||
const TIMER_INTERVAL_MS: u64 = 500;
|
||||
|
||||
struct BftSink<E> {
|
||||
network: Arc<net::ConsensusService>,
|
||||
parent_hash: HeaderHash,
|
||||
network: Arc<net::ConsensusService<Block>>,
|
||||
parent_hash: Hash,
|
||||
_e: ::std::marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
struct Messages {
|
||||
network_stream: net::BftMessageStream,
|
||||
network_stream: net::BftMessageStream<Block>,
|
||||
local_id: AuthorityId,
|
||||
authorities: Vec<AuthorityId>,
|
||||
}
|
||||
|
||||
impl Stream for Messages {
|
||||
type Item = bft::Communication;
|
||||
type Item = bft::Communication<Block>;
|
||||
type Error = bft::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
@@ -81,10 +80,10 @@ impl Stream for Messages {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, authorities: &[AuthorityId]) -> Result<Option<bft::Communication>, bft::Error> {
|
||||
fn process_message(msg: net::LocalizedBftMessage<Block>, local_id: &AuthorityId, authorities: &[AuthorityId]) -> Result<Option<bft::Communication<Block>>, bft::Error> {
|
||||
Ok(Some(match msg.message {
|
||||
net::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c {
|
||||
net::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({
|
||||
net::generic_message::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c {
|
||||
net::generic_message::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({
|
||||
if &proposal.sender == local_id { return Ok(None) }
|
||||
let proposal = bft::generic::LocalizedProposal {
|
||||
round_number: proposal.round_number as usize,
|
||||
@@ -105,7 +104,7 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
|
||||
trace!(target: "bft", "importing proposal message for round {} from {}", proposal.round_number, Hash::from(proposal.sender));
|
||||
proposal
|
||||
}),
|
||||
net::SignedConsensusMessage::Vote(vote) => bft::generic::LocalizedMessage::Vote({
|
||||
net::generic_message::SignedConsensusMessage::Vote(vote) => bft::generic::LocalizedMessage::Vote({
|
||||
if &vote.sender == local_id { return Ok(None) }
|
||||
let vote = bft::generic::LocalizedVote {
|
||||
sender: vote.sender,
|
||||
@@ -114,21 +113,21 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
|
||||
signer: ed25519::Public(vote.sender),
|
||||
},
|
||||
vote: match vote.vote {
|
||||
net::ConsensusVote::Prepare(r, h) => bft::generic::Vote::Prepare(r as usize, h),
|
||||
net::ConsensusVote::Commit(r, h) => bft::generic::Vote::Commit(r as usize, h),
|
||||
net::ConsensusVote::AdvanceRound(r) => bft::generic::Vote::AdvanceRound(r as usize),
|
||||
net::generic_message::ConsensusVote::Prepare(r, h) => bft::generic::Vote::Prepare(r as usize, h),
|
||||
net::generic_message::ConsensusVote::Commit(r, h) => bft::generic::Vote::Commit(r as usize, h),
|
||||
net::generic_message::ConsensusVote::AdvanceRound(r) => bft::generic::Vote::AdvanceRound(r as usize),
|
||||
}
|
||||
};
|
||||
bft::check_vote(authorities, &msg.parent_hash, &vote)?;
|
||||
bft::check_vote::<Block>(authorities, &msg.parent_hash, &vote)?;
|
||||
|
||||
trace!(target: "bft", "importing vote {:?} from {}", vote.vote, Hash::from(vote.sender));
|
||||
vote
|
||||
}),
|
||||
}),
|
||||
net::BftMessage::Auxiliary(a) => {
|
||||
let justification = bft::UncheckedJustification::from(a);
|
||||
net::generic_message::BftMessage::Auxiliary(a) => {
|
||||
let justification = bft::UncheckedJustification::<Hash>::from(a);
|
||||
// TODO: get proper error
|
||||
let justification: Result<_, bft::Error> = bft::check_prepare_justification(authorities, msg.parent_hash, justification)
|
||||
let justification: Result<_, bft::Error> = bft::check_prepare_justification::<Block>(authorities, msg.parent_hash, justification)
|
||||
.map_err(|_| bft::ErrorKind::InvalidJustification.into());
|
||||
bft::generic::Communication::Auxiliary(justification?)
|
||||
},
|
||||
@@ -136,15 +135,15 @@ fn process_message(msg: net::LocalizedBftMessage, local_id: &AuthorityId, author
|
||||
}
|
||||
|
||||
impl<E> Sink for BftSink<E> {
|
||||
type SinkItem = bft::Communication;
|
||||
type SinkItem = bft::Communication<Block>;
|
||||
// TODO: replace this with the ! type when that's stabilized
|
||||
type SinkError = E;
|
||||
|
||||
fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend<bft::Communication, E> {
|
||||
let network_message = net::LocalizedBftMessage {
|
||||
fn start_send(&mut self, message: bft::Communication<Block>) -> ::futures::StartSend<bft::Communication<Block>, E> {
|
||||
let network_message = net::generic_message::LocalizedBftMessage {
|
||||
message: match message {
|
||||
bft::generic::Communication::Consensus(c) => net::BftMessage::Consensus(match c {
|
||||
bft::generic::LocalizedMessage::Propose(proposal) => net::SignedConsensusMessage::Propose(net::SignedConsensusProposal {
|
||||
bft::generic::Communication::Consensus(c) => net::generic_message::BftMessage::Consensus(match c {
|
||||
bft::generic::LocalizedMessage::Propose(proposal) => net::generic_message::SignedConsensusMessage::Propose(net::generic_message::SignedConsensusProposal {
|
||||
round_number: proposal.round_number as u32,
|
||||
proposal: proposal.proposal,
|
||||
digest: proposal.digest,
|
||||
@@ -152,17 +151,17 @@ impl<E> Sink for BftSink<E> {
|
||||
digest_signature: proposal.digest_signature.signature,
|
||||
full_signature: proposal.full_signature.signature,
|
||||
}),
|
||||
bft::generic::LocalizedMessage::Vote(vote) => net::SignedConsensusMessage::Vote(net::SignedConsensusVote {
|
||||
bft::generic::LocalizedMessage::Vote(vote) => net::generic_message::SignedConsensusMessage::Vote(net::generic_message::SignedConsensusVote {
|
||||
sender: vote.sender,
|
||||
signature: vote.signature.signature,
|
||||
vote: match vote.vote {
|
||||
bft::generic::Vote::Prepare(r, h) => net::ConsensusVote::Prepare(r as u32, h),
|
||||
bft::generic::Vote::Commit(r, h) => net::ConsensusVote::Commit(r as u32, h),
|
||||
bft::generic::Vote::AdvanceRound(r) => net::ConsensusVote::AdvanceRound(r as u32),
|
||||
bft::generic::Vote::Prepare(r, h) => net::generic_message::ConsensusVote::Prepare(r as u32, h),
|
||||
bft::generic::Vote::Commit(r, h) => net::generic_message::ConsensusVote::Commit(r as u32, h),
|
||||
bft::generic::Vote::AdvanceRound(r) => net::generic_message::ConsensusVote::AdvanceRound(r as u32),
|
||||
}
|
||||
}),
|
||||
}),
|
||||
bft::generic::Communication::Auxiliary(justification) => net::BftMessage::Auxiliary(justification.uncheck().into()),
|
||||
bft::generic::Communication::Auxiliary(justification) => net::generic_message::BftMessage::Auxiliary(justification.uncheck().into()),
|
||||
},
|
||||
parent_hash: self.parent_hash,
|
||||
};
|
||||
@@ -175,7 +174,7 @@ impl<E> Sink for BftSink<E> {
|
||||
}
|
||||
}
|
||||
|
||||
struct Network(Arc<net::ConsensusService>);
|
||||
struct Network(Arc<net::ConsensusService<Block>>);
|
||||
|
||||
impl super::Network for Network {
|
||||
type TableRouter = Router;
|
||||
@@ -189,20 +188,20 @@ impl super::Network for Network {
|
||||
fn start_bft<F, C>(
|
||||
header: &Header,
|
||||
handle: reactor::Handle,
|
||||
client: &bft::Authorities,
|
||||
network: Arc<net::ConsensusService>,
|
||||
bft_service: &BftService<F, C>,
|
||||
client: &bft::Authorities<Block>,
|
||||
network: Arc<net::ConsensusService<Block>>,
|
||||
bft_service: &BftService<Block, F, C>,
|
||||
) where
|
||||
F: bft::ProposerFactory + 'static,
|
||||
C: bft::BlockImport + bft::Authorities + 'static,
|
||||
<F as bft::ProposerFactory>::Error: ::std::fmt::Debug,
|
||||
<F::Proposer as bft::Proposer>::Error: ::std::fmt::Display + Into<error::Error>,
|
||||
F: bft::ProposerFactory<Block> + 'static,
|
||||
C: bft::BlockImport<Block> + bft::Authorities<Block> + 'static,
|
||||
<F as bft::ProposerFactory<Block>>::Error: ::std::fmt::Debug,
|
||||
<F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
|
||||
{
|
||||
let parent_hash = header.blake2_256().into();
|
||||
let parent_hash = header.hash();
|
||||
if bft_service.live_agreement().map_or(false, |h| h == parent_hash) {
|
||||
return;
|
||||
}
|
||||
let authorities = match client.authorities(&BlockId::Hash(parent_hash)) {
|
||||
let authorities = match client.authorities(&BlockId::hash(parent_hash)) {
|
||||
Ok(authorities) => authorities,
|
||||
Err(e) => {
|
||||
debug!("Error reading authorities: {:?}", e);
|
||||
@@ -235,14 +234,14 @@ impl Service {
|
||||
pub fn new<A, C>(
|
||||
client: Arc<C>,
|
||||
api: Arc<A>,
|
||||
network: Arc<net::ConsensusService>,
|
||||
network: Arc<net::ConsensusService<Block>>,
|
||||
transaction_pool: Arc<TransactionPool>,
|
||||
parachain_empty_duration: Duration,
|
||||
key: ed25519::Pair,
|
||||
) -> Service
|
||||
where
|
||||
A: LocalPolkadotApi + Send + Sync + 'static,
|
||||
C: BlockchainEvents + ChainHead + bft::BlockImport + bft::Authorities + Send + Sync + 'static,
|
||||
C: BlockchainEvents<Block> + ChainHead<Block> + bft::BlockImport<Block> + bft::Authorities<Block> + Send + Sync + 'static,
|
||||
{
|
||||
let (signal, exit) = ::exit_future::signal();
|
||||
let thread = thread::spawn(move || {
|
||||
@@ -346,36 +345,25 @@ impl ::collation::Collators for NoCollators {
|
||||
fn note_bad_collator(&self, _collator: AccountId) { }
|
||||
}
|
||||
|
||||
type FetchCandidateAdapter = future::Map<net::FetchFuture, fn(Vec<u8>) -> BlockData>;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Router {
|
||||
network: Arc<net::ConsensusService>,
|
||||
}
|
||||
|
||||
impl Router {
|
||||
fn fetch_candidate_adapter(data: Vec<u8>) -> BlockData {
|
||||
BlockData(data)
|
||||
}
|
||||
network: Arc<net::ConsensusService<Block>>,
|
||||
}
|
||||
|
||||
impl TableRouter for Router {
|
||||
type Error = Canceled;
|
||||
type FetchCandidate = FetchCandidateAdapter;
|
||||
type FetchCandidate = future::Empty<BlockData, Self::Error>;
|
||||
type FetchExtrinsic = future::FutureResult<Extrinsic, Self::Error>;
|
||||
|
||||
fn local_candidate_data(&self, hash: Hash, block_data: BlockData, _extrinsic: Extrinsic) {
|
||||
let data = block_data.0;
|
||||
self.network.set_local_candidate(Some((hash, data)))
|
||||
fn local_candidate_data(&self, _hash: Hash, _block_data: BlockData, _extrinsic: Extrinsic) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn fetch_block_data(&self, candidate: &CandidateReceipt) -> Self::FetchCandidate {
|
||||
let hash = candidate.hash();
|
||||
self.network.fetch_candidate(&hash).map(Self::fetch_candidate_adapter)
|
||||
fn fetch_block_data(&self, _candidate: &CandidateReceipt) -> Self::FetchCandidate {
|
||||
future::empty()
|
||||
}
|
||||
|
||||
fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic {
|
||||
future::ok(Extrinsic)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -486,7 +486,7 @@ mod tests {
|
||||
|
||||
let candidate = CandidateReceipt {
|
||||
parachain_index: para_id,
|
||||
collator: [1; 32],
|
||||
collator: [1; 32].into(),
|
||||
head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]),
|
||||
balance_uploads: Vec::new(),
|
||||
egress_queue_roots: Vec::new(),
|
||||
@@ -536,7 +536,7 @@ mod tests {
|
||||
|
||||
let candidate = CandidateReceipt {
|
||||
parachain_index: para_id,
|
||||
collator: [1; 32],
|
||||
collator: [1; 32].into(),
|
||||
head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]),
|
||||
balance_uploads: Vec::new(),
|
||||
egress_queue_roots: Vec::new(),
|
||||
|
||||
@@ -5,17 +5,5 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Polkadot node implementation in Rust."
|
||||
|
||||
[dependencies]
|
||||
hex-literal = "0.1"
|
||||
triehash = { version = "0.1" }
|
||||
ed25519 = { path = "../../substrate/ed25519" }
|
||||
substrate-codec = { path = "../../substrate/codec" }
|
||||
substrate-runtime-io = { path = "../../substrate/runtime-io" }
|
||||
substrate-runtime-support = { path = "../../substrate/runtime-support" }
|
||||
substrate-state-machine = { path = "../../substrate/state-machine" }
|
||||
substrate-executor = { path = "../../substrate/executor" }
|
||||
substrate-primitives = { path = "../../substrate/primitives" }
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
polkadot-runtime = { path = "../runtime" }
|
||||
|
||||
[dev-dependencies]
|
||||
substrate-keyring = { path = "../../substrate/keyring" }
|
||||
|
||||
@@ -19,12 +19,5 @@
|
||||
|
||||
extern crate polkadot_runtime;
|
||||
#[macro_use] extern crate substrate_executor;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate polkadot_primitives as polkadot_primitives;
|
||||
extern crate ed25519;
|
||||
extern crate triehash;
|
||||
|
||||
native_executor_instance!(pub Executor, polkadot_runtime::api::dispatch, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm"));
|
||||
|
||||
@@ -21,12 +21,6 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
extern crate substrate_runtime_std as rstd;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
@@ -35,27 +29,43 @@ extern crate substrate_serializer;
|
||||
|
||||
extern crate substrate_codec as codec;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use primitives::bytes;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use runtime_primitives::traits::BlakeTwo256;
|
||||
use runtime_primitives::generic;
|
||||
use codec::{Input, Slicable};
|
||||
|
||||
pub mod parachain;
|
||||
|
||||
/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody
|
||||
/// (who matters). Essentially this means that a majority of validators have decided it is
|
||||
/// "correct".
|
||||
pub const EVERYBODY: AccountId = [255u8; 32];
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
|
||||
|
||||
/// Something that identifies a block.
|
||||
pub use primitives::block::Id as BlockId;
|
||||
/// Opaque, encoded, unchecked extrinsic.
|
||||
pub type UncheckedExtrinsic = Vec<u8>;
|
||||
|
||||
/// The type of digest item.
|
||||
pub use primitives::block::Log as Log;
|
||||
/// A "future-proof" block type for Polkadot. This will be resilient to upgrades in transaction
|
||||
/// format, because it doesn't attempt to decode extrinsics.
|
||||
///
|
||||
/// Specialized code needs to link to (at least one version of) the runtime directly
|
||||
/// in order to handle the extrinsics within.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
|
||||
/// An index to a block.
|
||||
/// 32-bits will allow for 136 years of blocks assuming 1 block per second.
|
||||
/// TODO: switch to u32
|
||||
pub type BlockNumber = u64;
|
||||
|
||||
/// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost
|
||||
/// certainly continue to be the same as the substrate's `AuthorityId`.
|
||||
pub type AccountId = primitives::AuthorityId;
|
||||
/// Alias to Ed25519 pubkey that identifies an account on the relay chain.
|
||||
pub type AccountId = primitives::hash::H256;
|
||||
|
||||
/// The Ed25519 pub key of an session that belongs to an authority of the relay chain. This is
|
||||
/// exactly equivalent to what the substrate calls an "authority".
|
||||
@@ -64,14 +74,15 @@ pub type SessionKey = primitives::AuthorityId;
|
||||
/// Indentifier for a chain. 32-bit should be plenty.
|
||||
pub type ChainId = u32;
|
||||
|
||||
/// Index of a transaction in the relay chain. 32-bit should be plenty.
|
||||
pub type Index = u32;
|
||||
|
||||
/// A hash of some data used by the relay chain.
|
||||
pub type Hash = primitives::H256;
|
||||
|
||||
/// Index of a transaction in the relay chain. 32-bit should be plenty.
|
||||
pub type Index = u32;
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a signature on the relay chain.
|
||||
pub type Signature = runtime_primitives::Ed25519Signature;
|
||||
/// Equipped with logic for possibly "unsigned" messages.
|
||||
pub type Signature = runtime_primitives::MaybeUnsigned<runtime_primitives::Ed25519Signature>;
|
||||
|
||||
/// A timestamp: seconds since the unix epoch.
|
||||
pub type Timestamp = u64;
|
||||
@@ -84,3 +95,22 @@ pub type Timestamp = u64;
|
||||
/// We round denomination to 10^12 (12 sdf), and leave the other redundancy at the upper end so
|
||||
/// that 32 bits may be multiplied with a balance in 128 bits without worrying about overflow.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// "generic" block ID for the future-proof block type.
|
||||
// TODO: parameterize blockid only as necessary.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
|
||||
/// A log entry in the block.
|
||||
#[derive(PartialEq, Eq, Clone, Default)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
impl Slicable for Log {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Vec::<u8>::decode(input).map(Log)
|
||||
}
|
||||
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
self.0.using_encoded(f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,22 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Parachain data types.
|
||||
//! Polkadot parachain types.
|
||||
|
||||
use codec::{Slicable, Input};
|
||||
use rstd::prelude::*;
|
||||
use rstd::cmp::Ordering;
|
||||
use super::Hash;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use primitives::bytes;
|
||||
use primitives;
|
||||
use codec::{Input, Slicable};
|
||||
use rstd::cmp::{PartialOrd, Ord, Ordering};
|
||||
use rstd::vec::Vec;
|
||||
use ::Hash;
|
||||
|
||||
/// Signature on candidate's block data by a collator.
|
||||
pub type CandidateSignature = ::runtime_primitives::Ed25519Signature;
|
||||
|
||||
/// Unique identifier of a parachain.
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct Id(u32);
|
||||
|
||||
impl From<Id> for u32 {
|
||||
@@ -67,7 +70,6 @@ pub enum Chain {
|
||||
impl Slicable for Chain {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
let disc = input.read_byte()?;
|
||||
|
||||
match disc {
|
||||
0 => Some(Chain::Relay),
|
||||
1 => Some(Chain::Parachain(Slicable::decode(input)?)),
|
||||
@@ -84,7 +86,6 @@ impl Slicable for Chain {
|
||||
id.using_encoded(|s| v.extend(s));
|
||||
}
|
||||
}
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
@@ -128,7 +129,7 @@ impl Slicable for DutyRoster {
|
||||
|
||||
/// Extrinsic data for a parachain.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
||||
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
|
||||
pub struct Extrinsic;
|
||||
@@ -137,14 +138,14 @@ pub struct Extrinsic;
|
||||
///
|
||||
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
||||
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
|
||||
pub struct Candidate {
|
||||
/// The ID of the parachain this is a proposal for.
|
||||
pub parachain_index: Id,
|
||||
/// Collator's signature
|
||||
pub collator_signature: ::Signature,
|
||||
pub collator_signature: CandidateSignature,
|
||||
/// Unprocessed ingress queue.
|
||||
///
|
||||
/// Ordered by parachain ID and block number.
|
||||
@@ -155,20 +156,20 @@ pub struct Candidate {
|
||||
|
||||
/// Candidate receipt type.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
||||
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
|
||||
pub struct CandidateReceipt {
|
||||
/// The ID of the parachain this is a candidate for.
|
||||
pub parachain_index: Id,
|
||||
/// The collator's relay-chain account ID
|
||||
pub collator: ::AccountId,
|
||||
pub collator: super::AccountId,
|
||||
/// The head-data
|
||||
pub head_data: HeadData,
|
||||
/// Balance uploads to the relay chain.
|
||||
pub balance_uploads: Vec<(::AccountId, u64)>,
|
||||
pub balance_uploads: Vec<(super::AccountId, u64)>,
|
||||
/// Egress queue roots.
|
||||
pub egress_queue_roots: Vec<(Id, primitives::H256)>,
|
||||
pub egress_queue_roots: Vec<(Id, Hash)>,
|
||||
/// Fees paid from the chain to the relay chain validators
|
||||
pub fees: u64,
|
||||
}
|
||||
@@ -203,8 +204,8 @@ impl CandidateReceipt {
|
||||
/// Get the blake2_256 hash
|
||||
#[cfg(feature = "std")]
|
||||
pub fn hash(&self) -> Hash {
|
||||
let encoded = self.encode();
|
||||
primitives::hashing::blake2_256(&encoded).into()
|
||||
use runtime_primitives::traits::{BlakeTwo256, Hashing};
|
||||
BlakeTwo256::hash_of(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ impl Ord for CandidateReceipt {
|
||||
|
||||
/// Parachain ingress queue message.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Consolidated ingress queue data.
|
||||
@@ -232,34 +233,34 @@ pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>
|
||||
/// This is just an ordered vector of other parachains' egress queues,
|
||||
/// obtained according to the routing rules.
|
||||
#[derive(Default, PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct ConsolidatedIngress(pub Vec<(Id, Vec<Message>)>);
|
||||
|
||||
/// Parachain block data.
|
||||
///
|
||||
/// contains everything required to validate para-block, may contain block and witness data
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Parachain header raw bytes wrapper type.
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Parachain head data included in the chain.
|
||||
#[derive(PartialEq, Eq, Clone, PartialOrd, Ord)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Parachain validation code.
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Activitiy bit field
|
||||
#[derive(PartialEq, Eq, Clone, Default)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
||||
pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
impl Slicable for Activity {
|
||||
@@ -339,41 +340,3 @@ impl Slicable for Statement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_serializer as ser;
|
||||
|
||||
#[test]
|
||||
fn test_candidate() {
|
||||
assert_eq!(ser::to_string_pretty(&Candidate {
|
||||
parachain_index: 5.into(),
|
||||
collator_signature: primitives::hash::H512::from(10).into(),
|
||||
unprocessed_ingress: ConsolidatedIngress(vec![
|
||||
(Id(1), vec![Message(vec![2])]),
|
||||
(Id(2), vec![Message(vec![2]), Message(vec![3])]),
|
||||
]),
|
||||
block: BlockData(vec![1, 2, 3]),
|
||||
}), r#"{
|
||||
"parachainIndex": 5,
|
||||
"collatorSignature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a",
|
||||
"unprocessedIngress": [
|
||||
[
|
||||
1,
|
||||
[
|
||||
"0x02"
|
||||
]
|
||||
],
|
||||
[
|
||||
2,
|
||||
[
|
||||
"0x02",
|
||||
"0x03"
|
||||
]
|
||||
]
|
||||
],
|
||||
"block": "0x010203"
|
||||
}"#);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ log = { version = "0.3", optional = true }
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { path = "../../safe-mix", default_features = false}
|
||||
polkadot-primitives = { path = "../primitives", default_features = false }
|
||||
substrate-codec = { path = "../../substrate/codec" }
|
||||
substrate-serializer = { path = "../../substrate/serializer" }
|
||||
substrate-runtime-std = { path = "../../substrate/runtime-std" }
|
||||
@@ -25,7 +26,6 @@ substrate-runtime-session = { path = "../../substrate/runtime/session" }
|
||||
substrate-runtime-staking = { path = "../../substrate/runtime/staking" }
|
||||
substrate-runtime-system = { path = "../../substrate/runtime/system" }
|
||||
substrate-runtime-timestamp = { path = "../../substrate/runtime/timestamp" }
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.1.0"
|
||||
@@ -33,6 +33,7 @@ hex-literal = "0.1.0"
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"polkadot-primitives/std",
|
||||
"substrate-codec/std",
|
||||
"substrate-primitives/std",
|
||||
"substrate-runtime-std/std",
|
||||
@@ -47,7 +48,6 @@ std = [
|
||||
"substrate-runtime-staking/std",
|
||||
"substrate-runtime-system/std",
|
||||
"substrate-runtime-timestamp/std",
|
||||
"polkadot-primitives/std",
|
||||
"serde_derive",
|
||||
"serde/std",
|
||||
"log",
|
||||
|
||||
@@ -18,11 +18,18 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_support;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
@@ -37,7 +44,10 @@ extern crate substrate_serializer;
|
||||
#[cfg_attr(feature = "std", macro_use)]
|
||||
extern crate substrate_primitives;
|
||||
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_std as rstd;
|
||||
|
||||
extern crate polkadot_primitives as primitives;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_runtime_consensus as consensus;
|
||||
extern crate substrate_runtime_council as council;
|
||||
@@ -47,14 +57,13 @@ extern crate substrate_runtime_session as session;
|
||||
extern crate substrate_runtime_staking as staking;
|
||||
extern crate substrate_runtime_system as system;
|
||||
extern crate substrate_runtime_timestamp as timestamp;
|
||||
extern crate polkadot_primitives;
|
||||
|
||||
mod parachains;
|
||||
|
||||
use runtime_io::BlakeTwo256;
|
||||
use polkadot_primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature};
|
||||
use runtime_primitives::generic;
|
||||
use runtime_primitives::traits::{Identity, HasPublicAux};
|
||||
use rstd::prelude::*;
|
||||
use primitives::{AccountId, Balance, BlockNumber, Hash, Index, Log, SessionKey, Signature};
|
||||
use primitives::parachain::CandidateReceipt;
|
||||
use runtime_primitives::{generic, traits::{HasPublicAux, BlakeTwo256, Convert}};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use runtime_primitives::BuildExternalities;
|
||||
@@ -62,13 +71,113 @@ pub use runtime_primitives::BuildExternalities;
|
||||
pub use consensus::Call as ConsensusCall;
|
||||
pub use timestamp::Call as TimestampCall;
|
||||
pub use parachains::Call as ParachainsCall;
|
||||
|
||||
pub use primitives::Header;
|
||||
|
||||
/// The position of the timestamp set extrinsic.
|
||||
pub const TIMESTAMP_SET_POSITION: u32 = 0;
|
||||
/// The position of the parachains set extrinsic.
|
||||
pub const PARACHAINS_SET_POSITION: u32 = 1;
|
||||
|
||||
/// Block Id type for this block.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
|
||||
/// Extrinsic type as expected by this runtime.
|
||||
pub type Extrinsic = generic::Extrinsic<AccountId, Index, Call>;
|
||||
|
||||
/// Block type as expected by this runtime.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
|
||||
/// Provides a type-safe wrapper around a structurally valid block.
|
||||
#[cfg(feature = "std")]
|
||||
pub struct CheckedBlock {
|
||||
inner: Block,
|
||||
file_line: Option<(&'static str, u32)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl CheckedBlock {
|
||||
/// Create a new checked block. Fails if the block is not structurally valid.
|
||||
pub fn new(block: Block) -> Result<Self, Block> {
|
||||
let has_timestamp = block.extrinsics.get(TIMESTAMP_SET_POSITION as usize).map_or(false, |xt| {
|
||||
!xt.is_signed() && match xt.extrinsic.function {
|
||||
Call::Timestamp(TimestampCall::set(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
|
||||
if !has_timestamp { return Err(block) }
|
||||
|
||||
let has_heads = block.extrinsics.get(PARACHAINS_SET_POSITION as usize).map_or(false, |xt| {
|
||||
!xt.is_signed() && match xt.extrinsic.function {
|
||||
Call::Parachains(ParachainsCall::set_heads(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
|
||||
if !has_heads { return Err(block) }
|
||||
Ok(CheckedBlock {
|
||||
inner: block,
|
||||
file_line: None,
|
||||
})
|
||||
}
|
||||
|
||||
// Creates a new checked block, asserting that it is valid.
|
||||
#[doc(hidden)]
|
||||
pub fn new_unchecked(block: Block, file: &'static str, line: u32) -> Self {
|
||||
CheckedBlock {
|
||||
inner: block,
|
||||
file_line: Some((file, line)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the timestamp from the block.
|
||||
pub fn timestamp(&self) -> ::primitives::Timestamp {
|
||||
let x = self.inner.extrinsics.get(TIMESTAMP_SET_POSITION as usize).and_then(|xt| match xt.extrinsic.function {
|
||||
Call::Timestamp(TimestampCall::set(x)) => Some(x),
|
||||
_ => None
|
||||
});
|
||||
|
||||
match x {
|
||||
Some(x) => x,
|
||||
None => panic!("Invalid polkadot block asserted at {:?}", self.file_line),
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the parachain heads from the block.
|
||||
pub fn parachain_heads(&self) -> &[CandidateReceipt] {
|
||||
let x = self.inner.extrinsics.get(PARACHAINS_SET_POSITION as usize).and_then(|xt| match xt.extrinsic.function {
|
||||
Call::Parachains(ParachainsCall::set_heads(ref x)) => Some(&x[..]),
|
||||
_ => None
|
||||
});
|
||||
|
||||
match x {
|
||||
Some(x) => x,
|
||||
None => panic!("Invalid polkadot block asserted at {:?}", self.file_line),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert into inner block.
|
||||
pub fn into_inner(self) -> Block { self.inner }
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ::std::ops::Deref for CheckedBlock {
|
||||
type Target = Block;
|
||||
|
||||
fn deref(&self) -> &Block { &self.inner }
|
||||
}
|
||||
|
||||
/// Assert that a block is structurally valid. May lead to panic in the future
|
||||
/// in case it isn't.
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_export]
|
||||
macro_rules! assert_polkadot_block {
|
||||
($block: expr) => {
|
||||
$crate::CheckedBlock::new_unchecked($block, file!(), line!())
|
||||
}
|
||||
}
|
||||
|
||||
/// Concrete runtime type used to parameterize the various modules.
|
||||
pub struct Concrete;
|
||||
|
||||
@@ -83,7 +192,7 @@ impl system::Trait for Concrete {
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = generic::Digest<Log>;
|
||||
type AccountId = AccountId;
|
||||
type Header = generic::Header<BlockNumber, Hash, Log>;
|
||||
type Header = Header;
|
||||
}
|
||||
/// System module for this concrete runtime.
|
||||
pub type System = system::Module<Concrete>;
|
||||
@@ -102,8 +211,16 @@ impl timestamp::Trait for Concrete {
|
||||
/// Timestamp module for this concrete runtime.
|
||||
pub type Timestamp = timestamp::Module<Concrete>;
|
||||
|
||||
/// Session key conversion.
|
||||
pub struct SessionKeyConversion;
|
||||
impl Convert<AccountId, SessionKey> for SessionKeyConversion {
|
||||
fn convert(a: AccountId) -> SessionKey {
|
||||
a.0
|
||||
}
|
||||
}
|
||||
|
||||
impl session::Trait for Concrete {
|
||||
type ConvertAccountIdToSessionKey = Identity;
|
||||
type ConvertAccountIdToSessionKey = SessionKeyConversion;
|
||||
}
|
||||
/// Session module for this concrete runtime.
|
||||
pub type Session = session::Module<Concrete>;
|
||||
@@ -135,6 +252,9 @@ impl parachains::Trait for Concrete {
|
||||
pub type Parachains = parachains::Module<Concrete>;
|
||||
|
||||
impl_outer_dispatch! {
|
||||
/// Call type for polkadot transactions.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub enum Call where aux: <Concrete as HasPublicAux>::PublicAux {
|
||||
Consensus = 0,
|
||||
Session = 1,
|
||||
@@ -146,6 +266,9 @@ impl_outer_dispatch! {
|
||||
Parachains = 8,
|
||||
}
|
||||
|
||||
/// Internal calls.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
Consensus = 0,
|
||||
Session = 1,
|
||||
@@ -156,14 +279,6 @@ impl_outer_dispatch! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Block header type as expected by this runtime.
|
||||
pub type Header = generic::Header<BlockNumber, Hash, Log>;
|
||||
/// Block type as expected by this runtime.
|
||||
pub type Block = generic::Block<BlockNumber, Hash, Log, AccountId, Index, Call, Signature>;
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<AccountId, Index, Call, Signature>;
|
||||
/// Extrinsic type as expected by this runtime.
|
||||
pub type Extrinsic = generic::Extrinsic<AccountId, Index, Call>;
|
||||
/// Executive: handles dispatch to the various modules.
|
||||
pub type Executive = executive::Executive<Concrete, Block, Staking,
|
||||
(((((((), Parachains), Council), Democracy), Staking), Session), Timestamp)>;
|
||||
@@ -180,6 +295,35 @@ impl_outer_config! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces the list of inherent extrinsics.
|
||||
pub fn inherent_extrinsics(timestamp: ::primitives::Timestamp, parachain_heads: Vec<CandidateReceipt>) -> Vec<UncheckedExtrinsic> {
|
||||
vec![
|
||||
UncheckedExtrinsic {
|
||||
extrinsic: Extrinsic {
|
||||
signed: Default::default(),
|
||||
function: Call::Timestamp(TimestampCall::set(timestamp)),
|
||||
index: 0,
|
||||
},
|
||||
signature: Default::default(),
|
||||
},
|
||||
UncheckedExtrinsic {
|
||||
extrinsic: Extrinsic {
|
||||
signed: Default::default(),
|
||||
function: Call::Parachains(ParachainsCall::set_heads(parachain_heads)),
|
||||
index: 0,
|
||||
},
|
||||
signature: Default::default(),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/// Checks an unchecked extrinsic for validity.
|
||||
pub fn check_extrinsic(xt: UncheckedExtrinsic) -> bool {
|
||||
use runtime_primitives::traits::Checkable;
|
||||
|
||||
xt.check().is_ok()
|
||||
}
|
||||
|
||||
pub mod api {
|
||||
impl_stubs!(
|
||||
authorities => |()| super::Consensus::authorities(),
|
||||
@@ -187,6 +331,7 @@ pub mod api {
|
||||
apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic),
|
||||
execute_block => |block| super::Executive::execute_block(block),
|
||||
finalise_block => |()| super::Executive::finalise_block(),
|
||||
inherent_extrinsics => |(timestamp, heads)| super::inherent_extrinsics(timestamp, heads),
|
||||
validator_count => |()| super::Session::validator_count(),
|
||||
validators => |()| super::Session::validators()
|
||||
);
|
||||
@@ -290,9 +435,9 @@ mod tests {
|
||||
});
|
||||
|
||||
let raw = block.encode();
|
||||
let decoded_substrate = primitives::block::Block::decode(&mut &raw[..]).unwrap();
|
||||
let encoded_substrate = decoded_substrate.encode();
|
||||
let decoded = Block::decode(&mut &encoded_substrate[..]).unwrap();
|
||||
let decoded_primitive = ::primitives::Block::decode(&mut &raw[..]).unwrap();
|
||||
let encoded_primitive = decoded_primitive.encode();
|
||||
let decoded = Block::decode(&mut &encoded_primitive[..]).unwrap();
|
||||
|
||||
assert_eq!(block, decoded);
|
||||
}
|
||||
@@ -301,11 +446,11 @@ mod tests {
|
||||
fn serialize_unchecked() {
|
||||
let tx = UncheckedExtrinsic {
|
||||
extrinsic: Extrinsic {
|
||||
signed: [1; 32],
|
||||
signed: [1; 32].into(),
|
||||
index: 999,
|
||||
function: Call::Timestamp(TimestampCall::set(135135)),
|
||||
},
|
||||
signature: primitives::hash::H512([0; 64]).into(),
|
||||
signature: runtime_primitives::Ed25519Signature(primitives::hash::H512([0; 64])).into(),
|
||||
};
|
||||
// 71000000
|
||||
// 0101010101010101010101010101010101010101010101010101010101010101
|
||||
@@ -322,7 +467,7 @@ mod tests {
|
||||
#[test]
|
||||
fn serialize_checked() {
|
||||
let xt = Extrinsic {
|
||||
signed: hex!["0d71d1a9cad6f2ab773435a7dec1bac019994d05d1dd5eb3108211dcf25c9d1e"],
|
||||
signed: hex!["0d71d1a9cad6f2ab773435a7dec1bac019994d05d1dd5eb3108211dcf25c9d1e"].into(),
|
||||
index: 0,
|
||||
function: Call::CouncilVoting(council::voting::Call::propose(Box::new(
|
||||
PrivCall::Consensus(consensus::PrivCall::set_code(
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
|
||||
//! Main parachains logic. For now this is just the determination of which validators do what.
|
||||
|
||||
use polkadot_primitives;
|
||||
use primitives;
|
||||
use rstd::prelude::*;
|
||||
use codec::{Slicable, Joiner};
|
||||
use runtime_support::Hashable;
|
||||
|
||||
use runtime_primitives::traits::{Executable, RefInto, MaybeEmpty};
|
||||
use polkadot_primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt};
|
||||
use primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt};
|
||||
use {system, session};
|
||||
|
||||
use runtime_support::{StorageValue, StorageMap};
|
||||
use runtime_support::dispatch::Result;
|
||||
use substrate_runtime_support::{Hashable, StorageValue, StorageMap};
|
||||
use substrate_runtime_support::dispatch::Result;
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use rstd::marker::PhantomData;
|
||||
@@ -34,7 +33,7 @@ use rstd::marker::PhantomData;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use {runtime_io, runtime_primitives};
|
||||
|
||||
pub trait Trait: system::Trait<Hash = polkadot_primitives::Hash> + session::Trait {
|
||||
pub trait Trait: system::Trait<Hash = primitives::Hash> + session::Trait {
|
||||
/// The position of the set_heads call in the block.
|
||||
const SET_POSITION: u32;
|
||||
|
||||
@@ -42,7 +41,11 @@ pub trait Trait: system::Trait<Hash = polkadot_primitives::Hash> + session::Trai
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
/// Parachains module.
|
||||
pub struct Module<T: Trait>;
|
||||
|
||||
/// Call type for parachains.
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum Call where aux: <T as Trait>::PublicAux {
|
||||
// provide candidate receipts for parachains, in ascending order by id.
|
||||
fn set_heads(aux, heads: Vec<CandidateReceipt>) -> Result = 0;
|
||||
@@ -227,7 +230,7 @@ mod tests {
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::H256;
|
||||
use runtime_primitives::BuildExternalities;
|
||||
use runtime_primitives::traits::{HasPublicAux, Identity};
|
||||
use runtime_primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
|
||||
use runtime_primitives::testing::{Digest, Header};
|
||||
use consensus;
|
||||
|
||||
@@ -243,7 +246,7 @@ mod tests {
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = runtime_io::BlakeTwo256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Header = Header;
|
||||
|
||||
+246
-192
@@ -11,19 +11,9 @@ name = "base58"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bigint"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -37,33 +27,55 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.1"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.4"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "coco"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.1.6"
|
||||
@@ -75,20 +87,15 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-primitives 0.1.0",
|
||||
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "elastic-array"
|
||||
version = "0.9.0"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -99,15 +106,37 @@ name = "environmental"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-bigint"
|
||||
name = "ethbloom"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-types-serialize"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -119,12 +148,23 @@ dependencies = [
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -148,16 +188,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal-impl"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -170,12 +210,12 @@ source = "git+https://github.com/paritytech/integer-sqrt-rs.git#886e9cb983c46498
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -185,12 +225,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.36"
|
||||
version = "0.2.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -206,9 +246,14 @@ name = "log"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.3.0"
|
||||
@@ -229,7 +274,7 @@ name = "num_cpus"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -245,9 +290,9 @@ name = "parity-wasm"
|
||||
version = "0.27.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -255,43 +300,35 @@ name = "parity-wasm"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.2.10"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plain_hasher"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polkadot-primitives"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-primitives 0.1.0",
|
||||
@@ -334,12 +371,20 @@ name = "proc-macro-hack-impl"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pwasm-alloc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pwasm-libc 0.1.0",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -351,15 +396,18 @@ name = "pwasm-utils"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
@@ -367,7 +415,7 @@ version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -377,7 +425,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -386,19 +434,19 @@ name = "rayon"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.3.0"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -408,20 +456,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -437,17 +484,17 @@ source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "safe-mix"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -457,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.6.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -470,31 +517,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.27"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.27"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -511,8 +549,8 @@ name = "substrate-keyring"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ed25519 0.1.0",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -520,25 +558,26 @@ name = "substrate-primitives"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
|
||||
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
|
||||
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-consensus"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -563,10 +602,11 @@ dependencies = [
|
||||
name = "substrate-runtime-council"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-keyring 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -585,9 +625,10 @@ dependencies = [
|
||||
name = "substrate-runtime-democracy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-consensus 0.1.0",
|
||||
@@ -604,8 +645,8 @@ dependencies = [
|
||||
name = "substrate-runtime-executive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
"substrate-runtime-primitives 0.1.0",
|
||||
@@ -620,12 +661,12 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"ed25519 0.1.0",
|
||||
"environmental 0.1.0",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"substrate-state-machine 0.1.0",
|
||||
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -634,8 +675,8 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -647,21 +688,22 @@ dependencies = [
|
||||
name = "substrate-runtime-sandbox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
"substrate-runtime-std 0.1.0",
|
||||
"wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "substrate-runtime-session"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-keyring 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -677,9 +719,10 @@ dependencies = [
|
||||
name = "substrate-runtime-staking"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-keyring 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
@@ -700,7 +743,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"pwasm-alloc 0.1.0",
|
||||
"pwasm-libc 0.1.0",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -708,9 +751,9 @@ name = "substrate-runtime-support"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ed25519 0.1.0",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -721,9 +764,9 @@ dependencies = [
|
||||
name = "substrate-runtime-system"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safe-mix 0.1.0",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -736,8 +779,9 @@ dependencies = [
|
||||
name = "substrate-runtime-timestamp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-runtime-io 0.1.0",
|
||||
@@ -751,43 +795,39 @@ dependencies = [
|
||||
name = "substrate-state-machine"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"substrate-primitives 0.1.0",
|
||||
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triehash"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -803,14 +843,25 @@ name = "uint"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -820,10 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasmi"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -850,32 +901,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
[metadata]
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
|
||||
"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
|
||||
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
|
||||
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
|
||||
"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
|
||||
"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
||||
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
|
||||
"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85"
|
||||
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
|
||||
"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
|
||||
"checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
|
||||
"checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6"
|
||||
"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002"
|
||||
"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
|
||||
"checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
|
||||
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
|
||||
"checksum hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd546ef520ab3745f1aae5f2cdc6de9e6498e94d1ab138b9eb3ddfbf335847fb"
|
||||
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631"
|
||||
"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95"
|
||||
"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a"
|
||||
"checksum integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)" = "<none>"
|
||||
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
|
||||
"checksum keccak-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b7f51f30d7986536accaec4a6a288008dfb3dbffe8a2863a65292bc395a3ae7"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
|
||||
"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
|
||||
"checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206"
|
||||
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
|
||||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
|
||||
@@ -883,39 +938,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum parity-wasm 0.27.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4dc02a80a0315b109e48992c46942c79bcdb8fac416dd575d330ed9ced6cbd"
|
||||
"checksum parity-wasm 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41083957b80abb8a01fac4d2773d5f92653aed8f0b740c8d3da1da62c7857abe"
|
||||
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
|
||||
"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8"
|
||||
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
|
||||
"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
|
||||
"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
|
||||
"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0"
|
||||
"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892"
|
||||
"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46"
|
||||
"checksum pwasm-utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3a822d2a1624b10c46572c231c149575bcc261c37d84fd3f1a2f5ae1f65515"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
|
||||
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
||||
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
|
||||
"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
|
||||
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
|
||||
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
|
||||
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
|
||||
"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9"
|
||||
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
|
||||
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
|
||||
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
|
||||
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
|
||||
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
|
||||
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
|
||||
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
|
||||
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
|
||||
"checksum serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
|
||||
"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
|
||||
"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7"
|
||||
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0"
|
||||
"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7"
|
||||
"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
|
||||
"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f"
|
||||
"checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce"
|
||||
"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435"
|
||||
"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
|
||||
"checksum wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26b20dbeb7caee04597a5d2c93e2b3e64872c6ea2af732d7ad49dbec44067c35"
|
||||
"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
@@ -8,6 +8,7 @@ crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
|
||||
polkadot-primitives = { path = "../../primitives", default-features = false }
|
||||
safe-mix = { path = "../../../safe-mix", default-features = false }
|
||||
substrate-codec = { path = "../../../substrate/codec", default-features = false }
|
||||
substrate-primitives = { path = "../../../substrate/primitives", default-features = false }
|
||||
@@ -23,11 +24,11 @@ substrate-runtime-session = { path = "../../../substrate/runtime/session", defau
|
||||
substrate-runtime-staking = { path = "../../../substrate/runtime/staking", default-features = false }
|
||||
substrate-runtime-system = { path = "../../../substrate/runtime/system", default-features = false }
|
||||
substrate-runtime-timestamp = { path = "../../../substrate/runtime/timestamp", default-features = false }
|
||||
polkadot-primitives = { path = "../../primitives", default-features = false }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std = [
|
||||
"polkadot-primitives/std",
|
||||
"safe-mix/std",
|
||||
"substrate-codec/std",
|
||||
"substrate-primitives/std",
|
||||
@@ -43,7 +44,6 @@ std = [
|
||||
"substrate-runtime-staking/std",
|
||||
"substrate-runtime-system/std",
|
||||
"substrate-runtime-timestamp/std",
|
||||
"polkadot-primitives/std",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -19,6 +19,7 @@
|
||||
|
||||
extern crate futures;
|
||||
extern crate ed25519;
|
||||
extern crate exit_future;
|
||||
extern crate parking_lot;
|
||||
extern crate tokio_timer;
|
||||
extern crate polkadot_primitives;
|
||||
@@ -28,17 +29,16 @@ extern crate polkadot_api;
|
||||
extern crate polkadot_consensus as consensus;
|
||||
extern crate polkadot_transaction_pool as transaction_pool;
|
||||
extern crate polkadot_keystore as keystore;
|
||||
extern crate substrate_client as client;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_network as network;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_client_db as client_db;
|
||||
extern crate substrate_executor;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
|
||||
extern crate exit_future;
|
||||
extern crate tokio_core;
|
||||
extern crate substrate_client as client;
|
||||
extern crate substrate_client_db as client_db;
|
||||
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
@@ -56,13 +56,13 @@ use std::thread;
|
||||
use futures::prelude::*;
|
||||
use tokio_core::reactor::Core;
|
||||
use codec::Slicable;
|
||||
use primitives::block::{Id as BlockId, ExtrinsicHash, HeaderHash, Header};
|
||||
use primitives::{AuthorityId};
|
||||
use primitives::AuthorityId;
|
||||
use transaction_pool::TransactionPool;
|
||||
use substrate_executor::NativeExecutor;
|
||||
use polkadot_executor::Executor as LocalDispatch;
|
||||
use keystore::Store as Keystore;
|
||||
use polkadot_api::PolkadotApi;
|
||||
use polkadot_primitives::{Block, BlockId, Hash, Header};
|
||||
use polkadot_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
|
||||
SessionConfig, StakingConfig, BuildExternalities};
|
||||
use client::backend::Backend;
|
||||
@@ -78,8 +78,8 @@ type CodeExecutor = NativeExecutor<LocalDispatch>;
|
||||
/// Polkadot service.
|
||||
pub struct Service<B, E> {
|
||||
thread: Option<thread::JoinHandle<()>>,
|
||||
client: Arc<Client<B, E>>,
|
||||
network: Arc<network::Service>,
|
||||
client: Arc<Client<B, E, Block>>,
|
||||
network: Arc<network::Service<Block>>,
|
||||
transaction_pool: Arc<TransactionPool>,
|
||||
signal: Option<Signal>,
|
||||
_consensus: Option<consensus::Service>,
|
||||
@@ -87,18 +87,18 @@ pub struct Service<B, E> {
|
||||
|
||||
struct TransactionPoolAdapter<B, E, A> where A: Send + Sync, E: Send + Sync {
|
||||
pool: Arc<TransactionPool>,
|
||||
client: Arc<Client<B, E>>,
|
||||
client: Arc<Client<B, E, Block>>,
|
||||
api: Arc<A>,
|
||||
}
|
||||
|
||||
impl<B, E, A> network::TransactionPool for TransactionPoolAdapter<B, E, A>
|
||||
impl<B, E, A> network::TransactionPool<Block> for TransactionPoolAdapter<B, E, A>
|
||||
where
|
||||
B: Backend + Send + Sync,
|
||||
E: client::CallExecutor + Send + Sync,
|
||||
client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
B: Backend<Block> + Send + Sync,
|
||||
E: client::CallExecutor<Block> + Send + Sync,
|
||||
client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>,
|
||||
A: PolkadotApi + Send + Sync,
|
||||
{
|
||||
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)> {
|
||||
fn transactions(&self) -> Vec<(Hash, Vec<u8>)> {
|
||||
let best_block = match self.client.info() {
|
||||
Ok(info) => info.chain.best_hash,
|
||||
Err(e) => {
|
||||
@@ -107,21 +107,25 @@ impl<B, E, A> network::TransactionPool for TransactionPoolAdapter<B, E, A>
|
||||
}
|
||||
};
|
||||
|
||||
let id = self.api.check_id(BlockId::Hash(best_block)).expect("Best block is always valid; qed.");
|
||||
let id = match self.api.check_id(BlockId::hash(best_block)) {
|
||||
Ok(id) => id,
|
||||
Err(_) => return Vec::new(),
|
||||
};
|
||||
|
||||
let ready = transaction_pool::Ready::create(id, &*self.api);
|
||||
|
||||
self.pool.cull_and_get_pending(ready, |pending| pending
|
||||
.map(|t| {
|
||||
let hash = ::primitives::Hash::from(&t.hash()[..]);
|
||||
let tx = codec::Slicable::encode(t.as_transaction());
|
||||
(hash, tx)
|
||||
let hash = t.hash().clone();
|
||||
(hash, t.primitive_extrinsic())
|
||||
})
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
fn import(&self, transaction: &[u8]) -> Option<ExtrinsicHash> {
|
||||
if let Some(uxt) = codec::Slicable::decode(&mut &transaction[..]) {
|
||||
fn import(&self, transaction: &Vec<u8>) -> Option<Hash> {
|
||||
let encoded = transaction.encode();
|
||||
if let Some(uxt) = codec::Slicable::decode(&mut &encoded[..]) {
|
||||
match self.pool.import_unchecked_extrinsic(uxt) {
|
||||
Ok(xt) => Some(*xt.hash()),
|
||||
Err(e) => match *e.kind() {
|
||||
@@ -138,7 +142,7 @@ impl<B, E, A> network::TransactionPool for TransactionPoolAdapter<B, E, A>
|
||||
}
|
||||
}
|
||||
|
||||
fn on_broadcasted(&self, propagations: HashMap<ExtrinsicHash, Vec<String>>) {
|
||||
fn on_broadcasted(&self, propagations: HashMap<Hash, Vec<String>>) {
|
||||
self.pool.on_broadcasted(propagations)
|
||||
}
|
||||
}
|
||||
@@ -165,12 +169,12 @@ fn poc_2_testnet_config() -> ChainConfig {
|
||||
}),
|
||||
system: None,
|
||||
session: Some(SessionConfig {
|
||||
validators: initial_authorities.clone(),
|
||||
validators: initial_authorities.iter().cloned().map(Into::into).collect(),
|
||||
session_length: 720, // that's 1 hour per session.
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
intentions: initial_authorities.clone(),
|
||||
intentions: initial_authorities.iter().cloned().map(Into::into).collect(),
|
||||
transaction_base_fee: 100,
|
||||
transaction_byte_fee: 1,
|
||||
balances: endowed_accounts.iter().map(|&k|(k, 1u128 << 60)).collect(),
|
||||
@@ -210,12 +214,12 @@ fn poc_2_testnet_config() -> ChainConfig {
|
||||
|
||||
fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
|
||||
let endowed_accounts = vec![
|
||||
ed25519::Pair::from_seed(b"Alice ").public().into(),
|
||||
ed25519::Pair::from_seed(b"Bob ").public().into(),
|
||||
ed25519::Pair::from_seed(b"Charlie ").public().into(),
|
||||
ed25519::Pair::from_seed(b"Dave ").public().into(),
|
||||
ed25519::Pair::from_seed(b"Eve ").public().into(),
|
||||
ed25519::Pair::from_seed(b"Ferdie ").public().into(),
|
||||
ed25519::Pair::from_seed(b"Alice ").public().0.into(),
|
||||
ed25519::Pair::from_seed(b"Bob ").public().0.into(),
|
||||
ed25519::Pair::from_seed(b"Charlie ").public().0.into(),
|
||||
ed25519::Pair::from_seed(b"Dave ").public().0.into(),
|
||||
ed25519::Pair::from_seed(b"Eve ").public().0.into(),
|
||||
ed25519::Pair::from_seed(b"Ferdie ").public().0.into(),
|
||||
];
|
||||
let genesis_config = GenesisConfig {
|
||||
consensus: Some(ConsensusConfig {
|
||||
@@ -224,12 +228,12 @@ fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
|
||||
}),
|
||||
system: None,
|
||||
session: Some(SessionConfig {
|
||||
validators: initial_authorities.clone(),
|
||||
validators: initial_authorities.iter().cloned().map(Into::into).collect(),
|
||||
session_length: 10,
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
intentions: initial_authorities.clone(),
|
||||
intentions: initial_authorities.iter().cloned().map(Into::into).collect(),
|
||||
transaction_base_fee: 1,
|
||||
transaction_byte_fee: 0,
|
||||
balances: endowed_accounts.iter().map(|&k|(k, (1u128 << 60))).collect(),
|
||||
@@ -243,7 +247,7 @@ fn testnet_config(initial_authorities: Vec<AuthorityId>) -> ChainConfig {
|
||||
minimum_deposit: 10,
|
||||
}),
|
||||
council: Some(CouncilConfig {
|
||||
active_council: endowed_accounts.iter().filter(|a| initial_authorities.iter().find(|b| a == b).is_none()).map(|a| (a.clone(), 1000000)).collect(),
|
||||
active_council: endowed_accounts.iter().filter(|a| initial_authorities.iter().find(|&b| &a.0 == b).is_none()).map(|a| (a.clone(), 1000000)).collect(),
|
||||
candidacy_bond: 10,
|
||||
voter_bond: 2,
|
||||
present_slash_per_voter: 1,
|
||||
@@ -280,16 +284,23 @@ struct GenesisBuilder {
|
||||
config: GenesisConfig,
|
||||
}
|
||||
|
||||
impl client::GenesisBuilder for GenesisBuilder {
|
||||
impl client::GenesisBuilder<Block> for GenesisBuilder {
|
||||
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
|
||||
let storage = self.config.build_externalities();
|
||||
let block = genesis::construct_genesis_block(&storage);
|
||||
(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
|
||||
let block = genesis::construct_genesis_block::<Block>(&storage);
|
||||
(block.header, storage.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates light client and register protocol with the network service
|
||||
pub fn new_light(config: Configuration) -> Result<Service<client::light::Backend, client::RemoteCallExecutor<client::light::Backend, network::OnDemand<network::Service>>>, error::Error> {
|
||||
pub fn new_light(config: Configuration)
|
||||
-> Result<
|
||||
Service<
|
||||
client::light::Backend<Block>,
|
||||
client::RemoteCallExecutor<client::light::Backend<Block>, network::OnDemand<Block, network::Service<Block>>>
|
||||
>,
|
||||
error::Error,
|
||||
> {
|
||||
Service::new(move |_, executor, genesis_builder: GenesisBuilder| {
|
||||
let client_backend = client::light::new_light_backend();
|
||||
let fetch_checker = Arc::new(client::light::new_fetch_checker(client_backend.clone(), executor));
|
||||
@@ -303,7 +314,7 @@ pub fn new_light(config: Configuration) -> Result<Service<client::light::Backend
|
||||
}
|
||||
|
||||
/// Creates full client and register protocol with the network service
|
||||
pub fn new_full(config: Configuration) -> Result<Service<client_db::Backend, client::LocalCallExecutor<client_db::Backend, CodeExecutor>>, error::Error> {
|
||||
pub fn new_full(config: Configuration) -> Result<Service<client_db::Backend<Block>, client::LocalCallExecutor<client_db::Backend<Block>, CodeExecutor>>, error::Error> {
|
||||
let is_validator = (config.roles & Role::VALIDATOR) == Role::VALIDATOR;
|
||||
Service::new(|db_settings, executor, genesis_builder: GenesisBuilder|
|
||||
Ok((Arc::new(client_db::new_client(db_settings, executor, genesis_builder)?), None)),
|
||||
@@ -330,9 +341,9 @@ pub fn new_full(config: Configuration) -> Result<Service<client_db::Backend, cli
|
||||
|
||||
impl<B, E> Service<B, E>
|
||||
where
|
||||
B: Backend + Send + Sync + 'static,
|
||||
E: CallExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error>
|
||||
B: Backend<Block> + Send + Sync + 'static,
|
||||
E: CallExecutor<Block> + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
/// Creates and register protocol with the network service
|
||||
fn new<F, G, C, A>(client_creator: F, api_creator: G, consensus_creator: C, mut config: Configuration) -> Result<Self, error::Error>
|
||||
@@ -341,13 +352,13 @@ impl<B, E> Service<B, E>
|
||||
client_db::DatabaseSettings,
|
||||
CodeExecutor,
|
||||
GenesisBuilder,
|
||||
) -> Result<(Arc<Client<B, E>>, Option<Arc<network::OnDemand<network::Service>>>), error::Error>,
|
||||
) -> Result<(Arc<Client<B, E, Block>>, Option<Arc<network::OnDemand<Block, network::Service<Block>>>>), error::Error>,
|
||||
G: Fn(
|
||||
Arc<Client<B, E>>,
|
||||
Arc<Client<B, E, Block>>,
|
||||
) -> Arc<A>,
|
||||
C: Fn(
|
||||
Arc<Client<B, E>>,
|
||||
Arc<network::Service>,
|
||||
Arc<Client<B, E, Block>>,
|
||||
Arc<network::Service<Block>>,
|
||||
Arc<TransactionPool>,
|
||||
&Keystore
|
||||
) -> Result<Option<consensus::Service>, error::Error>,
|
||||
@@ -405,7 +416,6 @@ impl<B, E> Service<B, E>
|
||||
on_demand: on_demand.clone().map(|d| d as Arc<network::OnDemandService>),
|
||||
transaction_pool: transaction_pool_adapter,
|
||||
};
|
||||
|
||||
let network = network::Service::new(network_params)?;
|
||||
let barrier = ::std::sync::Arc::new(Barrier::new(2));
|
||||
on_demand.map(|on_demand| on_demand.set_service_link(Arc::downgrade(&network)));
|
||||
@@ -468,12 +478,12 @@ impl<B, E> Service<B, E>
|
||||
}
|
||||
|
||||
/// Get shared client instance.
|
||||
pub fn client(&self) -> Arc<Client<B, E>> {
|
||||
pub fn client(&self) -> Arc<Client<B, E, Block>> {
|
||||
self.client.clone()
|
||||
}
|
||||
|
||||
/// Get shared network instance.
|
||||
pub fn network(&self) -> Arc<network::Service> {
|
||||
pub fn network(&self) -> Arc<network::Service<Block>> {
|
||||
self.network.clone()
|
||||
}
|
||||
|
||||
@@ -484,11 +494,11 @@ impl<B, E> Service<B, E>
|
||||
}
|
||||
|
||||
/// Produce a task which prunes any finalized transactions from the pool.
|
||||
pub fn prune_imported<A>(api: &A, pool: &TransactionPool, hash: HeaderHash)
|
||||
pub fn prune_imported<A>(api: &A, pool: &TransactionPool, hash: Hash)
|
||||
where
|
||||
A: PolkadotApi,
|
||||
{
|
||||
match api.check_id(BlockId::Hash(hash)) {
|
||||
match api.check_id(BlockId::hash(hash)) {
|
||||
Ok(id) => {
|
||||
let ready = transaction_pool::Ready::create(id, api);
|
||||
pool.cull(None, ready);
|
||||
|
||||
@@ -21,8 +21,8 @@ pub mod generic;
|
||||
|
||||
pub use generic::Table;
|
||||
|
||||
use primitives::parachain::{Id, CandidateReceipt};
|
||||
use primitives::{SessionKey, Hash, Signature};
|
||||
use primitives::parachain::{Id, CandidateReceipt, CandidateSignature as Signature};
|
||||
use primitives::{SessionKey, Hash};
|
||||
|
||||
/// Statements about candidates on the network.
|
||||
pub type Statement = generic::Statement<CandidateReceipt, Hash>;
|
||||
|
||||
@@ -40,106 +40,23 @@ use std::{
|
||||
|
||||
use codec::Slicable;
|
||||
use extrinsic_pool::{Pool, txpool::{self, Readiness, scoring::{Change, Choice}}};
|
||||
use extrinsic_pool::api::ExtrinsicPool;
|
||||
use polkadot_api::PolkadotApi;
|
||||
use primitives::parachain::CandidateReceipt;
|
||||
use primitives::{AccountId, Timestamp, Hash};
|
||||
use runtime::{Block, UncheckedExtrinsic, TimestampCall, ParachainsCall, Call};
|
||||
use substrate_primitives::block::{Extrinsic, ExtrinsicHash};
|
||||
use substrate_primitives::hexdisplay::HexDisplay;
|
||||
use substrate_runtime_primitives::traits::{Bounded, Checkable};
|
||||
use primitives::{AccountId, Hash, UncheckedExtrinsic as FutureProofUncheckedExtrinsic};
|
||||
use runtime::UncheckedExtrinsic;
|
||||
use substrate_runtime_primitives::traits::{Bounded, Checkable, BlakeTwo256, Hashing};
|
||||
|
||||
pub use extrinsic_pool::txpool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps};
|
||||
pub use error::{Error, ErrorKind, Result};
|
||||
|
||||
/// Useful functions for working with Polkadot blocks.
|
||||
pub struct PolkadotBlock {
|
||||
block: Block,
|
||||
location: Option<(&'static str, usize)>,
|
||||
}
|
||||
|
||||
impl PolkadotBlock {
|
||||
/// Create a new block, checking high-level well-formedness.
|
||||
pub fn from(unchecked: Block) -> ::std::result::Result<Self, Block> {
|
||||
if unchecked.extrinsics.len() < 2 {
|
||||
return Err(unchecked);
|
||||
}
|
||||
if unchecked.extrinsics[0].is_signed() {
|
||||
return Err(unchecked);
|
||||
}
|
||||
if unchecked.extrinsics[1].is_signed() {
|
||||
return Err(unchecked);
|
||||
}
|
||||
|
||||
match unchecked.extrinsics[0].extrinsic.function {
|
||||
Call::Timestamp(TimestampCall::set(_)) => {},
|
||||
_ => return Err(unchecked),
|
||||
}
|
||||
|
||||
match unchecked.extrinsics[1].extrinsic.function {
|
||||
Call::Parachains(ParachainsCall::set_heads(_)) => {},
|
||||
_ => return Err(unchecked),
|
||||
}
|
||||
|
||||
// any further checks...
|
||||
Ok(PolkadotBlock { block: unchecked, location: None })
|
||||
}
|
||||
|
||||
/// Create a new block, skipping any high-level well-formedness checks. WARNING: This could
|
||||
/// result in internal functions panicking if the block is, in fact, not well-formed.
|
||||
pub fn force_from(known_good: Block, file: &'static str, line: usize) -> Self {
|
||||
PolkadotBlock { block: known_good, location: Some((file, line)) }
|
||||
}
|
||||
|
||||
/// Retrieve the timestamp of a Polkadot block.
|
||||
pub fn timestamp(&self) -> Timestamp {
|
||||
if let Call::Timestamp(TimestampCall::set(t)) = self.block.extrinsics[0].extrinsic.function {
|
||||
t
|
||||
} else {
|
||||
if let Some((file, line)) = self.location {
|
||||
panic!("Invalid block used in `PolkadotBlock::force_from` at {}:{}", file, line);
|
||||
} else {
|
||||
panic!("Invalid block made it through the PolkadotBlock verification!?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the parachain candidates proposed for this block.
|
||||
pub fn parachain_heads(&self) -> &[CandidateReceipt] {
|
||||
if let Call::Parachains(ParachainsCall::set_heads(ref t)) = self.block.extrinsics[1].extrinsic.function {
|
||||
&t[..]
|
||||
} else {
|
||||
if let Some((file, line)) = self.location {
|
||||
panic!("Invalid block used in `PolkadotBlock::force_from` at {}:{}", file, line);
|
||||
} else {
|
||||
panic!("Invalid block made it through the PolkadotBlock verification!?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_polkadot_block {
|
||||
($known_good:expr) => ( PolkadotBlock::force_from(known_good, file!(), line!()) )
|
||||
}
|
||||
|
||||
impl ::std::ops::Deref for PolkadotBlock {
|
||||
type Target = Block;
|
||||
fn deref(&self) -> &Block {
|
||||
&self.block
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PolkadotBlock> for Block {
|
||||
fn from(pd: PolkadotBlock) -> Self {
|
||||
pd.block
|
||||
}
|
||||
}
|
||||
/// Type alias for convenience.
|
||||
pub type CheckedExtrinsic = <UncheckedExtrinsic as Checkable>::Checked;
|
||||
|
||||
/// A verified transaction which should be includable and non-inherent.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VerifiedTransaction {
|
||||
inner: <UncheckedExtrinsic as Checkable>::Checked,
|
||||
hash: ExtrinsicHash,
|
||||
inner: CheckedExtrinsic,
|
||||
hash: Hash,
|
||||
encoded_size: usize,
|
||||
}
|
||||
|
||||
@@ -150,10 +67,10 @@ impl VerifiedTransaction {
|
||||
bail!(ErrorKind::IsInherent(xt))
|
||||
}
|
||||
|
||||
let message = codec::Slicable::encode(&xt);
|
||||
let message = Slicable::encode(&xt);
|
||||
match xt.check() {
|
||||
Ok(xt) => {
|
||||
let hash = substrate_primitives::hashing::blake2_256(&message);
|
||||
let hash = BlakeTwo256::hash(&message);
|
||||
Ok(VerifiedTransaction {
|
||||
inner: xt,
|
||||
hash: hash.into(),
|
||||
@@ -169,8 +86,14 @@ impl VerifiedTransaction {
|
||||
self.as_ref().as_unchecked()
|
||||
}
|
||||
|
||||
/// Convert to primitive unchecked extrinsic.
|
||||
pub fn primitive_extrinsic(&self) -> ::primitives::UncheckedExtrinsic {
|
||||
Slicable::decode(&mut self.as_transaction().encode().as_slice())
|
||||
.expect("UncheckedExtrinsic shares repr with Vec<u8>; qed")
|
||||
}
|
||||
|
||||
/// Consume the verified transaciton, yielding the unchecked counterpart.
|
||||
pub fn into_inner(self) -> <UncheckedExtrinsic as Checkable>::Checked {
|
||||
pub fn into_inner(self) -> CheckedExtrinsic {
|
||||
self.inner
|
||||
}
|
||||
|
||||
@@ -190,8 +113,8 @@ impl VerifiedTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef< <UncheckedExtrinsic as Checkable>::Checked > for VerifiedTransaction {
|
||||
fn as_ref(&self) -> &<UncheckedExtrinsic as Checkable>::Checked {
|
||||
impl AsRef<CheckedExtrinsic> for VerifiedTransaction {
|
||||
fn as_ref(&self) -> &CheckedExtrinsic {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
@@ -303,15 +226,12 @@ impl<'a, T: 'a + PolkadotApi> txpool::Ready<VerifiedTransaction> for Ready<'a, T
|
||||
|
||||
pub struct Verifier;
|
||||
|
||||
impl txpool::Verifier<Extrinsic> for Verifier {
|
||||
impl txpool::Verifier<UncheckedExtrinsic> for Verifier {
|
||||
type VerifiedTransaction = VerifiedTransaction;
|
||||
type Error = Error;
|
||||
|
||||
fn verify_transaction(&self, xt: Extrinsic) -> Result<Self::VerifiedTransaction> {
|
||||
info!("Extrinsic submitted: {}", HexDisplay::from(&xt.0));
|
||||
let uxt = xt.using_encoded(|ref mut s| UncheckedExtrinsic::decode(s))
|
||||
.ok_or_else(|| ErrorKind::InvalidExtrinsicFormat)?;
|
||||
info!("Correctly formatted: {:?}", uxt);
|
||||
fn verify_transaction(&self, uxt: UncheckedExtrinsic) -> Result<Self::VerifiedTransaction> {
|
||||
info!("Extrinsic Submitted: {:?}", uxt);
|
||||
VerifiedTransaction::create(uxt)
|
||||
}
|
||||
}
|
||||
@@ -320,7 +240,7 @@ impl txpool::Verifier<Extrinsic> for Verifier {
|
||||
///
|
||||
/// Wraps a `extrinsic_pool::Pool`.
|
||||
pub struct TransactionPool {
|
||||
inner: Pool<Verifier, Scoring, Error>,
|
||||
inner: Pool<UncheckedExtrinsic, Hash, Verifier, Scoring, Error>,
|
||||
}
|
||||
|
||||
impl TransactionPool {
|
||||
@@ -337,14 +257,25 @@ impl TransactionPool {
|
||||
}
|
||||
|
||||
impl Deref for TransactionPool {
|
||||
type Target = Pool<Verifier, Scoring, Error>;
|
||||
type Target = Pool<UncheckedExtrinsic, Hash, Verifier, Scoring, Error>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
}
|
||||
impl ExtrinsicPool<FutureProofUncheckedExtrinsic, Hash> for TransactionPool {
|
||||
type Error = Error;
|
||||
|
||||
fn submit(&self, xts: Vec<FutureProofUncheckedExtrinsic>) -> Result<Vec<Hash>> {
|
||||
// TODO: more general transaction pool, which can handle more kinds of vec-encoded transactions,
|
||||
// even when runtime is out of date.
|
||||
xts.into_iter()
|
||||
.map(|xt| xt.encode())
|
||||
.map(|encoded| UncheckedExtrinsic::decode(&mut &encoded[..]))
|
||||
.map(|maybe_decoded| maybe_decoded.ok_or_else(|| ErrorKind::InvalidExtrinsicFormat.into()))
|
||||
.map(|x| x.and_then(|x| self.import_unchecked_extrinsic(x)))
|
||||
.map(|x| x.map(|x| x.hash().clone()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ futures = "0.1.17"
|
||||
substrate-codec = { path = "../codec" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
substrate-runtime-support = { path = "../runtime-support" }
|
||||
substrate-runtime-primitives = { path = "../runtime/primitives" }
|
||||
ed25519 = { path = "../ed25519" }
|
||||
tokio-timer = "0.1.2"
|
||||
parking_lot = "0.4"
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
error_chain! {
|
||||
errors {
|
||||
/// Missing state at block with given Id.
|
||||
StateUnavailable(b: ::primitives::block::Id) {
|
||||
/// Missing state at block with given descriptor.
|
||||
StateUnavailable(b: String) {
|
||||
description("State missing at given block."),
|
||||
display("State unavailable at block {:?}", b),
|
||||
display("State unavailable at block {}", b),
|
||||
}
|
||||
|
||||
/// I/O terminated unexpectedly
|
||||
|
||||
+169
-142
@@ -22,6 +22,7 @@ pub mod generic;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate ed25519;
|
||||
extern crate tokio_timer;
|
||||
extern crate parking_lot;
|
||||
@@ -41,9 +42,9 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use codec::Slicable;
|
||||
use ed25519::LocalizedSignature;
|
||||
use runtime_support::Hashable;
|
||||
use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification};
|
||||
use primitives::block::{Block, Id as BlockId, Header, HeaderHash};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{Block, Header};
|
||||
use runtime_primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification};
|
||||
use primitives::AuthorityId;
|
||||
|
||||
use futures::{task, Async, Stream, Sink, Future, IntoFuture};
|
||||
@@ -56,27 +57,27 @@ pub use error::{Error, ErrorKind};
|
||||
|
||||
/// Messages over the proposal.
|
||||
/// Each message carries an associated round number.
|
||||
pub type Message = generic::Message<Block, HeaderHash>;
|
||||
pub type Message<B> = generic::Message<B, <B as Block>::Hash>;
|
||||
|
||||
/// Localized message type.
|
||||
pub type LocalizedMessage = generic::LocalizedMessage<
|
||||
Block,
|
||||
HeaderHash,
|
||||
pub type LocalizedMessage<B> = generic::LocalizedMessage<
|
||||
B,
|
||||
<B as Block>::Hash,
|
||||
AuthorityId,
|
||||
LocalizedSignature
|
||||
>;
|
||||
|
||||
/// Justification of some hash.
|
||||
pub type Justification = generic::Justification<HeaderHash, LocalizedSignature>;
|
||||
pub type Justification<H> = generic::Justification<H, LocalizedSignature>;
|
||||
|
||||
/// Justification of a prepare message.
|
||||
pub type PrepareJustification = generic::PrepareJustification<HeaderHash, LocalizedSignature>;
|
||||
pub type PrepareJustification<H> = generic::PrepareJustification<H, LocalizedSignature>;
|
||||
|
||||
/// Unchecked justification.
|
||||
pub type UncheckedJustification = generic::UncheckedJustification<HeaderHash, LocalizedSignature>;
|
||||
pub type UncheckedJustification<H> = generic::UncheckedJustification<H, LocalizedSignature>;
|
||||
|
||||
impl From<PrimitiveJustification> for UncheckedJustification {
|
||||
fn from(just: PrimitiveJustification) -> Self {
|
||||
impl<H> From<PrimitiveJustification<H>> for UncheckedJustification<H> {
|
||||
fn from(just: PrimitiveJustification<H>) -> Self {
|
||||
UncheckedJustification {
|
||||
round_number: just.round_number as usize,
|
||||
digest: just.hash,
|
||||
@@ -88,46 +89,46 @@ impl From<PrimitiveJustification> for UncheckedJustification {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UncheckedJustification> for PrimitiveJustification {
|
||||
fn from(just: UncheckedJustification) -> Self {
|
||||
impl<H> Into<PrimitiveJustification<H>> for UncheckedJustification<H> {
|
||||
fn into(self) -> PrimitiveJustification<H> {
|
||||
PrimitiveJustification {
|
||||
round_number: just.round_number as u32,
|
||||
hash: just.digest,
|
||||
signatures: just.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(),
|
||||
round_number: self.round_number as u32,
|
||||
hash: self.digest,
|
||||
signatures: self.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of a committed round of BFT
|
||||
pub type Committed = generic::Committed<Block, HeaderHash, LocalizedSignature>;
|
||||
pub type Committed<B> = generic::Committed<B, <B as Block>::Hash, LocalizedSignature>;
|
||||
|
||||
/// Communication between BFT participants.
|
||||
pub type Communication = generic::Communication<Block, HeaderHash, AuthorityId, LocalizedSignature>;
|
||||
pub type Communication<B> = generic::Communication<B, <B as Block>::Hash, AuthorityId, LocalizedSignature>;
|
||||
|
||||
/// Misbehavior observed from BFT participants.
|
||||
pub type Misbehavior = generic::Misbehavior<HeaderHash, LocalizedSignature>;
|
||||
pub type Misbehavior<H> = generic::Misbehavior<H, LocalizedSignature>;
|
||||
|
||||
/// Proposer factory. Can be used to create a proposer instance.
|
||||
pub trait ProposerFactory {
|
||||
pub trait ProposerFactory<B: Block> {
|
||||
/// The proposer type this creates.
|
||||
type Proposer: Proposer;
|
||||
type Proposer: Proposer<B>;
|
||||
/// Error which can occur upon creation.
|
||||
type Error: From<Error>;
|
||||
|
||||
/// Initialize the proposal logic on top of a specific header.
|
||||
// TODO: provide state context explicitly?
|
||||
fn init(&self, parent_header: &Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Self::Error>;
|
||||
fn init(&self, parent_header: &B::Header, authorities: &[AuthorityId], sign_with: Arc<ed25519::Pair>) -> Result<Self::Proposer, Self::Error>;
|
||||
}
|
||||
|
||||
/// Logic for a proposer.
|
||||
///
|
||||
/// This will encapsulate creation and evaluation of proposals at a specific
|
||||
/// block.
|
||||
pub trait Proposer {
|
||||
pub trait Proposer<B: Block> {
|
||||
/// Error type which can occur when proposing or evaluating.
|
||||
type Error: From<Error> + From<InputStreamConcluded> + 'static;
|
||||
/// Future that resolves to a created proposal.
|
||||
type Create: IntoFuture<Item=Block,Error=Self::Error>;
|
||||
/// Future that resolves to a committed proposal.
|
||||
type Create: IntoFuture<Item=B,Error=Self::Error>;
|
||||
/// Future that resolves when a proposal is evaluated.
|
||||
type Evaluate: IntoFuture<Item=bool,Error=Self::Error>;
|
||||
|
||||
@@ -135,10 +136,10 @@ pub trait Proposer {
|
||||
fn propose(&self) -> Self::Create;
|
||||
|
||||
/// Evaluate proposal. True means valid.
|
||||
fn evaluate(&self, proposal: &Block) -> Self::Evaluate;
|
||||
fn evaluate(&self, proposal: &B) -> Self::Evaluate;
|
||||
|
||||
/// Import witnessed misbehavior.
|
||||
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, Misbehavior)>);
|
||||
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, Misbehavior<B::Hash>)>);
|
||||
|
||||
/// Determine the proposer for a given round. This should be a deterministic function
|
||||
/// with consistent results across all authorities.
|
||||
@@ -146,33 +147,37 @@ pub trait Proposer {
|
||||
}
|
||||
|
||||
/// Block import trait.
|
||||
pub trait BlockImport {
|
||||
pub trait BlockImport<B: Block> {
|
||||
/// Import a block alongside its corresponding justification.
|
||||
fn import_block(&self, block: Block, justification: Justification);
|
||||
fn import_block(&self, block: B, justification: Justification<B::Hash>);
|
||||
}
|
||||
|
||||
/// Trait for getting the authorities at a given block.
|
||||
pub trait Authorities {
|
||||
pub trait Authorities<B: Block> {
|
||||
/// Get the authorities at the given block.
|
||||
fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, Error>;
|
||||
fn authorities(&self, at: &BlockId<B>) -> Result<Vec<AuthorityId>, Error>;
|
||||
}
|
||||
|
||||
/// Instance of BFT agreement.
|
||||
struct BftInstance<P> {
|
||||
struct BftInstance<B: Block, P> {
|
||||
key: Arc<ed25519::Pair>,
|
||||
authorities: Vec<AuthorityId>,
|
||||
parent_hash: HeaderHash,
|
||||
parent_hash: B::Hash,
|
||||
timer: Timer,
|
||||
round_timeout_multiplier: u64,
|
||||
proposer: P,
|
||||
}
|
||||
|
||||
impl<P: Proposer> generic::Context for BftInstance<P> {
|
||||
impl<B: Block, P: Proposer<B>> generic::Context for BftInstance<B, P>
|
||||
where
|
||||
B: Clone + Eq,
|
||||
B::Hash: ::std::hash::Hash,
|
||||
{
|
||||
type Error = P::Error;
|
||||
type AuthorityId = AuthorityId;
|
||||
type Digest = HeaderHash;
|
||||
type Digest = B::Hash;
|
||||
type Signature = LocalizedSignature;
|
||||
type Candidate = Block;
|
||||
type Candidate = B;
|
||||
type RoundTimeout = Box<Future<Item=(),Error=Self::Error> + Send>;
|
||||
type CreateProposal = <P::Create as IntoFuture>::Future;
|
||||
type EvaluateProposal = <P::Evaluate as IntoFuture>::Future;
|
||||
@@ -185,11 +190,11 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
|
||||
self.proposer.propose().into_future()
|
||||
}
|
||||
|
||||
fn candidate_digest(&self, proposal: &Block) -> HeaderHash {
|
||||
proposal.header.blake2_256().into()
|
||||
fn candidate_digest(&self, proposal: &B) -> B::Hash {
|
||||
proposal.hash()
|
||||
}
|
||||
|
||||
fn sign_local(&self, message: Message) -> LocalizedMessage {
|
||||
fn sign_local(&self, message: Message<B>) -> LocalizedMessage<B> {
|
||||
sign_message(message, &*self.key, self.parent_hash.clone())
|
||||
}
|
||||
|
||||
@@ -197,7 +202,7 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
|
||||
self.proposer.round_proposer(round, &self.authorities[..])
|
||||
}
|
||||
|
||||
fn proposal_valid(&self, proposal: &Block) -> Self::EvaluateProposal {
|
||||
fn proposal_valid(&self, proposal: &B) -> Self::EvaluateProposal {
|
||||
self.proposer.evaluate(proposal).into_future()
|
||||
}
|
||||
|
||||
@@ -217,23 +222,27 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
|
||||
|
||||
/// A future that resolves either when canceled (witnessing a block from the network at same height)
|
||||
/// or when agreement completes.
|
||||
pub struct BftFuture<P, I, InStream, OutSink> where
|
||||
P: Proposer,
|
||||
InStream: Stream<Item=Communication, Error=P::Error>,
|
||||
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>,
|
||||
pub struct BftFuture<B, P, I, InStream, OutSink> where
|
||||
B: Block + Clone + Eq,
|
||||
B::Hash: ::std::hash::Hash,
|
||||
P: Proposer<B>,
|
||||
InStream: Stream<Item=Communication<B>, Error=P::Error>,
|
||||
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
|
||||
{
|
||||
inner: generic::Agreement<BftInstance<P>, InStream, OutSink>,
|
||||
inner: generic::Agreement<BftInstance<B, P>, InStream, OutSink>,
|
||||
cancel: Arc<AtomicBool>,
|
||||
send_task: Option<oneshot::Sender<task::Task>>,
|
||||
import: Arc<I>,
|
||||
}
|
||||
|
||||
impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> where
|
||||
P: Proposer,
|
||||
impl<B, P, I, InStream, OutSink> Future for BftFuture<B, P, I, InStream, OutSink> where
|
||||
B: Block + Clone + Eq,
|
||||
B::Hash: ::std::hash::Hash,
|
||||
P: Proposer<B>,
|
||||
P::Error: ::std::fmt::Display,
|
||||
I: BlockImport,
|
||||
InStream: Stream<Item=Communication, Error=P::Error>,
|
||||
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>,
|
||||
I: BlockImport<B>,
|
||||
InStream: Stream<Item=Communication<B>, Error=P::Error>,
|
||||
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
|
||||
{
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
@@ -258,7 +267,7 @@ impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> wher
|
||||
// we will get the block from the network later.
|
||||
if let Some(justified_block) = committed.candidate {
|
||||
info!(target: "bft", "Importing block #{} ({}) directly from BFT consensus",
|
||||
justified_block.header.number, HeaderHash::from(justified_block.header.blake2_256()));
|
||||
justified_block.header().number(), justified_block.hash());
|
||||
|
||||
self.import.import_block(justified_block, committed.justification)
|
||||
}
|
||||
@@ -267,10 +276,12 @@ impl<P, I, InStream, OutSink> Future for BftFuture<P, I, InStream, OutSink> wher
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, I, InStream, OutSink> Drop for BftFuture<P, I, InStream, OutSink> where
|
||||
P: Proposer,
|
||||
InStream: Stream<Item=Communication, Error=P::Error>,
|
||||
OutSink: Sink<SinkItem=Communication, SinkError=P::Error>,
|
||||
impl<B, P, I, InStream, OutSink> Drop for BftFuture<B, P, I, InStream, OutSink> where
|
||||
B: Block + Clone + Eq,
|
||||
B::Hash: ::std::hash::Hash,
|
||||
P: Proposer<B>,
|
||||
InStream: Stream<Item=Communication<B>, Error=P::Error>,
|
||||
OutSink: Sink<SinkItem=Communication<B>, SinkError=P::Error>,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
// TODO: have a trait member to pass misbehavior reports into.
|
||||
@@ -301,24 +312,26 @@ impl Drop for AgreementHandle {
|
||||
|
||||
/// The BftService kicks off the agreement process on top of any blocks it
|
||||
/// is notified of.
|
||||
pub struct BftService<P, I> {
|
||||
pub struct BftService<B: Block, P, I> {
|
||||
client: Arc<I>,
|
||||
live_agreement: Mutex<Option<(HeaderHash, AgreementHandle)>>,
|
||||
live_agreement: Mutex<Option<(B::Hash, AgreementHandle)>>,
|
||||
timer: Timer,
|
||||
round_timeout_multiplier: u64,
|
||||
key: Arc<ed25519::Pair>, // TODO: key changing over time.
|
||||
factory: P,
|
||||
}
|
||||
|
||||
impl<P, I> BftService<P, I>
|
||||
impl<B, P, I> BftService<B, P, I>
|
||||
where
|
||||
P: ProposerFactory,
|
||||
<P::Proposer as Proposer>::Error: ::std::fmt::Display,
|
||||
I: BlockImport + Authorities,
|
||||
B: Block + Clone + Eq,
|
||||
B::Hash: ::std::hash::Hash,
|
||||
P: ProposerFactory<B>,
|
||||
<P::Proposer as Proposer<B>>::Error: ::std::fmt::Display,
|
||||
I: BlockImport<B> + Authorities<B>,
|
||||
{
|
||||
|
||||
/// Create a new service instance.
|
||||
pub fn new(client: Arc<I>, key: Arc<ed25519::Pair>, factory: P) -> BftService<P, I> {
|
||||
pub fn new(client: Arc<I>, key: Arc<ed25519::Pair>, factory: P) -> BftService<B, P, I> {
|
||||
BftService {
|
||||
client: client,
|
||||
live_agreement: Mutex::new(None),
|
||||
@@ -340,17 +353,17 @@ impl<P, I> BftService<P, I>
|
||||
/// If the local signing key is an authority, this will begin the consensus process to build a
|
||||
/// block on top of it. If the executor fails to run the future, an error will be returned.
|
||||
/// Returns `None` if the agreement on the block with given parent is already in progress.
|
||||
pub fn build_upon<InStream, OutSink>(&self, header: &Header, input: InStream, output: OutSink)
|
||||
-> Result<Option<BftFuture<<P as ProposerFactory>::Proposer, I, InStream, OutSink>>, P::Error> where
|
||||
InStream: Stream<Item=Communication, Error=<<P as ProposerFactory>::Proposer as Proposer>::Error>,
|
||||
OutSink: Sink<SinkItem=Communication, SinkError=<<P as ProposerFactory>::Proposer as Proposer>::Error>,
|
||||
pub fn build_upon<InStream, OutSink>(&self, header: &B::Header, input: InStream, output: OutSink)
|
||||
-> Result<Option<BftFuture<B, <P as ProposerFactory<B>>::Proposer, I, InStream, OutSink>>, P::Error> where
|
||||
InStream: Stream<Item=Communication<B>, Error=<<P as ProposerFactory<B>>::Proposer as Proposer<B>>::Error>,
|
||||
OutSink: Sink<SinkItem=Communication<B>, SinkError=<<P as ProposerFactory<B>>::Proposer as Proposer<B>>::Error>,
|
||||
{
|
||||
let hash = header.blake2_256().into();
|
||||
if self.live_agreement.lock().as_ref().map_or(false, |&(h, _)| h == hash) {
|
||||
let hash = header.hash();
|
||||
if self.live_agreement.lock().as_ref().map_or(false, |&(ref h, _)| h == &hash) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let authorities = self.client.authorities(&BlockId::Hash(hash))?;
|
||||
let authorities = self.client.authorities(&BlockId::Hash(hash.clone()))?;
|
||||
|
||||
let n = authorities.len();
|
||||
let max_faulty = max_faulty_of(n);
|
||||
@@ -368,7 +381,7 @@ impl<P, I> BftService<P, I>
|
||||
|
||||
let bft_instance = BftInstance {
|
||||
proposer,
|
||||
parent_hash: hash,
|
||||
parent_hash: hash.clone(),
|
||||
round_timeout_multiplier: self.round_timeout_multiplier,
|
||||
timer: self.timer.clone(),
|
||||
key: self.key.clone(),
|
||||
@@ -409,8 +422,8 @@ impl<P, I> BftService<P, I>
|
||||
}
|
||||
|
||||
/// Get current agreement parent hash if any.
|
||||
pub fn live_agreement(&self) -> Option<HeaderHash> {
|
||||
self.live_agreement.lock().as_ref().map(|&(h, _)| h.clone())
|
||||
pub fn live_agreement(&self) -> Option<B::Hash> {
|
||||
self.live_agreement.lock().as_ref().map(|&(ref h, _)| h.clone())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -427,8 +440,8 @@ pub fn bft_threshold(n: usize) -> usize {
|
||||
n - max_faulty_of(n)
|
||||
}
|
||||
|
||||
fn check_justification_signed_message(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification)
|
||||
-> Result<Justification, UncheckedJustification>
|
||||
fn check_justification_signed_message<H>(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification<H>)
|
||||
-> Result<Justification<H>, UncheckedJustification<H>>
|
||||
{
|
||||
// TODO: return additional error information.
|
||||
just.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| {
|
||||
@@ -447,12 +460,12 @@ fn check_justification_signed_message(authorities: &[AuthorityId], message: &[u8
|
||||
/// Provide all valid authorities.
|
||||
///
|
||||
/// On failure, returns the justification back.
|
||||
pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification)
|
||||
-> Result<Justification, UncheckedJustification>
|
||||
pub fn check_justification<B: Block>(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification<B::Hash>)
|
||||
-> Result<Justification<B::Hash>, UncheckedJustification<B::Hash>>
|
||||
{
|
||||
let message = Slicable::encode(&PrimitiveMessage {
|
||||
let message = Slicable::encode(&PrimitiveMessage::<B, _> {
|
||||
parent,
|
||||
action: PrimitiveAction::Commit(just.round_number as u32, just.digest),
|
||||
action: PrimitiveAction::Commit(just.round_number as u32, just.digest.clone()),
|
||||
});
|
||||
|
||||
check_justification_signed_message(authorities, &message[..], just)
|
||||
@@ -462,12 +475,12 @@ pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just
|
||||
/// Provide all valid authorities.
|
||||
///
|
||||
/// On failure, returns the justification back.
|
||||
pub fn check_prepare_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification)
|
||||
-> Result<PrepareJustification, UncheckedJustification>
|
||||
pub fn check_prepare_justification<B: Block>(authorities: &[AuthorityId], parent: B::Hash, just: UncheckedJustification<B::Hash>)
|
||||
-> Result<PrepareJustification<B::Hash>, UncheckedJustification<B::Hash>>
|
||||
{
|
||||
let message = Slicable::encode(&PrimitiveMessage {
|
||||
let message = Slicable::encode(&PrimitiveMessage::<B, _> {
|
||||
parent,
|
||||
action: PrimitiveAction::Prepare(just.round_number as u32, just.digest),
|
||||
action: PrimitiveAction::Prepare(just.round_number as u32, just.digest.clone()),
|
||||
});
|
||||
|
||||
check_justification_signed_message(authorities, &message[..], just)
|
||||
@@ -475,10 +488,10 @@ pub fn check_prepare_justification(authorities: &[AuthorityId], parent: HeaderHa
|
||||
|
||||
/// Check proposal message signatures and authority.
|
||||
/// Provide all valid authorities.
|
||||
pub fn check_proposal(
|
||||
pub fn check_proposal<B: Block + Clone>(
|
||||
authorities: &[AuthorityId],
|
||||
parent_hash: &HeaderHash,
|
||||
propose: &::generic::LocalizedProposal<Block, HeaderHash, AuthorityId, LocalizedSignature>)
|
||||
parent_hash: &B::Hash,
|
||||
propose: &::generic::LocalizedProposal<B, B::Hash, AuthorityId, LocalizedSignature>)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
if !authorities.contains(&propose.sender) {
|
||||
@@ -487,16 +500,16 @@ pub fn check_proposal(
|
||||
|
||||
let action_header = PrimitiveAction::ProposeHeader(propose.round_number as u32, propose.digest.clone());
|
||||
let action_propose = PrimitiveAction::Propose(propose.round_number as u32, propose.proposal.clone());
|
||||
check_action(action_header, parent_hash, &propose.digest_signature)?;
|
||||
check_action(action_propose, parent_hash, &propose.full_signature)
|
||||
check_action::<B>(action_header, parent_hash, &propose.digest_signature)?;
|
||||
check_action::<B>(action_propose, parent_hash, &propose.full_signature)
|
||||
}
|
||||
|
||||
/// Check vote message signatures and authority.
|
||||
/// Provide all valid authorities.
|
||||
pub fn check_vote(
|
||||
pub fn check_vote<B: Block>(
|
||||
authorities: &[AuthorityId],
|
||||
parent_hash: &HeaderHash,
|
||||
vote: &::generic::LocalizedVote<HeaderHash, AuthorityId, LocalizedSignature>)
|
||||
parent_hash: &B::Hash,
|
||||
vote: &::generic::LocalizedVote<B::Hash, AuthorityId, LocalizedSignature>)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
if !authorities.contains(&vote.sender) {
|
||||
@@ -504,14 +517,14 @@ pub fn check_vote(
|
||||
}
|
||||
|
||||
let action = match vote.vote {
|
||||
::generic::Vote::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
|
||||
::generic::Vote::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
|
||||
::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()),
|
||||
::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()),
|
||||
::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
|
||||
};
|
||||
check_action(action, parent_hash, &vote.signature)
|
||||
check_action::<B>(action, parent_hash, &vote.signature)
|
||||
}
|
||||
|
||||
fn check_action(action: PrimitiveAction, parent_hash: &HeaderHash, sig: &LocalizedSignature) -> Result<(), Error> {
|
||||
fn check_action<B: Block>(action: PrimitiveAction<B, B::Hash>, parent_hash: &B::Hash, sig: &LocalizedSignature) -> Result<(), Error> {
|
||||
let primitive = PrimitiveMessage {
|
||||
parent: parent_hash.clone(),
|
||||
action,
|
||||
@@ -526,12 +539,12 @@ fn check_action(action: PrimitiveAction, parent_hash: &HeaderHash, sig: &Localiz
|
||||
}
|
||||
|
||||
/// Sign a BFT message with the given key.
|
||||
pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHash) -> LocalizedMessage {
|
||||
pub fn sign_message<B: Block + Clone>(message: Message<B>, key: &ed25519::Pair, parent_hash: B::Hash) -> LocalizedMessage<B> {
|
||||
let signer = key.public();
|
||||
|
||||
let sign_action = |action| {
|
||||
let sign_action = |action: PrimitiveAction<B, B::Hash>| {
|
||||
let primitive = PrimitiveMessage {
|
||||
parent: parent_hash,
|
||||
parent: parent_hash.clone(),
|
||||
action,
|
||||
};
|
||||
|
||||
@@ -544,7 +557,7 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
|
||||
|
||||
match message {
|
||||
::generic::Message::Propose(r, proposal) => {
|
||||
let header_hash: HeaderHash = proposal.header.blake2_256().into();
|
||||
let header_hash = proposal.hash();
|
||||
let action_header = PrimitiveAction::ProposeHeader(r as u32, header_hash.clone());
|
||||
let action_propose = PrimitiveAction::Propose(r as u32, proposal.clone());
|
||||
|
||||
@@ -559,8 +572,8 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
|
||||
}
|
||||
::generic::Message::Vote(vote) => {
|
||||
let action = match vote {
|
||||
::generic::Vote::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
|
||||
::generic::Vote::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
|
||||
::generic::Vote::Prepare(r, ref h) => PrimitiveAction::Prepare(r as u32, h.clone()),
|
||||
::generic::Vote::Commit(r, ref h) => PrimitiveAction::Commit(r as u32, h.clone()),
|
||||
::generic::Vote::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
|
||||
};
|
||||
|
||||
@@ -577,7 +590,8 @@ pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHa
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::collections::HashSet;
|
||||
use primitives::block;
|
||||
use runtime_primitives::testing::{Block as GenericTestBlock, Header as TestHeader};
|
||||
use primitives::H256;
|
||||
use self::tokio_core::reactor::{Core};
|
||||
use self::keyring::Keyring;
|
||||
use futures::stream;
|
||||
@@ -586,19 +600,21 @@ mod tests {
|
||||
extern crate substrate_keyring as keyring;
|
||||
extern crate tokio_core;
|
||||
|
||||
type TestBlock = GenericTestBlock<()>;
|
||||
|
||||
struct FakeClient {
|
||||
authorities: Vec<AuthorityId>,
|
||||
imported_heights: Mutex<HashSet<block::Number>>
|
||||
imported_heights: Mutex<HashSet<u64>>
|
||||
}
|
||||
|
||||
impl BlockImport for FakeClient {
|
||||
fn import_block(&self, block: Block, _justification: Justification) {
|
||||
impl BlockImport<TestBlock> for FakeClient {
|
||||
fn import_block(&self, block: TestBlock, _justification: Justification<H256>) {
|
||||
assert!(self.imported_heights.lock().insert(block.header.number))
|
||||
}
|
||||
}
|
||||
|
||||
impl Authorities for FakeClient {
|
||||
fn authorities(&self, _at: &BlockId) -> Result<Vec<AuthorityId>, Error> {
|
||||
impl Authorities<TestBlock> for FakeClient {
|
||||
fn authorities(&self, _at: &BlockId<TestBlock>) -> Result<Vec<AuthorityId>, Error> {
|
||||
Ok(self.authorities.clone())
|
||||
}
|
||||
}
|
||||
@@ -607,10 +623,10 @@ mod tests {
|
||||
struct Output<E>(::std::marker::PhantomData<E>);
|
||||
|
||||
impl<E> Sink for Output<E> {
|
||||
type SinkItem = Communication;
|
||||
type SinkItem = Communication<TestBlock>;
|
||||
type SinkError = E;
|
||||
|
||||
fn start_send(&mut self, _item: Communication) -> ::futures::StartSend<Communication, E> {
|
||||
fn start_send(&mut self, _item: Communication<TestBlock>) -> ::futures::StartSend<Communication<TestBlock>, E> {
|
||||
Ok(::futures::AsyncSink::Ready)
|
||||
}
|
||||
|
||||
@@ -620,34 +636,35 @@ mod tests {
|
||||
}
|
||||
|
||||
struct DummyFactory;
|
||||
struct DummyProposer(block::Number);
|
||||
struct DummyProposer(u64);
|
||||
|
||||
impl ProposerFactory for DummyFactory {
|
||||
impl ProposerFactory<TestBlock> for DummyFactory {
|
||||
type Proposer = DummyProposer;
|
||||
type Error = Error;
|
||||
|
||||
fn init(&self, parent_header: &Header, _authorities: &[AuthorityId], _sign_with: Arc<ed25519::Pair>) -> Result<DummyProposer, Error> {
|
||||
fn init(&self, parent_header: &TestHeader, _authorities: &[AuthorityId], _sign_with: Arc<ed25519::Pair>) -> Result<DummyProposer, Error> {
|
||||
Ok(DummyProposer(parent_header.number + 1))
|
||||
}
|
||||
}
|
||||
|
||||
impl Proposer for DummyProposer {
|
||||
impl Proposer<TestBlock> for DummyProposer {
|
||||
type Error = Error;
|
||||
type Create = Result<Block, Error>;
|
||||
type Create = Result<TestBlock, Error>;
|
||||
type Evaluate = Result<bool, Error>;
|
||||
|
||||
fn propose(&self) -> Result<Block, Error> {
|
||||
Ok(Block {
|
||||
header: Header::from_block_number(self.0),
|
||||
transactions: Default::default()
|
||||
fn propose(&self) -> Result<TestBlock, Error> {
|
||||
|
||||
Ok(TestBlock {
|
||||
header: from_block_number(self.0),
|
||||
extrinsics: Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn evaluate(&self, proposal: &Block) -> Result<bool, Error> {
|
||||
fn evaluate(&self, proposal: &TestBlock) -> Result<bool, Error> {
|
||||
Ok(proposal.header.number == self.0)
|
||||
}
|
||||
|
||||
fn import_misbehavior(&self, _misbehavior: Vec<(AuthorityId, Misbehavior)>) {}
|
||||
fn import_misbehavior(&self, _misbehavior: Vec<(AuthorityId, Misbehavior<H256>)>) {}
|
||||
|
||||
fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId {
|
||||
authorities[round_number % authorities.len()].clone()
|
||||
@@ -655,7 +672,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn make_service(client: FakeClient)
|
||||
-> BftService<DummyFactory, FakeClient>
|
||||
-> BftService<TestBlock, DummyFactory, FakeClient>
|
||||
{
|
||||
BftService {
|
||||
client: Arc::new(client),
|
||||
@@ -667,13 +684,23 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_vote(vote: ::generic::Vote<HeaderHash>, key: &ed25519::Pair, parent_hash: HeaderHash) -> LocalizedSignature {
|
||||
match sign_message(vote.into(), key, parent_hash) {
|
||||
fn sign_vote(vote: ::generic::Vote<H256>, key: &ed25519::Pair, parent_hash: H256) -> LocalizedSignature {
|
||||
match sign_message::<TestBlock>(vote.into(), key, parent_hash) {
|
||||
::generic::LocalizedMessage::Vote(vote) => vote.signature,
|
||||
_ => panic!("signing vote leads to signed vote"),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_block_number(num: u64) -> TestHeader {
|
||||
TestHeader::new(
|
||||
num,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn future_gets_preempted() {
|
||||
let client = FakeClient {
|
||||
@@ -690,12 +717,12 @@ mod tests {
|
||||
|
||||
let service = make_service(client);
|
||||
|
||||
let first = Header::from_block_number(2);
|
||||
let first_hash = first.blake2_256().into();
|
||||
let first = from_block_number(2);
|
||||
let first_hash = first.hash();
|
||||
|
||||
let mut second = Header::from_block_number(3);
|
||||
let mut second = from_block_number(3);
|
||||
second.parent_hash = first_hash;
|
||||
let second_hash = second.blake2_256().into();
|
||||
let second_hash = second.hash();
|
||||
|
||||
let bft = service.build_upon(&first, stream::empty(), Output(Default::default())).unwrap();
|
||||
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash);
|
||||
@@ -749,7 +776,7 @@ mod tests {
|
||||
}).collect(),
|
||||
};
|
||||
|
||||
assert!(check_justification(&authorities, parent_hash, unchecked).is_ok());
|
||||
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_ok());
|
||||
|
||||
let unchecked = UncheckedJustification {
|
||||
digest: hash,
|
||||
@@ -759,7 +786,7 @@ mod tests {
|
||||
}).collect(),
|
||||
};
|
||||
|
||||
assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
|
||||
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
|
||||
|
||||
// not enough signatures.
|
||||
let unchecked = UncheckedJustification {
|
||||
@@ -770,7 +797,7 @@ mod tests {
|
||||
}).collect(),
|
||||
};
|
||||
|
||||
assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
|
||||
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
|
||||
|
||||
// wrong hash.
|
||||
let unchecked = UncheckedJustification {
|
||||
@@ -781,7 +808,7 @@ mod tests {
|
||||
}).collect(),
|
||||
};
|
||||
|
||||
assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
|
||||
assert!(check_justification::<TestBlock>(&authorities, parent_hash, unchecked).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -793,9 +820,9 @@ mod tests {
|
||||
Keyring::Eve.to_raw_public(),
|
||||
];
|
||||
|
||||
let block = Block {
|
||||
header: Header::from_block_number(1),
|
||||
transactions: Default::default()
|
||||
let block = TestBlock {
|
||||
header: from_block_number(1),
|
||||
extrinsics: Default::default()
|
||||
};
|
||||
|
||||
let proposal = sign_message(::generic::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);;
|
||||
@@ -812,7 +839,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// Not an authority
|
||||
let proposal = sign_message(::generic::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);;
|
||||
let proposal = sign_message::<TestBlock>(::generic::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);;
|
||||
if let ::generic::LocalizedMessage::Propose(proposal) = proposal {
|
||||
assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err());
|
||||
} else {
|
||||
@@ -822,28 +849,28 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn vote_check_works() {
|
||||
let parent_hash = Default::default();
|
||||
let hash = [0xff; 32].into();
|
||||
let parent_hash: H256 = Default::default();
|
||||
let hash: H256 = [0xff; 32].into();
|
||||
|
||||
let authorities = vec![
|
||||
Keyring::Alice.to_raw_public(),
|
||||
Keyring::Eve.to_raw_public(),
|
||||
];
|
||||
|
||||
let vote = sign_message(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);;
|
||||
let vote = sign_message::<TestBlock>(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);;
|
||||
if let ::generic::LocalizedMessage::Vote(vote) = vote {
|
||||
assert!(check_vote(&authorities, &parent_hash, &vote).is_ok());
|
||||
assert!(check_vote::<TestBlock>(&authorities, &parent_hash, &vote).is_ok());
|
||||
let mut invalid_sender = vote.clone();
|
||||
invalid_sender.signature.signer = Keyring::Eve.into();
|
||||
assert!(check_vote(&authorities, &parent_hash, &invalid_sender).is_err());
|
||||
assert!(check_vote::<TestBlock>(&authorities, &parent_hash, &invalid_sender).is_err());
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
// Not an authority
|
||||
let vote = sign_message(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);;
|
||||
let vote = sign_message::<TestBlock>(::generic::Message::Vote(::generic::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);;
|
||||
if let ::generic::LocalizedMessage::Vote(vote) = vote {
|
||||
assert!(check_vote(&authorities, &parent_hash, &vote).is_err());
|
||||
assert!(check_vote::<TestBlock>(&authorities, &parent_hash, &vote).is_err());
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ substrate-executor = { path = "../executor" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
substrate-runtime-io = { path = "../runtime-io" }
|
||||
substrate-runtime-support = { path = "../runtime-support" }
|
||||
substrate-runtime-primitives = { path = "../runtime/primitives" }
|
||||
substrate-state-machine = { path = "../state-machine" }
|
||||
substrate-keyring = { path = "../../substrate/keyring" }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ hashdb = { git = "https://github.com/paritytech/parity.git" }
|
||||
patricia-trie = { git = "https://github.com/paritytech/parity.git" }
|
||||
memorydb = { git = "https://github.com/paritytech/parity.git" }
|
||||
substrate-primitives = { path = "../../../substrate/primitives" }
|
||||
substrate-runtime-primitives = { path = "../../../substrate/runtime/primitives" }
|
||||
substrate-client = { path = "../../../substrate/client" }
|
||||
substrate-state-machine = { path = "../../../substrate/state-machine" }
|
||||
substrate-runtime-support = { path = "../../../substrate/runtime-support" }
|
||||
|
||||
@@ -27,6 +27,7 @@ extern crate patricia_trie;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate substrate_codec as codec;
|
||||
|
||||
#[macro_use]
|
||||
@@ -47,9 +48,9 @@ use kvdb::{KeyValueDB, DBTransaction};
|
||||
use memorydb::MemoryDB;
|
||||
use parking_lot::RwLock;
|
||||
use patricia_trie::{TrieDB, TrieDBMut, TrieError, Trie, TrieMut};
|
||||
use primitives::blake2_256;
|
||||
use primitives::block::{self, Id as BlockId, HeaderHash};
|
||||
use runtime_support::Hashable;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::bft::Justification;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, Hashing, HashingFor, Zero};
|
||||
use state_machine::backend::Backend as StateBackend;
|
||||
use state_machine::CodeExecutor;
|
||||
|
||||
@@ -62,14 +63,17 @@ pub struct DatabaseSettings {
|
||||
}
|
||||
|
||||
/// Create an instance of db-backed client.
|
||||
pub fn new_client<E, F>(
|
||||
pub fn new_client<E, F, Block>(
|
||||
settings: DatabaseSettings,
|
||||
executor: E,
|
||||
genesis_builder: F,
|
||||
) -> Result<client::Client<Backend, client::LocalCallExecutor<Backend, E>>, client::error::Error>
|
||||
) -> Result<client::Client<Backend<Block>, client::LocalCallExecutor<Backend<Block>, E>, Block>, client::error::Error>
|
||||
where
|
||||
Block: BlockT,
|
||||
<Block::Header as HeaderT>::Number: As<u32>,
|
||||
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
|
||||
E: CodeExecutor,
|
||||
F: client::GenesisBuilder,
|
||||
F: client::GenesisBuilder<Block>,
|
||||
{
|
||||
let backend = Arc::new(Backend::new(&settings)?);
|
||||
let executor = client::LocalCallExecutor::new(backend.clone(), executor);
|
||||
@@ -90,24 +94,26 @@ mod meta {
|
||||
pub const BEST_BLOCK: &[u8; 4] = b"best";
|
||||
}
|
||||
|
||||
struct PendingBlock {
|
||||
header: block::Header,
|
||||
justification: Option<primitives::bft::Justification>,
|
||||
body: Option<block::Body>,
|
||||
struct PendingBlock<Block: BlockT> {
|
||||
header: Block::Header,
|
||||
justification: Option<Justification<Block::Hash>>,
|
||||
body: Option<Vec<Block::Extrinsic>>,
|
||||
is_best: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Meta {
|
||||
best_hash: HeaderHash,
|
||||
best_number: block::Number,
|
||||
genesis_hash: HeaderHash,
|
||||
struct Meta<N, H> {
|
||||
best_hash: H,
|
||||
best_number: N,
|
||||
genesis_hash: H,
|
||||
}
|
||||
|
||||
type BlockKey = [u8; 4];
|
||||
|
||||
// Little endian
|
||||
fn number_to_db_key(n: block::Number) -> BlockKey {
|
||||
fn number_to_db_key<N>(n: N) -> BlockKey where N: As<u32> {
|
||||
let n: u32 = n.as_();
|
||||
|
||||
[
|
||||
(n >> 24) as u8,
|
||||
((n >> 16) & 0xff) as u8,
|
||||
@@ -127,13 +133,13 @@ fn db_err(err: kvdb::Error) -> client::error::Error {
|
||||
}
|
||||
|
||||
/// Block database
|
||||
pub struct BlockchainDb {
|
||||
pub struct BlockchainDb<Block: BlockT> {
|
||||
db: Arc<KeyValueDB>,
|
||||
meta: RwLock<Meta>,
|
||||
meta: RwLock<Meta<<Block::Header as HeaderT>::Number, Block::Hash>>,
|
||||
}
|
||||
|
||||
impl BlockchainDb {
|
||||
fn id(&self, id: BlockId) -> Result<Option<BlockKey>, client::error::Error> {
|
||||
impl<Block: BlockT> BlockchainDb<Block> where <Block::Header as HeaderT>::Number: As<u32> {
|
||||
fn id(&self, id: BlockId<Block>) -> Result<Option<BlockKey>, client::error::Error> {
|
||||
match id {
|
||||
BlockId::Hash(h) => {
|
||||
{
|
||||
@@ -142,7 +148,7 @@ impl BlockchainDb {
|
||||
return Ok(Some(number_to_db_key(meta.best_number)));
|
||||
}
|
||||
}
|
||||
self.db.get(columns::BLOCK_INDEX, &h).map(|v| v.map(|v| {
|
||||
self.db.get(columns::BLOCK_INDEX, h.as_ref()).map(|v| v.map(|v| {
|
||||
let mut key: [u8; 4] = [0; 4];
|
||||
key.copy_from_slice(&v);
|
||||
key
|
||||
@@ -152,21 +158,21 @@ impl BlockchainDb {
|
||||
}
|
||||
}
|
||||
|
||||
fn new(db: Arc<KeyValueDB>) -> Result<BlockchainDb, client::error::Error> {
|
||||
fn new(db: Arc<KeyValueDB>) -> Result<Self, client::error::Error> {
|
||||
let (best_hash, best_number) = if let Some(Some(header)) = db.get(columns::META, meta::BEST_BLOCK).and_then(|id|
|
||||
match id {
|
||||
Some(id) => db.get(columns::HEADER, &id).map(|h| h.map(|b| block::Header::decode(&mut &b[..]))),
|
||||
Some(id) => db.get(columns::HEADER, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]))),
|
||||
None => Ok(None),
|
||||
}).map_err(db_err)?
|
||||
{
|
||||
let hash = header.blake2_256().into();
|
||||
debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number);
|
||||
(hash, header.number)
|
||||
let hash = header.hash();
|
||||
debug!("DB Opened blockchain db, best {:?} ({})", hash, header.number());
|
||||
(hash, header.number().clone())
|
||||
} else {
|
||||
(Default::default(), Default::default())
|
||||
(Default::default(), Zero::zero())
|
||||
};
|
||||
let genesis_hash = db.get(columns::HEADER, &number_to_db_key(0)).map_err(db_err)?
|
||||
.map(|b| blake2_256(&b)).unwrap_or_default().into();
|
||||
let genesis_hash = db.get(columns::HEADER, &number_to_db_key(<Block::Header as HeaderT>::Number::zero())).map_err(db_err)?
|
||||
.map(|b| HashingFor::<Block>::hash(&b)).unwrap_or_default().into();
|
||||
|
||||
Ok(BlockchainDb {
|
||||
db,
|
||||
@@ -178,7 +184,7 @@ impl BlockchainDb {
|
||||
})
|
||||
}
|
||||
|
||||
fn read_db(&self, id: BlockId, column: Option<u32>) -> Result<Option<DBValue>, client::error::Error> {
|
||||
fn read_db(&self, id: BlockId<Block>, column: Option<u32>) -> Result<Option<DBValue>, client::error::Error> {
|
||||
self.id(id).and_then(|key|
|
||||
match key {
|
||||
Some(key) => self.db.get(column, &key).map_err(db_err),
|
||||
@@ -186,10 +192,10 @@ impl BlockchainDb {
|
||||
})
|
||||
}
|
||||
|
||||
fn update_meta(&self, hash: block::HeaderHash, number: block::Number, is_best: bool) {
|
||||
fn update_meta(&self, hash: Block::Hash, number: <Block::Header as HeaderT>::Number, is_best: bool) {
|
||||
if is_best {
|
||||
let mut meta = self.meta.write();
|
||||
if number == 0 {
|
||||
if number == Zero::zero() {
|
||||
meta.genesis_hash = hash;
|
||||
}
|
||||
meta.best_number = number;
|
||||
@@ -198,10 +204,10 @@ impl BlockchainDb {
|
||||
}
|
||||
}
|
||||
|
||||
impl client::blockchain::Backend for BlockchainDb {
|
||||
fn header(&self, id: BlockId) -> Result<Option<block::Header>, client::error::Error> {
|
||||
impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> where <Block::Header as HeaderT>::Number: As<u32> {
|
||||
fn header(&self, id: BlockId<Block>) -> Result<Option<Block::Header>, client::error::Error> {
|
||||
match self.read_db(id, columns::HEADER)? {
|
||||
Some(header) => match block::Header::decode(&mut &header[..]) {
|
||||
Some(header) => match Block::Header::decode(&mut &header[..]) {
|
||||
Some(header) => Ok(Some(header)),
|
||||
None => return Err(client::error::ErrorKind::Backend("Error decoding header".into()).into()),
|
||||
}
|
||||
@@ -209,9 +215,9 @@ impl client::blockchain::Backend for BlockchainDb {
|
||||
}
|
||||
}
|
||||
|
||||
fn body(&self, id: BlockId) -> Result<Option<block::Body>, client::error::Error> {
|
||||
fn body(&self, id: BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, client::error::Error> {
|
||||
match self.read_db(id, columns::BODY)? {
|
||||
Some(body) => match block::Body::decode(&mut &body[..]) {
|
||||
Some(body) => match Slicable::decode(&mut &body[..]) {
|
||||
Some(body) => Ok(Some(body)),
|
||||
None => return Err(client::error::ErrorKind::Backend("Error decoding body".into()).into()),
|
||||
}
|
||||
@@ -219,9 +225,9 @@ impl client::blockchain::Backend for BlockchainDb {
|
||||
}
|
||||
}
|
||||
|
||||
fn justification(&self, id: BlockId) -> Result<Option<primitives::bft::Justification>, client::error::Error> {
|
||||
fn justification(&self, id: BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, client::error::Error> {
|
||||
match self.read_db(id, columns::JUSTIFICATION)? {
|
||||
Some(justification) => match primitives::bft::Justification::decode(&mut &justification[..]) {
|
||||
Some(justification) => match Slicable::decode(&mut &justification[..]) {
|
||||
Some(justification) => Ok(Some(justification)),
|
||||
None => return Err(client::error::ErrorKind::Backend("Error decoding justification".into()).into()),
|
||||
}
|
||||
@@ -229,7 +235,7 @@ impl client::blockchain::Backend for BlockchainDb {
|
||||
}
|
||||
}
|
||||
|
||||
fn info(&self) -> Result<client::blockchain::Info, client::error::Error> {
|
||||
fn info(&self) -> Result<client::blockchain::Info<Block>, client::error::Error> {
|
||||
let meta = self.meta.read();
|
||||
Ok(client::blockchain::Info {
|
||||
best_hash: meta.best_hash,
|
||||
@@ -238,7 +244,7 @@ impl client::blockchain::Backend for BlockchainDb {
|
||||
})
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId) -> Result<client::blockchain::BlockStatus, client::error::Error> {
|
||||
fn status(&self, id: BlockId<Block>) -> Result<client::blockchain::BlockStatus, client::error::Error> {
|
||||
let exists = match id {
|
||||
BlockId::Hash(_) => self.id(id)?.is_some(),
|
||||
BlockId::Number(n) => n <= self.meta.read().best_number,
|
||||
@@ -249,28 +255,28 @@ impl client::blockchain::Backend for BlockchainDb {
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, number: block::Number) -> Result<Option<block::HeaderHash>, client::error::Error> {
|
||||
fn hash(&self, number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, client::error::Error> {
|
||||
self.read_db(BlockId::Number(number), columns::HEADER).map(|x|
|
||||
x.map(|raw| blake2_256(&raw[..])).map(Into::into)
|
||||
x.map(|raw| HashingFor::<Block>::hash(&raw[..])).map(Into::into)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Database transaction
|
||||
pub struct BlockImportOperation {
|
||||
pub struct BlockImportOperation<Block: BlockT> {
|
||||
old_state: DbState,
|
||||
updates: MemoryDB,
|
||||
pending_block: Option<PendingBlock>,
|
||||
pending_block: Option<PendingBlock<Block>>,
|
||||
}
|
||||
|
||||
impl client::backend::BlockImportOperation for BlockImportOperation {
|
||||
impl<Block: BlockT> client::backend::BlockImportOperation<Block> for BlockImportOperation<Block> {
|
||||
type State = DbState;
|
||||
|
||||
fn state(&self) -> Result<Option<&Self::State>, client::error::Error> {
|
||||
Ok(Some(&self.old_state))
|
||||
}
|
||||
|
||||
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_best: bool) -> Result<(), client::error::Error> {
|
||||
fn set_block_data(&mut self, header: Block::Header, body: Option<Vec<Block::Extrinsic>>, justification: Option<Justification<Block::Hash>>, is_best: bool) -> Result<(), client::error::Error> {
|
||||
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
|
||||
self.pending_block = Some(PendingBlock {
|
||||
header,
|
||||
@@ -423,15 +429,15 @@ impl state_machine::Backend for DbState {
|
||||
|
||||
/// Disk backend. Keeps data in a key-value store. In archive mode, trie nodes are kept from all blocks.
|
||||
/// Otherwise, trie nodes are kept only from the most recent block.
|
||||
pub struct Backend {
|
||||
pub struct Backend<Block: BlockT> {
|
||||
db: Arc<KeyValueDB>,
|
||||
blockchain: BlockchainDb,
|
||||
blockchain: BlockchainDb<Block>,
|
||||
archive: bool,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
impl<Block: BlockT> Backend<Block> where <Block::Header as HeaderT>::Number: As<u32> {
|
||||
/// Create a new instance of database backend.
|
||||
pub fn new(config: &DatabaseSettings) -> Result<Backend, client::error::Error> {
|
||||
pub fn new(config: &DatabaseSettings) -> Result<Self, client::error::Error> {
|
||||
let mut db_config = DatabaseConfig::with_columns(Some(columns::NUM_COLUMNS));
|
||||
db_config.memory_budget = config.cache_size;
|
||||
db_config.wal = true;
|
||||
@@ -442,13 +448,13 @@ impl Backend {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn new_test() -> Backend {
|
||||
fn new_test() -> Self {
|
||||
let db = Arc::new(::kvdb_memorydb::create(columns::NUM_COLUMNS));
|
||||
|
||||
Backend::from_kvdb(db as Arc<_>, false).expect("failed to create test-db")
|
||||
}
|
||||
|
||||
fn from_kvdb(db: Arc<KeyValueDB>, archive: bool) -> Result<Backend, client::error::Error> {
|
||||
fn from_kvdb(db: Arc<KeyValueDB>, archive: bool) -> Result<Self, client::error::Error> {
|
||||
let blockchain = BlockchainDb::new(db.clone())?;
|
||||
|
||||
Ok(Backend {
|
||||
@@ -459,12 +465,15 @@ impl Backend {
|
||||
}
|
||||
}
|
||||
|
||||
impl client::backend::Backend for Backend {
|
||||
type BlockImportOperation = BlockImportOperation;
|
||||
type Blockchain = BlockchainDb;
|
||||
impl<Block: BlockT> client::backend::Backend<Block> for Backend<Block> where
|
||||
<Block::Header as HeaderT>::Number: As<u32>,
|
||||
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
|
||||
{
|
||||
type BlockImportOperation = BlockImportOperation<Block>;
|
||||
type Blockchain = BlockchainDb<Block>;
|
||||
type State = DbState;
|
||||
|
||||
fn begin_operation(&self, block: BlockId) -> Result<Self::BlockImportOperation, client::error::Error> {
|
||||
fn begin_operation(&self, block: BlockId<Block>) -> Result<Self::BlockImportOperation, client::error::Error> {
|
||||
let state = self.state_at(block)?;
|
||||
Ok(BlockImportOperation {
|
||||
pending_block: None,
|
||||
@@ -476,9 +485,9 @@ impl client::backend::Backend for Backend {
|
||||
fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> Result<(), client::error::Error> {
|
||||
let mut transaction = DBTransaction::new();
|
||||
if let Some(pending_block) = operation.pending_block {
|
||||
let hash: block::HeaderHash = pending_block.header.blake2_256().into();
|
||||
let number = pending_block.header.number;;
|
||||
let key = number_to_db_key(pending_block.header.number);
|
||||
let hash = pending_block.header.hash();
|
||||
let number = pending_block.header.number().clone();
|
||||
let key = number_to_db_key(pending_block.header.number().clone());
|
||||
transaction.put(columns::HEADER, &key, &pending_block.header.encode());
|
||||
if let Some(body) = pending_block.body {
|
||||
transaction.put(columns::BODY, &key, &body.encode());
|
||||
@@ -486,7 +495,7 @@ impl client::backend::Backend for Backend {
|
||||
if let Some(justification) = pending_block.justification {
|
||||
transaction.put(columns::JUSTIFICATION, &key, &justification.encode());
|
||||
}
|
||||
transaction.put(columns::BLOCK_INDEX, &hash, &key);
|
||||
transaction.put(columns::BLOCK_INDEX, hash.as_ref(), &key);
|
||||
if pending_block.is_best {
|
||||
transaction.put(columns::META, meta::BEST_BLOCK, &key);
|
||||
}
|
||||
@@ -504,11 +513,11 @@ impl client::backend::Backend for Backend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn blockchain(&self) -> &BlockchainDb {
|
||||
fn blockchain(&self) -> &BlockchainDb<Block> {
|
||||
&self.blockchain
|
||||
}
|
||||
|
||||
fn state_at(&self, block: BlockId) -> Result<Self::State, client::error::Error> {
|
||||
fn state_at(&self, block: BlockId<Block>) -> Result<Self::State, client::error::Error> {
|
||||
use client::blockchain::Backend as BcBackend;
|
||||
|
||||
// special case for genesis initialization
|
||||
@@ -527,15 +536,19 @@ impl client::backend::Backend for Backend {
|
||||
}
|
||||
|
||||
self.blockchain.header(block).and_then(|maybe_hdr| maybe_hdr.map(|hdr| {
|
||||
let root: [u8; 32] = hdr.state_root().clone().into();
|
||||
DbState {
|
||||
db: self.db.clone(),
|
||||
root: hdr.state_root.0.into(),
|
||||
root: root.into(),
|
||||
}
|
||||
}).ok_or_else(|| client::error::ErrorKind::UnknownBlock(block).into()))
|
||||
}).ok_or_else(|| client::error::ErrorKind::UnknownBlock(format!("{:?}", block)).into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl client::backend::LocalBackend for Backend {}
|
||||
impl<Block: BlockT> client::backend::LocalBackend<Block> for Backend<Block> where
|
||||
<Block::Header as HeaderT>::Number: As<u32>,
|
||||
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
|
||||
{}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@@ -543,10 +556,13 @@ mod tests {
|
||||
use client::backend::Backend as BTrait;
|
||||
use client::backend::BlockImportOperation as Op;
|
||||
use client::blockchain::Backend as BCTrait;
|
||||
use runtime_primitives::testing::{Header, Block as RawBlock};
|
||||
|
||||
type Block = RawBlock<u64>;
|
||||
|
||||
#[test]
|
||||
fn block_hash_inserted_correctly() {
|
||||
let db = Backend::new_test();
|
||||
let db = Backend::<Block>::new_test();
|
||||
for i in 0..10 {
|
||||
assert!(db.blockchain().hash(i).unwrap().is_none());
|
||||
|
||||
@@ -558,7 +574,7 @@ mod tests {
|
||||
};
|
||||
|
||||
let mut op = db.begin_operation(id).unwrap();
|
||||
let header = block::Header {
|
||||
let header = Header {
|
||||
number: i,
|
||||
parent_hash: Default::default(),
|
||||
state_root: Default::default(),
|
||||
@@ -581,10 +597,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn set_state_data() {
|
||||
let db = Backend::new_test();
|
||||
let db = Backend::<Block>::new_test();
|
||||
{
|
||||
let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
|
||||
let mut header = block::Header {
|
||||
let mut header = Header {
|
||||
number: 0,
|
||||
parent_hash: Default::default(),
|
||||
state_root: Default::default(),
|
||||
@@ -623,7 +639,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut op = db.begin_operation(BlockId::Number(0)).unwrap();
|
||||
let mut header = block::Header {
|
||||
let mut header = Header {
|
||||
number: 1,
|
||||
parent_hash: Default::default(),
|
||||
state_root: Default::default(),
|
||||
@@ -660,11 +676,11 @@ mod tests {
|
||||
#[test]
|
||||
fn delete_only_when_negative_rc() {
|
||||
let key;
|
||||
let db = Backend::new_test();
|
||||
let db = Backend::<Block>::new_test();
|
||||
|
||||
{
|
||||
let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
|
||||
let mut header = block::Header {
|
||||
let mut header = Header {
|
||||
number: 0,
|
||||
parent_hash: Default::default(),
|
||||
state_root: Default::default(),
|
||||
@@ -697,7 +713,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut op = db.begin_operation(BlockId::Number(0)).unwrap();
|
||||
let mut header = block::Header {
|
||||
let mut header = Header {
|
||||
number: 1,
|
||||
parent_hash: Default::default(),
|
||||
state_root: Default::default(),
|
||||
@@ -729,7 +745,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut op = db.begin_operation(BlockId::Number(1)).unwrap();
|
||||
let mut header = block::Header {
|
||||
let mut header = Header {
|
||||
number: 1,
|
||||
parent_hash: Default::default(),
|
||||
state_root: Default::default(),
|
||||
|
||||
@@ -18,18 +18,26 @@
|
||||
|
||||
use state_machine::backend::Backend as StateBackend;
|
||||
use error;
|
||||
use primitives::block::{self, Id as BlockId};
|
||||
use primitives;
|
||||
use runtime_primitives::bft::Justification;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
|
||||
/// Block insertion operation. Keeps hold if the inserted block state and data.
|
||||
pub trait BlockImportOperation {
|
||||
pub trait BlockImportOperation<Block: BlockT> {
|
||||
/// Associated state backend type.
|
||||
type State: StateBackend;
|
||||
|
||||
/// Returns pending state. Returns None for backends with locally-unavailable state data.
|
||||
fn state(&self) -> error::Result<Option<&Self::State>>;
|
||||
/// Append block data to the transaction.
|
||||
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()>;
|
||||
fn set_block_data(
|
||||
&mut self,
|
||||
header: Block::Header,
|
||||
body: Option<Vec<Block::Extrinsic>>,
|
||||
justification: Option<Justification<Block::Hash>>,
|
||||
is_new_best: bool
|
||||
) -> error::Result<()>;
|
||||
|
||||
/// Inject storage data into the database.
|
||||
fn update_storage(&mut self, update: <Self::State as StateBackend>::Transaction) -> error::Result<()>;
|
||||
/// Inject storage data into the database replacing any existing data.
|
||||
@@ -44,27 +52,27 @@ pub trait BlockImportOperation {
|
||||
///
|
||||
/// The same applies for live `BlockImportOperation`s: while an import operation building on a parent `P`
|
||||
/// is alive, the state for `P` should not be pruned.
|
||||
pub trait Backend: Send + Sync {
|
||||
pub trait Backend<Block: BlockT>: Send + Sync {
|
||||
/// Associated block insertion operation type.
|
||||
type BlockImportOperation: BlockImportOperation;
|
||||
type BlockImportOperation: BlockImportOperation<Block>;
|
||||
/// Associated blockchain backend type.
|
||||
type Blockchain: ::blockchain::Backend;
|
||||
type Blockchain: ::blockchain::Backend<Block>;
|
||||
/// Associated state backend type.
|
||||
type State: StateBackend;
|
||||
|
||||
/// Begin a new block insertion transaction with given parent block id.
|
||||
/// When constructing the genesis, this is called with all-zero hash.
|
||||
fn begin_operation(&self, block: BlockId) -> error::Result<Self::BlockImportOperation>;
|
||||
fn begin_operation(&self, block: BlockId<Block>) -> error::Result<Self::BlockImportOperation>;
|
||||
/// Commit block insertion.
|
||||
fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>;
|
||||
/// Returns reference to blockchain backend.
|
||||
fn blockchain(&self) -> &Self::Blockchain;
|
||||
/// Returns state backend with post-state of given block.
|
||||
fn state_at(&self, block: BlockId) -> error::Result<Self::State>;
|
||||
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State>;
|
||||
}
|
||||
|
||||
/// Mark for all Backend implementations, that are making use of state data, stored locally.
|
||||
pub trait LocalBackend: Backend {}
|
||||
pub trait LocalBackend<Block: BlockT>: Backend<Block> {}
|
||||
|
||||
/// Mark for all Backend implementations, that are fetching required state data from remote nodes.
|
||||
pub trait RemoteBackend: Backend {}
|
||||
pub trait RemoteBackend<Block: BlockT>: Backend<Block> {}
|
||||
|
||||
@@ -17,80 +17,101 @@
|
||||
//! Utility struct to build a block.
|
||||
|
||||
use std::vec::Vec;
|
||||
use codec::{Joiner, Slicable};
|
||||
use codec::Slicable;
|
||||
use state_machine;
|
||||
use primitives::{Header, Block};
|
||||
use primitives::block::{Id as BlockId, Extrinsic};
|
||||
use runtime_primitives::traits::{Header as HeaderT, Hashing as HashingT, Block as BlockT, One, HashingFor};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use {backend, error, Client, CallExecutor};
|
||||
use triehash::ordered_trie_root;
|
||||
|
||||
/// Utility for building new (valid) blocks from a stream of transactions.
|
||||
pub struct BlockBuilder<B, E> where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor + Clone,
|
||||
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
/// Utility for building new (valid) blocks from a stream of extrinsics.
|
||||
pub struct BlockBuilder<B, E, Block> where
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block> + Clone,
|
||||
Block: BlockT,
|
||||
error::Error: From<<<B as backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
header: Header,
|
||||
transactions: Vec<Extrinsic>,
|
||||
header: <Block as BlockT>::Header,
|
||||
extrinsics: Vec<<Block as BlockT>::Extrinsic>,
|
||||
executor: E,
|
||||
state: B::State,
|
||||
changes: state_machine::OverlayedChanges,
|
||||
}
|
||||
|
||||
impl<B, E> BlockBuilder<B, E> where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor + Clone,
|
||||
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
impl<B, E, Block> BlockBuilder<B, E, Block> where
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block> + Clone,
|
||||
Block: BlockT,
|
||||
error::Error: From<<<B as backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
/// Create a new instance of builder from the given client, building on the latest block.
|
||||
pub fn new(client: &Client<B, E>) -> error::Result<Self> {
|
||||
pub fn new(client: &Client<B, E, Block>) -> error::Result<Self> {
|
||||
client.info().and_then(|i| Self::at_block(&BlockId::Hash(i.chain.best_hash), client))
|
||||
}
|
||||
|
||||
/// Create a new instance of builder from the given client using a particular block's ID to
|
||||
/// build upon.
|
||||
pub fn at_block(block_id: &BlockId, client: &Client<B, E>) -> error::Result<Self> {
|
||||
pub fn at_block(block_id: &BlockId<Block>, client: &Client<B, E, Block>) -> error::Result<Self> {
|
||||
let number = client.block_number_from_id(block_id)?
|
||||
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?
|
||||
+ One::one();
|
||||
|
||||
let parent_hash = client.block_hash_from_id(block_id)?
|
||||
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?;
|
||||
|
||||
let executor = client.executor().clone();
|
||||
let state = client.state_at(block_id)?;
|
||||
let mut changes = Default::default();
|
||||
let header = <<Block as BlockT>::Header as HeaderT>::new(
|
||||
number,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
parent_hash,
|
||||
Default::default()
|
||||
);
|
||||
|
||||
executor.call_at_state(&state, &mut changes, "initialise_block", &header.encode())?;
|
||||
|
||||
Ok(BlockBuilder {
|
||||
header: Header {
|
||||
number: client.block_number_from_id(block_id)?.ok_or(error::ErrorKind::UnknownBlock(*block_id))? + 1,
|
||||
parent_hash: client.block_hash_from_id(block_id)?.ok_or(error::ErrorKind::UnknownBlock(*block_id))?,
|
||||
state_root: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
digest: Default::default(),
|
||||
},
|
||||
transactions: Default::default(),
|
||||
executor: client.executor().clone(),
|
||||
state: client.state_at(block_id)?,
|
||||
changes: Default::default(),
|
||||
header,
|
||||
extrinsics: Vec::new(),
|
||||
executor,
|
||||
state,
|
||||
changes,
|
||||
})
|
||||
}
|
||||
|
||||
/// Push a transaction onto the block's list of transactions. This will ensure the transaction
|
||||
/// Push onto the block's list of extrinsics. This will ensure the extrinsic
|
||||
/// can be validly executed (by executing it); if it is invalid, it'll be returned along with
|
||||
/// the error. Otherwise, it will return a mutable reference to self (in order to chain).
|
||||
pub fn push(&mut self, tx: Extrinsic) -> error::Result<()> {
|
||||
let (output, _) = self.executor.call_at_state(
|
||||
&self.state,
|
||||
&mut self.changes,
|
||||
"execute_transaction",
|
||||
&vec![].and(&self.header).and(&tx))?;
|
||||
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime so must be valid");
|
||||
self.transactions.push(tx);
|
||||
Ok(())
|
||||
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> error::Result<()> {
|
||||
match self.executor.call_at_state(&self.state, &mut self.changes, "apply_extrinsic", &xt.encode()) {
|
||||
Ok(_) => {
|
||||
self.extrinsics.push(xt);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
self.changes.discard_prospective();
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume the builder to return a valid `Block` containing all pushed transactions.
|
||||
/// Consume the builder to return a valid `Block` containing all pushed extrinsics.
|
||||
pub fn bake(mut self) -> error::Result<Block> {
|
||||
self.header.extrinsics_root = ordered_trie_root(self.transactions.iter().map(Slicable::encode)).0.into();
|
||||
let (output, _) = self.executor.call_at_state(
|
||||
&self.state,
|
||||
&mut self.changes,
|
||||
"finalise_block",
|
||||
&self.header.encode())?;
|
||||
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime so must be valid");
|
||||
Ok(Block {
|
||||
header: self.header,
|
||||
transactions: self.transactions,
|
||||
})
|
||||
&[],
|
||||
)?;
|
||||
self.header = <<Block as BlockT>::Header as Slicable>::decode(&mut &output[..])
|
||||
.expect("Header came straight out of runtime so must be valid");
|
||||
|
||||
debug_assert_eq!(
|
||||
self.header.extrinsics_root().clone(),
|
||||
HashingFor::<Block>::ordered_trie_root(self.extrinsics.iter().map(Slicable::encode)),
|
||||
);
|
||||
|
||||
Ok(<Block as BlockT>::new(self.header, self.extrinsics))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,26 @@
|
||||
|
||||
//! Polkadot blockchain trait
|
||||
|
||||
use primitives::block::{self, Id as BlockId};
|
||||
use primitives;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::bft::Justification;
|
||||
|
||||
use error::Result;
|
||||
|
||||
/// Blockchain database backend. Does not perform any validation.
|
||||
pub trait Backend: Send + Sync {
|
||||
pub trait Backend<Block: BlockT>: Send + Sync {
|
||||
/// Get block header. Returns `None` if block is not found.
|
||||
fn header(&self, id: BlockId) -> Result<Option<block::Header>>;
|
||||
fn header(&self, id: BlockId<Block>) -> Result<Option<<Block as BlockT>::Header>>;
|
||||
/// Get block body. Returns `None` if block is not found.
|
||||
fn body(&self, id: BlockId) -> Result<Option<block::Body>>;
|
||||
fn body(&self, id: BlockId<Block>) -> Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
|
||||
/// Get block justification. Returns `None` if justification does not exist.
|
||||
fn justification(&self, id: BlockId) -> Result<Option<primitives::bft::Justification>>;
|
||||
fn justification(&self, id: BlockId<Block>) -> Result<Option<Justification<Block::Hash>>>;
|
||||
/// Get blockchain info.
|
||||
fn info(&self) -> Result<Info>;
|
||||
fn info(&self) -> Result<Info<Block>>;
|
||||
/// Get block status.
|
||||
fn status(&self, id: BlockId) -> Result<BlockStatus>;
|
||||
fn status(&self, id: BlockId<Block>) -> Result<BlockStatus>;
|
||||
/// Get block hash by number. Returns `None` if the header is not in the chain.
|
||||
fn hash(&self, number: block::Number) -> Result<Option<block::HeaderHash>>;
|
||||
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> Result<Option<<<Block as BlockT>::Header as HeaderT>::Hash>>;
|
||||
}
|
||||
|
||||
/// Block import outcome
|
||||
@@ -50,13 +52,13 @@ pub enum ImportResult<E> {
|
||||
|
||||
/// Blockchain info
|
||||
#[derive(Debug)]
|
||||
pub struct Info {
|
||||
pub struct Info<Block: BlockT> {
|
||||
/// Best block hash.
|
||||
pub best_hash: block::HeaderHash,
|
||||
pub best_hash: <<Block as BlockT>::Header as HeaderT>::Hash,
|
||||
/// Best block number.
|
||||
pub best_number: block::Number,
|
||||
pub best_number: <<Block as BlockT>::Header as HeaderT>::Number,
|
||||
/// Genesis block hash.
|
||||
pub genesis_hash: block::HeaderHash,
|
||||
pub genesis_hash: <<Block as BlockT>::Header as HeaderT>::Hash,
|
||||
}
|
||||
|
||||
/// Block status.
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use futures::{IntoFuture, Future};
|
||||
use primitives::block::Id as BlockId;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use state_machine::{self, OverlayedChanges, Backend as StateBackend, CodeExecutor};
|
||||
use state_machine::backend::InMemory as InMemoryStateBackend;
|
||||
use triehash::trie_root;
|
||||
|
||||
use backend;
|
||||
use blockchain::Backend as ChainBackend;
|
||||
@@ -36,14 +36,14 @@ pub struct CallResult {
|
||||
}
|
||||
|
||||
/// Method call executor.
|
||||
pub trait CallExecutor {
|
||||
pub trait CallExecutor<B: BlockT> {
|
||||
/// Externalities error type.
|
||||
type Error: state_machine::Error;
|
||||
|
||||
/// Execute a call to a contract on top of state in a block of given hash.
|
||||
///
|
||||
/// No changes are made.
|
||||
fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> Result<CallResult, error::Error>;
|
||||
fn call(&self, id: &BlockId<B>, method: &str, call_data: &[u8]) -> Result<CallResult, error::Error>;
|
||||
|
||||
/// Execute a call to a contract on top of given state.
|
||||
///
|
||||
@@ -81,15 +81,16 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> CallExecutor for LocalCallExecutor<B, E>
|
||||
impl<B, E, Block> CallExecutor<Block> for LocalCallExecutor<B, E>
|
||||
where
|
||||
B: backend::LocalBackend,
|
||||
B: backend::LocalBackend<Block>,
|
||||
E: CodeExecutor,
|
||||
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
|
||||
{
|
||||
type Error = E::Error;
|
||||
|
||||
fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
|
||||
fn call(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let (return_data, _) = self.call_at_state(&self.backend.state_at(*id)?, &mut changes, method, call_data)?;
|
||||
Ok(CallResult{ return_data, changes })
|
||||
@@ -113,19 +114,20 @@ impl<B, F> RemoteCallExecutor<B, F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, F> CallExecutor for RemoteCallExecutor<B, F>
|
||||
impl<B, F, Block> CallExecutor<Block> for RemoteCallExecutor<B, F>
|
||||
where
|
||||
B: backend::RemoteBackend,
|
||||
F: Fetcher,
|
||||
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
|
||||
B: backend::RemoteBackend<Block>,
|
||||
F: Fetcher<Block>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
|
||||
{
|
||||
type Error = error::Error;
|
||||
|
||||
fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
|
||||
fn call(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
|
||||
let block_hash = match *id {
|
||||
BlockId::Hash(hash) => hash,
|
||||
BlockId::Number(number) => self.backend.blockchain().hash(number)?
|
||||
.ok_or_else(|| error::ErrorKind::UnknownBlock(BlockId::Number(number)))?,
|
||||
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", number)))?,
|
||||
};
|
||||
|
||||
self.fetcher.remote_call(RemoteCallRequest {
|
||||
@@ -141,22 +143,25 @@ impl<B, F> CallExecutor for RemoteCallExecutor<B, F>
|
||||
}
|
||||
|
||||
/// Check remote execution proof.
|
||||
pub fn check_execution_proof<B, E>(backend: &B, executor: &E, request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> Result<CallResult, error::Error>
|
||||
pub fn check_execution_proof<B, E, Block>(backend: &B, executor: &E, request: &RemoteCallRequest<Block::Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> Result<CallResult, error::Error>
|
||||
where
|
||||
B: backend::RemoteBackend,
|
||||
B: backend::RemoteBackend<Block>,
|
||||
E: CodeExecutor,
|
||||
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
|
||||
{
|
||||
use runtime_primitives::traits::{Header, Hashing, HashingFor};
|
||||
|
||||
let (remote_result, remote_proof) = remote_proof;
|
||||
|
||||
let remote_state = state_from_execution_proof(remote_proof);
|
||||
let remote_state_root = trie_root(remote_state.pairs().into_iter()).0;
|
||||
let remote_state_root = HashingFor::<Block>::trie_root(remote_state.pairs().into_iter());
|
||||
|
||||
let local_header = backend.blockchain().header(BlockId::Hash(request.block))?;
|
||||
let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(BlockId::Hash(request.block)))?;
|
||||
let local_state_root = local_header.state_root;
|
||||
let local_header = local_header.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", request.block)))?;
|
||||
let local_state_root = local_header.state_root().clone();
|
||||
|
||||
if remote_state_root != *local_state_root {
|
||||
if remote_state_root != local_state_root {
|
||||
return Err(error::ErrorKind::InvalidExecutionProof.into());
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
use std::sync::Arc;
|
||||
use futures::sync::mpsc;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use primitives::{self, block, AuthorityId};
|
||||
use primitives::block::{Id as BlockId, HeaderHash};
|
||||
use primitives::AuthorityId;
|
||||
use runtime_primitives::{bft::Justification, generic::BlockId};
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One};
|
||||
use primitives::storage::{StorageKey, StorageData};
|
||||
use runtime_support::Hashable;
|
||||
use codec::Slicable;
|
||||
use codec::{Slicable};
|
||||
use state_machine::{self, Ext, OverlayedChanges, Backend as StateBackend, CodeExecutor};
|
||||
|
||||
use backend::{self, BlockImportOperation};
|
||||
@@ -32,45 +32,45 @@ use call_executor::{CallExecutor, LocalCallExecutor};
|
||||
use {error, in_mem, block_builder, runtime_io, bft};
|
||||
|
||||
/// Type that implements `futures::Stream` of block import events.
|
||||
pub type BlockchainEventStream = mpsc::UnboundedReceiver<BlockImportNotification>;
|
||||
pub type BlockchainEventStream<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
|
||||
|
||||
/// Polkadot Client genesis block builder.
|
||||
pub trait GenesisBuilder {
|
||||
pub trait GenesisBuilder<B: BlockT> {
|
||||
/// Build genesis block.
|
||||
fn build(self) -> (block::Header, Vec<(Vec<u8>, Vec<u8>)>);
|
||||
fn build(self) -> (B::Header, Vec<(Vec<u8>, Vec<u8>)>);
|
||||
}
|
||||
|
||||
/// Polkadot Client
|
||||
pub struct Client<B, E> {
|
||||
pub struct Client<B, E, Block> where Block: BlockT {
|
||||
backend: Arc<B>,
|
||||
executor: E,
|
||||
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification>>>,
|
||||
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification<Block>>>>,
|
||||
import_lock: Mutex<()>,
|
||||
importing_block: RwLock<Option<HeaderHash>>, // holds the block hash currently being imported. TODO: replace this with block queue
|
||||
importing_block: RwLock<Option<Block::Hash>>, // holds the block hash currently being imported. TODO: replace this with block queue
|
||||
}
|
||||
|
||||
/// A source of blockchain evenets.
|
||||
pub trait BlockchainEvents {
|
||||
pub trait BlockchainEvents<Block: BlockT> {
|
||||
/// Get block import event stream.
|
||||
fn import_notification_stream(&self) -> BlockchainEventStream;
|
||||
fn import_notification_stream(&self) -> mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
|
||||
}
|
||||
|
||||
/// Chain head information.
|
||||
pub trait ChainHead {
|
||||
pub trait ChainHead<Block: BlockT> {
|
||||
/// Get best block header.
|
||||
fn best_block_header(&self) -> Result<block::Header, error::Error>;
|
||||
fn best_block_header(&self) -> Result<<Block as BlockT>::Header, error::Error>;
|
||||
}
|
||||
|
||||
/// Client info
|
||||
// TODO: split queue info from chain info and amalgamate into single struct.
|
||||
#[derive(Debug)]
|
||||
pub struct ClientInfo {
|
||||
pub struct ClientInfo<Block: BlockT> {
|
||||
/// Best block hash.
|
||||
pub chain: ChainInfo,
|
||||
pub chain: ChainInfo<Block>,
|
||||
/// Best block number in the queue.
|
||||
pub best_queued_number: Option<block::Number>,
|
||||
pub best_queued_number: Option<<<Block as BlockT>::Header as HeaderT>::Number>,
|
||||
/// Best queued block hash.
|
||||
pub best_queued_hash: Option<block::HeaderHash>,
|
||||
pub best_queued_hash: Option<Block::Hash>,
|
||||
}
|
||||
|
||||
/// Block import result.
|
||||
@@ -120,49 +120,51 @@ pub enum BlockOrigin {
|
||||
|
||||
/// Summary of an imported block
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BlockImportNotification {
|
||||
pub struct BlockImportNotification<Block: BlockT> {
|
||||
/// Imported block header hash.
|
||||
pub hash: block::HeaderHash,
|
||||
pub hash: Block::Hash,
|
||||
/// Imported block origin.
|
||||
pub origin: BlockOrigin,
|
||||
/// Imported block header.
|
||||
pub header: block::Header,
|
||||
pub header: Block::Header,
|
||||
/// Is this the new best block.
|
||||
pub is_new_best: bool,
|
||||
}
|
||||
|
||||
/// A header paired with a justification which has already been checked.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct JustifiedHeader {
|
||||
header: block::Header,
|
||||
justification: bft::Justification,
|
||||
pub struct JustifiedHeader<Block: BlockT> {
|
||||
header: <Block as BlockT>::Header,
|
||||
justification: ::bft::Justification<Block::Hash>,
|
||||
}
|
||||
|
||||
impl JustifiedHeader {
|
||||
impl<Block: BlockT> JustifiedHeader<Block> {
|
||||
/// Deconstruct the justified header into parts.
|
||||
pub fn into_inner(self) -> (block::Header, bft::Justification) {
|
||||
pub fn into_inner(self) -> (<Block as BlockT>::Header, ::bft::Justification<Block::Hash>) {
|
||||
(self.header, self.justification)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an instance of in-memory client.
|
||||
pub fn new_in_mem<E, F>(
|
||||
pub fn new_in_mem<E, F, Block>(
|
||||
executor: E,
|
||||
genesis_builder: F
|
||||
) -> error::Result<Client<in_mem::Backend, LocalCallExecutor<in_mem::Backend, E>>>
|
||||
) -> error::Result<Client<in_mem::Backend<Block>, LocalCallExecutor<in_mem::Backend<Block>, E>, Block>>
|
||||
where
|
||||
E: CodeExecutor,
|
||||
F: GenesisBuilder,
|
||||
F: GenesisBuilder<Block>,
|
||||
Block: BlockT,
|
||||
{
|
||||
let backend = Arc::new(in_mem::Backend::new());
|
||||
let executor = LocalCallExecutor::new(backend.clone(), executor);
|
||||
Client::new(backend, executor, genesis_builder)
|
||||
}
|
||||
|
||||
impl<B, E> Client<B, E> where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor,
|
||||
error::Error: From<<<B as backend::Backend>::State as StateBackend>::Error>,
|
||||
impl<B, E, Block: BlockT> Client<B, E, Block> where
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
|
||||
{
|
||||
/// Creates new Polkadot Client with given blockchain and code executor.
|
||||
pub fn new<F>(
|
||||
@@ -171,12 +173,12 @@ impl<B, E> Client<B, E> where
|
||||
genesis_builder: F,
|
||||
) -> error::Result<Self>
|
||||
where
|
||||
F: GenesisBuilder
|
||||
F: GenesisBuilder<Block>
|
||||
{
|
||||
if backend.blockchain().header(BlockId::Number(0))?.is_none() {
|
||||
if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() {
|
||||
trace!("Empty database, writing genesis block");
|
||||
let (genesis_header, genesis_store) = genesis_builder.build();
|
||||
let mut op = backend.begin_operation(BlockId::Hash(block::HeaderHash::default()))?;
|
||||
let mut op = backend.begin_operation(BlockId::Hash(Default::default()))?;
|
||||
op.reset_storage(genesis_store.into_iter())?;
|
||||
op.set_block_data(genesis_header, Some(vec![]), None, true)?;
|
||||
backend.commit_operation(op)?;
|
||||
@@ -191,7 +193,7 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Get a reference to the state at a given block.
|
||||
pub fn state_at(&self, block: &BlockId) -> error::Result<B::State> {
|
||||
pub fn state_at(&self, block: &BlockId<Block>) -> error::Result<B::State> {
|
||||
self.backend.state_at(*block)
|
||||
}
|
||||
|
||||
@@ -201,7 +203,7 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Return single storage entry of contract under given address in state in a block of given hash.
|
||||
pub fn storage(&self, id: &BlockId, key: &StorageKey) -> error::Result<StorageData> {
|
||||
pub fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> error::Result<StorageData> {
|
||||
Ok(StorageData(self.state_at(id)?
|
||||
.storage(&key.0)?
|
||||
.ok_or_else(|| error::ErrorKind::NoValueForKey(key.0.clone()))?
|
||||
@@ -209,12 +211,12 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Get the code at a given block.
|
||||
pub fn code_at(&self, id: &BlockId) -> error::Result<Vec<u8>> {
|
||||
pub fn code_at(&self, id: &BlockId<Block>) -> error::Result<Vec<u8>> {
|
||||
self.storage(id, &StorageKey(b":code".to_vec())).map(|data| data.0)
|
||||
}
|
||||
|
||||
/// Get the set of authorities at a given block.
|
||||
pub fn authorities_at(&self, id: &BlockId) -> error::Result<Vec<AuthorityId>> {
|
||||
pub fn authorities_at(&self, id: &BlockId<Block>) -> error::Result<Vec<AuthorityId>> {
|
||||
self.executor.call(id, "authorities",&[])
|
||||
.and_then(|r| Vec::<AuthorityId>::decode(&mut &r.return_data[..])
|
||||
.ok_or(error::ErrorKind::AuthLenInvalid.into()))
|
||||
@@ -229,7 +231,7 @@ impl<B, E> Client<B, E> where
|
||||
/// AND returning execution proof.
|
||||
///
|
||||
/// No changes are made.
|
||||
pub fn execution_proof(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<(Vec<u8>, Vec<Vec<u8>>)> {
|
||||
pub fn execution_proof(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<(Vec<u8>, Vec<Vec<u8>>)> {
|
||||
use call_executor::state_to_execution_proof;
|
||||
|
||||
let result = self.executor.call(id, method, call_data);
|
||||
@@ -248,7 +250,7 @@ impl<B, E> Client<B, E> where
|
||||
/// Set up the native execution environment to call into a native runtime code.
|
||||
pub fn using_environment_at<F: FnOnce() -> T, T>(
|
||||
&self,
|
||||
id: &BlockId,
|
||||
id: &BlockId<Block>,
|
||||
overlay: &mut OverlayedChanges,
|
||||
f: F
|
||||
) -> error::Result<T> {
|
||||
@@ -256,24 +258,29 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Create a new block, built on the head of the chain.
|
||||
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E>> where E: Clone {
|
||||
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E, Block>> where E: Clone {
|
||||
block_builder::BlockBuilder::new(self)
|
||||
}
|
||||
|
||||
/// Create a new block, built on top of `parent`.
|
||||
pub fn new_block_at(&self, parent: &BlockId) -> error::Result<block_builder::BlockBuilder<B, E>> where E: Clone {
|
||||
pub fn new_block_at(&self, parent: &BlockId<Block>) -> error::Result<block_builder::BlockBuilder<B, E, Block>> where E: Clone {
|
||||
block_builder::BlockBuilder::at_block(parent, &self)
|
||||
}
|
||||
|
||||
/// Check a header's justification.
|
||||
pub fn check_justification(
|
||||
&self,
|
||||
header: block::Header,
|
||||
justification: bft::UncheckedJustification,
|
||||
) -> error::Result<JustifiedHeader> {
|
||||
let authorities = self.authorities_at(&BlockId::Hash(header.parent_hash))?;
|
||||
let just = bft::check_justification(&authorities[..], header.parent_hash, justification)
|
||||
.map_err(|_| error::ErrorKind::BadJustification(BlockId::Hash(header.blake2_256().into())))?;
|
||||
header: <Block as BlockT>::Header,
|
||||
justification: ::bft::UncheckedJustification<Block::Hash>,
|
||||
) -> error::Result<JustifiedHeader<Block>> {
|
||||
let parent_hash = header.parent_hash().clone();
|
||||
let authorities = self.authorities_at(&BlockId::Hash(parent_hash))?;
|
||||
let just = ::bft::check_justification::<Block>(&authorities[..], parent_hash, justification)
|
||||
.map_err(|_|
|
||||
error::ErrorKind::BadJustification(
|
||||
format!("{}", header.hash())
|
||||
)
|
||||
)?;
|
||||
Ok(JustifiedHeader {
|
||||
header,
|
||||
justification: just,
|
||||
@@ -284,16 +291,16 @@ impl<B, E> Client<B, E> where
|
||||
pub fn import_block(
|
||||
&self,
|
||||
origin: BlockOrigin,
|
||||
header: JustifiedHeader,
|
||||
body: Option<block::Body>,
|
||||
header: JustifiedHeader<Block>,
|
||||
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
|
||||
) -> error::Result<ImportResult> {
|
||||
let (header, justification) = header.into_inner();
|
||||
match self.backend.blockchain().status(BlockId::Hash(header.parent_hash))? {
|
||||
let parent_hash = header.parent_hash().clone();
|
||||
match self.backend.blockchain().status(BlockId::Hash(parent_hash))? {
|
||||
blockchain::BlockStatus::InChain => {},
|
||||
blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
|
||||
}
|
||||
let hash: block::HeaderHash = header.blake2_256().into();
|
||||
|
||||
let hash = header.hash();
|
||||
let _import_lock = self.import_lock.lock();
|
||||
*self.importing_block.write() = Some(hash);
|
||||
let result = self.execute_and_import_block(origin, hash, header, justification, body);
|
||||
@@ -304,17 +311,18 @@ impl<B, E> Client<B, E> where
|
||||
fn execute_and_import_block(
|
||||
&self,
|
||||
origin: BlockOrigin,
|
||||
hash: HeaderHash,
|
||||
header: block::Header,
|
||||
justification: bft::Justification,
|
||||
body: Option<block::Body>,
|
||||
hash: Block::Hash,
|
||||
header: Block::Header,
|
||||
justification: bft::Justification<Block::Hash>,
|
||||
body: Option<Vec<Block::Extrinsic>>,
|
||||
) -> error::Result<ImportResult> {
|
||||
let parent_hash = header.parent_hash().clone();
|
||||
match self.backend.blockchain().status(BlockId::Hash(hash))? {
|
||||
blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain),
|
||||
blockchain::BlockStatus::Unknown => {},
|
||||
}
|
||||
|
||||
let mut transaction = self.backend.begin_operation(BlockId::Hash(header.parent_hash))?;
|
||||
let mut transaction = self.backend.begin_operation(BlockId::Hash(parent_hash))?;
|
||||
let storage_update = match transaction.state()? {
|
||||
Some(transaction_state) => {
|
||||
let mut overlay = Default::default();
|
||||
@@ -322,7 +330,7 @@ impl<B, E> Client<B, E> where
|
||||
transaction_state,
|
||||
&mut overlay,
|
||||
"execute_block",
|
||||
&block::Block { header: header.clone(), transactions: body.clone().unwrap_or_default().clone() }.encode(),
|
||||
&<Block as BlockT>::new(header.clone(), body.clone().unwrap_or_default()).encode()
|
||||
)?;
|
||||
|
||||
Some(storage_update)
|
||||
@@ -330,15 +338,15 @@ impl<B, E> Client<B, E> where
|
||||
None => None,
|
||||
};
|
||||
|
||||
let is_new_best = header.number == self.backend.blockchain().info()?.best_number + 1;
|
||||
trace!("Imported {}, (#{}), best={}, origin={:?}", hash, header.number, is_new_best, origin);
|
||||
let is_new_best = header.number() == &(self.backend.blockchain().info()?.best_number + One::one());
|
||||
trace!("Imported {}, (#{}), best={}, origin={:?}", hash, header.number(), is_new_best, origin);
|
||||
transaction.set_block_data(header.clone(), body, Some(justification.uncheck().into()), is_new_best)?;
|
||||
if let Some(storage_update) = storage_update {
|
||||
transaction.update_storage(storage_update)?;
|
||||
}
|
||||
self.backend.commit_operation(transaction)?;
|
||||
if origin == BlockOrigin::NetworkBroadcast || origin == BlockOrigin::Own || origin == BlockOrigin::ConsensusBroadcast {
|
||||
let notification = BlockImportNotification {
|
||||
let notification = BlockImportNotification::<Block> {
|
||||
hash: hash,
|
||||
origin: origin,
|
||||
header: header,
|
||||
@@ -351,7 +359,7 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Get blockchain info.
|
||||
pub fn info(&self) -> error::Result<ClientInfo> {
|
||||
pub fn info(&self) -> error::Result<ClientInfo<Block>> {
|
||||
let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?;
|
||||
Ok(ClientInfo {
|
||||
chain: info,
|
||||
@@ -361,7 +369,7 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Get block status.
|
||||
pub fn block_status(&self, id: &BlockId) -> error::Result<BlockStatus> {
|
||||
pub fn block_status(&self, id: &BlockId<Block>) -> error::Result<BlockStatus> {
|
||||
// TODO: more efficient implementation
|
||||
if let BlockId::Hash(ref h) = id {
|
||||
if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) {
|
||||
@@ -375,12 +383,12 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Get block hash by number.
|
||||
pub fn block_hash(&self, block_number: block::Number) -> error::Result<Option<block::HeaderHash>> {
|
||||
pub fn block_hash(&self, block_number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
|
||||
self.backend.blockchain().hash(block_number)
|
||||
}
|
||||
|
||||
/// Convert an arbitrary block ID into a block hash.
|
||||
pub fn block_hash_from_id(&self, id: &BlockId) -> error::Result<Option<block::HeaderHash>> {
|
||||
pub fn block_hash_from_id(&self, id: &BlockId<Block>) -> error::Result<Option<Block::Hash>> {
|
||||
match *id {
|
||||
BlockId::Hash(h) => Ok(Some(h)),
|
||||
BlockId::Number(n) => self.block_hash(n),
|
||||
@@ -388,83 +396,91 @@ impl<B, E> Client<B, E> where
|
||||
}
|
||||
|
||||
/// Convert an arbitrary block ID into a block hash.
|
||||
pub fn block_number_from_id(&self, id: &BlockId) -> error::Result<Option<block::Number>> {
|
||||
pub fn block_number_from_id(&self, id: &BlockId<Block>) -> error::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
|
||||
match *id {
|
||||
BlockId::Hash(_) => Ok(self.header(id)?.map(|h| h.number)),
|
||||
BlockId::Hash(_) => Ok(self.header(id)?.map(|h| h.number().clone())),
|
||||
BlockId::Number(n) => Ok(Some(n)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get block header by id.
|
||||
pub fn header(&self, id: &BlockId) -> error::Result<Option<block::Header>> {
|
||||
pub fn header(&self, id: &BlockId<Block>) -> error::Result<Option<<Block as BlockT>::Header>> {
|
||||
self.backend.blockchain().header(*id)
|
||||
}
|
||||
|
||||
/// Get block body by id.
|
||||
pub fn body(&self, id: &BlockId) -> error::Result<Option<block::Body>> {
|
||||
pub fn body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
self.backend.blockchain().body(*id)
|
||||
}
|
||||
|
||||
/// Get block justification set by id.
|
||||
pub fn justification(&self, id: &BlockId) -> error::Result<Option<primitives::bft::Justification>> {
|
||||
pub fn justification(&self, id: &BlockId<Block>) -> error::Result<Option<Justification<Block::Hash>>> {
|
||||
self.backend.blockchain().justification(*id)
|
||||
}
|
||||
|
||||
/// Get best block header.
|
||||
pub fn best_block_header(&self) -> error::Result<block::Header> {
|
||||
pub fn best_block_header(&self) -> error::Result<<Block as BlockT>::Header> {
|
||||
let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?;
|
||||
Ok(self.header(&BlockId::Hash(info.best_hash))?.expect("Best block header must always exist"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> bft::BlockImport for Client<B, E>
|
||||
impl<B, E, Block> bft::BlockImport<Block> for Client<B, E, Block>
|
||||
where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor,
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
fn import_block(&self, block: block::Block, justification: bft::Justification) {
|
||||
fn import_block(&self, block: Block, justification: ::bft::Justification<Block::Hash>) {
|
||||
let (header, extrinsics) = block.deconstruct();
|
||||
let justified_header = JustifiedHeader {
|
||||
header: block.header,
|
||||
header: header,
|
||||
justification,
|
||||
};
|
||||
|
||||
let _ = self.import_block(BlockOrigin::ConsensusBroadcast, justified_header, Some(block.transactions));
|
||||
let _ = self.import_block(BlockOrigin::ConsensusBroadcast, justified_header, Some(extrinsics));
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> bft::Authorities for Client<B, E>
|
||||
impl<B, E, Block> bft::Authorities<Block> for Client<B, E, Block>
|
||||
where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor,
|
||||
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<B::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, bft::Error> {
|
||||
self.authorities_at(at).map_err(|_| bft::ErrorKind::StateUnavailable(*at).into())
|
||||
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, bft::Error> {
|
||||
self.authorities_at(at).map_err(|_| {
|
||||
let descriptor = format!("{:?}", at);
|
||||
bft::ErrorKind::StateUnavailable(descriptor).into()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> BlockchainEvents for Client<B, E>
|
||||
impl<B, E, Block> BlockchainEvents<Block> for Client<B, E, Block>
|
||||
where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor,
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
/// Get block import event stream.
|
||||
fn import_notification_stream(&self) -> BlockchainEventStream {
|
||||
fn import_notification_stream(&self) -> mpsc::UnboundedReceiver<BlockImportNotification<Block>> {
|
||||
let (sink, stream) = mpsc::unbounded();
|
||||
self.import_notification_sinks.lock().push(sink);
|
||||
stream
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> ChainHead for Client<B, E>
|
||||
impl<B, E, Block> ChainHead<Block> for Client<B, E, Block>
|
||||
where
|
||||
B: backend::Backend,
|
||||
E: CallExecutor,
|
||||
B: backend::Backend<Block>,
|
||||
E: CallExecutor<Block>,
|
||||
Block: BlockT,
|
||||
error::Error: From<<B::State as state_machine::backend::Backend>::Error>
|
||||
{
|
||||
fn best_block_header(&self) -> error::Result<block::Header> {
|
||||
fn best_block_header(&self) -> error::Result<<Block as BlockT>::Header> {
|
||||
Client::best_block_header(self)
|
||||
}
|
||||
}
|
||||
@@ -474,20 +490,18 @@ mod tests {
|
||||
use super::*;
|
||||
use codec::Slicable;
|
||||
use keyring::Keyring;
|
||||
use primitives::block::Extrinsic as PrimitiveExtrinsic;
|
||||
use test_client::{self, TestClient};
|
||||
use test_client::client::BlockOrigin;
|
||||
use test_client::runtime as test_runtime;
|
||||
use test_client::runtime::{UncheckedTransaction, Transaction};
|
||||
use test_client::runtime::{Transfer, Extrinsic};
|
||||
|
||||
#[test]
|
||||
fn client_initialises_from_genesis_ok() {
|
||||
let client = test_client::new();
|
||||
let genesis_hash = client.block_hash(0).unwrap().unwrap();
|
||||
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::latest_block_hash()).unwrap(), genesis_hash);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public())).unwrap(), 1000);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public())).unwrap(), 0);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public().into())).unwrap(), 1000);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public().into())).unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -511,17 +525,11 @@ mod tests {
|
||||
client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(client.info().unwrap().chain.best_number, 1);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::latest_block_hash()).unwrap(), client.block_hash(1).unwrap().unwrap());
|
||||
}
|
||||
|
||||
trait Signable {
|
||||
fn signed(self) -> PrimitiveExtrinsic;
|
||||
}
|
||||
impl Signable for Transaction {
|
||||
fn signed(self) -> PrimitiveExtrinsic {
|
||||
let signature = Keyring::from_raw_public(self.from.clone()).unwrap().sign(&self.encode());
|
||||
PrimitiveExtrinsic::decode(&mut UncheckedTransaction { signature, tx: self }.encode().as_ref()).unwrap()
|
||||
}
|
||||
fn sign_tx(tx: Transfer) -> Extrinsic {
|
||||
let signature = Keyring::from_raw_public(tx.from.0.clone()).unwrap().sign(&tx.encode()).into();
|
||||
Extrinsic { transfer: tx, signature }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -530,18 +538,18 @@ mod tests {
|
||||
|
||||
let mut builder = client.new_block().unwrap();
|
||||
|
||||
builder.push(Transaction {
|
||||
from: Keyring::Alice.to_raw_public(),
|
||||
to: Keyring::Ferdie.to_raw_public(),
|
||||
builder.push(sign_tx(Transfer {
|
||||
from: Keyring::Alice.to_raw_public().into(),
|
||||
to: Keyring::Ferdie.to_raw_public().into(),
|
||||
amount: 42,
|
||||
nonce: 0
|
||||
}.signed()).unwrap();
|
||||
nonce: 0,
|
||||
})).unwrap();
|
||||
|
||||
client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(client.info().unwrap().chain.best_number, 1);
|
||||
assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap());
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public())).unwrap(), 958);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public())).unwrap(), 42);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Alice.to_raw_public().into())).unwrap(), 958);
|
||||
assert_eq!(client.using_environment(|| test_runtime::system::balance_of(Keyring::Ferdie.to_raw_public().into())).unwrap(), 42);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ error_chain! {
|
||||
}
|
||||
|
||||
/// Unknown block.
|
||||
UnknownBlock(h: ::primitives::block::Id) {
|
||||
UnknownBlock(h: String) {
|
||||
description("unknown block"),
|
||||
display("UnknownBlock: {}", h),
|
||||
display("UnknownBlock: {}", &*h),
|
||||
}
|
||||
|
||||
/// Execution error.
|
||||
@@ -77,9 +77,9 @@ error_chain! {
|
||||
}
|
||||
|
||||
/// Bad justification for header.
|
||||
BadJustification(h: ::primitives::block::Id) {
|
||||
BadJustification(h: String) {
|
||||
description("bad justification for header"),
|
||||
display("bad justification for header: {}", h),
|
||||
display("bad justification for header: {}", &*h),
|
||||
}
|
||||
|
||||
/// Not available on light client.
|
||||
@@ -110,8 +110,8 @@ impl From<Box<state_machine::Error>> for Error {
|
||||
}
|
||||
|
||||
impl From<state_machine::backend::Void> for Error {
|
||||
fn from(_e: state_machine::backend::Void) -> Self {
|
||||
unreachable!()
|
||||
fn from(e: state_machine::backend::Void) -> Self {
|
||||
match e {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,54 +17,56 @@
|
||||
//! Tool for creating the genesis block.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use primitives::{Block, Header};
|
||||
use triehash::trie_root;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing as HashingT, Zero};
|
||||
|
||||
/// Create a genesis block, given the initial storage.
|
||||
pub fn construct_genesis_block(storage: &HashMap<Vec<u8>, Vec<u8>>) -> Block {
|
||||
let state_root = trie_root(storage.clone().into_iter()).0.into();
|
||||
let header = Header {
|
||||
parent_hash: Default::default(),
|
||||
number: 0,
|
||||
state_root,
|
||||
extrinsics_root: trie_root(vec![].into_iter()).0.into(),
|
||||
digest: Default::default(),
|
||||
};
|
||||
Block {
|
||||
header,
|
||||
transactions: vec![],
|
||||
}
|
||||
pub fn construct_genesis_block<
|
||||
Block: BlockT
|
||||
> (
|
||||
storage: &HashMap<Vec<u8>, Vec<u8>>
|
||||
) -> Block {
|
||||
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashingT>::trie_root(storage.clone().into_iter());
|
||||
let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashingT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>());
|
||||
Block::new(
|
||||
<<Block as BlockT>::Header as HeaderT>::new(
|
||||
Zero::zero(),
|
||||
extrinsics_root,
|
||||
state_root,
|
||||
Default::default(),
|
||||
Default::default()
|
||||
),
|
||||
Default::default()
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::{Slicable, Joiner};
|
||||
use runtime_support::Hashable;
|
||||
use keyring::Keyring;
|
||||
use executor::WasmExecutor;
|
||||
use state_machine::{execute, OverlayedChanges};
|
||||
use state_machine::backend::InMemory;
|
||||
use test_client;
|
||||
use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
|
||||
use test_client::runtime::{Hash, Block, BlockNumber, Header, Digest, Transaction,
|
||||
UncheckedTransaction};
|
||||
use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic};
|
||||
use ed25519::{Public, Pair};
|
||||
|
||||
native_executor_instance!(Executor, test_client::runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
|
||||
|
||||
fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transaction>) -> (Vec<u8>, Hash) {
|
||||
fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transfer>) -> (Vec<u8>, Hash) {
|
||||
use triehash::ordered_trie_root;
|
||||
|
||||
let transactions = txs.into_iter().map(|tx| {
|
||||
let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from)).unwrap())
|
||||
.sign(&tx.encode());
|
||||
let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from.0)).unwrap())
|
||||
.sign(&tx.encode()).into();
|
||||
|
||||
UncheckedTransaction { tx, signature }
|
||||
Extrinsic { transfer: tx, signature }
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let extrinsics_root = ordered_trie_root(transactions.iter().map(Slicable::encode)).0.into();
|
||||
|
||||
println!("root before: {:?}", extrinsics_root);
|
||||
let mut header = Header {
|
||||
parent_hash,
|
||||
number,
|
||||
@@ -72,19 +74,25 @@ mod tests {
|
||||
extrinsics_root,
|
||||
digest: Digest { logs: vec![], },
|
||||
};
|
||||
let hash = header.blake2_256();
|
||||
|
||||
let hash = header.hash();
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
|
||||
execute(
|
||||
backend,
|
||||
&mut overlay,
|
||||
&Executor::new(),
|
||||
"initialise_block",
|
||||
&header.encode(),
|
||||
).unwrap();
|
||||
|
||||
for tx in transactions.iter() {
|
||||
let (ret_data, _) = execute(
|
||||
execute(
|
||||
backend,
|
||||
&mut overlay,
|
||||
&Executor::new(),
|
||||
"execute_transaction",
|
||||
&vec![].and(&header).and(tx)
|
||||
"apply_extrinsic",
|
||||
&tx.encode(),
|
||||
).unwrap();
|
||||
header = Header::decode(&mut &ret_data[..]).unwrap();
|
||||
}
|
||||
|
||||
let (ret_data, _) = execute(
|
||||
@@ -92,11 +100,12 @@ mod tests {
|
||||
&mut overlay,
|
||||
&Executor::new(),
|
||||
"finalise_block",
|
||||
&vec![].and(&header)
|
||||
&[]
|
||||
).unwrap();
|
||||
header = Header::decode(&mut &ret_data[..]).unwrap();
|
||||
println!("root after: {:?}", header.extrinsics_root);
|
||||
|
||||
(vec![].and(&Block { header, transactions }), hash.into())
|
||||
(vec![].and(&Block { header, extrinsics: transactions }), hash)
|
||||
}
|
||||
|
||||
fn block1(genesis_hash: Hash, backend: &InMemory) -> (Vec<u8>, Hash) {
|
||||
@@ -105,9 +114,9 @@ mod tests {
|
||||
1,
|
||||
genesis_hash,
|
||||
hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(),
|
||||
vec![Transaction {
|
||||
from: Keyring::One.to_raw_public(),
|
||||
to: Keyring::Two.to_raw_public(),
|
||||
vec![Transfer {
|
||||
from: Keyring::One.to_raw_public().into(),
|
||||
to: Keyring::Two.to_raw_public().into(),
|
||||
amount: 69,
|
||||
nonce: 0,
|
||||
}]
|
||||
@@ -119,8 +128,8 @@ mod tests {
|
||||
let mut storage = GenesisConfig::new_simple(
|
||||
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
|
||||
).genesis_map();
|
||||
let block = construct_genesis_block(&storage);
|
||||
let genesis_hash = block.header.blake2_256().into();
|
||||
let block = construct_genesis_block::<Block>(&storage);
|
||||
let genesis_hash = block.header.hash();
|
||||
storage.extend(additional_storage_with_genesis(&block).into_iter());
|
||||
|
||||
let backend = InMemory::from(storage);
|
||||
@@ -141,8 +150,8 @@ mod tests {
|
||||
let mut storage = GenesisConfig::new_simple(
|
||||
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
|
||||
).genesis_map();
|
||||
let block = construct_genesis_block(&storage);
|
||||
let genesis_hash = block.header.blake2_256().into();
|
||||
let block = construct_genesis_block::<Block>(&storage);
|
||||
let genesis_hash = block.header.hash();
|
||||
storage.extend(additional_storage_with_genesis(&block).into_iter());
|
||||
|
||||
let backend = InMemory::from(storage);
|
||||
@@ -164,8 +173,8 @@ mod tests {
|
||||
let mut storage = GenesisConfig::new_simple(
|
||||
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 68
|
||||
).genesis_map();
|
||||
let block = construct_genesis_block(&storage);
|
||||
let genesis_hash = block.header.blake2_256().into();
|
||||
let block = construct_genesis_block::<Block>(&storage);
|
||||
let genesis_hash = block.header.hash();
|
||||
storage.extend(additional_storage_with_genesis(&block).into_iter());
|
||||
|
||||
let backend = InMemory::from(storage);
|
||||
|
||||
@@ -20,95 +20,136 @@ use std::collections::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
use error;
|
||||
use backend;
|
||||
use runtime_support::Hashable;
|
||||
use primitives;
|
||||
use primitives::block::{self, Id as BlockId, HeaderHash};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero};
|
||||
use runtime_primitives::bft::Justification;
|
||||
use blockchain::{self, BlockStatus};
|
||||
use state_machine::backend::{Backend as StateBackend, InMemory};
|
||||
|
||||
struct PendingBlock {
|
||||
block: Block,
|
||||
struct PendingBlock<B: BlockT> {
|
||||
block: StoredBlock<B>,
|
||||
is_best: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
struct Block {
|
||||
header: block::Header,
|
||||
justification: Option<primitives::bft::Justification>,
|
||||
body: Option<block::Body>,
|
||||
enum StoredBlock<B: BlockT> {
|
||||
Header(B::Header, Option<Justification<B::Hash>>),
|
||||
Full(B, Option<Justification<B::Hash>>),
|
||||
}
|
||||
|
||||
impl<B: BlockT> StoredBlock<B> {
|
||||
fn new(header: B::Header, body: Option<Vec<B::Extrinsic>>, just: Option<Justification<B::Hash>>) -> Self {
|
||||
match body {
|
||||
Some(body) => StoredBlock::Full(B::new(header, body), just),
|
||||
None => StoredBlock::Header(header, just),
|
||||
}
|
||||
}
|
||||
|
||||
fn header(&self) -> &B::Header {
|
||||
match *self {
|
||||
StoredBlock::Header(ref h, _) => h,
|
||||
StoredBlock::Full(ref b, _) => b.header(),
|
||||
}
|
||||
}
|
||||
|
||||
fn justification(&self) -> Option<&Justification<B::Hash>> {
|
||||
match *self {
|
||||
StoredBlock::Header(_, ref j) | StoredBlock::Full(_, ref j) => j.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
fn extrinsics(&self) -> Option<&[B::Extrinsic]> {
|
||||
match *self {
|
||||
StoredBlock::Header(_, _) => None,
|
||||
StoredBlock::Full(ref b, _) => Some(b.extrinsics())
|
||||
}
|
||||
}
|
||||
|
||||
fn into_inner(self) -> (B::Header, Option<Vec<B::Extrinsic>>, Option<Justification<B::Hash>>) {
|
||||
match self {
|
||||
StoredBlock::Header(header, just) => (header, None, just),
|
||||
StoredBlock::Full(block, just) => {
|
||||
let (header, body) = block.deconstruct();
|
||||
(header, Some(body), just)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BlockchainStorage {
|
||||
blocks: HashMap<HeaderHash, Block>,
|
||||
hashes: HashMap<block::Number, HeaderHash>,
|
||||
best_hash: HeaderHash,
|
||||
best_number: block::Number,
|
||||
genesis_hash: HeaderHash,
|
||||
struct BlockchainStorage<Block: BlockT> {
|
||||
blocks: HashMap<Block::Hash, StoredBlock<Block>>,
|
||||
hashes: HashMap<<<Block as BlockT>::Header as HeaderT>::Number, Block::Hash>,
|
||||
best_hash: Block::Hash,
|
||||
best_number: <<Block as BlockT>::Header as HeaderT>::Number,
|
||||
genesis_hash: Block::Hash,
|
||||
}
|
||||
|
||||
/// In-memory blockchain. Supports concurrent reads.
|
||||
pub struct Blockchain {
|
||||
storage: RwLock<BlockchainStorage>,
|
||||
pub struct Blockchain<Block: BlockT> {
|
||||
storage: RwLock<BlockchainStorage<Block>>,
|
||||
}
|
||||
|
||||
impl Clone for Blockchain {
|
||||
fn clone(&self) -> Blockchain {
|
||||
impl<Block: BlockT + Clone> Clone for Blockchain<Block> {
|
||||
fn clone(&self) -> Self {
|
||||
Blockchain {
|
||||
storage: RwLock::new(self.storage.read().clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockchain {
|
||||
/// Create new in-memory blockchain storage.
|
||||
pub fn new() -> Blockchain {
|
||||
Blockchain {
|
||||
storage: RwLock::new(
|
||||
BlockchainStorage {
|
||||
blocks: HashMap::new(),
|
||||
hashes: HashMap::new(),
|
||||
best_hash: HeaderHash::default(),
|
||||
best_number: 0,
|
||||
genesis_hash: HeaderHash::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> Blockchain<Block> {
|
||||
/// Get header hash of given block.
|
||||
pub fn id(&self, id: BlockId) -> Option<HeaderHash> {
|
||||
pub fn id(&self, id: BlockId<Block>) -> Option<Block::Hash> {
|
||||
match id {
|
||||
BlockId::Hash(h) => Some(h),
|
||||
BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert block.
|
||||
pub fn insert(&self, hash: HeaderHash, header: block::Header, justification: Option<primitives::bft::Justification>, body: Option<block::Body>, is_new_best: bool) {
|
||||
let number = header.number;
|
||||
let mut storage = self.storage.write();
|
||||
storage.blocks.insert(hash, Block {
|
||||
header: header,
|
||||
body: body,
|
||||
justification: justification,
|
||||
});
|
||||
storage.hashes.insert(number, hash);
|
||||
if is_new_best {
|
||||
storage.best_hash = hash;
|
||||
storage.best_number = number;
|
||||
/// Create new in-memory blockchain storage.
|
||||
pub fn new() -> Self {
|
||||
Blockchain {
|
||||
storage: RwLock::new(
|
||||
BlockchainStorage {
|
||||
blocks: HashMap::new(),
|
||||
hashes: HashMap::new(),
|
||||
best_hash: Default::default(),
|
||||
best_number: Zero::zero(),
|
||||
genesis_hash: Default::default(),
|
||||
})
|
||||
}
|
||||
if number == 0 {
|
||||
}
|
||||
|
||||
/// Insert a block header and associated data.
|
||||
pub fn insert(
|
||||
&self,
|
||||
hash: Block::Hash,
|
||||
header: <Block as BlockT>::Header,
|
||||
justification: Option<Justification<Block::Hash>>,
|
||||
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
|
||||
is_new_best: bool
|
||||
) {
|
||||
let number = header.number().clone();
|
||||
let mut storage = self.storage.write();
|
||||
storage.blocks.insert(hash.clone(), StoredBlock::new(header, body, justification));
|
||||
storage.hashes.insert(number, hash.clone());
|
||||
if is_new_best {
|
||||
storage.best_hash = hash.clone();
|
||||
storage.best_number = number.clone();
|
||||
}
|
||||
if number == Zero::zero() {
|
||||
storage.genesis_hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare this blockchain with another in-mem blockchain
|
||||
pub fn equals_to(&self, other: &Blockchain) -> bool {
|
||||
pub fn equals_to(&self, other: &Self) -> bool {
|
||||
self.canon_equals_to(other) && self.storage.read().blocks == other.storage.read().blocks
|
||||
}
|
||||
|
||||
/// Compare canonical chain to other canonical chain.
|
||||
pub fn canon_equals_to(&self, other: &Blockchain) -> bool {
|
||||
pub fn canon_equals_to(&self, other: &Self) -> bool {
|
||||
let this = self.storage.read();
|
||||
let other = other.storage.read();
|
||||
this.hashes == other.hashes
|
||||
@@ -118,20 +159,27 @@ impl Blockchain {
|
||||
}
|
||||
}
|
||||
|
||||
impl blockchain::Backend for Blockchain {
|
||||
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).map(|b| b.header.clone())))
|
||||
impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
|
||||
fn header(&self, id: BlockId<Block>) -> error::Result<Option<<Block as BlockT>::Header>> {
|
||||
Ok(self.id(id).and_then(|hash| {
|
||||
self.storage.read().blocks.get(&hash).map(|b| b.header().clone())
|
||||
}))
|
||||
}
|
||||
|
||||
fn body(&self, id: BlockId) -> error::Result<Option<block::Body>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.body.clone())))
|
||||
fn body(&self, id: BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
Ok(self.id(id).and_then(|hash| {
|
||||
self.storage.read().blocks.get(&hash)
|
||||
.and_then(|b| b.extrinsics().map(|x| x.to_vec()))
|
||||
}))
|
||||
}
|
||||
|
||||
fn justification(&self, id: BlockId) -> error::Result<Option<primitives::bft::Justification>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.justification.clone())))
|
||||
fn justification(&self, id: BlockId<Block>) -> error::Result<Option<Justification<Block::Hash>>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b|
|
||||
b.justification().map(|x| x.clone()))
|
||||
))
|
||||
}
|
||||
|
||||
fn info(&self) -> error::Result<blockchain::Info> {
|
||||
fn info(&self) -> error::Result<blockchain::Info<Block>> {
|
||||
let storage = self.storage.read();
|
||||
Ok(blockchain::Info {
|
||||
best_hash: storage.best_hash,
|
||||
@@ -140,40 +188,42 @@ impl blockchain::Backend for Blockchain {
|
||||
})
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId) -> error::Result<BlockStatus> {
|
||||
fn status(&self, id: BlockId<Block>) -> error::Result<BlockStatus> {
|
||||
match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) {
|
||||
true => Ok(BlockStatus::InChain),
|
||||
false => Ok(BlockStatus::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, number: block::Number) -> error::Result<Option<block::HeaderHash>> {
|
||||
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
|
||||
Ok(self.id(BlockId::Number(number)))
|
||||
}
|
||||
}
|
||||
|
||||
/// In-memory operation.
|
||||
pub struct BlockImportOperation {
|
||||
pending_block: Option<PendingBlock>,
|
||||
pub struct BlockImportOperation<Block: BlockT> {
|
||||
pending_block: Option<PendingBlock<Block>>,
|
||||
old_state: InMemory,
|
||||
new_state: Option<InMemory>,
|
||||
}
|
||||
|
||||
impl backend::BlockImportOperation for BlockImportOperation {
|
||||
impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperation<Block> {
|
||||
type State = InMemory;
|
||||
|
||||
fn state(&self) -> error::Result<Option<&Self::State>> {
|
||||
Ok(Some(&self.old_state))
|
||||
}
|
||||
|
||||
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()> {
|
||||
fn set_block_data(
|
||||
&mut self,
|
||||
header: <Block as BlockT>::Header,
|
||||
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
|
||||
justification: Option<Justification<Block::Hash>>,
|
||||
is_new_best: bool
|
||||
) -> error::Result<()> {
|
||||
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
|
||||
self.pending_block = Some(PendingBlock {
|
||||
block: Block {
|
||||
header: header,
|
||||
body: body,
|
||||
justification: justification,
|
||||
},
|
||||
block: StoredBlock::new(header, body, justification),
|
||||
is_best: is_new_best,
|
||||
});
|
||||
Ok(())
|
||||
@@ -191,14 +241,18 @@ impl backend::BlockImportOperation for BlockImportOperation {
|
||||
}
|
||||
|
||||
/// In-memory backend. Keeps all states and blocks in memory. Useful for testing.
|
||||
pub struct Backend {
|
||||
states: RwLock<HashMap<block::HeaderHash, InMemory>>,
|
||||
blockchain: Blockchain,
|
||||
pub struct Backend<Block> where
|
||||
Block: BlockT,
|
||||
{
|
||||
states: RwLock<HashMap<Block::Hash, InMemory>>,
|
||||
blockchain: Blockchain<Block>,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
impl<Block> Backend<Block> where
|
||||
Block: BlockT,
|
||||
{
|
||||
/// Create a new instance of in-mem backend.
|
||||
pub fn new() -> Backend {
|
||||
pub fn new() -> Backend<Block> {
|
||||
Backend {
|
||||
states: RwLock::new(HashMap::new()),
|
||||
blockchain: Blockchain::new(),
|
||||
@@ -206,14 +260,16 @@ impl Backend {
|
||||
}
|
||||
}
|
||||
|
||||
impl backend::Backend for Backend {
|
||||
type BlockImportOperation = BlockImportOperation;
|
||||
type Blockchain = Blockchain;
|
||||
impl<Block> backend::Backend<Block> for Backend<Block> where
|
||||
Block: BlockT,
|
||||
{
|
||||
type BlockImportOperation = BlockImportOperation<Block>;
|
||||
type Blockchain = Blockchain<Block>;
|
||||
type State = InMemory;
|
||||
|
||||
fn begin_operation(&self, block: BlockId) -> error::Result<Self::BlockImportOperation> {
|
||||
fn begin_operation(&self, block: BlockId<Block>) -> error::Result<Self::BlockImportOperation> {
|
||||
let state = match block {
|
||||
BlockId::Hash(h) if h.is_zero() => Self::State::default(),
|
||||
BlockId::Hash(ref h) if h.clone() == Default::default() => Self::State::default(),
|
||||
_ => self.state_at(block)?,
|
||||
};
|
||||
|
||||
@@ -226,24 +282,26 @@ impl backend::Backend for Backend {
|
||||
|
||||
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
|
||||
if let Some(pending_block) = operation.pending_block {
|
||||
let hash = pending_block.block.header.blake2_256().into();
|
||||
let old_state = &operation.old_state;
|
||||
let (header, body, justification) = pending_block.block.into_inner();
|
||||
let hash = header.hash();
|
||||
|
||||
self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone()));
|
||||
self.blockchain.insert(hash, pending_block.block.header, pending_block.block.justification, pending_block.block.body, pending_block.is_best);
|
||||
self.blockchain.insert(hash, header, justification, body, pending_block.is_best);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn blockchain(&self) -> &Blockchain {
|
||||
fn blockchain(&self) -> &Self::Blockchain {
|
||||
&self.blockchain
|
||||
}
|
||||
|
||||
fn state_at(&self, block: BlockId) -> error::Result<Self::State> {
|
||||
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State> {
|
||||
match self.blockchain.id(block).and_then(|id| self.states.read().get(&id).cloned()) {
|
||||
Some(state) => Ok(state),
|
||||
None => Err(error::ErrorKind::UnknownBlock(block).into()),
|
||||
None => Err(error::ErrorKind::UnknownBlock(format!("{}", block)).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl backend::LocalBackend for Backend {}
|
||||
impl<Block: BlockT> backend::LocalBackend<Block> for Backend<Block> {}
|
||||
|
||||
@@ -24,6 +24,7 @@ extern crate substrate_codec as codec;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
#[cfg(test)] extern crate substrate_keyring as keyring;
|
||||
#[cfg(test)] extern crate substrate_test_client as test_client;
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use futures::future::IntoFuture;
|
||||
use primitives;
|
||||
use primitives::block::{self, Id as BlockId, HeaderHash};
|
||||
use runtime_support::Hashable;
|
||||
use state_machine::CodeExecutor;
|
||||
use state_machine::backend::Backend as StateBackend;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::bft::Justification;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use blockchain::{self, BlockStatus};
|
||||
use backend;
|
||||
use call_executor::{CallResult, RemoteCallExecutor, check_execution_proof};
|
||||
@@ -32,9 +32,9 @@ use error;
|
||||
use in_mem::Blockchain as InMemBlockchain;
|
||||
|
||||
/// Remote call request.
|
||||
pub struct RemoteCallRequest {
|
||||
/// Call at state of given block.
|
||||
pub block: HeaderHash,
|
||||
pub struct RemoteCallRequest<H> {
|
||||
/// Call at state of block referenced by given header hash.
|
||||
pub block: H,
|
||||
/// Method to call.
|
||||
pub method: String,
|
||||
/// Call data.
|
||||
@@ -43,62 +43,62 @@ pub struct RemoteCallRequest {
|
||||
|
||||
/// Light client data fetcher. Implementations of this trait must check if remote data
|
||||
/// is correct (see FetchedDataChecker) and return already checked data.
|
||||
pub trait Fetcher: Send + Sync {
|
||||
pub trait Fetcher<B: BlockT>: Send + Sync {
|
||||
/// Remote call result future.
|
||||
type RemoteCallResult: IntoFuture<Item=CallResult, Error=error::Error>;
|
||||
|
||||
/// Fetch remote call result.
|
||||
fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult;
|
||||
fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Self::RemoteCallResult;
|
||||
}
|
||||
|
||||
/// Light client remote data checker.
|
||||
pub trait FetchChecker: Send + Sync {
|
||||
pub trait FetchChecker<B: BlockT>: Send + Sync {
|
||||
/// Check remote method execution proof.
|
||||
fn check_execution_proof(&self, request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult>;
|
||||
fn check_execution_proof(&self, request: &RemoteCallRequest<B::Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult>;
|
||||
}
|
||||
|
||||
/// Light client backend.
|
||||
pub struct Backend {
|
||||
blockchain: Blockchain,
|
||||
pub struct Backend<B: BlockT> {
|
||||
blockchain: Blockchain<B>,
|
||||
}
|
||||
|
||||
/// Light client blockchain.
|
||||
pub struct Blockchain {
|
||||
storage: InMemBlockchain,
|
||||
pub struct Blockchain<B: BlockT> {
|
||||
storage: InMemBlockchain<B>,
|
||||
}
|
||||
|
||||
/// Block (header and justification) import operation.
|
||||
pub struct BlockImportOperation {
|
||||
pending_block: Option<PendingBlock>,
|
||||
pub struct BlockImportOperation<B: BlockT> {
|
||||
pending_block: Option<PendingBlock<B>>,
|
||||
}
|
||||
|
||||
/// On-demand state.
|
||||
#[derive(Clone)]
|
||||
pub struct OnDemandState {
|
||||
pub struct OnDemandState<H> {
|
||||
/// Hash of the block, state is valid for.
|
||||
_block: HeaderHash,
|
||||
_block: H,
|
||||
}
|
||||
|
||||
/// Remote data checker.
|
||||
pub struct LightDataChecker<E> {
|
||||
pub struct LightDataChecker<E, B: BlockT> {
|
||||
/// Backend reference.
|
||||
backend: Arc<Backend>,
|
||||
backend: Arc<Backend<B>>,
|
||||
/// Executor.
|
||||
executor: E,
|
||||
}
|
||||
|
||||
struct PendingBlock {
|
||||
header: block::Header,
|
||||
justification: Option<primitives::bft::Justification>,
|
||||
struct PendingBlock<B: BlockT> {
|
||||
header: B::Header,
|
||||
justification: Option<Justification<B::Hash>>,
|
||||
is_best: bool,
|
||||
}
|
||||
|
||||
impl backend::Backend for Backend {
|
||||
type BlockImportOperation = BlockImportOperation;
|
||||
type Blockchain = Blockchain;
|
||||
type State = OnDemandState;
|
||||
impl<B: BlockT> backend::Backend<B> for Backend<B> {
|
||||
type BlockImportOperation = BlockImportOperation<B>;
|
||||
type Blockchain = Blockchain<B>;
|
||||
type State = OnDemandState<B::Hash>;
|
||||
|
||||
fn begin_operation(&self, _block: BlockId) -> error::Result<Self::BlockImportOperation> {
|
||||
fn begin_operation(&self, _block: BlockId<B>) -> error::Result<Self::BlockImportOperation> {
|
||||
Ok(BlockImportOperation {
|
||||
pending_block: None,
|
||||
})
|
||||
@@ -106,34 +106,34 @@ impl backend::Backend for Backend {
|
||||
|
||||
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
|
||||
if let Some(pending_block) = operation.pending_block {
|
||||
let hash = pending_block.header.blake2_256().into();
|
||||
let hash = pending_block.header.hash();
|
||||
self.blockchain.storage.insert(hash, pending_block.header, pending_block.justification, None, pending_block.is_best);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn blockchain(&self) -> &Blockchain {
|
||||
fn blockchain(&self) -> &Blockchain<B> {
|
||||
&self.blockchain
|
||||
}
|
||||
|
||||
fn state_at(&self, block: BlockId) -> error::Result<Self::State> {
|
||||
fn state_at(&self, block: BlockId<B>) -> error::Result<Self::State> {
|
||||
Ok(OnDemandState {
|
||||
_block: self.blockchain.storage.id(block).ok_or(error::ErrorKind::UnknownBlock(block))?,
|
||||
_block: self.blockchain.storage.id(block).ok_or(error::ErrorKind::UnknownBlock(format!("{:?}", block)))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl backend::RemoteBackend for Backend {}
|
||||
impl<B: BlockT> backend::RemoteBackend<B> for Backend<B> {}
|
||||
|
||||
impl backend::BlockImportOperation for BlockImportOperation {
|
||||
type State = OnDemandState;
|
||||
impl<B: BlockT> backend::BlockImportOperation<B> for BlockImportOperation<B> {
|
||||
type State = OnDemandState<B::Hash>;
|
||||
|
||||
fn state(&self) -> error::Result<Option<&Self::State>> {
|
||||
// None means 'locally-stateless' backend
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn set_block_data(&mut self, header: block::Header, _body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()> {
|
||||
fn set_block_data(&mut self, header: B::Header, _body: Option<Vec<B::Extrinsic>>, justification: Option<Justification<B::Hash>>, is_new_best: bool) -> error::Result<()> {
|
||||
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
|
||||
self.pending_block = Some(PendingBlock {
|
||||
header,
|
||||
@@ -154,34 +154,34 @@ impl backend::BlockImportOperation for BlockImportOperation {
|
||||
}
|
||||
}
|
||||
|
||||
impl blockchain::Backend for Blockchain {
|
||||
fn header(&self, id: BlockId) -> error::Result<Option<block::Header>> {
|
||||
impl<B: BlockT> blockchain::Backend<B> for Blockchain<B> {
|
||||
fn header(&self, id: BlockId<B>) -> error::Result<Option<B::Header>> {
|
||||
self.storage.header(id)
|
||||
}
|
||||
|
||||
fn body(&self, _id: BlockId) -> error::Result<Option<block::Body>> {
|
||||
fn body(&self, _id: BlockId<B>) -> error::Result<Option<Vec<B::Extrinsic>>> {
|
||||
// TODO [light]: fetch from remote node
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn justification(&self, id: BlockId) -> error::Result<Option<primitives::bft::Justification>> {
|
||||
fn justification(&self, id: BlockId<B>) -> error::Result<Option<Justification<B::Hash>>> {
|
||||
self.storage.justification(id)
|
||||
}
|
||||
|
||||
fn info(&self) -> error::Result<blockchain::Info> {
|
||||
fn info(&self) -> error::Result<blockchain::Info<B>> {
|
||||
self.storage.info()
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId) -> error::Result<BlockStatus> {
|
||||
fn status(&self, id: BlockId<B>) -> error::Result<BlockStatus> {
|
||||
self.storage.status(id)
|
||||
}
|
||||
|
||||
fn hash(&self, number: block::Number) -> error::Result<Option<block::HeaderHash>> {
|
||||
fn hash(&self, number: <B::Header as HeaderT>::Number) -> error::Result<Option<B::Hash>> {
|
||||
self.storage.hash(number)
|
||||
}
|
||||
}
|
||||
|
||||
impl StateBackend for OnDemandState {
|
||||
impl<H: Clone> StateBackend for OnDemandState<H> {
|
||||
type Error = error::Error;
|
||||
type Transaction = ();
|
||||
|
||||
@@ -191,7 +191,8 @@ impl StateBackend for OnDemandState {
|
||||
}
|
||||
|
||||
fn storage_root<I>(&self, _delta: I) -> ([u8; 32], Self::Transaction)
|
||||
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)> {
|
||||
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
|
||||
{
|
||||
([0; 32], ())
|
||||
}
|
||||
|
||||
@@ -201,43 +202,46 @@ impl StateBackend for OnDemandState {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> FetchChecker for LightDataChecker<E>
|
||||
impl<E, B> FetchChecker<B> for LightDataChecker<E, B>
|
||||
where
|
||||
E: CodeExecutor,
|
||||
B: BlockT,
|
||||
{
|
||||
fn check_execution_proof(&self, request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult> {
|
||||
fn check_execution_proof(&self, request: &RemoteCallRequest<B::Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> error::Result<CallResult> {
|
||||
check_execution_proof(&*self.backend, &self.executor, request, remote_proof)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an instance of light client backend.
|
||||
pub fn new_light_backend() -> Arc<Backend> {
|
||||
pub fn new_light_backend<B: BlockT>() -> Arc<Backend<B>> {
|
||||
let storage = InMemBlockchain::new();
|
||||
let blockchain = Blockchain { storage };
|
||||
Arc::new(Backend { blockchain })
|
||||
}
|
||||
|
||||
/// Create an instance of light client.
|
||||
pub fn new_light<F, B>(
|
||||
backend: Arc<Backend>,
|
||||
pub fn new_light<F, B, Block>(
|
||||
backend: Arc<Backend<Block>>,
|
||||
fetcher: Arc<F>,
|
||||
genesis_builder: B,
|
||||
) -> error::Result<Client<Backend, RemoteCallExecutor<Backend, F>>>
|
||||
) -> error::Result<Client<Backend<Block>, RemoteCallExecutor<Backend<Block>, F>, Block>>
|
||||
where
|
||||
F: Fetcher,
|
||||
B: GenesisBuilder,
|
||||
F: Fetcher<Block>,
|
||||
B: GenesisBuilder<Block>,
|
||||
Block: BlockT,
|
||||
{
|
||||
let executor = RemoteCallExecutor::new(backend.clone(), fetcher);
|
||||
Client::new(backend, executor, genesis_builder)
|
||||
}
|
||||
|
||||
/// Create an instance of fetch data checker.
|
||||
pub fn new_fetch_checker<E>(
|
||||
backend: Arc<Backend>,
|
||||
pub fn new_fetch_checker<E, Block>(
|
||||
backend: Arc<Backend<Block>>,
|
||||
executor: E,
|
||||
) -> LightDataChecker<E>
|
||||
) -> LightDataChecker<E, Block>
|
||||
where
|
||||
E: CodeExecutor,
|
||||
Block: BlockT,
|
||||
{
|
||||
LightDataChecker { backend, executor }
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -8,5 +8,4 @@ error-chain = "0.11"
|
||||
futures = "0.1"
|
||||
log = "0.3"
|
||||
parking_lot = "0.4"
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
transaction-pool = "1.12"
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
|
||||
//! External API for extrinsic pool.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use txpool::{self, VerifiedTransaction};
|
||||
use primitives::{
|
||||
Hash,
|
||||
block::{Extrinsic, ExtrinsicHash},
|
||||
};
|
||||
|
||||
/// Extrinsic pool error.
|
||||
pub trait Error: ::std::error::Error + Send + Sized {
|
||||
@@ -38,18 +35,19 @@ impl Error for txpool::Error {
|
||||
}
|
||||
|
||||
/// Extrinsic pool.
|
||||
pub trait ExtrinsicPool: Send + Sync + 'static {
|
||||
pub trait ExtrinsicPool<Ex, Hash>: Send + Sync + 'static {
|
||||
/// Error type
|
||||
type Error: Error;
|
||||
|
||||
/// Submit a collection of extrinsics to the pool.
|
||||
fn submit(&self, xt: Vec<Extrinsic>) -> Result<Vec<ExtrinsicHash>, Self::Error>;
|
||||
fn submit(&self, xt: Vec<Ex>) -> Result<Vec<Hash>, Self::Error>;
|
||||
}
|
||||
|
||||
// Blanket implementation for anything that `Derefs` to the pool.
|
||||
impl<V, S, E, T> ExtrinsicPool for T where
|
||||
T: Deref<Target=super::Pool<V, S, E>> + Send + Sync + 'static,
|
||||
V: txpool::Verifier<Extrinsic>,
|
||||
impl<Ex, Hash, V, S, E, T> ExtrinsicPool<Ex, Hash> for T where
|
||||
Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
|
||||
T: Deref<Target=super::Pool<Ex, Hash, V, S, E>> + Send + Sync + 'static,
|
||||
V: txpool::Verifier<Ex>,
|
||||
S: txpool::Scoring<V::VerifiedTransaction>,
|
||||
V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>,
|
||||
E: From<V::Error>,
|
||||
@@ -58,7 +56,7 @@ impl<V, S, E, T> ExtrinsicPool for T where
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn submit(&self, xt: Vec<Extrinsic>) -> Result<Vec<ExtrinsicHash>, Self::Error> {
|
||||
fn submit(&self, xt: Vec<Ex>) -> Result<Vec<Hash>, Self::Error> {
|
||||
self.deref().submit(xt).map(|result| result.into_iter().map(|xt| *xt.hash()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
extern crate futures;
|
||||
extern crate parking_lot;
|
||||
extern crate substrate_primitives as primitives;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@@ -16,29 +16,29 @@
|
||||
|
||||
use std::{
|
||||
sync::Arc,
|
||||
fmt,
|
||||
collections::HashMap,
|
||||
};
|
||||
use primitives::Hash;
|
||||
use txpool;
|
||||
|
||||
use watcher;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Listener {
|
||||
watchers: HashMap<Hash, watcher::Sender>
|
||||
pub struct Listener<H: ::std::hash::Hash + Eq> {
|
||||
watchers: HashMap<H, watcher::Sender<H>>
|
||||
}
|
||||
|
||||
impl Listener {
|
||||
pub fn create_watcher<T: txpool::VerifiedTransaction<Hash=Hash>>(&mut self, xt: Arc<T>) -> watcher::Watcher {
|
||||
impl<H: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default> Listener<H> {
|
||||
pub fn create_watcher<T: txpool::VerifiedTransaction<Hash=H>>(&mut self, xt: Arc<T>) -> watcher::Watcher<H> {
|
||||
let sender = self.watchers.entry(*xt.hash()).or_insert_with(watcher::Sender::default);
|
||||
sender.new_watcher()
|
||||
}
|
||||
|
||||
pub fn broadcasted(&mut self, hash: &Hash, peers: Vec<String>) {
|
||||
pub fn broadcasted(&mut self, hash: &H, peers: Vec<String>) {
|
||||
self.fire(hash, |watcher| watcher.broadcast(peers));
|
||||
}
|
||||
|
||||
fn fire<F: FnOnce(&mut watcher::Sender)>(&mut self, hash: &Hash, fun: F) {
|
||||
fn fire<F>(&mut self, hash: &H, fun: F) where F: FnOnce(&mut watcher::Sender<H>) {
|
||||
let clean = if let Some(h) = self.watchers.get_mut(hash) {
|
||||
fun(h);
|
||||
h.is_done()
|
||||
@@ -52,7 +52,10 @@ impl Listener {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: txpool::VerifiedTransaction<Hash=Hash>> txpool::Listener<T> for Listener {
|
||||
impl<H, T> txpool::Listener<T> for Listener<H> where
|
||||
H: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
|
||||
T: txpool::VerifiedTransaction<Hash=H>,
|
||||
{
|
||||
fn added(&mut self, tx: &Arc<T>, old: Option<&Arc<T>>) {
|
||||
if let Some(old) = old {
|
||||
let hash = tx.hash();
|
||||
@@ -81,9 +84,7 @@ impl<T: txpool::VerifiedTransaction<Hash=Hash>> txpool::Listener<T> for Listener
|
||||
|
||||
fn mined(&mut self, tx: &Arc<T>) {
|
||||
// TODO [ToDr] latest block number?
|
||||
let header_hash = 1.into();
|
||||
let header_hash = Default::default();
|
||||
self.fire(tx.hash(), |watcher| watcher.finalised(header_hash))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
@@ -23,28 +24,29 @@ use std::{
|
||||
use futures::sync::mpsc;
|
||||
use parking_lot::{RwLock, Mutex};
|
||||
use txpool;
|
||||
use primitives::{Hash, block::Extrinsic};
|
||||
|
||||
use listener::Listener;
|
||||
use watcher::Watcher;
|
||||
|
||||
/// Extrinsics pool.
|
||||
pub struct Pool<V, S, E> where
|
||||
V: txpool::Verifier<Extrinsic>,
|
||||
pub struct Pool<Ex, Hash, V, S, E> where
|
||||
Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex,
|
||||
V: txpool::Verifier<Ex>,
|
||||
S: txpool::Scoring<V::VerifiedTransaction>,
|
||||
{
|
||||
_error: Mutex<PhantomData<E>>,
|
||||
pool: RwLock<txpool::Pool<
|
||||
V::VerifiedTransaction,
|
||||
S,
|
||||
Listener,
|
||||
Listener<Hash>,
|
||||
>>,
|
||||
verifier: V,
|
||||
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<Weak<V::VerifiedTransaction>>>>,
|
||||
}
|
||||
|
||||
impl<V, S, E> Pool<V, S, E> where
|
||||
V: txpool::Verifier<Extrinsic>,
|
||||
impl<Ex, Hash, V, S, E> Pool<Ex, Hash, V, S, E> where
|
||||
Hash: ::std::hash::Hash + Eq + Copy + fmt::Debug + fmt::LowerHex + Default,
|
||||
V: txpool::Verifier<Ex>,
|
||||
S: txpool::Scoring<V::VerifiedTransaction>,
|
||||
V::VerifiedTransaction: txpool::VerifiedTransaction<Hash=Hash>,
|
||||
E: From<V::Error>,
|
||||
@@ -86,7 +88,7 @@ impl<V, S, E> Pool<V, S, E> where
|
||||
}
|
||||
|
||||
/// Imports a bunch of extrinsics to the pool
|
||||
pub fn submit(&self, xts: Vec<Extrinsic>) -> Result<Vec<Arc<V::VerifiedTransaction>>, E> {
|
||||
pub fn submit(&self, xts: Vec<Ex>) -> Result<Vec<Arc<V::VerifiedTransaction>>, E> {
|
||||
xts
|
||||
.into_iter()
|
||||
.map(|xt| self.verifier.verify_transaction(xt))
|
||||
@@ -97,7 +99,7 @@ impl<V, S, E> Pool<V, S, E> where
|
||||
}
|
||||
|
||||
/// Import a single extrinsic and starts to watch their progress in the pool.
|
||||
pub fn submit_and_watch(&self, xt: Extrinsic) -> Result<Watcher, E> {
|
||||
pub fn submit_and_watch(&self, xt: Ex) -> Result<Watcher<Hash>, E> {
|
||||
let xt = self.submit(vec![xt])?.pop().expect("One extrinsic passed; one result returned; qed");
|
||||
Ok(self.pool.write().listener_mut().create_watcher(xt))
|
||||
}
|
||||
@@ -122,7 +124,7 @@ impl<V, S, E> Pool<V, S, E> where
|
||||
/// Cull transactions from the queue and then compute the pending set.
|
||||
pub fn cull_and_get_pending<R, F, T>(&self, ready: R, f: F) -> T where
|
||||
R: txpool::Ready<V::VerifiedTransaction> + Clone,
|
||||
F: FnOnce(txpool::PendingIterator<V::VerifiedTransaction, R, S, Listener>) -> T,
|
||||
F: FnOnce(txpool::PendingIterator<V::VerifiedTransaction, R, S, Listener<Hash>>) -> T,
|
||||
{
|
||||
let mut pool = self.pool.write();
|
||||
pool.cull(None, ready.clone());
|
||||
|
||||
@@ -15,17 +15,14 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use futures::sync::mpsc;
|
||||
use primitives::{
|
||||
block::{HeaderHash, ExtrinsicHash}
|
||||
};
|
||||
|
||||
/// Possible extrinsic status events
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Status {
|
||||
pub enum Status<H> {
|
||||
/// Extrinsic has been finalised in block with given hash.
|
||||
Finalised(HeaderHash),
|
||||
Finalised(H),
|
||||
/// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid.
|
||||
Usurped(ExtrinsicHash),
|
||||
Usurped(H),
|
||||
/// The extrinsic has been broadcast to the given peers.
|
||||
Broadcast(Vec<String>),
|
||||
/// Extrinsic has been dropped from the pool because of the limit.
|
||||
@@ -36,19 +33,19 @@ pub enum Status {
|
||||
///
|
||||
/// Represents a stream of status updates for particular extrinsic.
|
||||
#[derive(Debug)]
|
||||
pub struct Watcher {
|
||||
receiver: mpsc::UnboundedReceiver<Status>,
|
||||
pub struct Watcher<H> {
|
||||
receiver: mpsc::UnboundedReceiver<Status<H>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct Sender {
|
||||
receivers: Vec<mpsc::UnboundedSender<Status>>,
|
||||
pub(crate) struct Sender<H> {
|
||||
receivers: Vec<mpsc::UnboundedSender<Status<H>>>,
|
||||
finalised: bool,
|
||||
}
|
||||
|
||||
impl Sender {
|
||||
impl<H: Clone> Sender<H> {
|
||||
/// Add a new watcher to this sender object.
|
||||
pub fn new_watcher(&mut self) -> Watcher {
|
||||
pub fn new_watcher(&mut self) -> Watcher<H> {
|
||||
let (tx, receiver) = mpsc::unbounded();
|
||||
self.receivers.push(tx);
|
||||
Watcher {
|
||||
@@ -57,12 +54,12 @@ impl Sender {
|
||||
}
|
||||
|
||||
/// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid.
|
||||
pub fn usurped(&mut self, hash: ExtrinsicHash) {
|
||||
pub fn usurped(&mut self, hash: H) {
|
||||
self.send(Status::Usurped(hash))
|
||||
}
|
||||
|
||||
/// Extrinsic has been finalised in block with given hash.
|
||||
pub fn finalised(&mut self, hash: HeaderHash) {
|
||||
pub fn finalised(&mut self, hash: H) {
|
||||
self.send(Status::Finalised(hash));
|
||||
self.finalised = true;
|
||||
}
|
||||
@@ -82,7 +79,7 @@ impl Sender {
|
||||
self.finalised || self.receivers.is_empty()
|
||||
}
|
||||
|
||||
fn send(&mut self, status: Status) {
|
||||
fn send(&mut self, status: Status<H>) {
|
||||
self.receivers.retain(|sender| sender.unbounded_send(status.clone()).is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
substrate-codec = { path = "../codec", default-features = false }
|
||||
substrate-primitives = { path = "../primitives", default-features = false }
|
||||
substrate-runtime-primitives = { path = "../runtime/primitives", default-features = false }
|
||||
substrate-runtime-io = { path = "../runtime-io", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
@@ -14,4 +15,4 @@ substrate-keyring = { path = "../keyring" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["substrate-codec/std", "substrate-primitives/std", "substrate-runtime-io/std"]
|
||||
std = ["substrate-codec/std", "substrate-primitives/std", "substrate-runtime-primitives/std", "substrate-runtime-io/std"]
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate substrate_bft;
|
||||
@@ -29,23 +30,27 @@ extern crate substrate_keyring as keyring;
|
||||
|
||||
use codec::Slicable;
|
||||
use primitives::{AuthorityId, Signature};
|
||||
use primitives::block::HeaderHash;
|
||||
use primitives::bft::{Action, Message, MisbehaviorKind};
|
||||
|
||||
use runtime_primitives::bft::{Action, Message, MisbehaviorKind};
|
||||
|
||||
// check a message signature. returns true if signed by that authority.
|
||||
fn check_message_sig(message: Message, signature: &Signature, from: &AuthorityId) -> bool {
|
||||
let msg = message.encode();
|
||||
fn check_message_sig<B: Slicable, H: Slicable>(
|
||||
message: Message<B, H>,
|
||||
signature: &Signature,
|
||||
from: &AuthorityId
|
||||
) -> bool {
|
||||
let msg: Vec<u8> = message.encode();
|
||||
runtime_io::ed25519_verify(&signature.0, &msg, from)
|
||||
}
|
||||
|
||||
fn prepare(parent: HeaderHash, round_number: u32, hash: HeaderHash) -> Message {
|
||||
fn prepare<B, H>(parent: H, round_number: u32, hash: H) -> Message<B, H> {
|
||||
Message {
|
||||
parent,
|
||||
action: Action::Prepare(round_number, hash),
|
||||
}
|
||||
}
|
||||
|
||||
fn commit(parent: HeaderHash, round_number: u32, hash: HeaderHash) -> Message {
|
||||
fn commit<B, H>(parent: H, round_number: u32, hash: H) -> Message<B, H> {
|
||||
Message {
|
||||
parent,
|
||||
action: Action::Commit(round_number, hash),
|
||||
@@ -57,21 +62,21 @@ fn commit(parent: HeaderHash, round_number: u32, hash: HeaderHash) -> Message {
|
||||
/// Doesn't check that the header hash in question is
|
||||
/// valid or whether the misbehaving authority was part of
|
||||
/// the set at that block.
|
||||
pub fn evaluate_misbehavior(
|
||||
pub fn evaluate_misbehavior<B: Slicable, H: Slicable + Copy>(
|
||||
misbehaved: &AuthorityId,
|
||||
parent_hash: HeaderHash,
|
||||
kind: &MisbehaviorKind,
|
||||
parent_hash: H,
|
||||
kind: &MisbehaviorKind<H>,
|
||||
) -> bool {
|
||||
match *kind {
|
||||
MisbehaviorKind::BftDoublePrepare(round, (h_1, ref s_1), (h_2, ref s_2)) => {
|
||||
s_1 != s_2 &&
|
||||
check_message_sig(prepare(parent_hash, round, h_1), s_1, misbehaved) &&
|
||||
check_message_sig(prepare(parent_hash, round, h_2), s_2, misbehaved)
|
||||
check_message_sig::<B, H>(prepare::<B, H>(parent_hash, round, h_1), s_1, misbehaved) &&
|
||||
check_message_sig::<B, H>(prepare::<B, H>(parent_hash, round, h_2), s_2, misbehaved)
|
||||
}
|
||||
MisbehaviorKind::BftDoubleCommit(round, (h_1, ref s_1), (h_2, ref s_2)) => {
|
||||
s_1 != s_2 &&
|
||||
check_message_sig(commit(parent_hash, round, h_1), s_1, misbehaved) &&
|
||||
check_message_sig(commit(parent_hash, round, h_2), s_2, misbehaved)
|
||||
check_message_sig::<B, H>(commit::<B, H>(parent_hash, round, h_1), s_1, misbehaved) &&
|
||||
check_message_sig::<B, H>(commit::<B, H>(parent_hash, round, h_2), s_2, misbehaved)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,8 +89,12 @@ mod tests {
|
||||
use keyring::ed25519;
|
||||
use keyring::Keyring;
|
||||
|
||||
fn sign_prepare(key: &ed25519::Pair, round: u32, hash: HeaderHash, parent_hash: HeaderHash) -> (HeaderHash, Signature) {
|
||||
let msg = substrate_bft::sign_message(
|
||||
use runtime_primitives::testing::{H256, Block as RawBlock};
|
||||
|
||||
type Block = RawBlock<u64>;
|
||||
|
||||
fn sign_prepare(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
|
||||
let msg = substrate_bft::sign_message::<Block>(
|
||||
generic::Message::Vote(generic::Vote::Prepare(round as _, hash)),
|
||||
key,
|
||||
parent_hash
|
||||
@@ -97,8 +106,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_commit(key: &ed25519::Pair, round: u32, hash: HeaderHash, parent_hash: HeaderHash) -> (HeaderHash, Signature) {
|
||||
let msg = substrate_bft::sign_message(
|
||||
fn sign_commit(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
|
||||
let msg = substrate_bft::sign_message::<Block>(
|
||||
generic::Message::Vote(generic::Vote::Commit(round as _, hash)),
|
||||
key,
|
||||
parent_hash
|
||||
@@ -117,7 +126,7 @@ mod tests {
|
||||
let hash_1 = [0; 32].into();
|
||||
let hash_2 = [1; 32].into();
|
||||
|
||||
assert!(evaluate_misbehavior(
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().0,
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoublePrepare(
|
||||
@@ -129,7 +138,7 @@ mod tests {
|
||||
|
||||
// same signature twice is not misbehavior.
|
||||
let signed = sign_prepare(&key, 1, hash_1, parent_hash);
|
||||
assert!(evaluate_misbehavior(
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().0,
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoublePrepare(
|
||||
@@ -140,7 +149,7 @@ mod tests {
|
||||
) == false);
|
||||
|
||||
// misbehavior has wrong target.
|
||||
assert!(evaluate_misbehavior(
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&Keyring::Two.to_raw_public(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoublePrepare(
|
||||
@@ -158,7 +167,7 @@ mod tests {
|
||||
let hash_1 = [0; 32].into();
|
||||
let hash_2 = [1; 32].into();
|
||||
|
||||
assert!(evaluate_misbehavior(
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().0,
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoubleCommit(
|
||||
@@ -170,7 +179,7 @@ mod tests {
|
||||
|
||||
// same signature twice is not misbehavior.
|
||||
let signed = sign_commit(&key, 1, hash_1, parent_hash);
|
||||
assert!(evaluate_misbehavior(
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().0,
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoubleCommit(
|
||||
@@ -181,7 +190,7 @@ mod tests {
|
||||
) == false);
|
||||
|
||||
// misbehavior has wrong target.
|
||||
assert!(evaluate_misbehavior(
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&Keyring::Two.to_raw_public(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoubleCommit(
|
||||
|
||||
@@ -27,6 +27,7 @@ substrate-client = { path = "../../substrate/client" }
|
||||
substrate-state-machine = { path = "../../substrate/state-machine" }
|
||||
substrate-serializer = { path = "../../substrate/serializer" }
|
||||
substrate-runtime-support = { path = "../../substrate/runtime-support" }
|
||||
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
|
||||
substrate-bft = { path = "../../substrate/bft" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -20,47 +20,47 @@ use std::ops::Range;
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::collections::hash_map::Entry;
|
||||
use network::PeerId;
|
||||
use primitives::block::Number as BlockNumber;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use message;
|
||||
|
||||
const MAX_PARALLEL_DOWNLOADS: u32 = 1;
|
||||
|
||||
/// Block data with origin.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlockData {
|
||||
pub block: message::BlockData,
|
||||
pub struct BlockData<B: BlockT> {
|
||||
pub block: message::BlockData<B>,
|
||||
pub origin: PeerId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum BlockRangeState {
|
||||
enum BlockRangeState<B: BlockT> {
|
||||
Downloading {
|
||||
len: BlockNumber,
|
||||
len: u64,
|
||||
downloading: u32,
|
||||
},
|
||||
Complete(Vec<BlockData>),
|
||||
Complete(Vec<BlockData<B>>),
|
||||
}
|
||||
|
||||
impl BlockRangeState {
|
||||
pub fn len(&self) -> BlockNumber {
|
||||
impl<B: BlockT> BlockRangeState<B> where B::Header: HeaderT<Number=u64> {
|
||||
pub fn len(&self) -> u64 {
|
||||
match *self {
|
||||
BlockRangeState::Downloading { len, .. } => len,
|
||||
BlockRangeState::Complete(ref blocks) => blocks.len() as BlockNumber,
|
||||
BlockRangeState::Complete(ref blocks) => blocks.len() as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of blocks being downloaded.
|
||||
#[derive(Default)]
|
||||
pub struct BlockCollection {
|
||||
pub struct BlockCollection<B: BlockT> {
|
||||
/// Downloaded blocks.
|
||||
blocks: BTreeMap<BlockNumber, BlockRangeState>,
|
||||
peer_requests: HashMap<PeerId, BlockNumber>,
|
||||
blocks: BTreeMap<u64, BlockRangeState<B>>,
|
||||
peer_requests: HashMap<PeerId, u64>,
|
||||
}
|
||||
|
||||
impl BlockCollection {
|
||||
impl<B: BlockT> BlockCollection<B> where B::Header: HeaderT<Number=u64> {
|
||||
/// Create a new instance.
|
||||
pub fn new() -> BlockCollection {
|
||||
pub fn new() -> Self {
|
||||
BlockCollection {
|
||||
blocks: BTreeMap::new(),
|
||||
peer_requests: HashMap::new(),
|
||||
@@ -74,7 +74,7 @@ impl BlockCollection {
|
||||
}
|
||||
|
||||
/// Insert a set of blocks into collection.
|
||||
pub fn insert(&mut self, start: BlockNumber, blocks: Vec<message::BlockData>, peer_id: PeerId) {
|
||||
pub fn insert(&mut self, start: u64, blocks: Vec<message::BlockData<B>>, peer_id: PeerId) {
|
||||
if blocks.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -96,13 +96,13 @@ impl BlockCollection {
|
||||
}
|
||||
|
||||
/// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded.
|
||||
pub fn needed_blocks(&mut self, peer_id: PeerId, count: usize, peer_best: BlockNumber, common: BlockNumber) -> Option<Range<BlockNumber>> {
|
||||
pub fn needed_blocks(&mut self, peer_id: PeerId, count: usize, peer_best: u64, common: u64) -> Option<Range<u64>> {
|
||||
// First block number that we need to download
|
||||
let first_different = common + 1;
|
||||
let count = count as BlockNumber;
|
||||
let count = count as u64;
|
||||
let (mut range, downloading) = {
|
||||
let mut downloading_iter = self.blocks.iter().peekable();
|
||||
let mut prev: Option<(&BlockNumber, &BlockRangeState)> = None;
|
||||
let mut prev: Option<(&u64, &BlockRangeState<B>)> = None;
|
||||
loop {
|
||||
let next = downloading_iter.next();
|
||||
break match &(prev, next) {
|
||||
@@ -137,7 +137,7 @@ impl BlockCollection {
|
||||
}
|
||||
|
||||
/// Get a valid chain of blocks ordered in descending order and ready for importing into blockchain.
|
||||
pub fn drain(&mut self, from: BlockNumber) -> Vec<BlockData> {
|
||||
pub fn drain(&mut self, from: u64) -> Vec<BlockData<B>> {
|
||||
let mut drained = Vec::new();
|
||||
let mut ranges = Vec::new();
|
||||
{
|
||||
@@ -145,7 +145,7 @@ impl BlockCollection {
|
||||
for (start, range_data) in &mut self.blocks {
|
||||
match range_data {
|
||||
&mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => {
|
||||
prev = *start + blocks.len() as BlockNumber;
|
||||
prev = *start + blocks.len() as u64;
|
||||
let mut blocks = mem::replace(blocks, Vec::new());
|
||||
drained.append(&mut blocks);
|
||||
ranges.push(*start);
|
||||
@@ -191,16 +191,19 @@ impl BlockCollection {
|
||||
mod test {
|
||||
use super::{BlockCollection, BlockData};
|
||||
use message;
|
||||
use primitives::block::HeaderHash;
|
||||
use runtime_primitives::testing::Block as RawBlock;
|
||||
use primitives::H256;
|
||||
|
||||
fn is_empty(bc: &BlockCollection) -> bool {
|
||||
type Block = RawBlock<u64>;
|
||||
|
||||
fn is_empty(bc: &BlockCollection<Block>) -> bool {
|
||||
bc.blocks.is_empty() &&
|
||||
bc.peer_requests.is_empty()
|
||||
}
|
||||
|
||||
fn generate_blocks(n: usize) -> Vec<message::BlockData> {
|
||||
(0 .. n).map(|_| message::BlockData {
|
||||
hash: HeaderHash::random(),
|
||||
fn generate_blocks(n: usize) -> Vec<message::BlockData<Block>> {
|
||||
(0 .. n).map(|_| message::generic::BlockData {
|
||||
hash: H256::random(),
|
||||
header: None,
|
||||
body: None,
|
||||
message_queue: None,
|
||||
|
||||
@@ -19,72 +19,74 @@
|
||||
use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus, BlockOrigin, CallExecutor};
|
||||
use client::error::Error;
|
||||
use state_machine;
|
||||
use primitives::block::{self, Id as BlockId};
|
||||
use primitives::bft::Justification;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::bft::Justification;
|
||||
|
||||
pub trait Client: Send + Sync {
|
||||
pub trait Client<Block: BlockT>: Send + Sync {
|
||||
/// Import a new block. Parent is supposed to be existing in the blockchain.
|
||||
fn import(&self, is_best: bool, header: block::Header, justification: Justification, body: Option<block::Body>) -> Result<ImportResult, Error>;
|
||||
fn import(&self, is_best: bool, header: Block::Header, justification: Justification<Block::Hash>, body: Option<Vec<Block::Extrinsic>>) -> Result<ImportResult, Error>;
|
||||
|
||||
/// Get blockchain info.
|
||||
fn info(&self) -> Result<ClientInfo, Error>;
|
||||
fn info(&self) -> Result<ClientInfo<Block>, Error>;
|
||||
|
||||
/// Get block status.
|
||||
fn block_status(&self, id: &BlockId) -> Result<BlockStatus, Error>;
|
||||
fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error>;
|
||||
|
||||
/// Get block hash by number.
|
||||
fn block_hash(&self, block_number: block::Number) -> Result<Option<block::HeaderHash>, Error>;
|
||||
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error>;
|
||||
|
||||
/// Get block header.
|
||||
fn header(&self, id: &BlockId) -> Result<Option<block::Header>, Error>;
|
||||
fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error>;
|
||||
|
||||
/// Get block body.
|
||||
fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error>;
|
||||
fn body(&self, id: &BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, Error>;
|
||||
|
||||
/// Get block justification.
|
||||
fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error>;
|
||||
fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, Error>;
|
||||
|
||||
/// Get method execution proof.
|
||||
fn execution_proof(&self, block: &block::HeaderHash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error>;
|
||||
fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error>;
|
||||
}
|
||||
|
||||
impl<B, E> Client for PolkadotClient<B, E> where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: CallExecutor + Send + Sync + 'static,
|
||||
Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>, {
|
||||
impl<B, E, Block> Client<Block> for PolkadotClient<B, E, Block> where
|
||||
B: client::backend::Backend<Block> + Send + Sync + 'static,
|
||||
E: CallExecutor<Block> + Send + Sync + 'static,
|
||||
Block: BlockT,
|
||||
Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>, {
|
||||
|
||||
fn import(&self, is_best: bool, header: block::Header, justification: Justification, body: Option<block::Body>) -> Result<ImportResult, Error> {
|
||||
fn import(&self, is_best: bool, header: Block::Header, justification: Justification<Block::Hash>, body: Option<Vec<Block::Extrinsic>>) -> Result<ImportResult, Error> {
|
||||
// TODO: defer justification check.
|
||||
let justified_header = self.check_justification(header, justification.into())?;
|
||||
let origin = if is_best { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync };
|
||||
(self as &PolkadotClient<B, E>).import_block(origin, justified_header, body)
|
||||
(self as &PolkadotClient<B, E, Block>).import_block(origin, justified_header, body)
|
||||
}
|
||||
|
||||
fn info(&self) -> Result<ClientInfo, Error> {
|
||||
(self as &PolkadotClient<B, E>).info()
|
||||
fn info(&self) -> Result<ClientInfo<Block>, Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).info()
|
||||
}
|
||||
|
||||
fn block_status(&self, id: &BlockId) -> Result<BlockStatus, Error> {
|
||||
(self as &PolkadotClient<B, E>).block_status(id)
|
||||
fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).block_status(id)
|
||||
}
|
||||
|
||||
fn block_hash(&self, block_number: block::Number) -> Result<Option<block::HeaderHash>, Error> {
|
||||
(self as &PolkadotClient<B, E>).block_hash(block_number)
|
||||
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).block_hash(block_number)
|
||||
}
|
||||
|
||||
fn header(&self, id: &BlockId) -> Result<Option<block::Header>, Error> {
|
||||
(self as &PolkadotClient<B, E>).header(id)
|
||||
fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).header(id)
|
||||
}
|
||||
|
||||
fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error> {
|
||||
(self as &PolkadotClient<B, E>).body(id)
|
||||
fn body(&self, id: &BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).body(id)
|
||||
}
|
||||
|
||||
fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error> {
|
||||
(self as &PolkadotClient<B, E>).justification(id)
|
||||
fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification<Block::Hash>>, Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).justification(id)
|
||||
}
|
||||
|
||||
fn execution_proof(&self, block: &block::HeaderHash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error> {
|
||||
(self as &PolkadotClient<B, E>).execution_proof(&BlockId::Hash(block.clone()), method, data)
|
||||
fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error> {
|
||||
(self as &PolkadotClient<B, E, Block>).execution_proof(&BlockId::Hash(block.clone()), method, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,46 +17,35 @@
|
||||
//! Consensus related bits of the network service.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use futures::sync::{oneshot, mpsc};
|
||||
use futures::sync::mpsc;
|
||||
use std::time::{Instant, Duration};
|
||||
use io::SyncIo;
|
||||
use protocol::Protocol;
|
||||
use network::PeerId;
|
||||
use primitives::{Hash, block::Id as BlockId, block::Header};
|
||||
use message::{self, Message};
|
||||
use runtime_support::Hashable;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use message::{self, generic::Message as GenericMessage};
|
||||
|
||||
// TODO: Add additional spam/DoS attack protection.
|
||||
const MESSAGE_LIFETIME: Duration = Duration::from_secs(600);
|
||||
|
||||
struct CandidateRequest {
|
||||
id: message::RequestId,
|
||||
completion: oneshot::Sender<Vec<u8>>,
|
||||
}
|
||||
|
||||
struct PeerConsensus {
|
||||
candidate_fetch: Option<CandidateRequest>,
|
||||
candidate_available: Option<Hash>,
|
||||
known_messages: HashSet<Hash>,
|
||||
struct PeerConsensus<H> {
|
||||
known_messages: HashSet<H>,
|
||||
}
|
||||
|
||||
/// Consensus network protocol handler. Manages statements and candidate requests.
|
||||
pub struct Consensus {
|
||||
peers: HashMap<PeerId, PeerConsensus>,
|
||||
our_candidate: Option<(Hash, Vec<u8>)>,
|
||||
statement_sink: Option<mpsc::UnboundedSender<message::Statement>>,
|
||||
bft_message_sink: Option<(mpsc::UnboundedSender<message::LocalizedBftMessage>, Hash)>,
|
||||
messages: Vec<(Hash, Instant, message::Message)>,
|
||||
message_hashes: HashSet<Hash>,
|
||||
pub struct Consensus<B: BlockT> {
|
||||
peers: HashMap<PeerId, PeerConsensus<B::Hash>>,
|
||||
bft_message_sink: Option<(mpsc::UnboundedSender<message::LocalizedBftMessage<B>>, B::Hash)>,
|
||||
messages: Vec<(B::Hash, Instant, message::Message<B>)>,
|
||||
message_hashes: HashSet<B::Hash>,
|
||||
}
|
||||
|
||||
impl Consensus {
|
||||
impl<B: BlockT> Consensus<B> where B::Header: HeaderT<Number=u64> {
|
||||
/// Create a new instance.
|
||||
pub fn new() -> Consensus {
|
||||
pub fn new() -> Self {
|
||||
Consensus {
|
||||
peers: HashMap::new(),
|
||||
our_candidate: None,
|
||||
statement_sink: None,
|
||||
bft_message_sink: None,
|
||||
messages: Default::default(),
|
||||
message_hashes: Default::default(),
|
||||
@@ -65,12 +54,11 @@ impl Consensus {
|
||||
|
||||
/// Closes all notification streams.
|
||||
pub fn restart(&mut self) {
|
||||
self.statement_sink = None;
|
||||
self.bft_message_sink = None;
|
||||
}
|
||||
|
||||
/// Handle new connected peer.
|
||||
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, roles: &[message::Role]) {
|
||||
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, roles: &[message::Role]) {
|
||||
if roles.iter().any(|r| *r == message::Role::Validator) {
|
||||
trace!(target:"sync", "Registering validator {}", peer_id);
|
||||
// Send out all known messages.
|
||||
@@ -81,14 +69,12 @@ impl Consensus {
|
||||
protocol.send_message(io, peer_id, message.clone());
|
||||
}
|
||||
self.peers.insert(peer_id, PeerConsensus {
|
||||
candidate_fetch: None,
|
||||
candidate_available: None,
|
||||
known_messages,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::Message, hash: Hash) {
|
||||
fn propagate(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, message: message::Message<B>, hash: B::Hash) {
|
||||
for (id, ref mut peer) in self.peers.iter_mut() {
|
||||
if peer.known_messages.insert(hash.clone()) {
|
||||
protocol.send_message(io, *id, message.clone());
|
||||
@@ -96,48 +82,13 @@ impl Consensus {
|
||||
}
|
||||
}
|
||||
|
||||
fn register_message(&mut self, hash: Hash, message: message::Message) {
|
||||
fn register_message(&mut self, hash: B::Hash, message: message::Message<B>) {
|
||||
if self.message_hashes.insert(hash) {
|
||||
self.messages.push((hash, Instant::now(), message));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, statement: message::Statement, hash: Hash) {
|
||||
if self.message_hashes.contains(&hash) {
|
||||
trace!(target:"sync", "Ignored already known statement from {}", peer_id);
|
||||
}
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
// TODO: validate signature?
|
||||
match &statement.statement {
|
||||
&message::UnsignedStatement::Candidate(ref receipt) => peer.candidate_available = Some(Hash::from(receipt.blake2_256())),
|
||||
&message::UnsignedStatement::Available(ref hash) => peer.candidate_available = Some(*hash),
|
||||
&message::UnsignedStatement::Valid(_) | &message::UnsignedStatement::Invalid(_) => (),
|
||||
}
|
||||
peer.known_messages.insert(hash);
|
||||
if let Some(sink) = self.statement_sink.take() {
|
||||
if let Err(e) = sink.unbounded_send(statement.clone()) {
|
||||
trace!(target:"sync", "Error broadcasting statement notification: {:?}", e);
|
||||
} else {
|
||||
self.statement_sink = Some(sink);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trace!(target:"sync", "Ignored statement from unregistered peer {}", peer_id);
|
||||
return;
|
||||
}
|
||||
let message = Message::Statement(statement);
|
||||
self.register_message(hash.clone(), message.clone());
|
||||
// Propagate to other peers.
|
||||
self.propagate(io, protocol, message, hash);
|
||||
}
|
||||
|
||||
pub fn statements(&mut self) -> mpsc::UnboundedReceiver<message::Statement>{
|
||||
let (sink, stream) = mpsc::unbounded();
|
||||
self.statement_sink = Some(sink);
|
||||
stream
|
||||
}
|
||||
|
||||
pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::LocalizedBftMessage, hash: Hash) {
|
||||
pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, message: message::LocalizedBftMessage<B>, hash: B::Hash) {
|
||||
if self.message_hashes.contains(&hash) {
|
||||
trace!(target:"sync", "Ignored already known BFT message from {}", peer_id);
|
||||
return;
|
||||
@@ -149,7 +100,7 @@ impl Consensus {
|
||||
return;
|
||||
},
|
||||
(Ok(info), Ok(Some(header))) => {
|
||||
if header.number < info.chain.best_number {
|
||||
if header.number() < &info.chain.best_number {
|
||||
trace!(target:"sync", "Ignored ancient BFT message from {}, hash={}", peer_id, message.parent_hash);
|
||||
return;
|
||||
}
|
||||
@@ -174,18 +125,18 @@ impl Consensus {
|
||||
return;
|
||||
}
|
||||
|
||||
let message = Message::BftMessage(message);
|
||||
let message = GenericMessage::BftMessage(message);
|
||||
self.register_message(hash.clone(), message.clone());
|
||||
// Propagate to other peers.
|
||||
self.propagate(io, protocol, message, hash);
|
||||
}
|
||||
|
||||
pub fn bft_messages(&mut self, parent_hash: Hash) -> mpsc::UnboundedReceiver<message::LocalizedBftMessage>{
|
||||
pub fn bft_messages(&mut self, parent_hash: B::Hash) -> mpsc::UnboundedReceiver<message::LocalizedBftMessage<B>> {
|
||||
let (sink, stream) = mpsc::unbounded();
|
||||
|
||||
for &(_, _, ref message) in self.messages.iter() {
|
||||
let bft_message = match *message {
|
||||
Message::BftMessage(ref msg) => msg,
|
||||
GenericMessage::BftMessage(ref msg) => msg,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
@@ -198,90 +149,20 @@ impl Consensus {
|
||||
stream
|
||||
}
|
||||
|
||||
pub fn fetch_candidate(&mut self, io: &mut SyncIo, protocol: &Protocol, hash: &Hash) -> oneshot::Receiver<Vec<u8>> {
|
||||
// Request from the first peer that has it available.
|
||||
// TODO: random peer selection.
|
||||
trace!(target:"sync", "Trying to fetch candidate {:?}", hash);
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
if let Some((peer_id, ref mut peer)) = self.peers.iter_mut()
|
||||
.find(|&(_, ref peer)| peer.candidate_fetch.is_none() && peer.candidate_available.as_ref().map_or(false, |h| h == hash)) {
|
||||
|
||||
trace!(target:"sync", "Fetching candidate from {}", peer_id);
|
||||
let id = 0; //TODO: generate unique id
|
||||
peer.candidate_fetch = Some(CandidateRequest {
|
||||
id: id,
|
||||
completion: sender,
|
||||
});
|
||||
let request = message::CandidateRequest {
|
||||
id: id,
|
||||
hash: *hash,
|
||||
};
|
||||
protocol.send_message(io, *peer_id, Message::CandidateRequest(request));
|
||||
}
|
||||
// If no peer found `sender` is dropped and `receiver` is canceled immediatelly.
|
||||
return receiver;
|
||||
}
|
||||
|
||||
pub fn send_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, statement: message::Statement) {
|
||||
// Broadcast statement to all validators.
|
||||
trace!(target:"sync", "Broadcasting statement {:?}", statement);
|
||||
let message = Message::Statement(statement);
|
||||
let hash = Protocol::hash_message(&message);
|
||||
self.register_message(hash.clone(), message.clone());
|
||||
self.propagate(io, protocol, message, hash);
|
||||
}
|
||||
|
||||
pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::LocalizedBftMessage) {
|
||||
pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, message: message::LocalizedBftMessage<B>) {
|
||||
// Broadcast message to all validators.
|
||||
trace!(target:"sync", "Broadcasting BFT message {:?}", message);
|
||||
let message = Message::BftMessage(message);
|
||||
let message = GenericMessage::BftMessage(message);
|
||||
let hash = Protocol::hash_message(&message);
|
||||
self.register_message(hash.clone(), message.clone());
|
||||
self.propagate(io, protocol, message, hash);
|
||||
}
|
||||
|
||||
pub fn set_local_candidate(&mut self, candidate: Option<(Hash, Vec<u8>)>) {
|
||||
trace!(target:"sync", "Set local candidate to {:?}", candidate.as_ref().map(|&(h, _)| h));
|
||||
self.our_candidate = candidate;
|
||||
}
|
||||
|
||||
pub fn on_candidate_request(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, request: message::CandidateRequest) {
|
||||
let response = match self.our_candidate {
|
||||
Some((ref hash, ref data)) if *hash == request.hash => Some(data.clone()),
|
||||
_ => None,
|
||||
};
|
||||
let msg = message::CandidateResponse {
|
||||
id: request.id,
|
||||
data: response,
|
||||
};
|
||||
protocol.send_message(io, peer_id, Message::CandidateResponse(msg));
|
||||
}
|
||||
|
||||
pub fn on_candidate_response(&mut self, io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId, response: message::CandidateResponse) {
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
if let Some(request) = peer.candidate_fetch.take() {
|
||||
if response.id == request.id {
|
||||
if let Some(data) = response.data {
|
||||
if let Err(e) = request.completion.send(data) {
|
||||
trace!(target:"sync", "Error sending candidate data notification: {:?}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trace!(target:"sync", "Unexpected candidate response from {}", peer_id);
|
||||
io.disable_peer(peer_id);
|
||||
}
|
||||
} else {
|
||||
trace!(target:"sync", "Unexpected candidate response from {}", peer_id);
|
||||
io.disable_peer(peer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId) {
|
||||
pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol<B>, peer_id: PeerId) {
|
||||
self.peers.remove(&peer_id);
|
||||
}
|
||||
|
||||
pub fn collect_garbage(&mut self, best_header: Option<&Header>) {
|
||||
pub fn collect_garbage(&mut self, best_header: Option<&B::Header>) {
|
||||
let hashes = &mut self.message_hashes;
|
||||
let before = self.messages.len();
|
||||
let now = Instant::now();
|
||||
@@ -289,8 +170,7 @@ impl Consensus {
|
||||
if timestamp >= now - MESSAGE_LIFETIME &&
|
||||
best_header.map_or(true, |header|
|
||||
match *message {
|
||||
Message::BftMessage(ref msg) => msg.parent_hash != header.parent_hash,
|
||||
Message::Statement(ref msg) => msg.parent_hash != header.parent_hash,
|
||||
GenericMessage::BftMessage(ref msg) => &msg.parent_hash != header.parent_hash(),
|
||||
_ => true,
|
||||
})
|
||||
{
|
||||
@@ -311,32 +191,33 @@ impl Consensus {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use primitives::Hash;
|
||||
use primitives::bft::Justification;
|
||||
use primitives::block::{HeaderHash, Header};
|
||||
use runtime_primitives::bft::Justification;
|
||||
use runtime_primitives::testing::{H256, Header, Block as RawBlock};
|
||||
use std::time::Instant;
|
||||
use message::{self, Message};
|
||||
use message::{self, generic::Message as GenericMessage};
|
||||
use super::{Consensus, MESSAGE_LIFETIME};
|
||||
|
||||
type Block = RawBlock<u64>;
|
||||
|
||||
#[test]
|
||||
fn collects_garbage() {
|
||||
let prev_hash = HeaderHash::random();
|
||||
let best_hash = HeaderHash::random();
|
||||
let mut consensus = Consensus::new();
|
||||
let prev_hash = H256::random();
|
||||
let best_hash = H256::random();
|
||||
let mut consensus = Consensus::<Block>::new();
|
||||
let now = Instant::now();
|
||||
let m1_hash = Hash::random();
|
||||
let m2_hash = Hash::random();
|
||||
let m1 = Message::BftMessage(message::LocalizedBftMessage {
|
||||
let m1_hash = H256::random();
|
||||
let m2_hash = H256::random();
|
||||
let m1 = GenericMessage::BftMessage(message::LocalizedBftMessage {
|
||||
parent_hash: prev_hash,
|
||||
message: message::BftMessage::Auxiliary(Justification {
|
||||
message: message::generic::BftMessage::Auxiliary(Justification {
|
||||
round_number: 0,
|
||||
hash: Default::default(),
|
||||
signatures: Default::default(),
|
||||
}),
|
||||
});
|
||||
let m2 = Message::BftMessage(message::LocalizedBftMessage {
|
||||
let m2 = GenericMessage::BftMessage(message::LocalizedBftMessage {
|
||||
parent_hash: best_hash,
|
||||
message: message::BftMessage::Auxiliary(Justification {
|
||||
message: message::generic::BftMessage::Auxiliary(Justification {
|
||||
round_number: 0,
|
||||
hash: Default::default(),
|
||||
signatures: Default::default(),
|
||||
@@ -353,7 +234,14 @@ mod tests {
|
||||
assert_eq!(consensus.message_hashes.len(), 2);
|
||||
|
||||
// random header, nothing should be cleared
|
||||
let mut header = Header::from_block_number(0);
|
||||
let mut header = Header {
|
||||
parent_hash: H256::default(),
|
||||
number: 0,
|
||||
state_root: H256::default(),
|
||||
extrinsics_root: H256::default(),
|
||||
digest: Default::default(),
|
||||
};
|
||||
|
||||
consensus.collect_garbage(Some(&header));
|
||||
assert_eq!(consensus.messages.len(), 2);
|
||||
assert_eq!(consensus.message_hashes.len(), 2);
|
||||
|
||||
@@ -30,6 +30,7 @@ extern crate substrate_state_machine as state_machine;
|
||||
extern crate substrate_serializer as ser;
|
||||
extern crate substrate_client as client;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate substrate_bft;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
@@ -59,19 +60,12 @@ pub mod error;
|
||||
|
||||
#[cfg(test)] mod test;
|
||||
|
||||
pub use service::{Service, FetchFuture, StatementStream, ConsensusService, BftMessageStream,
|
||||
pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream,
|
||||
TransactionPool, Params, ManageNetwork, SyncProvider};
|
||||
pub use protocol::{ProtocolStatus};
|
||||
pub use sync::{Status as SyncStatus, SyncState};
|
||||
pub use network::{NonReservedPeerMode, NetworkConfiguration};
|
||||
pub use network_devp2p::{ConnectionFilter, ConnectionDirection};
|
||||
pub use message::{Statement, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal};
|
||||
pub use network::{NonReservedPeerMode, NetworkConfiguration, ConnectionFilter, ConnectionDirection};
|
||||
pub use message::{generic as generic_message, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal};
|
||||
pub use error::Error;
|
||||
pub use config::{Role, ProtocolConfig};
|
||||
pub use on_demand::{OnDemand, OnDemandService, Response as OnDemandResponse};
|
||||
|
||||
// TODO: move it elsewhere
|
||||
fn header_hash(header: &primitives::Header) -> primitives::block::HeaderHash {
|
||||
use runtime_support::Hashable;
|
||||
header.blake2_256().into()
|
||||
}
|
||||
|
||||
@@ -16,14 +16,74 @@
|
||||
|
||||
//! Network packet message types. These get serialized and put into the lower level protocol payload.
|
||||
|
||||
use primitives::{AuthorityId, Hash};
|
||||
use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body, Block};
|
||||
use primitives::bft::Justification;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use service::Role as RoleFlags;
|
||||
use ed25519;
|
||||
|
||||
pub use self::generic::{BlockAnnounce, RemoteCallRequest, ConsensusVote, SignedConsensusVote, FromBlock};
|
||||
|
||||
pub type RequestId = u64;
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
/// Type alias for using the message type using block type parameters.
|
||||
pub type Message<B> = generic::Message<
|
||||
B,
|
||||
<B as BlockT>::Header,
|
||||
<B as BlockT>::Hash,
|
||||
<<B as BlockT>::Header as HeaderT>::Number,
|
||||
<B as BlockT>::Extrinsic,
|
||||
>;
|
||||
|
||||
/// Type alias for using the status type using block type parameters.
|
||||
pub type Status<B> = generic::Status<
|
||||
<B as BlockT>::Hash,
|
||||
<<B as BlockT>::Header as HeaderT>::Number,
|
||||
>;
|
||||
|
||||
/// Type alias for using the block request type using block type parameters.
|
||||
pub type BlockRequest<B> = generic::BlockRequest<
|
||||
<B as BlockT>::Hash,
|
||||
<<B as BlockT>::Header as HeaderT>::Number,
|
||||
>;
|
||||
|
||||
/// Type alias for using the localized bft message type using block type parameters.
|
||||
pub type LocalizedBftMessage<B> = generic::LocalizedBftMessage<
|
||||
B,
|
||||
<B as BlockT>::Hash,
|
||||
>;
|
||||
|
||||
/// Type alias for using the BlockData type using block type parameters.
|
||||
pub type BlockData<B> = generic::BlockData<
|
||||
<B as BlockT>::Header,
|
||||
<B as BlockT>::Hash,
|
||||
<B as BlockT>::Extrinsic,
|
||||
>;
|
||||
|
||||
/// Type alias for using the BlockResponse type using block type parameters.
|
||||
pub type BlockResponse<B> = generic::BlockResponse<
|
||||
<B as BlockT>::Header,
|
||||
<B as BlockT>::Hash,
|
||||
<B as BlockT>::Extrinsic,
|
||||
>;
|
||||
|
||||
/// Type alias for using the BftMessage type using block type parameters.
|
||||
pub type BftMessage<B> = generic::BftMessage<
|
||||
B,
|
||||
<B as BlockT>::Hash,
|
||||
>;
|
||||
|
||||
/// Type alias for using the SignedConsensusProposal type using block type parameters.
|
||||
pub type SignedConsensusProposal<B> = generic::SignedConsensusProposal<
|
||||
B,
|
||||
<B as BlockT>::Hash,
|
||||
>;
|
||||
|
||||
/// Type alias for using the SignedConsensusProposal type using block type parameters.
|
||||
pub type SignedConsensusMessage<B> = generic::SignedConsensusProposal<
|
||||
B,
|
||||
<B as BlockT>::Hash,
|
||||
>;
|
||||
|
||||
/// A set of transactions.
|
||||
pub type Transactions<E> = Vec<E>;
|
||||
|
||||
/// Configured node role.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
@@ -73,8 +133,8 @@ impl From<RoleFlags> for Vec<Role> where {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
|
||||
/// Bits of block data and associated artefacts to request.
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
|
||||
pub enum BlockAttribute {
|
||||
/// Include block header.
|
||||
Header,
|
||||
@@ -88,33 +148,6 @@ pub enum BlockAttribute {
|
||||
Justification,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Block data sent in the response.
|
||||
pub struct BlockData {
|
||||
/// Block header hash.
|
||||
pub hash: HeaderHash,
|
||||
/// Block header if requested.
|
||||
pub header: Option<Header>,
|
||||
/// Block body if requested.
|
||||
pub body: Option<Body>,
|
||||
/// Block receipt if requested.
|
||||
pub receipt: Option<Bytes>,
|
||||
/// Block message queue if requested.
|
||||
pub message_queue: Option<Bytes>,
|
||||
/// Justification if requested.
|
||||
pub justification: Option<Justification>,
|
||||
}
|
||||
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Identifies starting point of a block sequence.
|
||||
pub enum FromBlock {
|
||||
/// Start with given hash.
|
||||
Hash(HeaderHash),
|
||||
/// Start with given block number.
|
||||
Number(BlockNumber),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Block enumeration direction.
|
||||
pub enum Direction {
|
||||
@@ -124,219 +157,6 @@ pub enum Direction {
|
||||
Descending,
|
||||
}
|
||||
|
||||
/// A set of transactions.
|
||||
pub type Transactions = Vec<Vec<u8>>;
|
||||
|
||||
/// Statements circulated among peers.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum UnsignedStatement {
|
||||
/// Broadcast by a authority to indicate that this is his candidate for
|
||||
/// inclusion.
|
||||
///
|
||||
/// Broadcasting two different candidate messages per round is not allowed.
|
||||
Candidate(Vec<u8>),
|
||||
/// Broadcast by a authority to attest that the candidate with given digest
|
||||
/// is valid.
|
||||
Valid(Hash),
|
||||
/// Broadcast by a authority to attest that the auxiliary data for a candidate
|
||||
/// with given digest is available.
|
||||
Available(Hash),
|
||||
/// Broadcast by a authority to attest that the candidate with given digest
|
||||
/// is invalid.
|
||||
Invalid(Hash),
|
||||
}
|
||||
|
||||
/// A signed statement.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Statement {
|
||||
/// Parent relay chain block header hash.
|
||||
pub parent_hash: HeaderHash,
|
||||
/// The statement.
|
||||
pub statement: UnsignedStatement,
|
||||
/// The signature.
|
||||
pub signature: ed25519::Signature,
|
||||
/// The sender.
|
||||
pub sender: AuthorityId,
|
||||
}
|
||||
|
||||
|
||||
/// Communication that can occur between participants in consensus.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum BftMessage {
|
||||
/// A consensus message (proposal or vote)
|
||||
Consensus(SignedConsensusMessage),
|
||||
/// Auxiliary communication (just proof-of-lock for now).
|
||||
Auxiliary(Justification),
|
||||
}
|
||||
|
||||
/// BFT Consensus message with parent header hash attached to it.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct LocalizedBftMessage {
|
||||
/// Consensus message.
|
||||
pub message: BftMessage,
|
||||
/// Parent header hash.
|
||||
pub parent_hash: HeaderHash,
|
||||
}
|
||||
|
||||
/// A localized proposal message. Contains two signed pieces of data.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct SignedConsensusProposal {
|
||||
/// The round number.
|
||||
pub round_number: u32,
|
||||
/// The proposal sent.
|
||||
pub proposal: Block,
|
||||
/// The digest of the proposal.
|
||||
pub digest: Hash,
|
||||
/// The sender of the proposal
|
||||
pub sender: AuthorityId,
|
||||
/// The signature on the message (propose, round number, digest)
|
||||
pub digest_signature: ed25519::Signature,
|
||||
/// The signature on the message (propose, round number, proposal)
|
||||
pub full_signature: ed25519::Signature,
|
||||
}
|
||||
|
||||
/// A localized vote message, including the sender.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct SignedConsensusVote {
|
||||
/// The message sent.
|
||||
pub vote: ConsensusVote,
|
||||
/// The sender of the message
|
||||
pub sender: AuthorityId,
|
||||
/// The signature of the message.
|
||||
pub signature: ed25519::Signature,
|
||||
}
|
||||
|
||||
/// Votes during a consensus round.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum ConsensusVote {
|
||||
/// Prepare to vote for proposal with digest D.
|
||||
Prepare(u32, Hash),
|
||||
/// Commit to proposal with digest D..
|
||||
Commit(u32, Hash),
|
||||
/// Propose advancement to a new round.
|
||||
AdvanceRound(u32),
|
||||
}
|
||||
|
||||
/// A localized message.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum SignedConsensusMessage {
|
||||
/// A proposal.
|
||||
Propose(SignedConsensusProposal),
|
||||
/// A vote.
|
||||
Vote(SignedConsensusVote),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// A network message.
|
||||
pub enum Message {
|
||||
/// Status packet.
|
||||
Status(Status),
|
||||
/// Block request.
|
||||
BlockRequest(BlockRequest),
|
||||
/// Block response.
|
||||
BlockResponse(BlockResponse),
|
||||
/// Block announce.
|
||||
BlockAnnounce(BlockAnnounce),
|
||||
/// Transactions.
|
||||
Transactions(Transactions),
|
||||
/// Consensus statement.
|
||||
Statement(Statement),
|
||||
/// Candidate data request.
|
||||
CandidateRequest(CandidateRequest),
|
||||
/// Candidate response.
|
||||
CandidateResponse(CandidateResponse),
|
||||
/// BFT Consensus statement.
|
||||
BftMessage(LocalizedBftMessage),
|
||||
/// Remote method call request.
|
||||
RemoteCallRequest(RemoteCallRequest),
|
||||
/// Remote method call response.
|
||||
RemoteCallResponse(RemoteCallResponse),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Status {
|
||||
/// Protocol version.
|
||||
pub version: u32,
|
||||
/// Supported roles.
|
||||
pub roles: Vec<Role>,
|
||||
/// Best block number.
|
||||
pub best_number: BlockNumber,
|
||||
/// Best block hash.
|
||||
pub best_hash: HeaderHash,
|
||||
/// Genesis block hash.
|
||||
pub genesis_hash: HeaderHash,
|
||||
/// Signatue of `best_hash` made with validator address. Required for the validator role.
|
||||
pub validator_signature: Option<ed25519::Signature>,
|
||||
/// Validator address. Required for the validator role.
|
||||
pub validator_id: Option<AuthorityId>,
|
||||
/// Parachain id. Required for the collator role.
|
||||
pub parachain_id: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Request block data from a peer.
|
||||
pub struct BlockRequest {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Bits of block data to request.
|
||||
pub fields: Vec<BlockAttribute>,
|
||||
/// Start from this block.
|
||||
pub from: FromBlock,
|
||||
/// End at this block. An implementation defined maximum is used when unspecified.
|
||||
pub to: Option<HeaderHash>,
|
||||
/// Sequence direction.
|
||||
pub direction: Direction,
|
||||
/// Maximum number of blocks to return. An implementation defined maximum is used when unspecified.
|
||||
pub max: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Request candidate block data from a peer.
|
||||
pub struct CandidateRequest {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Candidate receipt hash.
|
||||
pub hash: Hash,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Candidate block data response.
|
||||
pub struct CandidateResponse {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Candidate data. Empty if the peer does not have the candidate anymore.
|
||||
pub data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Response to `BlockRequest`
|
||||
pub struct BlockResponse {
|
||||
/// Id of a request this response was made for.
|
||||
pub id: RequestId,
|
||||
/// Block data for the requested sequence.
|
||||
pub blocks: Vec<BlockData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Announce a new complete relay chain block on the network.
|
||||
pub struct BlockAnnounce {
|
||||
/// New block header.
|
||||
pub header: Header,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Remote call request.
|
||||
pub struct RemoteCallRequest {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Block at which to perform call.
|
||||
pub block: HeaderHash,
|
||||
/// Method name.
|
||||
pub method: String,
|
||||
/// Call data.
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Remote call response.
|
||||
pub struct RemoteCallResponse {
|
||||
@@ -347,3 +167,192 @@ pub struct RemoteCallResponse {
|
||||
/// Execution proof.
|
||||
pub proof: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
/// Generic types.
|
||||
pub mod generic {
|
||||
use primitives::AuthorityId;
|
||||
use runtime_primitives::bft::Justification;
|
||||
use ed25519;
|
||||
|
||||
use super::{Role, BlockAttribute, RemoteCallResponse, RequestId, Transactions, Direction};
|
||||
/// Block data sent in the response.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct BlockData<Header, Hash, Extrinsic> {
|
||||
/// Block header hash.
|
||||
pub hash: Hash,
|
||||
/// Block header if requested.
|
||||
pub header: Option<Header>,
|
||||
/// Block body if requested.
|
||||
pub body: Option<Vec<Extrinsic>>,
|
||||
/// Block receipt if requested.
|
||||
pub receipt: Option<Vec<u8>>,
|
||||
/// Block message queue if requested.
|
||||
pub message_queue: Option<Vec<u8>>,
|
||||
/// Justification if requested.
|
||||
pub justification: Option<Justification<Hash>>,
|
||||
}
|
||||
|
||||
/// Identifies starting point of a block sequence.
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum FromBlock<Hash, Number> {
|
||||
/// Start with given hash.
|
||||
Hash(Hash),
|
||||
/// Start with given block number.
|
||||
Number(Number),
|
||||
}
|
||||
|
||||
/// Communication that can occur between participants in consensus.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum BftMessage<Block, Hash> {
|
||||
/// A consensus message (proposal or vote)
|
||||
Consensus(SignedConsensusMessage<Block, Hash>),
|
||||
/// Auxiliary communication (just proof-of-lock for now).
|
||||
Auxiliary(Justification<Hash>),
|
||||
}
|
||||
|
||||
/// BFT Consensus message with parent header hash attached to it.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct LocalizedBftMessage<Block, Hash> {
|
||||
/// Consensus message.
|
||||
pub message: BftMessage<Block, Hash>,
|
||||
/// Parent header hash.
|
||||
pub parent_hash: Hash,
|
||||
}
|
||||
|
||||
/// A localized proposal message. Contains two signed pieces of data.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct SignedConsensusProposal<Block, Hash> {
|
||||
/// The round number.
|
||||
pub round_number: u32,
|
||||
/// The proposal sent.
|
||||
pub proposal: Block,
|
||||
/// The digest of the proposal.
|
||||
pub digest: Hash,
|
||||
/// The sender of the proposal
|
||||
pub sender: AuthorityId,
|
||||
/// The signature on the message (propose, round number, digest)
|
||||
pub digest_signature: ed25519::Signature,
|
||||
/// The signature on the message (propose, round number, proposal)
|
||||
pub full_signature: ed25519::Signature,
|
||||
}
|
||||
|
||||
/// A localized vote message, including the sender.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct SignedConsensusVote<H> {
|
||||
/// The message sent.
|
||||
pub vote: ConsensusVote<H>,
|
||||
/// The sender of the message
|
||||
pub sender: AuthorityId,
|
||||
/// The signature of the message.
|
||||
pub signature: ed25519::Signature,
|
||||
}
|
||||
|
||||
/// Votes during a consensus round.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum ConsensusVote<H> {
|
||||
/// Prepare to vote for proposal with digest D.
|
||||
Prepare(u32, H),
|
||||
/// Commit to proposal with digest D..
|
||||
Commit(u32, H),
|
||||
/// Propose advancement to a new round.
|
||||
AdvanceRound(u32),
|
||||
}
|
||||
|
||||
/// A localized message.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum SignedConsensusMessage<Block, Hash> {
|
||||
/// A proposal.
|
||||
Propose(SignedConsensusProposal<Block, Hash>),
|
||||
/// A vote.
|
||||
Vote(SignedConsensusVote<Hash>),
|
||||
}
|
||||
|
||||
/// A network message.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum Message<Block, Header, Hash, Number, Extrinsic> {
|
||||
/// Status packet.
|
||||
Status(Status<Hash, Number>),
|
||||
/// Block request.
|
||||
BlockRequest(BlockRequest<Hash, Number>),
|
||||
/// Block response.
|
||||
BlockResponse(BlockResponse<Header, Hash, Extrinsic>),
|
||||
/// Block announce.
|
||||
BlockAnnounce(BlockAnnounce<Header>),
|
||||
/// Transactions.
|
||||
Transactions(Transactions<Extrinsic>),
|
||||
/// BFT Consensus statement.
|
||||
BftMessage(LocalizedBftMessage<Block, Hash>),
|
||||
/// Remote method call request.
|
||||
RemoteCallRequest(RemoteCallRequest<Hash>),
|
||||
/// Remote method call response.
|
||||
RemoteCallResponse(RemoteCallResponse),
|
||||
}
|
||||
|
||||
/// Status sent on connection.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct Status<Hash, Number> {
|
||||
/// Protocol version.
|
||||
pub version: u32,
|
||||
/// Supported roles.
|
||||
pub roles: Vec<Role>,
|
||||
/// Best block number.
|
||||
pub best_number: Number,
|
||||
/// Best block hash.
|
||||
pub best_hash: Hash,
|
||||
/// Genesis block hash.
|
||||
pub genesis_hash: Hash,
|
||||
/// Signatue of `best_hash` made with validator address. Required for the validator role.
|
||||
pub validator_signature: Option<ed25519::Signature>,
|
||||
/// Validator address. Required for the validator role.
|
||||
pub validator_id: Option<AuthorityId>,
|
||||
/// Parachain id. Required for the collator role.
|
||||
pub parachain_id: Option<u64>,
|
||||
}
|
||||
|
||||
/// Request block data from a peer.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct BlockRequest<Hash, Number> {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Bits of block data to request.
|
||||
pub fields: Vec<BlockAttribute>,
|
||||
/// Start from this block.
|
||||
pub from: FromBlock<Hash, Number>,
|
||||
/// End at this block. An implementation defined maximum is used when unspecified.
|
||||
pub to: Option<Hash>,
|
||||
/// Sequence direction.
|
||||
pub direction: Direction,
|
||||
/// Maximum number of blocks to return. An implementation defined maximum is used when unspecified.
|
||||
pub max: Option<u32>,
|
||||
}
|
||||
|
||||
/// Response to `BlockRequest`
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct BlockResponse<Header, Hash, Extrinsic> {
|
||||
/// Id of a request this response was made for.
|
||||
pub id: RequestId,
|
||||
/// Block data for the requested sequence.
|
||||
pub blocks: Vec<BlockData<Header, Hash, Extrinsic>>,
|
||||
}
|
||||
|
||||
/// Announce a new complete relay chain block on the network.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct BlockAnnounce<H> {
|
||||
/// New block header.
|
||||
pub header: H,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
/// Remote call request.
|
||||
pub struct RemoteCallRequest<H> {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Block at which to perform call.
|
||||
pub block: H,
|
||||
/// Method name.
|
||||
pub method: String,
|
||||
/// Call data.
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ use io::SyncIo;
|
||||
use message;
|
||||
use network::PeerId;
|
||||
use service;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
/// Remote request timeout.
|
||||
const REQUEST_TIMEOUT: Duration = Duration::from_secs(15);
|
||||
@@ -50,9 +51,9 @@ pub trait OnDemandService: Send + Sync {
|
||||
}
|
||||
|
||||
/// On-demand requests service. Dispatches requests to appropriate peers.
|
||||
pub struct OnDemand<E: service::ExecuteInContext> {
|
||||
core: Mutex<OnDemandCore<E>>,
|
||||
checker: Arc<FetchChecker>,
|
||||
pub struct OnDemand<B: BlockT, E: service::ExecuteInContext<B>> {
|
||||
core: Mutex<OnDemandCore<B, E>>,
|
||||
checker: Arc<FetchChecker<B>>,
|
||||
}
|
||||
|
||||
/// On-demand response.
|
||||
@@ -61,19 +62,19 @@ pub struct Response {
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct OnDemandCore<E: service::ExecuteInContext> {
|
||||
struct OnDemandCore<B: BlockT, E: service::ExecuteInContext<B>> {
|
||||
service: Weak<E>,
|
||||
next_request_id: u64,
|
||||
pending_requests: VecDeque<Request>,
|
||||
active_peers: LinkedHashMap<PeerId, Request>,
|
||||
pending_requests: VecDeque<Request<B::Hash>>,
|
||||
active_peers: LinkedHashMap<PeerId, Request<B::Hash>>,
|
||||
idle_peers: VecDeque<PeerId>,
|
||||
}
|
||||
|
||||
struct Request {
|
||||
struct Request<H> {
|
||||
id: u64,
|
||||
timestamp: Instant,
|
||||
sender: Sender<client::CallResult>,
|
||||
request: RemoteCallRequest,
|
||||
request: RemoteCallRequest<H>,
|
||||
}
|
||||
|
||||
impl Future for Response {
|
||||
@@ -86,9 +87,12 @@ impl Future for Response {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> OnDemand<E> where E: service::ExecuteInContext {
|
||||
impl<B: BlockT, E> OnDemand<B, E> where
|
||||
E: service::ExecuteInContext<B>,
|
||||
B::Header: HeaderT<Number=u64>,
|
||||
{
|
||||
/// Creates new on-demand service.
|
||||
pub fn new(checker: Arc<FetchChecker>) -> Self {
|
||||
pub fn new(checker: Arc<FetchChecker<B>>) -> Self {
|
||||
OnDemand {
|
||||
checker,
|
||||
core: Mutex::new(OnDemandCore {
|
||||
@@ -107,7 +111,7 @@ impl<E> OnDemand<E> where E: service::ExecuteInContext {
|
||||
}
|
||||
|
||||
/// Execute method call on remote node, returning execution result and proof.
|
||||
pub fn remote_call(&self, request: RemoteCallRequest) -> Response {
|
||||
pub fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Response {
|
||||
let (sender, receiver) = channel();
|
||||
let result = Response {
|
||||
receiver: receiver,
|
||||
@@ -123,7 +127,11 @@ impl<E> OnDemand<E> where E: service::ExecuteInContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> OnDemandService for OnDemand<E> where E: service::ExecuteInContext {
|
||||
impl<B, E> OnDemandService for OnDemand<B, E> where
|
||||
B: BlockT,
|
||||
E: service::ExecuteInContext<B>,
|
||||
B::Header: HeaderT<Number=u64>,
|
||||
{
|
||||
fn on_connect(&self, peer: PeerId, role: service::Role) {
|
||||
if !role.intersects(service::Role::FULL | service::Role::COLLATOR | service::Role::VALIDATOR) { // TODO: correct?
|
||||
return;
|
||||
@@ -175,15 +183,23 @@ impl<E> OnDemandService for OnDemand<E> where E: service::ExecuteInContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Fetcher for OnDemand<E> where E: service::ExecuteInContext {
|
||||
impl<B, E> Fetcher<B> for OnDemand<B, E> where
|
||||
B: BlockT,
|
||||
E: service::ExecuteInContext<B>,
|
||||
B::Header: HeaderT<Number=u64>,
|
||||
{
|
||||
type RemoteCallResult = Response;
|
||||
|
||||
fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult {
|
||||
self.remote_call(request)
|
||||
fn remote_call(&self, request: RemoteCallRequest<B::Hash>) -> Self::RemoteCallResult {
|
||||
OnDemand::remote_call(self, request)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
|
||||
impl<B, E> OnDemandCore<B, E> where
|
||||
B: BlockT,
|
||||
E: service::ExecuteInContext<B> ,
|
||||
B::Header: HeaderT<Number=u64>
|
||||
{
|
||||
pub fn add_peer(&mut self, peer: PeerId) {
|
||||
self.idle_peers.push_back(peer);
|
||||
}
|
||||
@@ -214,7 +230,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, sender: Sender<client::CallResult>, request: RemoteCallRequest) {
|
||||
pub fn insert(&mut self, sender: Sender<client::CallResult>, request: RemoteCallRequest<B::Hash>) {
|
||||
let request_id = self.next_request_id;
|
||||
self.next_request_id += 1;
|
||||
|
||||
@@ -226,7 +242,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, peer: PeerId, id: u64) -> Option<Request> {
|
||||
pub fn remove(&mut self, peer: PeerId, id: u64) -> Option<Request<B::Hash>> {
|
||||
match self.active_peers.entry(peer) {
|
||||
Entry::Occupied(entry) => match entry.get().id == id {
|
||||
true => {
|
||||
@@ -263,7 +279,7 @@ impl<E> OnDemandCore<E> where E: service::ExecuteInContext {
|
||||
data: request.request.call_data.clone(),
|
||||
};
|
||||
|
||||
protocol.send_message(ctx, peer, message::Message::RemoteCallRequest(message))
|
||||
protocol.send_message(ctx, peer, message::generic::Message::RemoteCallRequest(message))
|
||||
});
|
||||
self.active_peers.insert(peer, request);
|
||||
}
|
||||
@@ -286,16 +302,17 @@ mod tests {
|
||||
use service::{Role, ExecuteInContext};
|
||||
use test::TestIo;
|
||||
use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService};
|
||||
use test_client::runtime::{Block, Hash};
|
||||
|
||||
struct DummyExecutor;
|
||||
struct DummyFetchChecker { ok: bool }
|
||||
|
||||
impl ExecuteInContext for DummyExecutor {
|
||||
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, _closure: F) {}
|
||||
impl ExecuteInContext<Block> for DummyExecutor {
|
||||
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<Block>)>(&self, _closure: F) {}
|
||||
}
|
||||
|
||||
impl FetchChecker for DummyFetchChecker {
|
||||
fn check_execution_proof(&self, _request: &RemoteCallRequest, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> client::error::Result<client::CallResult> {
|
||||
impl FetchChecker<Block> for DummyFetchChecker {
|
||||
fn check_execution_proof(&self, _request: &RemoteCallRequest<Hash>, remote_proof: (Vec<u8>, Vec<Vec<u8>>)) -> client::error::Result<client::CallResult> {
|
||||
match self.ok {
|
||||
true => Ok(client::CallResult {
|
||||
return_data: remote_proof.0,
|
||||
@@ -306,19 +323,19 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn dummy(ok: bool) -> (Arc<DummyExecutor>, Arc<OnDemand<DummyExecutor>>) {
|
||||
fn dummy(ok: bool) -> (Arc<DummyExecutor>, Arc<OnDemand<Block, DummyExecutor>>) {
|
||||
let executor = Arc::new(DummyExecutor);
|
||||
let service = Arc::new(OnDemand::new(Arc::new(DummyFetchChecker { ok })));
|
||||
service.set_service_link(Arc::downgrade(&executor));
|
||||
(executor, service)
|
||||
}
|
||||
|
||||
fn total_peers(on_demand: &OnDemand<DummyExecutor>) -> usize {
|
||||
fn total_peers(on_demand: &OnDemand<Block, DummyExecutor>) -> usize {
|
||||
let core = on_demand.core.lock();
|
||||
core.idle_peers.len() + core.active_peers.len()
|
||||
}
|
||||
|
||||
fn receive_response(on_demand: &OnDemand<DummyExecutor>, network: &mut TestIo, peer: PeerId, id: message::RequestId) {
|
||||
fn receive_response(on_demand: &OnDemand<Block, DummyExecutor>, network: &mut TestIo, peer: PeerId, id: message::RequestId) {
|
||||
on_demand.on_remote_response(network, peer, message::RemoteCallResponse {
|
||||
id: id,
|
||||
value: vec![1],
|
||||
|
||||
@@ -19,23 +19,21 @@ use std::{mem, cmp};
|
||||
use std::sync::Arc;
|
||||
use std::time;
|
||||
use parking_lot::{RwLock, Mutex};
|
||||
use futures::sync::oneshot;
|
||||
use serde_json;
|
||||
use primitives::block::{HeaderHash, ExtrinsicHash, Number as BlockNumber, Header, Id as BlockId};
|
||||
use primitives::{Hash, blake2_256};
|
||||
use runtime_support::Hashable;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hashing, HashingFor};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use network::PeerId;
|
||||
|
||||
use message::{self, Message};
|
||||
use message::generic::Message as GenericMessage;
|
||||
use sync::{ChainSync, Status as SyncStatus, SyncState};
|
||||
use consensus::Consensus;
|
||||
use service::{Role, TransactionPool, StatementStream, BftMessageStream};
|
||||
use service::{Role, TransactionPool, BftMessageStream};
|
||||
use config::ProtocolConfig;
|
||||
use chain::Client;
|
||||
use on_demand::OnDemandService;
|
||||
use io::SyncIo;
|
||||
use error;
|
||||
use super::header_hash;
|
||||
|
||||
const REQUEST_TIMEOUT_SEC: u64 = 40;
|
||||
const PROTOCOL_VERSION: u32 = 0;
|
||||
@@ -44,25 +42,25 @@ const PROTOCOL_VERSION: u32 = 0;
|
||||
const MAX_BLOCK_DATA_RESPONSE: u32 = 128;
|
||||
|
||||
// Lock must always be taken in order declared here.
|
||||
pub struct Protocol {
|
||||
pub struct Protocol<B: BlockT> {
|
||||
config: ProtocolConfig,
|
||||
chain: Arc<Client>,
|
||||
chain: Arc<Client<B>>,
|
||||
on_demand: Option<Arc<OnDemandService>>,
|
||||
genesis_hash: HeaderHash,
|
||||
sync: RwLock<ChainSync>,
|
||||
consensus: Mutex<Consensus>,
|
||||
genesis_hash: B::Hash,
|
||||
sync: RwLock<ChainSync<B>>,
|
||||
consensus: Mutex<Consensus<B>>,
|
||||
// All connected peers
|
||||
peers: RwLock<HashMap<PeerId, Peer>>,
|
||||
peers: RwLock<HashMap<PeerId, Peer<B>>>,
|
||||
// Connected peers pending Status message.
|
||||
handshaking_peers: RwLock<HashMap<PeerId, time::Instant>>,
|
||||
transaction_pool: Arc<TransactionPool>,
|
||||
transaction_pool: Arc<TransactionPool<B>>,
|
||||
}
|
||||
|
||||
/// Syncing status and statistics
|
||||
#[derive(Clone)]
|
||||
pub struct ProtocolStatus {
|
||||
pub struct ProtocolStatus<B: BlockT> {
|
||||
/// Sync status.
|
||||
pub sync: SyncStatus,
|
||||
pub sync: SyncStatus<B>,
|
||||
/// Total number of connected peers
|
||||
pub num_peers: usize,
|
||||
/// Total number of active peers.
|
||||
@@ -70,42 +68,49 @@ pub struct ProtocolStatus {
|
||||
}
|
||||
|
||||
/// Peer information
|
||||
struct Peer {
|
||||
struct Peer<B: BlockT> {
|
||||
/// Protocol version
|
||||
protocol_version: u32,
|
||||
/// Roles
|
||||
roles: Role,
|
||||
/// Peer best block hash
|
||||
best_hash: HeaderHash,
|
||||
best_hash: B::Hash,
|
||||
/// Peer best block number
|
||||
best_number: BlockNumber,
|
||||
best_number: <B::Header as HeaderT>::Number,
|
||||
/// Pending block request if any
|
||||
block_request: Option<message::BlockRequest>,
|
||||
block_request: Option<message::BlockRequest<B>>,
|
||||
/// Request timestamp
|
||||
request_timestamp: Option<time::Instant>,
|
||||
/// Holds a set of transactions known to this peer.
|
||||
known_transactions: HashSet<ExtrinsicHash>,
|
||||
known_transactions: HashSet<B::Hash>,
|
||||
/// Holds a set of blocks known to this peer.
|
||||
known_blocks: HashSet<HeaderHash>,
|
||||
known_blocks: HashSet<B::Hash>,
|
||||
/// Request counter,
|
||||
next_request_id: message::RequestId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PeerInfo {
|
||||
pub struct PeerInfo<B: BlockT> {
|
||||
/// Roles
|
||||
pub roles: Role,
|
||||
/// Protocol version
|
||||
pub protocol_version: u32,
|
||||
/// Peer best block hash
|
||||
pub best_hash: HeaderHash,
|
||||
pub best_hash: B::Hash,
|
||||
/// Peer best block number
|
||||
pub best_number: BlockNumber,
|
||||
pub best_number: <B::Header as HeaderT>::Number,
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
impl<B: BlockT> Protocol<B> where
|
||||
B::Header: HeaderT<Number=u64>
|
||||
{
|
||||
/// Create a new instance.
|
||||
pub fn new(config: ProtocolConfig, chain: Arc<Client>, on_demand: Option<Arc<OnDemandService>>, transaction_pool: Arc<TransactionPool>) -> error::Result<Protocol> {
|
||||
pub fn new(
|
||||
config: ProtocolConfig,
|
||||
chain: Arc<Client<B>>,
|
||||
on_demand: Option<Arc<OnDemandService>>,
|
||||
transaction_pool: Arc<TransactionPool<B>>
|
||||
) -> error::Result<Self> {
|
||||
let info = chain.info()?;
|
||||
let sync = ChainSync::new(config.roles, &info);
|
||||
let protocol = Protocol {
|
||||
@@ -123,7 +128,7 @@ impl Protocol {
|
||||
}
|
||||
|
||||
/// Returns protocol status
|
||||
pub fn status(&self) -> ProtocolStatus {
|
||||
pub fn status(&self) -> ProtocolStatus<B> {
|
||||
let sync = self.sync.read();
|
||||
let peers = self.peers.read();
|
||||
ProtocolStatus {
|
||||
@@ -134,7 +139,7 @@ impl Protocol {
|
||||
}
|
||||
|
||||
pub fn handle_packet(&self, io: &mut SyncIo, peer_id: PeerId, data: &[u8]) {
|
||||
let message: Message = match serde_json::from_slice(data) {
|
||||
let message: Message<B> = match serde_json::from_slice(data) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
debug!("Invalid packet from {}: {}", peer_id, e);
|
||||
@@ -144,9 +149,9 @@ impl Protocol {
|
||||
};
|
||||
|
||||
match message {
|
||||
Message::Status(s) => self.on_status_message(io, peer_id, s),
|
||||
Message::BlockRequest(r) => self.on_block_request(io, peer_id, r),
|
||||
Message::BlockResponse(r) => {
|
||||
GenericMessage::Status(s) => self.on_status_message(io, peer_id, s),
|
||||
GenericMessage::BlockRequest(r) => self.on_block_request(io, peer_id, r),
|
||||
GenericMessage::BlockResponse(r) => {
|
||||
let request = {
|
||||
let mut peers = self.peers.write();
|
||||
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
|
||||
@@ -171,22 +176,19 @@ impl Protocol {
|
||||
}
|
||||
self.on_block_response(io, peer_id, request, r);
|
||||
},
|
||||
Message::BlockAnnounce(announce) => {
|
||||
GenericMessage::BlockAnnounce(announce) => {
|
||||
self.on_block_announce(io, peer_id, announce);
|
||||
},
|
||||
Message::Statement(s) => self.on_statement(io, peer_id, s, blake2_256(data).into()),
|
||||
Message::CandidateRequest(r) => self.on_candidate_request(io, peer_id, r),
|
||||
Message::CandidateResponse(r) => self.on_candidate_response(io, peer_id, r),
|
||||
Message::BftMessage(m) => self.on_bft_message(io, peer_id, m, blake2_256(data).into()),
|
||||
Message::Transactions(m) => self.on_transactions(io, peer_id, m),
|
||||
Message::RemoteCallRequest(request) => self.on_remote_call_request(io, peer_id, request),
|
||||
Message::RemoteCallResponse(response) => self.on_remote_call_response(io, peer_id, response)
|
||||
GenericMessage::BftMessage(m) => self.on_bft_message(io, peer_id, m, HashingFor::<B>::hash(data)),
|
||||
GenericMessage::Transactions(m) => self.on_transactions(io, peer_id, m),
|
||||
GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(io, peer_id, request),
|
||||
GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(io, peer_id, response)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_message(&self, io: &mut SyncIo, peer_id: PeerId, mut message: Message) {
|
||||
pub fn send_message(&self, io: &mut SyncIo, peer_id: PeerId, mut message: Message<B>) {
|
||||
match &mut message {
|
||||
&mut Message::BlockRequest(ref mut r) => {
|
||||
&mut GenericMessage::BlockRequest(ref mut r) => {
|
||||
let mut peers = self.peers.write();
|
||||
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
|
||||
r.id = peer.next_request_id;
|
||||
@@ -204,9 +206,9 @@ impl Protocol {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_message(message: &Message) -> Hash {
|
||||
pub fn hash_message(message: &Message<B>) -> B::Hash {
|
||||
let data = serde_json::to_vec(&message).expect("Serializer is infallible; qed");
|
||||
blake2_256(&data).into()
|
||||
HashingFor::<B>::hash(&data)
|
||||
}
|
||||
|
||||
/// Called when a new peer is connected
|
||||
@@ -232,7 +234,7 @@ impl Protocol {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_block_request(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest) {
|
||||
fn on_block_request(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest<B>) {
|
||||
trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", request.id, peer, request.from, request.to, request.max);
|
||||
let mut blocks = Vec::new();
|
||||
let mut id = match request.from {
|
||||
@@ -255,9 +257,9 @@ impl Protocol {
|
||||
if blocks.len() >= max{
|
||||
break;
|
||||
}
|
||||
let number = header.number;
|
||||
let hash = header_hash(&header);
|
||||
let block_data = message::BlockData {
|
||||
let number = header.number().clone();
|
||||
let hash = header.hash();
|
||||
let block_data = message::generic::BlockData {
|
||||
hash: hash,
|
||||
header: if get_header { Some(header) } else { None },
|
||||
body: if get_body { self.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } else { None },
|
||||
@@ -276,69 +278,34 @@ impl Protocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
let response = message::BlockResponse {
|
||||
let response = message::generic::BlockResponse {
|
||||
id: request.id,
|
||||
blocks: blocks,
|
||||
};
|
||||
self.send_message(io, peer, Message::BlockResponse(response))
|
||||
self.send_message(io, peer, GenericMessage::BlockResponse(response))
|
||||
}
|
||||
|
||||
fn on_block_response(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest, response: message::BlockResponse) {
|
||||
fn on_block_response(&self, io: &mut SyncIo, peer: PeerId, request: message::BlockRequest<B>, response: message::BlockResponse<B>) {
|
||||
// TODO: validate response
|
||||
trace!(target: "sync", "BlockResponse {} from {} with {} blocks", response.id, peer, response.blocks.len());
|
||||
self.sync.write().on_block_data(io, self, peer, request, response);
|
||||
}
|
||||
|
||||
fn on_candidate_request(&self, io: &mut SyncIo, peer: PeerId, request: message::CandidateRequest) {
|
||||
trace!(target: "sync", "CandidateRequest {} from {} for {}", request.id, peer, request.hash);
|
||||
self.consensus.lock().on_candidate_request(io, self, peer, request);
|
||||
}
|
||||
|
||||
fn on_candidate_response(&self, io: &mut SyncIo, peer: PeerId, response: message::CandidateResponse) {
|
||||
trace!(target: "sync", "CandidateResponse {} from {} with {:?} bytes", response.id, peer, response.data.as_ref().map(|d| d.len()));
|
||||
self.consensus.lock().on_candidate_response(io, self, peer, response);
|
||||
}
|
||||
|
||||
fn on_statement(&self, io: &mut SyncIo, peer: PeerId, statement: message::Statement, hash: Hash) {
|
||||
trace!(target: "sync", "Statement from {}: {:?}", peer, statement);
|
||||
self.consensus.lock().on_statement(io, self, peer, statement, hash);
|
||||
}
|
||||
|
||||
fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage, hash: Hash) {
|
||||
fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage<B>, hash: B::Hash) {
|
||||
trace!(target: "sync", "BFT message from {}: {:?}", peer, message);
|
||||
self.consensus.lock().on_bft_message(io, self, peer, message, hash);
|
||||
}
|
||||
|
||||
/// See `ConsensusService` trait.
|
||||
pub fn send_bft_message(&self, io: &mut SyncIo, message: message::LocalizedBftMessage) {
|
||||
pub fn send_bft_message(&self, io: &mut SyncIo, message: message::LocalizedBftMessage<B>) {
|
||||
self.consensus.lock().send_bft_message(io, self, message)
|
||||
}
|
||||
|
||||
/// See `ConsensusService` trait.
|
||||
pub fn bft_messages(&self, parent_hash: Hash) -> BftMessageStream {
|
||||
pub fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B> {
|
||||
self.consensus.lock().bft_messages(parent_hash)
|
||||
}
|
||||
|
||||
/// See `ConsensusService` trait.
|
||||
pub fn statements(&self) -> StatementStream {
|
||||
self.consensus.lock().statements()
|
||||
}
|
||||
|
||||
/// See `ConsensusService` trait.
|
||||
pub fn fetch_candidate(&self, io: &mut SyncIo, hash: &Hash) -> oneshot::Receiver<Vec<u8>> {
|
||||
self.consensus.lock().fetch_candidate(io, self, hash)
|
||||
}
|
||||
|
||||
/// See `ConsensusService` trait.
|
||||
pub fn send_statement(&self, io: &mut SyncIo, statement: message::Statement) {
|
||||
self.consensus.lock().send_statement(io, self, statement)
|
||||
}
|
||||
|
||||
/// See `ConsensusService` trait.
|
||||
pub fn set_local_candidate(&self, candidate: Option<(Hash, Vec<u8>)>) {
|
||||
self.consensus.lock().set_local_candidate(candidate)
|
||||
}
|
||||
|
||||
/// Perform time based maintenance.
|
||||
pub fn tick(&self, io: &mut SyncIo) {
|
||||
self.maintain_peers(io);
|
||||
@@ -367,7 +334,7 @@ impl Protocol {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peer_info(&self, peer: PeerId) -> Option<PeerInfo> {
|
||||
pub fn peer_info(&self, peer: PeerId) -> Option<PeerInfo<B>> {
|
||||
self.peers.read().get(&peer).map(|p| {
|
||||
PeerInfo {
|
||||
roles: p.roles,
|
||||
@@ -379,7 +346,7 @@ impl Protocol {
|
||||
}
|
||||
|
||||
/// Called by peer to report status
|
||||
fn on_status_message(&self, io: &mut SyncIo, peer_id: PeerId, status: message::Status) {
|
||||
fn on_status_message(&self, io: &mut SyncIo, peer_id: PeerId, status: message::Status<B>) {
|
||||
trace!(target: "sync", "New peer {} {:?}", peer_id, status);
|
||||
if io.is_expired() {
|
||||
trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id));
|
||||
@@ -426,7 +393,7 @@ impl Protocol {
|
||||
}
|
||||
|
||||
/// Called when peer sends us new transactions
|
||||
fn on_transactions(&self, _io: &mut SyncIo, peer_id: PeerId, transactions: message::Transactions) {
|
||||
fn on_transactions(&self, _io: &mut SyncIo, peer_id: PeerId, transactions: message::Transactions<B::Extrinsic>) {
|
||||
// Accept transactions only when fully synced
|
||||
if self.sync.read().status().state != SyncState::Idle {
|
||||
trace!(target: "sync", "{} Ignoring transactions while syncing", peer_id);
|
||||
@@ -475,7 +442,7 @@ impl Protocol {
|
||||
}
|
||||
}
|
||||
trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), peer_id);
|
||||
self.send_message(io, *peer_id, Message::Transactions(to_send));
|
||||
self.send_message(io, *peer_id, GenericMessage::Transactions(to_send));
|
||||
}
|
||||
}
|
||||
self.transaction_pool.on_broadcasted(propagated_to);
|
||||
@@ -484,7 +451,7 @@ impl Protocol {
|
||||
/// Send Status message
|
||||
fn send_status(&self, io: &mut SyncIo, peer_id: PeerId) {
|
||||
if let Ok(info) = self.chain.info() {
|
||||
let status = message::Status {
|
||||
let status = message::generic::Status {
|
||||
version: PROTOCOL_VERSION,
|
||||
genesis_hash: info.chain.genesis_hash,
|
||||
roles: self.config.roles.into(),
|
||||
@@ -494,7 +461,7 @@ impl Protocol {
|
||||
validator_id: None,
|
||||
parachain_id: None,
|
||||
};
|
||||
self.send_message(io, peer_id, Message::Status(status))
|
||||
self.send_message(io, peer_id, GenericMessage::Status(status))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,9 +475,9 @@ impl Protocol {
|
||||
self.consensus.lock().restart();
|
||||
}
|
||||
|
||||
pub fn on_block_announce(&self, io: &mut SyncIo, peer_id: PeerId, announce: message::BlockAnnounce) {
|
||||
pub fn on_block_announce(&self, io: &mut SyncIo, peer_id: PeerId, announce: message::BlockAnnounce<B::Header>) {
|
||||
let header = announce.header;
|
||||
let hash: HeaderHash = header.blake2_256().into();
|
||||
let hash = header.hash();
|
||||
{
|
||||
let mut peers = self.peers.write();
|
||||
if let Some(ref mut peer) = peers.get_mut(&peer_id) {
|
||||
@@ -520,7 +487,7 @@ impl Protocol {
|
||||
self.sync.write().on_block_announce(io, self, peer_id, hash, &header);
|
||||
}
|
||||
|
||||
pub fn on_block_imported(&self, io: &mut SyncIo, hash: HeaderHash, header: &Header) {
|
||||
pub fn on_block_imported(&self, io: &mut SyncIo, hash: B::Hash, header: &B::Header) {
|
||||
self.sync.write().update_chain_info(&header);
|
||||
// send out block announcements
|
||||
let mut peers = self.peers.write();
|
||||
@@ -528,7 +495,7 @@ impl Protocol {
|
||||
for (peer_id, ref mut peer) in peers.iter_mut() {
|
||||
if peer.known_blocks.insert(hash.clone()) {
|
||||
trace!(target: "sync", "Announcing block {:?} to {}", hash, peer_id);
|
||||
self.send_message(io, *peer_id, Message::BlockAnnounce(message::BlockAnnounce {
|
||||
self.send_message(io, *peer_id, GenericMessage::BlockAnnounce(message::BlockAnnounce {
|
||||
header: header.clone()
|
||||
}));
|
||||
}
|
||||
@@ -537,7 +504,7 @@ impl Protocol {
|
||||
self.consensus.lock().collect_garbage(Some(&header));
|
||||
}
|
||||
|
||||
fn on_remote_call_request(&self, io: &mut SyncIo, peer_id: PeerId, request: message::RemoteCallRequest) {
|
||||
fn on_remote_call_request(&self, io: &mut SyncIo, peer_id: PeerId, request: message::RemoteCallRequest<B::Hash>) {
|
||||
trace!(target: "sync", "Remote request {} from {} ({} at {})", request.id, peer_id, request.method, request.block);
|
||||
let (value, proof) = match self.chain.execution_proof(&request.block, &request.method, &request.data) {
|
||||
Ok((value, proof)) => (value, proof),
|
||||
@@ -548,7 +515,7 @@ impl Protocol {
|
||||
},
|
||||
};
|
||||
|
||||
self.send_message(io, peer_id, message::Message::RemoteCallResponse(message::RemoteCallResponse {
|
||||
self.send_message(io, peer_id, GenericMessage::RemoteCallResponse(message::RemoteCallResponse {
|
||||
id: request.id, value, proof,
|
||||
}));
|
||||
}
|
||||
@@ -558,7 +525,7 @@ impl Protocol {
|
||||
self.on_demand.as_ref().map(|s| s.on_remote_response(io, peer_id, response));
|
||||
}
|
||||
|
||||
pub fn chain(&self) -> &Client {
|
||||
pub fn chain(&self) -> &Client<B> {
|
||||
&*self.chain
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,16 +22,15 @@ use futures::sync::{oneshot, mpsc};
|
||||
use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId,
|
||||
NetworkConfiguration , NonReservedPeerMode, ErrorKind};
|
||||
use network_devp2p::{NetworkService};
|
||||
use primitives::block::{ExtrinsicHash, Header, HeaderHash};
|
||||
use primitives::Hash;
|
||||
use core_io::{TimerToken};
|
||||
use io::NetSyncIo;
|
||||
use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo};
|
||||
use config::{ProtocolConfig};
|
||||
use error::Error;
|
||||
use chain::Client;
|
||||
use message::{Statement, LocalizedBftMessage};
|
||||
use message::LocalizedBftMessage;
|
||||
use on_demand::OnDemandService;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
/// Polkadot devp2p protocol id
|
||||
pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot";
|
||||
@@ -40,10 +39,8 @@ const V0_PACKET_COUNT: u8 = 1;
|
||||
|
||||
/// Type that represents fetch completion future.
|
||||
pub type FetchFuture = oneshot::Receiver<Vec<u8>>;
|
||||
/// Type that represents statement stream.
|
||||
pub type StatementStream = mpsc::UnboundedReceiver<Statement>;
|
||||
/// Type that represents bft messages stream.
|
||||
pub type BftMessageStream = mpsc::UnboundedReceiver<LocalizedBftMessage>;
|
||||
pub type BftMessageStream<B> = mpsc::UnboundedReceiver<LocalizedBftMessage<B>>;
|
||||
|
||||
const TICK_TOKEN: TimerToken = 0;
|
||||
const TICK_TIMEOUT: Duration = Duration::from_millis(1000);
|
||||
@@ -68,60 +65,51 @@ bitflags! {
|
||||
}
|
||||
|
||||
/// Sync status
|
||||
pub trait SyncProvider: Send + Sync {
|
||||
pub trait SyncProvider<B: BlockT>: Send + Sync {
|
||||
/// Get sync status
|
||||
fn status(&self) -> ProtocolStatus;
|
||||
fn status(&self) -> ProtocolStatus<B>;
|
||||
/// Get peers information
|
||||
fn peers(&self) -> Vec<PeerInfo>;
|
||||
fn peers(&self) -> Vec<PeerInfo<B>>;
|
||||
/// Get this node id if available.
|
||||
fn node_id(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
/// Transaction pool interface
|
||||
pub trait TransactionPool: Send + Sync {
|
||||
pub trait TransactionPool<B: BlockT>: Send + Sync {
|
||||
/// Get transactions from the pool that are ready to be propagated.
|
||||
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)>;
|
||||
fn transactions(&self) -> Vec<(B::Hash, B::Extrinsic)>;
|
||||
/// Import a transction into the pool.
|
||||
fn import(&self, transaction: &[u8]) -> Option<ExtrinsicHash>;
|
||||
fn import(&self, transaction: &B::Extrinsic) -> Option<B::Hash>;
|
||||
/// Notify the pool about transactions broadcast.
|
||||
fn on_broadcasted(&self, propagations: HashMap<ExtrinsicHash, Vec<String>>);
|
||||
fn on_broadcasted(&self, propagations: HashMap<B::Hash, Vec<String>>);
|
||||
}
|
||||
|
||||
/// ConsensusService
|
||||
pub trait ConsensusService: Send + Sync {
|
||||
/// Get statement stream.
|
||||
fn statements(&self) -> StatementStream;
|
||||
/// Send out a statement.
|
||||
fn send_statement(&self, statement: Statement);
|
||||
pub trait ConsensusService<B: BlockT>: Send + Sync {
|
||||
/// Maintain connectivity to given addresses.
|
||||
fn connect_to_authorities(&self, addresses: &[String]);
|
||||
/// Fetch candidate.
|
||||
fn fetch_candidate(&self, hash: &Hash) -> oneshot::Receiver<Vec<u8>>;
|
||||
/// Note local candidate. Accepts candidate receipt hash and candidate data.
|
||||
/// Pass `None` to clear the candidate.
|
||||
fn set_local_candidate(&self, candidate: Option<(Hash, Vec<u8>)>);
|
||||
|
||||
/// Get BFT message stream for messages corresponding to consensus on given
|
||||
/// parent hash.
|
||||
fn bft_messages(&self, parent_hash: Hash) -> BftMessageStream;
|
||||
fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B>;
|
||||
/// Send out a BFT message.
|
||||
fn send_bft_message(&self, message: LocalizedBftMessage);
|
||||
fn send_bft_message(&self, message: LocalizedBftMessage<B>);
|
||||
}
|
||||
|
||||
/// Service able to execute closure in the network context.
|
||||
pub trait ExecuteInContext: Send + Sync {
|
||||
pub trait ExecuteInContext<B: BlockT>: Send + Sync {
|
||||
/// Execute closure in network context.
|
||||
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, closure: F);
|
||||
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<B>)>(&self, closure: F);
|
||||
}
|
||||
|
||||
/// devp2p Protocol handler
|
||||
struct ProtocolHandler {
|
||||
protocol: Protocol,
|
||||
struct ProtocolHandler<B: BlockT> {
|
||||
protocol: Protocol<B>,
|
||||
}
|
||||
|
||||
/// Peer connection information
|
||||
#[derive(Debug)]
|
||||
pub struct PeerInfo {
|
||||
pub struct PeerInfo<B: BlockT> {
|
||||
/// Public node id
|
||||
pub id: Option<String>,
|
||||
/// Node client ID
|
||||
@@ -133,34 +121,34 @@ pub struct PeerInfo {
|
||||
/// Local endpoint address
|
||||
pub local_address: String,
|
||||
/// Dot protocol info.
|
||||
pub dot_info: Option<ProtocolPeerInfo>,
|
||||
pub dot_info: Option<ProtocolPeerInfo<B>>,
|
||||
}
|
||||
|
||||
/// Service initialization parameters.
|
||||
pub struct Params {
|
||||
pub struct Params<B: BlockT> {
|
||||
/// Configuration.
|
||||
pub config: ProtocolConfig,
|
||||
/// Network layer configuration.
|
||||
pub network_config: NetworkConfiguration,
|
||||
/// Polkadot relay chain access point.
|
||||
pub chain: Arc<Client>,
|
||||
pub chain: Arc<Client<B>>,
|
||||
/// On-demand service reference.
|
||||
pub on_demand: Option<Arc<OnDemandService>>,
|
||||
/// Transaction pool.
|
||||
pub transaction_pool: Arc<TransactionPool>,
|
||||
pub transaction_pool: Arc<TransactionPool<B>>,
|
||||
}
|
||||
|
||||
/// Polkadot network service. Handles network IO and manages connectivity.
|
||||
pub struct Service {
|
||||
pub struct Service<B: BlockT + 'static> where B::Header: HeaderT<Number=u64> {
|
||||
/// Network service
|
||||
network: NetworkService,
|
||||
/// Devp2p protocol handler
|
||||
handler: Arc<ProtocolHandler>,
|
||||
handler: Arc<ProtocolHandler<B>>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
impl<B: BlockT + 'static> Service<B> where B::Header: HeaderT<Number=u64> {
|
||||
/// Creates and register protocol with the network service
|
||||
pub fn new(params: Params) -> Result<Arc<Service>, Error> {
|
||||
pub fn new(params: Params<B>) -> Result<Arc<Service<B>>, Error> {
|
||||
let service = NetworkService::new(params.network_config.clone(), None)?;
|
||||
let sync = Arc::new(Service {
|
||||
network: service,
|
||||
@@ -173,7 +161,7 @@ impl Service {
|
||||
}
|
||||
|
||||
/// Called when a new block is imported by the client.
|
||||
pub fn on_block_imported(&self, hash: HeaderHash, header: &Header) {
|
||||
pub fn on_block_imported(&self, hash: B::Hash, header: &B::Header) {
|
||||
self.network.with_context(DOT_PROTOCOL_ID, |context| {
|
||||
self.handler.protocol.on_block_imported(&mut NetSyncIo::new(context), hash, header)
|
||||
});
|
||||
@@ -199,32 +187,32 @@ impl Service {
|
||||
|
||||
fn stop(&self) {
|
||||
self.handler.protocol.abort();
|
||||
self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
|
||||
self.network.stop();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Service {
|
||||
impl<B: BlockT + 'static> Drop for Service<B> where B::Header: HeaderT<Number=u64> {
|
||||
fn drop(&mut self) {
|
||||
self.stop();
|
||||
}
|
||||
}
|
||||
|
||||
impl ExecuteInContext for Service {
|
||||
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol)>(&self, closure: F) {
|
||||
impl<B: BlockT + 'static> ExecuteInContext<B> for Service<B> where B::Header: HeaderT<Number=u64> {
|
||||
fn execute_in_context<F: Fn(&mut NetSyncIo, &Protocol<B>)>(&self, closure: F) {
|
||||
self.network.with_context(DOT_PROTOCOL_ID, |context| {
|
||||
closure(&mut NetSyncIo::new(context), &self.handler.protocol)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl SyncProvider for Service {
|
||||
impl<B: BlockT + 'static> SyncProvider<B> for Service<B> where B::Header: HeaderT<Number=u64> {
|
||||
/// Get sync status
|
||||
fn status(&self) -> ProtocolStatus {
|
||||
fn status(&self) -> ProtocolStatus<B> {
|
||||
self.handler.protocol.status()
|
||||
}
|
||||
|
||||
/// Get sync peers
|
||||
fn peers(&self) -> Vec<PeerInfo> {
|
||||
fn peers(&self) -> Vec<PeerInfo<B>> {
|
||||
self.network.with_context_eval(DOT_PROTOCOL_ID, |ctx| {
|
||||
let peer_ids = self.network.connected_peers();
|
||||
|
||||
@@ -252,43 +240,23 @@ impl SyncProvider for Service {
|
||||
}
|
||||
|
||||
/// ConsensusService
|
||||
impl ConsensusService for Service {
|
||||
fn statements(&self) -> StatementStream {
|
||||
self.handler.protocol.statements()
|
||||
}
|
||||
|
||||
impl<B: BlockT + 'static> ConsensusService<B> for Service<B> where B::Header: HeaderT<Number=u64> {
|
||||
fn connect_to_authorities(&self, _addresses: &[String]) {
|
||||
//TODO: implement me
|
||||
}
|
||||
|
||||
fn fetch_candidate(&self, hash: &Hash) -> oneshot::Receiver<Vec<u8>> {
|
||||
self.network.with_context_eval(DOT_PROTOCOL_ID, |context| {
|
||||
self.handler.protocol.fetch_candidate(&mut NetSyncIo::new(context), hash)
|
||||
}).expect("DOT Service is registered")
|
||||
}
|
||||
|
||||
fn send_statement(&self, statement: Statement) {
|
||||
self.network.with_context(DOT_PROTOCOL_ID, |context| {
|
||||
self.handler.protocol.send_statement(&mut NetSyncIo::new(context), statement);
|
||||
});
|
||||
}
|
||||
|
||||
fn set_local_candidate(&self, candidate: Option<(Hash, Vec<u8>)>) {
|
||||
self.handler.protocol.set_local_candidate(candidate)
|
||||
}
|
||||
|
||||
fn bft_messages(&self, parent_hash: Hash) -> BftMessageStream {
|
||||
fn bft_messages(&self, parent_hash: B::Hash) -> BftMessageStream<B> {
|
||||
self.handler.protocol.bft_messages(parent_hash)
|
||||
}
|
||||
|
||||
fn send_bft_message(&self, message: LocalizedBftMessage) {
|
||||
fn send_bft_message(&self, message: LocalizedBftMessage<B>) {
|
||||
self.network.with_context(DOT_PROTOCOL_ID, |context| {
|
||||
self.handler.protocol.send_bft_message(&mut NetSyncIo::new(context), message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkProtocolHandler for ProtocolHandler {
|
||||
impl<B: BlockT + 'static> NetworkProtocolHandler for ProtocolHandler<B> where B::Header: HeaderT<Number=u64> {
|
||||
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
|
||||
io.register_timer(TICK_TOKEN, TICK_TIMEOUT)
|
||||
.expect("Error registering sync timer");
|
||||
@@ -319,7 +287,7 @@ impl NetworkProtocolHandler for ProtocolHandler {
|
||||
}
|
||||
|
||||
/// Trait for managing network
|
||||
pub trait ManageNetwork : Send + Sync {
|
||||
pub trait ManageNetwork: Send + Sync {
|
||||
/// Set to allow unreserved peers to connect
|
||||
fn accept_unreserved_peers(&self);
|
||||
/// Set to deny unreserved peers to connect
|
||||
@@ -335,7 +303,7 @@ pub trait ManageNetwork : Send + Sync {
|
||||
}
|
||||
|
||||
|
||||
impl ManageNetwork for Service {
|
||||
impl<B: BlockT + 'static> ManageNetwork for Service<B> where B::Header: HeaderT<Number=u64> {
|
||||
fn accept_unreserved_peers(&self) {
|
||||
self.network.set_non_reserved_mode(NonReservedPeerMode::Accept);
|
||||
}
|
||||
|
||||
@@ -19,38 +19,38 @@ use io::SyncIo;
|
||||
use protocol::Protocol;
|
||||
use network::PeerId;
|
||||
use client::{ImportResult, BlockStatus, ClientInfo};
|
||||
use primitives::block::{HeaderHash, Number as BlockNumber, Header, Id as BlockId};
|
||||
use blocks::{self, BlockCollection};
|
||||
use message::{self, Message};
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use message::{self, generic::Message as GenericMessage};
|
||||
use service::Role;
|
||||
use super::header_hash;
|
||||
|
||||
// Maximum blocks to request in a single packet.
|
||||
const MAX_BLOCKS_TO_REQUEST: usize = 128;
|
||||
|
||||
struct PeerSync {
|
||||
pub common_hash: HeaderHash,
|
||||
pub common_number: BlockNumber,
|
||||
pub best_hash: HeaderHash,
|
||||
pub best_number: BlockNumber,
|
||||
pub state: PeerSyncState,
|
||||
struct PeerSync<B: BlockT> {
|
||||
pub common_hash: B::Hash,
|
||||
pub common_number: <B::Header as HeaderT>::Number,
|
||||
pub best_hash: B::Hash,
|
||||
pub best_number: <B::Header as HeaderT>::Number,
|
||||
pub state: PeerSyncState<B>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
enum PeerSyncState {
|
||||
AncestorSearch(BlockNumber),
|
||||
enum PeerSyncState<B: BlockT> {
|
||||
AncestorSearch(<B::Header as HeaderT>::Number),
|
||||
Available,
|
||||
DownloadingNew(BlockNumber),
|
||||
DownloadingStale(HeaderHash),
|
||||
DownloadingNew(<B::Header as HeaderT>::Number),
|
||||
DownloadingStale(B::Hash),
|
||||
}
|
||||
|
||||
/// Relay chain sync strategy.
|
||||
pub struct ChainSync {
|
||||
genesis_hash: HeaderHash,
|
||||
peers: HashMap<PeerId, PeerSync>,
|
||||
blocks: BlockCollection,
|
||||
best_queued_number: BlockNumber,
|
||||
best_queued_hash: HeaderHash,
|
||||
pub struct ChainSync<B: BlockT> {
|
||||
genesis_hash: B::Hash,
|
||||
peers: HashMap<PeerId, PeerSync<B>>,
|
||||
blocks: BlockCollection<B>,
|
||||
best_queued_number: u64,
|
||||
best_queued_hash: B::Hash,
|
||||
required_block_attributes: Vec<message::BlockAttribute>,
|
||||
}
|
||||
|
||||
@@ -65,16 +65,18 @@ pub enum SyncState {
|
||||
|
||||
/// Syncing status and statistics
|
||||
#[derive(Clone)]
|
||||
pub struct Status {
|
||||
pub struct Status<B: BlockT> {
|
||||
/// Current global sync state.
|
||||
pub state: SyncState,
|
||||
/// Target sync block number.
|
||||
pub best_seen_block: Option<BlockNumber>,
|
||||
pub best_seen_block: Option<<B::Header as HeaderT>::Number>,
|
||||
}
|
||||
|
||||
impl ChainSync {
|
||||
impl<B: BlockT> ChainSync<B> where
|
||||
B::Header: HeaderT<Number=u64>,
|
||||
{
|
||||
/// Create a new instance.
|
||||
pub fn new(role: Role, info: &ClientInfo) -> ChainSync {
|
||||
pub fn new(role: Role, info: &ClientInfo<B>) -> Self {
|
||||
let mut required_block_attributes = vec![
|
||||
message::BlockAttribute::Header,
|
||||
message::BlockAttribute::Justification
|
||||
@@ -93,12 +95,12 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
|
||||
fn best_seen_block(&self) -> Option<BlockNumber> {
|
||||
fn best_seen_block(&self) -> Option<u64> {
|
||||
self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number)
|
||||
}
|
||||
|
||||
/// Returns sync status
|
||||
pub fn status(&self) -> Status {
|
||||
pub fn status(&self) -> Status<B> {
|
||||
let best_seen = self.best_seen_block();
|
||||
let state = match &best_seen {
|
||||
&Some(n) if n > self.best_queued_number && n - self.best_queued_number > 5 => SyncState::Downloading,
|
||||
@@ -111,7 +113,7 @@ impl ChainSync {
|
||||
}
|
||||
|
||||
/// Handle new connected peer.
|
||||
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
|
||||
pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId) {
|
||||
if let Some(info) = protocol.peer_info(peer_id) {
|
||||
match (protocol.chain().block_status(&BlockId::Hash(info.best_hash)), info.best_number) {
|
||||
(Err(e), _) => {
|
||||
@@ -165,7 +167,7 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_block_data(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, _request: message::BlockRequest, response: message::BlockResponse) {
|
||||
pub fn on_block_data(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, _request: message::BlockRequest<B>, response: message::BlockResponse<B>) {
|
||||
let count = response.blocks.len();
|
||||
let mut imported: usize = 0;
|
||||
let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
@@ -235,9 +237,9 @@ impl ChainSync {
|
||||
let block = block.block;
|
||||
match (block.header, block.justification) {
|
||||
(Some(header), Some(justification)) => {
|
||||
let number = header.number;
|
||||
let hash = header_hash(&header);
|
||||
let parent = header.parent_hash;
|
||||
let number = header.number().clone();
|
||||
let hash = header.hash();
|
||||
let parent = header.parent_hash().clone();
|
||||
let is_best = best_seen.as_ref().map_or(false, |n| number >= *n);
|
||||
|
||||
// check whether the block is known before importing.
|
||||
@@ -305,14 +307,14 @@ impl ChainSync {
|
||||
self.maintain_sync(io, protocol);
|
||||
}
|
||||
|
||||
fn maintain_sync(&mut self, io: &mut SyncIo, protocol: &Protocol) {
|
||||
fn maintain_sync(&mut self, io: &mut SyncIo, protocol: &Protocol<B>) {
|
||||
let peers: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
|
||||
for peer in peers {
|
||||
self.download_new(io, protocol, peer);
|
||||
}
|
||||
}
|
||||
|
||||
fn block_imported(&mut self, hash: &HeaderHash, number: BlockNumber) {
|
||||
fn block_imported(&mut self, hash: &B::Hash, number: u64) {
|
||||
if number > self.best_queued_number {
|
||||
self.best_queued_number = number;
|
||||
self.best_queued_hash = *hash;
|
||||
@@ -327,28 +329,29 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_chain_info(&mut self, best_header: &Header ) {
|
||||
let hash = header_hash(&best_header);
|
||||
self.block_imported(&hash, best_header.number)
|
||||
pub fn update_chain_info(&mut self, best_header: &B::Header) {
|
||||
let hash = best_header.hash();
|
||||
self.block_imported(&hash, best_header.number().clone())
|
||||
}
|
||||
|
||||
pub fn on_block_announce(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: HeaderHash, header: &Header) {
|
||||
pub fn on_block_announce(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, hash: B::Hash, header: &B::Header) {
|
||||
let number = *header.number();
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
if header.number > peer.best_number {
|
||||
peer.best_number = header.number;
|
||||
if number > peer.best_number {
|
||||
peer.best_number = number;
|
||||
peer.best_hash = hash;
|
||||
}
|
||||
if header.number <= self.best_queued_number && header.number > peer.common_number {
|
||||
peer.common_number = header.number;
|
||||
if number <= self.best_queued_number && number > peer.common_number {
|
||||
peer.common_number = number
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if !self.is_known_or_already_downloading(protocol, &hash) {
|
||||
let stale = header.number <= self.best_queued_number;
|
||||
let stale = number <= self.best_queued_number;
|
||||
if stale {
|
||||
if !self.is_known_or_already_downloading(protocol, &header.parent_hash) {
|
||||
if !self.is_known_or_already_downloading(protocol, header.parent_hash()) {
|
||||
trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", peer_id, hash, header);
|
||||
} else {
|
||||
trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", peer_id, hash, header);
|
||||
@@ -363,18 +366,18 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_known_or_already_downloading(&self, protocol: &Protocol, hash: &HeaderHash) -> bool {
|
||||
fn is_known_or_already_downloading(&self, protocol: &Protocol<B>, hash: &B::Hash) -> bool {
|
||||
self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash))
|
||||
|| protocol.chain().block_status(&BlockId::Hash(*hash)).ok().map_or(false, |s| s != BlockStatus::Unknown)
|
||||
}
|
||||
|
||||
pub fn peer_disconnected(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
|
||||
pub fn peer_disconnected(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId) {
|
||||
self.blocks.clear_peer_download(peer_id);
|
||||
self.peers.remove(&peer_id);
|
||||
self.maintain_sync(io, protocol);
|
||||
}
|
||||
|
||||
pub fn restart(&mut self, io: &mut SyncIo, protocol: &Protocol) {
|
||||
pub fn restart(&mut self, io: &mut SyncIo, protocol: &Protocol<B>) {
|
||||
self.blocks.clear();
|
||||
let ids: Vec<PeerId> = self.peers.keys().map(|p| *p).collect();
|
||||
for id in ids {
|
||||
@@ -399,11 +402,11 @@ impl ChainSync {
|
||||
}
|
||||
|
||||
// Download old block.
|
||||
fn download_stale(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, hash: &HeaderHash) {
|
||||
fn download_stale(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, hash: &B::Hash) {
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
match peer.state {
|
||||
PeerSyncState::Available => {
|
||||
let request = message::BlockRequest {
|
||||
let request = message::generic::BlockRequest {
|
||||
id: 0,
|
||||
fields: self.required_block_attributes.clone(),
|
||||
from: message::FromBlock::Hash(*hash),
|
||||
@@ -412,7 +415,7 @@ impl ChainSync {
|
||||
max: Some(1),
|
||||
};
|
||||
peer.state = PeerSyncState::DownloadingStale(*hash);
|
||||
protocol.send_message(io, peer_id, Message::BlockRequest(request));
|
||||
protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request));
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
@@ -420,14 +423,14 @@ impl ChainSync {
|
||||
}
|
||||
|
||||
// Issue a request for a peer to download new blocks, if any are available
|
||||
fn download_new(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId) {
|
||||
fn download_new(&mut self, io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId) {
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&peer_id) {
|
||||
trace!(target: "sync", "Considering new block download from {}, common block is {}, best is {:?}", peer_id, peer.common_number, peer.best_number);
|
||||
match peer.state {
|
||||
PeerSyncState::Available => {
|
||||
if let Some(range) = self.blocks.needed_blocks(peer_id, MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) {
|
||||
trace!(target: "sync", "Requesting blocks from {}, ({} to {})", peer_id, range.start, range.end);
|
||||
let request = message::BlockRequest {
|
||||
let request = message::generic::BlockRequest {
|
||||
id: 0,
|
||||
fields: self.required_block_attributes.clone(),
|
||||
from: message::FromBlock::Number(range.start),
|
||||
@@ -436,7 +439,7 @@ impl ChainSync {
|
||||
max: Some((range.end - range.start) as u32),
|
||||
};
|
||||
peer.state = PeerSyncState::DownloadingNew(range.start);
|
||||
protocol.send_message(io, peer_id, Message::BlockRequest(request));
|
||||
protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request));
|
||||
} else {
|
||||
trace!(target: "sync", "Nothing to request");
|
||||
}
|
||||
@@ -446,9 +449,9 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
|
||||
fn request_ancestry(io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, block: BlockNumber) {
|
||||
fn request_ancestry(io: &mut SyncIo, protocol: &Protocol<B>, peer_id: PeerId, block: u64) {
|
||||
trace!(target: "sync", "Requesting ancestry block #{} from {}", block, peer_id);
|
||||
let request = message::BlockRequest {
|
||||
let request = message::generic::BlockRequest {
|
||||
id: 0,
|
||||
fields: vec![message::BlockAttribute::Header, message::BlockAttribute::Justification],
|
||||
from: message::FromBlock::Number(block),
|
||||
@@ -456,6 +459,6 @@ impl ChainSync {
|
||||
direction: message::Direction::Ascending,
|
||||
max: Some(1),
|
||||
};
|
||||
protocol.send_message(io, peer_id, Message::BlockRequest(request));
|
||||
protocol.send_message(io, peer_id, GenericMessage::BlockRequest(request));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use message::*;
|
||||
use message::{Message, generic};
|
||||
use futures::Stream;
|
||||
use test_client::runtime::Block;
|
||||
|
||||
#[test]
|
||||
fn bft_messages_include_those_sent_before_asking_for_stream() {
|
||||
@@ -28,21 +29,22 @@ fn bft_messages_include_those_sent_before_asking_for_stream() {
|
||||
|
||||
let peer = net.peer(0);
|
||||
let mut io = TestIo::new(&peer.queue, None);
|
||||
let bft_message = BftMessage::Consensus(SignedConsensusMessage::Vote(SignedConsensusVote {
|
||||
vote: ConsensusVote::AdvanceRound(0),
|
||||
let bft_message = generic::BftMessage::Consensus(generic::SignedConsensusMessage::Vote(generic::SignedConsensusVote {
|
||||
vote: generic::ConsensusVote::AdvanceRound(0),
|
||||
sender: [0; 32],
|
||||
signature: Default::default(),
|
||||
}));
|
||||
|
||||
let parent_hash = peer.genesis_hash();
|
||||
|
||||
let localized = LocalizedBftMessage {
|
||||
let localized = ::message::LocalizedBftMessage::<Block> {
|
||||
message: bft_message,
|
||||
parent_hash: parent_hash,
|
||||
};
|
||||
|
||||
let message: Message<Block> = generic::Message::BftMessage(localized.clone());
|
||||
|
||||
let as_bytes = ::serde_json::to_vec(&Message::BftMessage(localized.clone())).unwrap();
|
||||
let as_bytes = ::serde_json::to_vec(&message).unwrap();
|
||||
peer.sync.handle_packet(&mut io, 1, &as_bytes[..]);
|
||||
|
||||
let stream = peer.sync.bft_messages(parent_hash);
|
||||
|
||||
@@ -23,17 +23,17 @@ use std::sync::Arc;
|
||||
use parking_lot::RwLock;
|
||||
use client;
|
||||
use client::block_builder::BlockBuilder;
|
||||
use primitives::block::{Id as BlockId, ExtrinsicHash, HeaderHash};
|
||||
use primitives;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use io::SyncIo;
|
||||
use protocol::Protocol;
|
||||
use config::ProtocolConfig;
|
||||
use service::TransactionPool;
|
||||
use network::{PeerId, SessionInfo, Error as NetworkError};
|
||||
use runtime_support::Hashable;
|
||||
use keyring::Keyring;
|
||||
use codec::Slicable;
|
||||
use test_client::{self, TestClient};
|
||||
use test_client::runtime::{Block, Hash, Transfer, Extrinsic};
|
||||
|
||||
pub struct TestIo<'p> {
|
||||
pub queue: &'p RwLock<VecDeque<TestPacket>>,
|
||||
@@ -100,8 +100,8 @@ pub struct TestPacket {
|
||||
}
|
||||
|
||||
pub struct Peer {
|
||||
client: Arc<client::Client<test_client::Backend, test_client::Executor>>,
|
||||
pub sync: Protocol,
|
||||
client: Arc<client::Client<test_client::Backend, test_client::Executor, Block>>,
|
||||
pub sync: Protocol<Block>,
|
||||
pub queue: RwLock<VecDeque<TestPacket>>,
|
||||
}
|
||||
|
||||
@@ -158,12 +158,12 @@ impl Peer {
|
||||
fn flush(&self) {
|
||||
}
|
||||
|
||||
fn generate_blocks<F>(&self, count: usize, mut edit_block: F) where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor>) {
|
||||
fn generate_blocks<F>(&self, count: usize, mut edit_block: F) where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor, Block>) {
|
||||
for _ in 0 .. count {
|
||||
let mut builder = self.client.new_block().unwrap();
|
||||
edit_block(&mut builder);
|
||||
let block = builder.bake().unwrap();
|
||||
trace!("Generating {}, (#{})", primitives::block::HeaderHash::from(block.header.blake2_256()), block.header.number);
|
||||
trace!("Generating {}, (#{})", block.hash(), block.header.number);
|
||||
self.client.justify_and_import(client::BlockOrigin::File, block).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -172,15 +172,14 @@ impl Peer {
|
||||
let mut nonce = 0;
|
||||
if with_tx {
|
||||
self.generate_blocks(count, |builder| {
|
||||
let tx = test_client::runtime::Transaction {
|
||||
from: Keyring::Alice.to_raw_public(),
|
||||
to: Keyring::Alice.to_raw_public(),
|
||||
let transfer = Transfer {
|
||||
from: Keyring::Alice.to_raw_public().into(),
|
||||
to: Keyring::Alice.to_raw_public().into(),
|
||||
amount: 1,
|
||||
nonce: nonce,
|
||||
nonce,
|
||||
};
|
||||
let signature = Keyring::from_raw_public(tx.from.clone()).unwrap().sign(&tx.encode());
|
||||
let tx = primitives::block::Extrinsic::decode(&mut test_client::runtime::UncheckedTransaction { signature, tx: tx }.encode().as_ref()).unwrap();
|
||||
builder.push(tx).unwrap();
|
||||
let signature = Keyring::from_raw_public(transfer.from.0).unwrap().sign(&transfer.encode()).into();
|
||||
builder.push(Extrinsic { transfer, signature }).unwrap();
|
||||
nonce = nonce + 1;
|
||||
});
|
||||
} else {
|
||||
@@ -188,7 +187,7 @@ impl Peer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genesis_hash(&self) -> HeaderHash {
|
||||
pub fn genesis_hash(&self) -> Hash {
|
||||
let info = self.client.info().expect("In-mem client does not fail");
|
||||
info.chain.genesis_hash
|
||||
}
|
||||
@@ -196,16 +195,16 @@ impl Peer {
|
||||
|
||||
struct EmptyTransactionPool;
|
||||
|
||||
impl TransactionPool for EmptyTransactionPool {
|
||||
fn transactions(&self) -> Vec<(ExtrinsicHash, Vec<u8>)> {
|
||||
impl TransactionPool<Block> for EmptyTransactionPool {
|
||||
fn transactions(&self) -> Vec<(Hash, Extrinsic)> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn import(&self, _transaction: &[u8]) -> Option<ExtrinsicHash> {
|
||||
fn import(&self, _transaction: &Extrinsic) -> Option<Hash> {
|
||||
None
|
||||
}
|
||||
|
||||
fn on_broadcasted(&self, _: HashMap<ExtrinsicHash, Vec<String>>) {}
|
||||
fn on_broadcasted(&self, _: HashMap<Hash, Vec<String>>) {}
|
||||
}
|
||||
|
||||
pub struct TestNet {
|
||||
|
||||
@@ -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
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_h160() {
|
||||
let tests = vec![
|
||||
(H160::from(0), "0x0000000000000000000000000000000000000000"),
|
||||
(Default::default(), "0x0000000000000000000000000000000000000000"),
|
||||
(H160::from(2), "0x0000000000000000000000000000000000000002"),
|
||||
(H160::from(15), "0x000000000000000000000000000000000000000f"),
|
||||
(H160::from(16), "0x0000000000000000000000000000000000000010"),
|
||||
@@ -84,7 +84,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_h256() {
|
||||
let tests = vec![
|
||||
(H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
(Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
(H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"),
|
||||
(H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"),
|
||||
(H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"),
|
||||
|
||||
@@ -54,17 +54,6 @@ extern crate substrate_serializer;
|
||||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
|
||||
// TODO: factor out to separate crate.
|
||||
#[macro_export]
|
||||
macro_rules! try_opt {
|
||||
($e: expr) => {
|
||||
match $e {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! map {
|
||||
($( $name:expr => $value:expr ),*) => (
|
||||
@@ -82,8 +71,6 @@ pub use hashing::{blake2_256, twox_128, twox_256};
|
||||
#[cfg(feature = "std")]
|
||||
pub mod hexdisplay;
|
||||
|
||||
pub mod bft;
|
||||
pub mod block;
|
||||
pub mod hash;
|
||||
pub mod sandbox;
|
||||
pub mod storage;
|
||||
@@ -92,12 +79,8 @@ pub mod uint;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::hash::{H160, H256};
|
||||
pub use self::hash::{H160, H256, H512};
|
||||
pub use self::uint::{U256, U512};
|
||||
pub use block::{Block, Header, Digest};
|
||||
|
||||
/// General hash type.
|
||||
pub type Hash = H256;
|
||||
|
||||
/// An identifier for an authority in the consensus algorithm. The same as ed25519::Public.
|
||||
pub type AuthorityId = [u8; 32];
|
||||
|
||||
@@ -10,3 +10,4 @@ jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git" }
|
||||
jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git" }
|
||||
log = "0.3"
|
||||
substrate-rpc = { path = "../rpc", version = "0.1" }
|
||||
substrate-runtime-primitives = { path = "../runtime/primitives" }
|
||||
|
||||
@@ -24,25 +24,28 @@ extern crate jsonrpc_core as rpc;
|
||||
extern crate jsonrpc_http_server as http;
|
||||
extern crate jsonrpc_pubsub as pubsub;
|
||||
extern crate jsonrpc_ws_server as ws;
|
||||
extern crate substrate_runtime_primitives;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::io;
|
||||
use substrate_runtime_primitives::traits::Block as BlockT;
|
||||
|
||||
type Metadata = apis::metadata::Metadata;
|
||||
type RpcHandler = pubsub::PubSubHandler<Metadata>;
|
||||
|
||||
/// Construct rpc `IoHandler`
|
||||
pub fn rpc_handler<S, C, A, Y>(
|
||||
pub fn rpc_handler<Block: BlockT, S, C, A, Y>(
|
||||
state: S,
|
||||
chain: C,
|
||||
author: A,
|
||||
system: Y,
|
||||
) -> RpcHandler where
|
||||
S: apis::state::StateApi,
|
||||
C: apis::chain::ChainApi<Metadata=Metadata>,
|
||||
A: apis::author::AuthorApi,
|
||||
Block: 'static,
|
||||
S: apis::state::StateApi<Block::Hash>,
|
||||
C: apis::chain::ChainApi<Block::Hash, Block::Header, Metadata=Metadata>,
|
||||
A: apis::author::AuthorApi<Block::Hash, Block::Extrinsic>,
|
||||
Y: apis::system::SystemApi,
|
||||
{
|
||||
let mut io = pubsub::PubSubHandler::default();
|
||||
|
||||
@@ -14,6 +14,7 @@ substrate-client = { path = "../client" }
|
||||
substrate-executor = { path = "../executor" }
|
||||
substrate-extrinsic-pool = { path = "../extrinsic-pool" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
substrate-runtime-primitives = { path = "../runtime/primitives" }
|
||||
substrate-state-machine = { path = "../state-machine" }
|
||||
tokio-core = "0.1.12"
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
//! Substrate block-author/full-node API.
|
||||
|
||||
use std::sync::Arc;
|
||||
use primitives::block::{Extrinsic, ExtrinsicHash};
|
||||
use extrinsic_pool::api::{Error, ExtrinsicPool};
|
||||
|
||||
pub mod error;
|
||||
@@ -29,17 +28,18 @@ use self::error::Result;
|
||||
|
||||
build_rpc_trait! {
|
||||
/// Substrate authoring RPC API
|
||||
pub trait AuthorApi {
|
||||
pub trait AuthorApi<Hash, Extrinsic> {
|
||||
/// Submit extrinsic for inclusion in block.
|
||||
#[rpc(name = "author_submitExtrinsic")]
|
||||
fn submit_extrinsic(&self, Extrinsic) -> Result<ExtrinsicHash>;
|
||||
fn submit_extrinsic(&self, Extrinsic) -> Result<Hash>;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AuthorApi for Arc<T> where
|
||||
T: ExtrinsicPool,
|
||||
impl<Ex, Hash, T> AuthorApi<Hash, Ex> for Arc<T> where
|
||||
T: ExtrinsicPool<Ex, Hash>,
|
||||
T::Error: 'static,
|
||||
{
|
||||
fn submit_extrinsic(&self, xt: Extrinsic) -> Result<ExtrinsicHash> {
|
||||
fn submit_extrinsic(&self, xt: Ex) -> Result<Hash> {
|
||||
self
|
||||
.submit(vec![xt])
|
||||
.map(|mut res| res.pop().expect("One extrinsic passed; one result back; qed"))
|
||||
|
||||
@@ -19,11 +19,13 @@ use super::*;
|
||||
use std::{fmt, sync::Arc};
|
||||
use extrinsic_pool::api;
|
||||
use parking_lot::Mutex;
|
||||
use primitives::block;
|
||||
|
||||
type Extrinsic = u64;
|
||||
type Hash = u64;
|
||||
|
||||
#[derive(Default)]
|
||||
struct DummyTxPool {
|
||||
submitted: Mutex<Vec<block::Extrinsic>>,
|
||||
submitted: Mutex<Vec<Extrinsic>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -38,14 +40,14 @@ impl fmt::Display for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl api::ExtrinsicPool for DummyTxPool {
|
||||
impl api::ExtrinsicPool<Extrinsic, Hash> for DummyTxPool {
|
||||
type Error = Error;
|
||||
|
||||
/// Submit extrinsic for inclusion in block.
|
||||
fn submit(&self, xt: Vec<Extrinsic>) -> ::std::result::Result<Vec<ExtrinsicHash>, Self::Error> {
|
||||
fn submit(&self, xt: Vec<Extrinsic>) -> ::std::result::Result<Vec<Hash>, Self::Error> {
|
||||
let mut submitted = self.submitted.lock();
|
||||
if submitted.len() < 1 {
|
||||
let hashes = xt.iter().map(|_xt| 1.into()).collect();
|
||||
let hashes = xt.iter().map(|_xt| 1).collect();
|
||||
submitted.extend(xt);
|
||||
Ok(hashes)
|
||||
} else {
|
||||
@@ -57,13 +59,12 @@ impl api::ExtrinsicPool for DummyTxPool {
|
||||
#[test]
|
||||
fn submit_transaction_should_not_cause_error() {
|
||||
let p = Arc::new(DummyTxPool::default());
|
||||
let hash: ExtrinsicHash = 1.into();
|
||||
|
||||
assert_matches!(
|
||||
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])),
|
||||
Ok(hash)
|
||||
AuthorApi::submit_extrinsic(&p, 5),
|
||||
Ok(1)
|
||||
);
|
||||
assert!(
|
||||
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])).is_err()
|
||||
AuthorApi::submit_extrinsic(&p, 5).is_err()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use primitives::block;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use client::{self, Client, BlockchainEvents};
|
||||
use state_machine;
|
||||
|
||||
@@ -38,23 +39,23 @@ use self::error::{Result, ResultExt};
|
||||
|
||||
build_rpc_trait! {
|
||||
/// Polkadot blockchain API
|
||||
pub trait ChainApi {
|
||||
pub trait ChainApi<Hash, Header> {
|
||||
type Metadata;
|
||||
|
||||
/// Get header of a relay chain block.
|
||||
#[rpc(name = "chain_getHeader")]
|
||||
fn header(&self, block::HeaderHash) -> Result<Option<block::Header>>;
|
||||
fn header(&self, Hash) -> Result<Option<Header>>;
|
||||
|
||||
/// Get hash of the head.
|
||||
#[rpc(name = "chain_getHead")]
|
||||
fn head(&self) -> Result<block::HeaderHash>;
|
||||
fn head(&self) -> Result<Hash>;
|
||||
|
||||
#[pubsub(name = "chain_newHead")] {
|
||||
/// Hello subscription
|
||||
/// New head subscription
|
||||
#[rpc(name = "subscribe_newHead")]
|
||||
fn subscribe_new_head(&self, Self::Metadata, pubsub::Subscriber<block::Header>);
|
||||
fn subscribe_new_head(&self, Self::Metadata, pubsub::Subscriber<Header>);
|
||||
|
||||
/// Unsubscribe from hello subscription.
|
||||
/// Unsubscribe from new head subscription.
|
||||
#[rpc(name = "unsubscribe_newHead")]
|
||||
fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>;
|
||||
}
|
||||
@@ -62,16 +63,16 @@ build_rpc_trait! {
|
||||
}
|
||||
|
||||
/// Chain API with subscriptions support.
|
||||
pub struct Chain<B, E> {
|
||||
pub struct Chain<B, E, Block: BlockT> {
|
||||
/// Substrate client.
|
||||
client: Arc<Client<B, E>>,
|
||||
client: Arc<Client<B, E, Block>>,
|
||||
/// Current subscriptions.
|
||||
subscriptions: Subscriptions,
|
||||
}
|
||||
|
||||
impl<B, E> Chain<B, E> {
|
||||
impl<B, E, Block: BlockT> Chain<B, E, Block> {
|
||||
/// Create new Chain API RPC handler.
|
||||
pub fn new(client: Arc<Client<B, E>>, remote: Remote) -> Self {
|
||||
pub fn new(client: Arc<Client<B, E, Block>>, remote: Remote) -> Self {
|
||||
Chain {
|
||||
client,
|
||||
subscriptions: Subscriptions::new(remote),
|
||||
@@ -79,22 +80,23 @@ impl<B, E> Chain<B, E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> ChainApi for Chain<B, E> where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: client::CallExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
impl<B, E, Block> ChainApi<Block::Hash, Block::Header> for Chain<B, E, Block> where
|
||||
Block: BlockT + 'static,
|
||||
B: client::backend::Backend<Block> + Send + Sync + 'static,
|
||||
E: client::CallExecutor<Block> + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
type Metadata = ::metadata::Metadata;
|
||||
|
||||
fn header(&self, hash: block::HeaderHash) -> Result<Option<block::Header>> {
|
||||
self.client.header(&block::Id::Hash(hash)).chain_err(|| "Blockchain error")
|
||||
fn header(&self, hash: Block::Hash) -> Result<Option<Block::Header>> {
|
||||
self.client.header(&BlockId::Hash(hash)).chain_err(|| "Blockchain error")
|
||||
}
|
||||
|
||||
fn head(&self) -> Result<block::HeaderHash> {
|
||||
fn head(&self) -> Result<Block::Hash> {
|
||||
Ok(self.client.info().chain_err(|| "Blockchain error")?.chain.best_hash)
|
||||
}
|
||||
|
||||
fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber<block::Header>) {
|
||||
fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber<Block::Header>) {
|
||||
self.subscriptions.add(subscriber, |sink| {
|
||||
let stream = self.client.import_notification_stream()
|
||||
.filter(|notification| notification.is_new_best)
|
||||
|
||||
@@ -18,6 +18,7 @@ use super::*;
|
||||
use jsonrpc_macros::pubsub;
|
||||
use client::BlockOrigin;
|
||||
use test_client::{self, TestClient};
|
||||
use test_client::runtime::Header;
|
||||
|
||||
#[test]
|
||||
fn should_return_header() {
|
||||
@@ -30,10 +31,10 @@ fn should_return_header() {
|
||||
};
|
||||
assert_matches!(
|
||||
client.header(client.client.genesis_hash()),
|
||||
Ok(Some(ref x)) if x == &block::Header {
|
||||
Ok(Some(ref x)) if x == &Header {
|
||||
parent_hash: 0.into(),
|
||||
number: 0,
|
||||
state_root: "0c81ab6cfac8c8d7201d78cb699b6b79d714462a4ba00abcacce22444babe315".into(),
|
||||
state_root: "9c70014029b05f780858f654bfcf297ca708b3663d32bc81486193e84a2f2f3d".into(),
|
||||
extrinsics_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into(),
|
||||
digest: Default::default(),
|
||||
}
|
||||
@@ -69,7 +70,7 @@ fn should_notify_about_latest_block() {
|
||||
// assert notification send to transport
|
||||
let (notification, next) = core.run(transport.into_future()).unwrap();
|
||||
assert_eq!(notification, Some(
|
||||
r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x72ae67388233893fb4594f13df56d4e654aa8721763bcd0bd4e187fee7b2f349","stateRoot":"0x2e1f2f1c53ffb1767fe1abf4fe5953cc87c7650d4af2d4393d1f72324f2cc5d7"},"subscription":0}}"#.to_owned()
|
||||
r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x45a44c50cae6ffcc413b65d6b4444a572fa4be2e5d1cd026cc113f9d8f9bc368","stateRoot":"0x987aa0851a133413b42c6d9aa3c91b1dddc2ad5337508ee8815116b11e44c64d"},"subscription":0}}"#.to_owned()
|
||||
));
|
||||
// no more notifications on this channel
|
||||
assert_eq!(core.run(next.into_future()).unwrap().0, None);
|
||||
|
||||
@@ -24,6 +24,7 @@ extern crate parking_lot;
|
||||
extern crate substrate_client as client;
|
||||
extern crate substrate_extrinsic_pool as extrinsic_pool;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_runtime_primitives as runtime_primitives;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
extern crate tokio_core;
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ mod tests;
|
||||
|
||||
use std::sync::Arc;
|
||||
use client::{self, Client, CallExecutor};
|
||||
use primitives::{block, Hash, blake2_256};
|
||||
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
use primitives::storage::{StorageKey, StorageData};
|
||||
use primitives::hexdisplay::HexDisplay;
|
||||
use state_machine;
|
||||
@@ -32,65 +34,67 @@ use self::error::Result;
|
||||
|
||||
build_rpc_trait! {
|
||||
/// Polkadot state API
|
||||
pub trait StateApi {
|
||||
/// Returns a storage entry.
|
||||
pub trait StateApi<Hash> {
|
||||
/// Returns a storage entry at a specific block's state.
|
||||
#[rpc(name = "state_getStorageAt")]
|
||||
fn storage_at(&self, StorageKey, block::HeaderHash) -> Result<StorageData>;
|
||||
fn storage_at(&self, StorageKey, Hash) -> Result<StorageData>;
|
||||
|
||||
/// Call a contract.
|
||||
/// Call a contract at a block's state.
|
||||
#[rpc(name = "state_callAt")]
|
||||
fn call_at(&self, String, Vec<u8>, block::HeaderHash) -> Result<Vec<u8>>;
|
||||
fn call_at(&self, String, Vec<u8>, Hash) -> Result<Vec<u8>>;
|
||||
|
||||
/// Returns the hash of a storage entry.
|
||||
/// Returns the hash of a storage entry at a block's state.
|
||||
#[rpc(name = "state_getStorageHashAt")]
|
||||
fn storage_hash_at(&self, StorageKey, block::HeaderHash) -> Result<Hash>;
|
||||
fn storage_hash_at(&self, StorageKey, Hash) -> Result<Hash>;
|
||||
|
||||
/// Returns the size of a storage entry.
|
||||
/// Returns the size of a storage entry at a block's state.
|
||||
#[rpc(name = "state_getStorageSizeAt")]
|
||||
fn storage_size_at(&self, StorageKey, block::HeaderHash) -> Result<u64>;
|
||||
fn storage_size_at(&self, StorageKey, Hash) -> Result<u64>;
|
||||
|
||||
/// Returns the hash of a storage entry.
|
||||
/// Returns the hash of a storage entry at the best block.
|
||||
#[rpc(name = "state_getStorageHash")]
|
||||
fn storage_hash(&self, StorageKey) -> Result<Hash>;
|
||||
|
||||
/// Returns the size of a storage entry.
|
||||
/// Returns the size of a storage entry at the best block.
|
||||
#[rpc(name = "state_getStorageSize")]
|
||||
fn storage_size(&self, StorageKey) -> Result<u64>;
|
||||
|
||||
/// Returns a storage entry.
|
||||
/// Returns a storage entry at the best block.
|
||||
#[rpc(name = "state_getStorage")]
|
||||
fn storage(&self, StorageKey) -> Result<StorageData>;
|
||||
|
||||
/// Call a contract.
|
||||
/// Call a contract at the best block.
|
||||
#[rpc(name = "state_call")]
|
||||
fn call(&self, String, Vec<u8>) -> Result<Vec<u8>>;
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> StateApi for Arc<Client<B, E>> where
|
||||
B: client::backend::Backend + Send + Sync + 'static,
|
||||
E: CallExecutor + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
impl<B, E, Block> StateApi<Block::Hash> for Arc<Client<B, E, Block>> where
|
||||
Block: BlockT + 'static,
|
||||
B: client::backend::Backend<Block> + Send + Sync + 'static,
|
||||
E: CallExecutor<Block> + Send + Sync + 'static,
|
||||
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
fn storage_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<StorageData> {
|
||||
fn storage_at(&self, key: StorageKey, block: Block::Hash) -> Result<StorageData> {
|
||||
trace!(target: "rpc", "Querying storage at {:?} for key {}", block, HexDisplay::from(&key.0));
|
||||
Ok(self.as_ref().storage(&block::Id::Hash(block), &key)?)
|
||||
Ok(self.as_ref().storage(&BlockId::Hash(block), &key)?)
|
||||
}
|
||||
|
||||
fn call_at(&self, method: String, data: Vec<u8>, block: block::HeaderHash) -> Result<Vec<u8>> {
|
||||
fn call_at(&self, method: String, data: Vec<u8>, block: Block::Hash) -> Result<Vec<u8>> {
|
||||
trace!(target: "rpc", "Calling runtime at {:?} for method {} ({})", block, method, HexDisplay::from(&data));
|
||||
Ok(self.as_ref().executor().call(&block::Id::Hash(block), &method, &data)?.return_data)
|
||||
Ok(self.as_ref().executor().call(&BlockId::Hash(block), &method, &data)?.return_data)
|
||||
}
|
||||
|
||||
fn storage_hash_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<Hash> {
|
||||
self.storage_at(key, block).map(|x| blake2_256(&x.0).into())
|
||||
fn storage_hash_at(&self, key: StorageKey, block: Block::Hash) -> Result<Block::Hash> {
|
||||
use runtime_primitives::traits::{Hashing, Header as HeaderT};
|
||||
self.storage_at(key, block).map(|x| <Block::Header as HeaderT>::Hashing::hash(&x.0))
|
||||
}
|
||||
|
||||
fn storage_size_at(&self, key: StorageKey, block: block::HeaderHash) -> Result<u64> {
|
||||
fn storage_size_at(&self, key: StorageKey, block: Block::Hash) -> Result<u64> {
|
||||
self.storage_at(key, block).map(|x| x.0.len() as u64)
|
||||
}
|
||||
|
||||
fn storage_hash(&self, key: StorageKey) -> Result<Hash> {
|
||||
fn storage_hash(&self, key: StorageKey) -> Result<Block::Hash> {
|
||||
self.storage_hash_at(key, self.as_ref().info()?.chain.best_hash)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ environmental = { path = "../environmental", optional = true }
|
||||
substrate-state-machine = { path = "../state-machine", optional = true }
|
||||
substrate-primitives = { path = "../primitives", default_features = false }
|
||||
substrate-codec = { path = "../codec", default_features = false }
|
||||
triehash = { version = "0.1", optional = true }
|
||||
triehash = { version = "0.1.2", optional = true }
|
||||
ed25519 = { path = "../ed25519", optional = true }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -30,37 +30,3 @@ include!("../with_std.rs");
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
include!("../without_std.rs");
|
||||
|
||||
/// Abstraction around hashing
|
||||
pub trait Hashing {
|
||||
/// The hash type produced.
|
||||
type Output;
|
||||
|
||||
/// Produce the hash of some byte-slice.
|
||||
fn hash(s: &[u8]) -> Self::Output;
|
||||
/// Produce the hash of some codec-encodable value.
|
||||
fn hash_of<S: codec::Slicable>(s: &S) -> Self::Output {
|
||||
codec::Slicable::using_encoded(s, Self::hash)
|
||||
}
|
||||
/// Produce the patricia-trie root of a mapping from indices to byte slices.
|
||||
fn enumerated_trie_root(items: &[&[u8]]) -> Self::Output;
|
||||
|
||||
/// Acquire the global storage root.
|
||||
fn storage_root() -> Self::Output;
|
||||
}
|
||||
|
||||
/// Blake2-256 Hashing implementation.
|
||||
pub struct BlakeTwo256;
|
||||
|
||||
impl Hashing for BlakeTwo256 {
|
||||
type Output = primitives::H256;
|
||||
fn hash(s: &[u8]) -> Self::Output {
|
||||
blake2_256(s).into()
|
||||
}
|
||||
fn enumerated_trie_root(items: &[&[u8]]) -> Self::Output {
|
||||
enumerated_trie_root(items).into()
|
||||
}
|
||||
fn storage_root() -> Self::Output {
|
||||
storage_root().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,11 +82,28 @@ pub fn storage_root() -> [u8; 32] {
|
||||
).unwrap_or([0u8; 32])
|
||||
}
|
||||
|
||||
/// "Commit" all existing operations and get the resultant storage root.
|
||||
/// A trie root formed from the enumerated items.
|
||||
pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] {
|
||||
triehash::ordered_trie_root(serialised_values.iter().map(|s| s.to_vec())).0
|
||||
}
|
||||
|
||||
/// A trie root formed from the iterated items.
|
||||
pub fn trie_root<
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: AsRef<[u8]> + Ord,
|
||||
B: AsRef<[u8]>,
|
||||
>(input: I) -> [u8; 32] {
|
||||
triehash::trie_root(input).0
|
||||
}
|
||||
|
||||
/// A trie root formed from the enumerated items.
|
||||
pub fn ordered_trie_root<
|
||||
I: IntoIterator<Item = A>,
|
||||
A: AsRef<[u8]>
|
||||
>(input: I) -> [u8; 32] {
|
||||
triehash::ordered_trie_root(input).0
|
||||
}
|
||||
|
||||
/// Verify a ed25519 signature.
|
||||
pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
ed25519::verify(sig, msg, pubkey)
|
||||
|
||||
@@ -138,6 +138,27 @@ pub fn enumerated_trie_root(values: &[&[u8]]) -> [u8; 32] {
|
||||
result
|
||||
}
|
||||
|
||||
/// A trie root formed from the iterated items.
|
||||
pub fn trie_root<
|
||||
I: IntoIterator<Item = (A, B)>,
|
||||
A: AsRef<[u8]> + Ord,
|
||||
B: AsRef<[u8]>,
|
||||
>(_input: I) -> [u8; 32] {
|
||||
unimplemented!()
|
||||
// TODO Maybe implement (though probably easier/cleaner to have blake2 be the only thing
|
||||
// implemneted natively and compile the trie logic as wasm).
|
||||
}
|
||||
|
||||
/// A trie root formed from the enumerated items.
|
||||
pub fn ordered_trie_root<
|
||||
I: IntoIterator<Item = A>,
|
||||
A: AsRef<[u8]>
|
||||
>(_input: I) -> [u8; 32] {
|
||||
unimplemented!()
|
||||
// TODO Maybe implement (though probably easier/cleaner to have blake2 be the only thing
|
||||
// implemneted natively and compile the trie logic as wasm).
|
||||
}
|
||||
|
||||
/// The current relay chain identifier.
|
||||
pub fn chain_id() -> u64 {
|
||||
unsafe {
|
||||
|
||||
@@ -20,6 +20,7 @@ pub use std::cell;
|
||||
pub use std::clone;
|
||||
pub use std::cmp;
|
||||
pub use std::fmt;
|
||||
pub use std::hash;
|
||||
pub use std::iter;
|
||||
pub use std::marker;
|
||||
pub use std::mem;
|
||||
|
||||
@@ -29,6 +29,7 @@ pub use core::cell;
|
||||
pub use core::clone;
|
||||
pub use core::cmp;
|
||||
pub use core::fmt;
|
||||
pub use core::hash;
|
||||
pub use core::intrinsics;
|
||||
pub use core::iter;
|
||||
pub use core::marker;
|
||||
|
||||
@@ -20,7 +20,6 @@ pub use rstd::prelude::{Vec, Clone, Eq, PartialEq};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::fmt;
|
||||
pub use rstd::result;
|
||||
pub use rstd::marker::PhantomData;
|
||||
#[cfg(feature = "std")]
|
||||
use serde;
|
||||
pub use codec::{Slicable, Input};
|
||||
@@ -47,6 +46,10 @@ pub trait AuxCallable {
|
||||
type Call: AuxDispatchable + Slicable + Clone + PartialEq + Eq;
|
||||
}
|
||||
|
||||
// dirty hack to work around serde_derive issue
|
||||
// https://github.com/rust-lang/rust/issues/51331
|
||||
pub type AuxCallableCallFor<A> = <A as AuxCallable>::Call;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub trait Callable {
|
||||
type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq;
|
||||
@@ -56,6 +59,10 @@ pub trait Callable {
|
||||
type Call: Dispatchable + Slicable + Clone + PartialEq + Eq;
|
||||
}
|
||||
|
||||
// dirty hack to work around serde_derive issue.
|
||||
// https://github.com/rust-lang/rust/issues/51331
|
||||
pub type CallableCallFor<C> = <C as Callable>::Call;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {}
|
||||
|
||||
@@ -68,26 +75,43 @@ pub trait Parameter: Slicable + Clone + Eq {}
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T> Parameter for T where T: Slicable + Clone + Eq {}
|
||||
|
||||
|
||||
/// Declare a struct for this module, then implement dispatch logic to create a pairing of several
|
||||
/// dispatch traits and enums.
|
||||
#[macro_export]
|
||||
macro_rules! decl_module {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$($rest:tt)*
|
||||
) => {
|
||||
pub struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>);
|
||||
// TODO: switching based on std feature is because of an issue in
|
||||
// serde-derive for when we attempt to derive `Deserialize` on these types,
|
||||
// in a situation where we've imported `substrate_runtime_support` as another name.
|
||||
#[cfg(feature = "std")]
|
||||
$(#[$attr])*
|
||||
pub struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>);
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
$(#[$attr])*
|
||||
pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>);
|
||||
|
||||
decl_dispatch! {
|
||||
impl for $mod_type<$trait_instance: $trait_name>;
|
||||
$($rest)*
|
||||
}
|
||||
};
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$($rest:tt)*
|
||||
) => {
|
||||
struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>);
|
||||
#[cfg(feature = "std")]
|
||||
$(#[$attr])*
|
||||
struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>);
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
$(#[$attr])*
|
||||
struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>);
|
||||
decl_dispatch! {
|
||||
impl for $mod_type<$trait_instance: $trait_name>;
|
||||
$($rest)*
|
||||
@@ -101,6 +125,7 @@ macro_rules! decl_dispatch {
|
||||
// WITHOUT AUX
|
||||
(
|
||||
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident {
|
||||
$(
|
||||
fn $fn_name:ident(
|
||||
@@ -115,6 +140,7 @@ macro_rules! decl_dispatch {
|
||||
) => {
|
||||
__decl_dispatch_module_without_aux! {
|
||||
impl for $mod_type<$trait_instance: $trait_name>;
|
||||
$(#[$attr])*
|
||||
pub enum $call_type;
|
||||
$(
|
||||
fn $fn_name( $( $param_name: $param ),* ) -> $result = $id;
|
||||
@@ -128,6 +154,7 @@ macro_rules! decl_dispatch {
|
||||
// WITH AUX
|
||||
(
|
||||
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident where aux: $aux_type:ty {
|
||||
$(
|
||||
fn $fn_name:ident(aux
|
||||
@@ -142,6 +169,7 @@ macro_rules! decl_dispatch {
|
||||
) => {
|
||||
__decl_dispatch_module_with_aux! {
|
||||
impl for $mod_type<$trait_instance: $trait_name>;
|
||||
$(#[$attr])*
|
||||
pub enum $call_type where aux: $aux_type;
|
||||
$(
|
||||
fn $fn_name(aux $(, $param_name: $param )*) -> $result = $id;
|
||||
@@ -172,6 +200,7 @@ macro_rules! decl_dispatch {
|
||||
macro_rules! __decl_dispatch_module_without_aux {
|
||||
(
|
||||
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident;
|
||||
$(
|
||||
fn $fn_name:ident(
|
||||
@@ -185,6 +214,7 @@ macro_rules! __decl_dispatch_module_without_aux {
|
||||
) => {
|
||||
__decl_dispatch_module_common! {
|
||||
impl for $mod_type<$trait_instance: $trait_name>;
|
||||
$(#[$attr])*
|
||||
pub enum $call_type;
|
||||
$( fn $fn_name( $( $param_name : $param ),* ) -> $result = $id ; )*
|
||||
}
|
||||
@@ -215,6 +245,7 @@ macro_rules! __decl_dispatch_module_without_aux {
|
||||
macro_rules! __decl_dispatch_module_with_aux {
|
||||
(
|
||||
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident where aux: $aux_type:ty;
|
||||
$(
|
||||
fn $fn_name:ident(aux
|
||||
@@ -228,6 +259,7 @@ macro_rules! __decl_dispatch_module_with_aux {
|
||||
) => {
|
||||
__decl_dispatch_module_common! {
|
||||
impl for $mod_type<$trait_instance: $trait_name>;
|
||||
$(#[$attr])*
|
||||
pub enum $call_type;
|
||||
$( fn $fn_name( $( $param_name : $param ),* ) -> $result = $id ; )*
|
||||
}
|
||||
@@ -254,11 +286,12 @@ macro_rules! __decl_dispatch_module_with_aux {
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum.
|
||||
#[macro_export]
|
||||
macro_rules! __decl_dispatch_module_common {
|
||||
(
|
||||
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident;
|
||||
$(
|
||||
fn $fn_name:ident(
|
||||
@@ -270,10 +303,20 @@ macro_rules! __decl_dispatch_module_common {
|
||||
= $id:expr ;
|
||||
)*
|
||||
) => {
|
||||
#[cfg_attr(feature = "std", derive(Serialize))]
|
||||
#[allow(missing_docs)]
|
||||
#[cfg(feature = "std")]
|
||||
$(#[$attr])*
|
||||
pub enum $call_type<$trait_instance: $trait_name> {
|
||||
__PhantomItem($crate::dispatch::PhantomData<$trait_instance>),
|
||||
__PhantomItem(::std::marker::PhantomData<$trait_instance>),
|
||||
$(
|
||||
#[allow(non_camel_case_types)]
|
||||
$fn_name ( $( $param ),* ),
|
||||
)*
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
$(#[$attr])*
|
||||
pub enum $call_type<$trait_instance: $trait_name> {
|
||||
__PhantomItem(::core::marker::PhantomData<$trait_instance>),
|
||||
$(
|
||||
#[allow(non_camel_case_types)]
|
||||
$fn_name ( $( $param ),* ),
|
||||
@@ -395,6 +438,7 @@ pub trait IsAuxSubType<T: AuxCallable> {
|
||||
macro_rules! impl_outer_dispatch {
|
||||
() => ();
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident where aux: $aux:ty {
|
||||
$(
|
||||
$camelcase:ident = $id:expr,
|
||||
@@ -402,12 +446,10 @@ macro_rules! impl_outer_dispatch {
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[allow(missing_docs)]
|
||||
$(#[$attr])*
|
||||
pub enum $call_type {
|
||||
$(
|
||||
$camelcase ( <$camelcase as $crate::dispatch::AuxCallable>::Call )
|
||||
$camelcase ( $crate::dispatch::AuxCallableCallFor<$camelcase> )
|
||||
,)*
|
||||
}
|
||||
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
|
||||
@@ -436,6 +478,7 @@ macro_rules! impl_outer_dispatch {
|
||||
impl_outer_dispatch!{ $($rest)* }
|
||||
};
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $call_type:ident {
|
||||
$(
|
||||
$camelcase:ident = $id:expr,
|
||||
@@ -443,12 +486,10 @@ macro_rules! impl_outer_dispatch {
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
#[allow(missing_docs)]
|
||||
$(#[$attr])*
|
||||
pub enum $call_type {
|
||||
$(
|
||||
$camelcase ( <$camelcase as $crate::dispatch::Callable>::Call )
|
||||
$camelcase ( $crate::dispatch::CallableCallFor<$camelcase> )
|
||||
,)*
|
||||
}
|
||||
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
|
||||
|
||||
@@ -21,14 +21,6 @@
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[allow(unused_imports)] // can be removed when fixed: https://github.com/rust-lang/rust/issues/43497
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use serde_derive::*;
|
||||
|
||||
extern crate substrate_runtime_std as rstd;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_primitives as primitives;
|
||||
|
||||
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
substrate-codec = { path = "../../codec", default_features = false }
|
||||
substrate-primitives = { path = "../../primitives", default_features = false }
|
||||
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
|
||||
@@ -18,6 +19,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
|
||||
default = ["std"]
|
||||
std = [
|
||||
"serde/std",
|
||||
"serde_derive",
|
||||
"substrate-codec/std",
|
||||
"substrate-primitives/std",
|
||||
"substrate-runtime-std/std",
|
||||
|
||||
@@ -25,6 +25,13 @@ extern crate substrate_runtime_std as rstd;
|
||||
#[macro_use]
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_runtime_primitives as primitives;
|
||||
extern crate substrate_codec as codec;
|
||||
@@ -36,8 +43,7 @@ use runtime_support::{storage, Parameter};
|
||||
use runtime_support::dispatch::Result;
|
||||
use runtime_support::storage::unhashed::StorageVec;
|
||||
use primitives::traits::RefInto;
|
||||
use substrate_primitives::bft::MisbehaviorReport;
|
||||
|
||||
use primitives::bft::MisbehaviorReport;
|
||||
|
||||
pub const AUTHORITY_AT: &'static [u8] = b":auth:";
|
||||
pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len";
|
||||
@@ -59,9 +65,13 @@ pub trait Trait: system::Trait {
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait>;
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum Call where aux: T::PublicAux {
|
||||
fn report_misbehavior(aux, report: MisbehaviorReport) -> Result = 0;
|
||||
fn report_misbehavior(aux, report: MisbehaviorReport<T::Hash, T::BlockNumber>) -> Result = 0;
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
fn set_code(new: Vec<u8>) -> Result = 0;
|
||||
fn set_storage(items: Vec<KeyValue>) -> Result = 1;
|
||||
@@ -89,7 +99,7 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
/// Report some misbehaviour.
|
||||
fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport) -> Result {
|
||||
fn report_misbehavior(_aux: &T::PublicAux, _report: MisbehaviorReport<T::Hash, T::BlockNumber>) -> Result {
|
||||
// TODO.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
hex-literal = "0.1.0"
|
||||
integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", branch = "master" }
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { path = "../../../safe-mix", default_features = false}
|
||||
substrate-keyring = { path = "../../keyring", optional = true }
|
||||
substrate-codec = { path = "../../codec", default_features = false }
|
||||
@@ -25,6 +26,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
|
||||
default = ["std"]
|
||||
std = [
|
||||
"serde/std",
|
||||
"serde_derive",
|
||||
"safe-mix/std",
|
||||
"substrate-keyring",
|
||||
"substrate-codec/std",
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")] extern crate serde;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate integer_sqrt;
|
||||
extern crate substrate_codec as codec;
|
||||
@@ -26,7 +31,7 @@ extern crate substrate_primitives;
|
||||
#[cfg(any(feature = "std", test))] extern crate substrate_keyring as keyring;
|
||||
#[macro_use] extern crate substrate_runtime_std as rstd;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
#[macro_use] extern crate substrate_runtime_support as runtime_support;
|
||||
#[macro_use] extern crate substrate_runtime_support;
|
||||
extern crate substrate_runtime_primitives as primitives;
|
||||
extern crate substrate_runtime_consensus as consensus;
|
||||
extern crate substrate_runtime_democracy as democracy;
|
||||
@@ -36,8 +41,8 @@ extern crate substrate_runtime_system as system;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use primitives::traits::{Zero, One, RefInto, As};
|
||||
use runtime_support::{StorageValue, StorageMap};
|
||||
use runtime_support::dispatch::Result;
|
||||
use substrate_runtime_support::{StorageValue, StorageMap};
|
||||
use substrate_runtime_support::dispatch::Result;
|
||||
|
||||
pub mod voting;
|
||||
|
||||
@@ -101,6 +106,8 @@ pub trait Trait: democracy::Trait {}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait>;
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum Call where aux: T::PublicAux {
|
||||
fn set_approvals(aux, votes: Vec<bool>, index: VoteIndex) -> Result = 0;
|
||||
fn reap_inactive_voter(aux, signed_index: u32, who: T::AccountId, who_index: u32, assumed_vote_index: VoteIndex) -> Result = 1;
|
||||
@@ -108,6 +115,8 @@ decl_module! {
|
||||
fn submit_candidacy(aux, slot: u32) -> Result = 3;
|
||||
fn present_winner(aux, candidate: T::AccountId, total: T::Balance, index: VoteIndex) -> Result = 4;
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
fn set_desired_seats(count: u32) -> Result = 0;
|
||||
fn remove_member(who: T::AccountId) -> Result = 1;
|
||||
@@ -597,10 +606,11 @@ mod tests {
|
||||
pub use runtime_io::with_externalities;
|
||||
pub use substrate_primitives::H256;
|
||||
use primitives::BuildExternalities;
|
||||
use primitives::traits::{HasPublicAux, Identity};
|
||||
use primitives::traits::{HasPublicAux, Identity, BlakeTwo256};
|
||||
use primitives::testing::{Digest, Header};
|
||||
|
||||
impl_outer_dispatch! {
|
||||
#[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)]
|
||||
pub enum Proposal {
|
||||
Staking = 0,
|
||||
Democracy = 1,
|
||||
@@ -619,7 +629,7 @@ mod tests {
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = runtime_io::BlakeTwo256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type Digest = Digest;
|
||||
type AccountId = u64;
|
||||
type Header = Header;
|
||||
|
||||
@@ -18,20 +18,24 @@
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::borrow::Borrow;
|
||||
use primitives::traits::{Executable, RefInto};
|
||||
use runtime_io::{Hashing, print};
|
||||
use runtime_support::{StorageValue, StorageMap, IsSubType};
|
||||
use runtime_support::dispatch::Result;
|
||||
use primitives::traits::{Executable, RefInto, Hashing};
|
||||
use runtime_io::print;
|
||||
use substrate_runtime_support::dispatch::Result;
|
||||
use substrate_runtime_support::{StorageValue, StorageMap, IsSubType};
|
||||
use {system, democracy};
|
||||
use super::{Trait, Module as Council};
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait>;
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum Call where aux: T::PublicAux {
|
||||
fn propose(aux, proposal: Box<T::Proposal>) -> Result = 0;
|
||||
fn vote(aux, proposal: T::Hash, approve: bool) -> Result = 1;
|
||||
fn veto(aux, proposal_hash: T::Hash) -> Result = 2;
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
||||
pub enum PrivCall {
|
||||
fn set_cooloff_period(blocks: T::BlockNumber) -> Result = 0;
|
||||
fn set_voting_period(blocks: T::BlockNumber) -> Result = 1;
|
||||
@@ -214,7 +218,7 @@ impl<T: Trait> Executable for Council<T> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ::tests::*;
|
||||
use runtime_support::Hashable;
|
||||
use substrate_runtime_support::Hashable;
|
||||
use democracy::VoteThreshold;
|
||||
|
||||
type CouncilVoting = super::Module<Test>;
|
||||
|
||||
@@ -6,6 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
hex-literal = "0.1.0"
|
||||
serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { path = "../../../safe-mix", default_features = false}
|
||||
substrate-codec = { path = "../../codec", default_features = false }
|
||||
substrate-primitives = { path = "../../primitives", default_features = false }
|
||||
@@ -22,6 +23,7 @@ substrate-runtime-system = { path = "../system", default_features = false }
|
||||
default = ["std"]
|
||||
std = [
|
||||
"serde/std",
|
||||
"serde_derive",
|
||||
"safe-mix/std",
|
||||
"substrate-codec/std",
|
||||
"substrate-primitives/std",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user