From c473c0c73472963b91cfd0b510f8003be8e3c9b7 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 25 May 2018 16:16:01 +0200 Subject: [PATCH] Minimal parachain framework part 1 (#113) * dynamic inclusion threshold calculator * collators interface * collation helpers * initial proposal-creation future * create proposer when asked to propose * remove local_availability duty * statement table tracks includable parachain count * beginnings of timing future * finish proposal logic * remove stray println * extract shared table to separate module * change ordering * includability tracking * fix doc * initial changes to parachains module * initialise dummy block before API calls * give polkadot control over round proposer based on random seed * propose only after enough candidates * flesh out parachains module a bit more * set_heads * actually introduce set_heads to runtime * update block_builder to accept parachains * split block validity errors from real errors in evaluation * update WASM runtimes * polkadot-api methods for parachains additions * delay evaluation until candidates are ready * comments * fix dynamic inclusion with zero initial * test for includability tracker * wasm validation of parachain candidates * move primitives to primitives crate * remove runtime-std dependency from codec * adjust doc * polkadot-parachain-primitives * kill legacy polkadot-validator crate * basic-add test chain * test for basic_add parachain * move to test-chains dir * use wasm-build * new wasm directory layout * reorganize a bit more * Fix for rh-minimal-parachain (#141) * Remove extern "C" We already encountered such behavior (bug?) in pwasm-std, I believe. * Fix `panic_fmt` signature by adding `_col` Wrong `panic_fmt` signature can inhibit some optimizations in LTO mode. * Add linker flags and use wasm-gc in build script Pass --import-memory to LLD to emit wasm binary with imported memory. Also use wasm-gc instead of wasm-build. * Fix effective_max. I'm not sure why it was the way it was actually. * Recompile wasm. * Fix indent * more basic_add tests * validate parachain WASM * produce statements on receiving statements * tests for reactive statement production * fix build * add OOM lang item to runtime-io * use dynamic_inclusion when evaluating as well * fix update_includable_count * remove dead code * grumbles * actually defer round_proposer logic * update wasm * address a few more grumbles * grumbles * update WASM checkins * remove dependency on tokio-timer --- polkadot/api/Cargo.toml | 1 - polkadot/api/src/lib.rs | 58 +- polkadot/collator/Cargo.toml | 4 +- polkadot/collator/src/lib.rs | 8 +- polkadot/consensus/Cargo.toml | 1 + polkadot/consensus/src/collation.rs | 176 ++++ polkadot/consensus/src/dynamic_inclusion.rs | 130 +++ polkadot/consensus/src/error.rs | 37 +- polkadot/consensus/src/evaluation.rs | 135 +++ polkadot/consensus/src/lib.rs | 858 +++++++++--------- polkadot/consensus/src/service.rs | 55 +- .../consensus/src/shared_table/includable.rs | 137 +++ polkadot/consensus/src/shared_table/mod.rs | 566 ++++++++++++ polkadot/parachain/Cargo.toml | 17 + polkadot/parachain/src/lib.rs | 146 +++ polkadot/parachain/src/wasm.rs | 166 ++++ polkadot/parachain/test-chains/.gitignore | 2 + .../test-chains/basic_add/Cargo.toml | 25 + .../test-chains/basic_add/src/lib.rs | 143 +++ .../parachain/test-chains/basic_add/src/src | 1 + .../test-chains/basic_add/src/wasm.rs | 58 ++ .../test-chains/build_test_chains.sh | 14 + polkadot/parachain/tests/basic_add.rs | 170 ++++ polkadot/parachain/tests/res/basic_add.wasm | Bin 0 -> 44941 bytes polkadot/primitives/src/lib.rs | 1 - polkadot/primitives/src/parachain.rs | 9 +- polkadot/primitives/src/validator.rs | 76 -- polkadot/runtime/Cargo.toml | 4 +- polkadot/runtime/src/lib.rs | 28 +- polkadot/runtime/src/parachains.rs | 209 ++++- polkadot/runtime/wasm/Cargo.lock | 3 - .../release/polkadot_runtime.compact.wasm | Bin 417199 -> 429539 bytes .../release/polkadot_runtime.wasm | Bin 461195 -> 475147 bytes polkadot/service/src/lib.rs | 8 +- polkadot/statement-table/src/generic.rs | 121 ++- polkadot/transaction-pool/src/lib.rs | 27 +- polkadot/validator/Cargo.toml | 11 - polkadot/validator/src/error.rs | 33 - polkadot/validator/src/lib.rs | 34 - polkadot/validator/src/parachains.rs | 68 -- polkadot/validator/src/validator.rs | 101 --- 41 files changed, 2769 insertions(+), 872 deletions(-) create mode 100644 polkadot/consensus/src/collation.rs create mode 100644 polkadot/consensus/src/dynamic_inclusion.rs create mode 100644 polkadot/consensus/src/evaluation.rs create mode 100644 polkadot/consensus/src/shared_table/includable.rs create mode 100644 polkadot/consensus/src/shared_table/mod.rs create mode 100644 polkadot/parachain/Cargo.toml create mode 100644 polkadot/parachain/src/lib.rs create mode 100644 polkadot/parachain/src/wasm.rs create mode 100644 polkadot/parachain/test-chains/.gitignore create mode 100644 polkadot/parachain/test-chains/basic_add/Cargo.toml create mode 100644 polkadot/parachain/test-chains/basic_add/src/lib.rs create mode 120000 polkadot/parachain/test-chains/basic_add/src/src create mode 100644 polkadot/parachain/test-chains/basic_add/src/wasm.rs create mode 100755 polkadot/parachain/test-chains/build_test_chains.sh create mode 100644 polkadot/parachain/tests/basic_add.rs create mode 100755 polkadot/parachain/tests/res/basic_add.wasm delete mode 100644 polkadot/primitives/src/validator.rs delete mode 100644 polkadot/validator/Cargo.toml delete mode 100644 polkadot/validator/src/error.rs delete mode 100644 polkadot/validator/src/lib.rs delete mode 100644 polkadot/validator/src/parachains.rs delete mode 100644 polkadot/validator/src/validator.rs diff --git a/polkadot/api/Cargo.toml b/polkadot/api/Cargo.toml index cb2204d69e..860536ac95 100644 --- a/polkadot/api/Cargo.toml +++ b/polkadot/api/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Parity Technologies "] [dependencies] error-chain = "0.11" -log = "0.3" polkadot-executor = { path = "../executor" } polkadot-runtime = { path = "../runtime" } polkadot-primitives = { path = "../primitives" } diff --git a/polkadot/api/src/lib.rs b/polkadot/api/src/lib.rs index a052785423..fd24f52766 100644 --- a/polkadot/api/src/lib.rs +++ b/polkadot/api/src/lib.rs @@ -40,8 +40,8 @@ use polkadot_executor::Executor as LocalDispatch; use substrate_executor::{NativeExecutionDispatch, NativeExecutor}; use state_machine::OverlayedChanges; use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; -use primitives::parachain::DutyRoster; -use runtime::{Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall}; +use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; +use runtime::{Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall, ParachainsCall}; error_chain! { errors { @@ -135,12 +135,21 @@ pub trait PolkadotApi { /// Get the index of an account at a block. fn index(&self, at: &Self::CheckedBlockId, account: AccountId) -> Result; + /// Get the active parachains at a block. + fn active_parachains(&self, at: &Self::CheckedBlockId) -> Result>; - /// Evaluate a block and see if it gives an error. - fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<()>; + /// Get the validation code of a parachain at a block. If the parachain is active, this will always return `Some`. + fn parachain_code(&self, at: &Self::CheckedBlockId, parachain: ParaId) -> Result>>; + + /// Get the chain head of a parachain. If the parachain is active, this will always return `Some`. + fn parachain_head(&self, at: &Self::CheckedBlockId, parachain: ParaId) -> Result>>; + + /// Evaluate a block. Returns true if the block is good, false if it is known to be bad, + /// and an error if we can't evaluate for some reason. + fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result; /// Create a block builder on top of the parent block. - fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: Timestamp) -> Result; + fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: Timestamp, parachains: Vec) -> Result; } /// A checked block ID used for the substrate-client implementation of CheckedBlockId; @@ -213,15 +222,36 @@ impl PolkadotApi for Client> with_runtime!(self, at, ::runtime::Timestamp::now) } - fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<()> { - with_runtime!(self, at, || ::runtime::Executive::execute_block(block)) + fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result { + use substrate_executor::error::ErrorKind as ExecErrorKind; + + let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(block)); + match res { + Ok(()) => Ok(true), + Err(err) => match err.kind() { + &ErrorKind::Executor(ExecErrorKind::Runtime) => Ok(false), + _ => Err(err) + } + } } fn index(&self, at: &CheckedId, account: AccountId) -> Result { with_runtime!(self, at, || ::runtime::System::account_index(account)) } - fn build_block(&self, parent: &CheckedId, timestamp: Timestamp) -> Result { + fn active_parachains(&self, at: &CheckedId) -> Result> { + with_runtime!(self, at, ::runtime::Parachains::active_parachains) + } + + fn parachain_code(&self, at: &CheckedId, parachain: ParaId) -> Result>> { + with_runtime!(self, at, || ::runtime::Parachains::parachain_code(parachain)) + } + + fn parachain_head(&self, at: &CheckedId, parachain: ParaId) -> Result>> { + with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain)) + } + + fn build_block(&self, parent: &CheckedId, timestamp: Timestamp, parachains: Vec) -> Result { let parent = parent.block_id(); let header = Header { parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?, @@ -239,6 +269,14 @@ impl PolkadotApi for Client> 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(), } ]; @@ -275,7 +313,7 @@ pub struct ClientBlockBuilder { impl ClientBlockBuilder where S::Error: Into { - // initialises a block ready to allow extrinsics to be applied. + // 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); @@ -406,7 +444,7 @@ mod tests { let client = client(); let id = client.check_id(BlockId::Number(0)).unwrap(); - let block_builder = client.build_block(&id, 1_000_000).unwrap(); + let block_builder = client.build_block(&id, 1_000_000, Vec::new()).unwrap(); let block = block_builder.bake(); assert_eq!(block.header.number, 1); diff --git a/polkadot/collator/Cargo.toml b/polkadot/collator/Cargo.toml index 6f1fa16302..42fc14c666 100644 --- a/polkadot/collator/Cargo.toml +++ b/polkadot/collator/Cargo.toml @@ -1,10 +1,12 @@ [package] name = "polkadot-collator" version = "0.1.0" -authors = ["Parity Technologies "] +authors = ["Parity Technologies "] description = "Abstract collation logic" [dependencies] 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-parachain = { path = "../parachain", version = "0.1" } diff --git a/polkadot/collator/src/lib.rs b/polkadot/collator/src/lib.rs index 14b430ebba..967a8e6de6 100644 --- a/polkadot/collator/src/lib.rs +++ b/polkadot/collator/src/lib.rs @@ -45,6 +45,7 @@ //! to be performed, as the collation logic itself. extern crate futures; +extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; extern crate polkadot_primitives; @@ -82,7 +83,6 @@ pub trait RelayChainContext { } /// Collate the necessary ingress queue using the given context. -// TODO: impl trait pub fn collate_ingress<'a, R>(relay_context: R) -> Box + 'a> where @@ -105,7 +105,7 @@ pub fn collate_ingress<'a, R>(relay_context: R) // and then by the parachain ID. // // then transform that into the consolidated egress queue. - let future = stream::futures_unordered(egress_fetch) + Box::new(stream::futures_unordered(egress_fetch) .fold(BTreeMap::new(), |mut map, (routing_id, egresses)| { for (depth, egress) in egresses.into_iter().rev().enumerate() { let depth = -(depth as i64); @@ -116,9 +116,7 @@ pub fn collate_ingress<'a, R>(relay_context: R) }) .map(|ordered| ordered.into_iter().map(|((_, id), egress)| (id, egress))) .map(|i| i.collect::>()) - .map(ConsolidatedIngress); - - Box::new(future) + .map(ConsolidatedIngress)) } /// Produce a candidate for the parachain. diff --git a/polkadot/consensus/Cargo.toml b/polkadot/consensus/Cargo.toml index 29d5588865..5be758a91b 100644 --- a/polkadot/consensus/Cargo.toml +++ b/polkadot/consensus/Cargo.toml @@ -13,6 +13,7 @@ log = "0.3" exit-future = "0.1" polkadot-api = { path = "../api" } polkadot-collator = { path = "../collator" } +polkadot-parachain = { path = "../parachain" } polkadot-primitives = { path = "../primitives" } polkadot-runtime = { path = "../runtime" } polkadot-statement-table = { path = "../statement-table" } diff --git a/polkadot/consensus/src/collation.rs b/polkadot/consensus/src/collation.rs new file mode 100644 index 0000000000..3738ae9004 --- /dev/null +++ b/polkadot/consensus/src/collation.rs @@ -0,0 +1,176 @@ +// 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 . + +//! Validator-side view of collation. +//! +//! This module contains type definitions, a trait for a batch of collators, and a trait for +//! attempting to fetch a collation repeatedly until a valid one is obtained. + +use std::sync::Arc; + +use polkadot_api::PolkadotApi; +use polkadot_primitives::{Hash, AccountId}; +use polkadot_primitives::parachain::{Id as ParaId, Chain, BlockData, Extrinsic, CandidateReceipt}; + +use futures::prelude::*; + +/// A full collation. +pub struct Collation { + /// Block data. + pub block_data: BlockData, + /// The candidate receipt itself. + pub receipt: CandidateReceipt, +} + +/// Encapsulates connections to collators and allows collation on any parachain. +/// +/// This is expected to be a lightweight, shared type like an `Arc`. +pub trait Collators: Clone { + /// Errors when producing collations. + type Error; + /// A full collation. + type Collation: IntoFuture; + + /// Collate on a specific parachain, building on a given relay chain parent hash. + fn collate(&self, parachain: ParaId, relay_parent: Hash) -> Self::Collation; + + /// Note a bad collator. TODO: take proof + fn note_bad_collator(&self, collator: AccountId); +} + +/// A future which resolves when a collation is available. +/// +/// This future is fused. +pub struct CollationFetch { + parachain: Option, + relay_parent_hash: Hash, + relay_parent: P::CheckedBlockId, + collators: C, + live_fetch: Option<::Future>, + client: Arc

, +} + +impl CollationFetch { + /// Create a new collation fetcher for the given chain. + pub fn new(parachain: Chain, relay_parent: P::CheckedBlockId, relay_parent_hash: Hash, collators: C, client: Arc

) -> Self { + CollationFetch { + relay_parent_hash, + relay_parent, + collators, + client, + parachain: match parachain { + Chain::Parachain(id) => Some(id), + Chain::Relay => None, + }, + live_fetch: None, + } + } +} + +impl Future for CollationFetch { + type Item = (Collation, Extrinsic); + type Error = C::Error; + + fn poll(&mut self) -> Poll<(Collation, Extrinsic), C::Error> { + let parachain = match self.parachain.as_ref() { + Some(p) => p.clone(), + None => return Ok(Async::NotReady), + }; + + loop { + let x = { + let (r, c) = (self.relay_parent_hash, &self.collators); + let poll = self.live_fetch + .get_or_insert_with(move || c.collate(parachain, r).into_future()) + .poll(); + + if let Err(_) = poll { self.parachain = None } + try_ready!(poll) + }; + + match validate_collation(&*self.client, &self.relay_parent, &x) { + Ok(()) => { + self.parachain = None; + + // TODO: generate extrinsic while verifying. + return Ok(Async::Ready((x, Extrinsic))); + } + Err(e) => { + debug!("Failed to validate parachain due to API error: {}", e); + + // just continue if we got a bad collation or failed to validate + self.live_fetch = None; + self.collators.note_bad_collator(x.receipt.collator) + } + } + } + } +} + +// Errors that can occur when validating a parachain. +error_chain! { + types { Error, ErrorKind, ResultExt; } + + errors { + InactiveParachain(id: ParaId) { + description("Collated for inactive parachain"), + display("Collated for inactive parachain: {:?}", id), + } + ValidationFailure { + description("Parachain candidate failed validation."), + display("Parachain candidate failed validation."), + } + WrongHeadData(expected: Vec, got: Vec) { + description("Parachain validation produced wrong head data."), + display("Parachain validation produced wrong head data (expected: {:?}, got {:?}", expected, got), + } + } + + links { + PolkadotApi(::polkadot_api::Error, ::polkadot_api::ErrorKind); + } +} + +/// Check whether a given collation is valid. Returns `Ok` on success, error otherwise. +pub fn validate_collation(client: &P, relay_parent: &P::CheckedBlockId, collation: &Collation) -> Result<(), Error> { + use parachain::{self, ValidationParams}; + + let para_id = collation.receipt.parachain_index; + let validation_code = client.parachain_code(relay_parent, para_id)? + .ok_or_else(|| ErrorKind::InactiveParachain(para_id))?; + + let chain_head = client.parachain_head(relay_parent, para_id)? + .ok_or_else(|| ErrorKind::InactiveParachain(para_id))?; + + let params = ValidationParams { + parent_head: chain_head, + block_data: collation.block_data.0.clone(), + }; + + match parachain::wasm::validate_candidate(&validation_code, params) { + Ok(result) => { + if result.head_data == collation.receipt.head_data.0 { + Ok(()) + } else { + Err(ErrorKind::WrongHeadData( + collation.receipt.head_data.0.clone(), + result.head_data + ).into()) + } + } + Err(_) => Err(ErrorKind::ValidationFailure.into()) + } +} diff --git a/polkadot/consensus/src/dynamic_inclusion.rs b/polkadot/consensus/src/dynamic_inclusion.rs new file mode 100644 index 0000000000..d48e486274 --- /dev/null +++ b/polkadot/consensus/src/dynamic_inclusion.rs @@ -0,0 +1,130 @@ +// 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 . + +//! Dynamic inclusion threshold over time. + +use std::time::{Duration, Instant}; + +fn duration_to_micros(duration: &Duration) -> u64 { + duration.as_secs() * 1_000_000 + (duration.subsec_nanos() / 1000) as u64 +} + +/// Dynamic inclusion threshold over time. +/// +/// The acceptable proportion of parachains which must have parachain candidates +/// reduces over time (eventually going to zero). +#[derive(Debug, Clone)] +pub struct DynamicInclusion { + start: Instant, + y: u64, + m: u64, +} + +impl DynamicInclusion { + /// Constructs a new dynamic inclusion threshold calculator based on the time now, + /// how many parachain candidates are required at the beginning, and when an empty + /// block will be allowed. + pub fn new(initial: usize, start: Instant, allow_empty: Duration) -> Self { + // linear function f(n_candidates) -> valid after microseconds + // f(0) = allow_empty + // f(initial) = 0 + // m is actually the negative slope to avoid using signed arithmetic. + let (y, m) = if initial != 0 { + let y = duration_to_micros(&allow_empty); + + (y, y / initial as u64) + } else { + (0, 0) + }; + + DynamicInclusion { + start, + y, + m, + } + } + + /// Returns the duration from `now` after which the amount of included parachain candidates + /// would be enough, or `None` if it is sufficient now. + /// + /// Panics if `now` is earlier than the `start`. + pub fn acceptable_in(&self, now: Instant, included: usize) -> Option { + let elapsed = now.duration_since(self.start); + let elapsed = duration_to_micros(&elapsed); + + let valid_after = self.y.saturating_sub(self.m * included as u64); + + if elapsed >= valid_after { + None + } else { + Some(Duration::from_millis((valid_after - elapsed) as u64 / 1000)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn full_immediately_allowed() { + let now = Instant::now(); + + let dynamic = DynamicInclusion::new( + 10, + now, + Duration::from_millis(4000), + ); + + assert!(dynamic.acceptable_in(now, 10).is_none()); + assert!(dynamic.acceptable_in(now, 11).is_none()); + assert!(dynamic.acceptable_in(now + Duration::from_millis(2000), 10).is_none()); + } + + #[test] + fn half_allowed_halfway() { + let now = Instant::now(); + + let dynamic = DynamicInclusion::new( + 10, + now, + Duration::from_millis(4000), + ); + + assert_eq!(dynamic.acceptable_in(now, 5), Some(Duration::from_millis(2000))); + assert!(dynamic.acceptable_in(now + Duration::from_millis(2000), 5).is_none()); + assert!(dynamic.acceptable_in(now + Duration::from_millis(3000), 5).is_none()); + assert!(dynamic.acceptable_in(now + Duration::from_millis(4000), 5).is_none()); + } + + #[test] + fn zero_initial_is_flat() { + let now = Instant::now(); + + let dynamic = DynamicInclusion::new( + 0, + now, + Duration::from_secs(10_000), + ); + + for i in 0..10_001 { + let now = now + Duration::from_secs(i); + assert!(dynamic.acceptable_in(now, 0).is_none()); + assert!(dynamic.acceptable_in(now, 1).is_none()); + assert!(dynamic.acceptable_in(now, 10).is_none()); + } + } +} diff --git a/polkadot/consensus/src/error.rs b/polkadot/consensus/src/error.rs index e2a4b3a483..ebc998ab69 100644 --- a/polkadot/consensus/src/error.rs +++ b/polkadot/consensus/src/error.rs @@ -16,45 +16,30 @@ //! Errors that can occur during the consensus process. -use primitives::block::{HeaderHash, Number}; +use polkadot_primitives::AccountId; + error_chain! { links { PolkadotApi(::polkadot_api::Error, ::polkadot_api::ErrorKind); Bft(::bft::Error, ::bft::ErrorKind); } - foreign_links { - Io(::std::io::Error); - SharedIo(::futures::future::SharedError<::std::io::Error>); - } - errors { InvalidDutyRosterLength(expected: usize, got: usize) { description("Duty Roster had invalid length"), display("Invalid duty roster length: expected {}, got {}", expected, got), } - ProposalNotForPolkadot { - description("Proposal provided not a Polkadot block."), - display("Proposal provided not a Polkadot block."), + NotValidator(id: AccountId) { + description("Local account ID not a validator at this block."), + display("Local account ID ({:?}) not a validator at this block.", id), } - TimestampInFuture { - description("Proposal had timestamp too far in the future."), - display("Proposal had timestamp too far in the future."), + PrematureDestruction { + description("Proposer destroyed before finishing proposing or evaluating"), + display("Proposer destroyed before finishing proposing or evaluating"), } - WrongParentHash(expected: HeaderHash, got: HeaderHash) { - description("Proposal had wrong parent hash."), - display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got), - } - WrongNumber(expected: Number, got: Number) { - description("Proposal had wrong number."), - display("Proposal had wrong number. Expected {:?}, got {:?}", expected, got), - } - ProposalTooLarge(size: usize) { - description("Proposal exceeded the maximum size."), - display( - "Proposal exceeded the maximum size of {} by {} bytes.", - ::MAX_TRANSACTIONS_SIZE, ::MAX_TRANSACTIONS_SIZE.saturating_sub(*size) - ), + Timer(e: String) { + description("Failed to register or resolve async timer."), + display("Timer failed: {}", e), } Executor(e: ::futures::future::ExecuteErrorKind) { description("Unable to dispatch agreement future"), diff --git a/polkadot/consensus/src/evaluation.rs b/polkadot/consensus/src/evaluation.rs new file mode 100644 index 0000000000..b5ef81d244 --- /dev/null +++ b/polkadot/consensus/src/evaluation.rs @@ -0,0 +1,135 @@ +// 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 . + +//! Polkadot block evaluation and evaluation errors. + +use super::MAX_TRANSACTIONS_SIZE; + +use codec::Slicable; +use polkadot_runtime::Block as PolkadotGenericBlock; +use polkadot_primitives::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 { + PolkadotApi(::polkadot_api::Error, ::polkadot_api::ErrorKind); + } + + errors { + ProposalNotForPolkadot { + description("Proposal provided not a Polkadot block."), + display("Proposal provided not a Polkadot block."), + } + TimestampInFuture { + description("Proposal had timestamp too far in the future."), + display("Proposal had timestamp too far in the future."), + } + TooManyCandidates(expected: usize, got: usize) { + description("Proposal included more candidates than is possible."), + display("Proposal included {} candidates for {} parachains", got, expected), + } + ParachainOutOfOrder { + description("Proposal included parachains out of order."), + display("Proposal included parachains out of order."), + } + UnknownParachain(id: ParaId) { + description("Proposal included unregistered parachain."), + display("Proposal included unregistered parachain {:?}", id), + } + WrongParentHash(expected: HeaderHash, got: HeaderHash) { + description("Proposal had wrong parent hash."), + display("Proposal had wrong parent hash. Expected {:?}, got {:?}", expected, got), + } + WrongNumber(expected: BlockNumber, got: BlockNumber) { + description("Proposal had wrong number."), + display("Proposal had wrong number. Expected {:?}, got {:?}", expected, got), + } + ProposalTooLarge(size: usize) { + description("Proposal exceeded the maximum size."), + display( + "Proposal exceeded the maximum size of {} by {} bytes.", + MAX_TRANSACTIONS_SIZE, MAX_TRANSACTIONS_SIZE.saturating_sub(*size) + ), + } + } +} + +/// Attempt to evaluate a substrate block as a polkadot block, returning error +/// upon any initial validity checks failing. +pub fn evaluate_initial( + proposal: &SubstrateBlock, + now: Timestamp, + parent_hash: &HeaderHash, + parent_number: BlockNumber, + active_parachains: &[ParaId], +) -> Result { + const MAX_TIMESTAMP_DRIFT: Timestamp = 60; + + let encoded = Slicable::encode(proposal); + let proposal = PolkadotGenericBlock::decode(&mut &encoded[..]) + .and_then(|b| PolkadotBlock::from(b).ok()) + .ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?; + + let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| { + a + Slicable::encode(tx).len() + }); + + if transactions_size > MAX_TRANSACTIONS_SIZE { + bail!(ErrorKind::ProposalTooLarge(transactions_size)) + } + + if proposal.header.parent_hash != *parent_hash { + bail!(ErrorKind::WrongParentHash(*parent_hash, proposal.header.parent_hash)); + } + + if proposal.header.number != parent_number + 1 { + bail!(ErrorKind::WrongNumber(parent_number + 1, proposal.header.number)); + } + + let block_timestamp = proposal.timestamp(); + + // lenient maximum -- small drifts will just be delayed using a timer. + if block_timestamp > now + MAX_TIMESTAMP_DRIFT { + bail!(ErrorKind::TimestampInFuture) + } + + { + let n_parachains = active_parachains.len(); + if proposal.parachain_heads().len() > n_parachains { + bail!(ErrorKind::TooManyCandidates(n_parachains, proposal.parachain_heads().len())); + } + + let mut last_id = None; + let mut iter = active_parachains.iter(); + for head in proposal.parachain_heads() { + // proposed heads must be ascending order by parachain ID without duplicate. + if last_id.as_ref().map_or(false, |x| x >= &head.parachain_index) { + bail!(ErrorKind::ParachainOutOfOrder); + } + + if !iter.any(|x| x == &head.parachain_index) { + // must be unknown since active parachains are always sorted. + bail!(ErrorKind::UnknownParachain(head.parachain_index)) + } + + last_id = Some(head.parachain_index); + } + } + + Ok(proposal) +} diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index e004a44df5..f9e3b35a26 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -29,15 +29,16 @@ //! //! Groups themselves may be compromised by malicious authorities. -extern crate futures; extern crate ed25519; extern crate parking_lot; 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 substrate_bft as bft; extern crate substrate_codec as codec; extern crate substrate_primitives as primitives; @@ -46,46 +47,60 @@ extern crate substrate_network; extern crate exit_future; extern crate tokio_core; -extern crate substrate_keyring; extern crate substrate_client as client; #[macro_use] extern crate error_chain; + +#[macro_use] +extern crate futures; + #[macro_use] extern crate log; +#[cfg(test)] +extern crate substrate_keyring; + use std::collections::{HashMap, HashSet}; use std::sync::Arc; +use std::time::{Duration, Instant}; use codec::Slicable; -use table::{Table, Context as TableContextTrait}; 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, DutyRoster, BlockData, Extrinsic, CandidateReceipt}; -use polkadot_runtime::Block as PolkadotGenericBlock; +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 primitives::AuthorityId; -use transaction_pool::{Ready, TransactionPool, PolkadotBlock}; +use transaction_pool::{Ready, TransactionPool}; +use tokio_core::reactor::{Handle, Timeout, Interval}; use futures::prelude::*; -use futures::future; -use future::Shared; +use futures::future::{self, Shared}; use parking_lot::Mutex; -use tokio_core::reactor::{Handle, Timeout}; +use collation::CollationFetch; +use dynamic_inclusion::DynamicInclusion; +pub use self::collation::{Collators, Collation}; pub use self::error::{ErrorKind, Error}; +pub use self::shared_table::{SharedTable, StatementSource, StatementProducer, ProducedStatements}; pub use service::Service; +mod collation; +mod dynamic_inclusion; +mod evaluation; mod error; mod service; +mod shared_table; // block size limit. const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024; /// A handle to a statement table router. -pub trait TableRouter { +/// +/// This is expected to be a lightweight, shared type like an `Arc`. +pub trait TableRouter: Clone { /// Errors when fetching data from the network. type Error; /// Future that resolves when candidate data is fetched. @@ -93,7 +108,7 @@ pub trait TableRouter { /// Future that resolves when extrinsic candidate data is fetched. type FetchExtrinsic: IntoFuture; - /// Note local candidate data. + /// 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); /// Fetch block data for a specific candidate. @@ -126,46 +141,6 @@ pub struct GroupInfo { pub needed_availability: usize, } -struct TableContext { - parent_hash: Hash, - key: Arc, - groups: HashMap, -} - -impl table::Context for TableContext { - fn is_member_of(&self, authority: &AuthorityId, group: &ParaId) -> bool { - self.groups.get(group).map_or(false, |g| g.validity_guarantors.contains(authority)) - } - - fn is_availability_guarantor_of(&self, authority: &AuthorityId, group: &ParaId) -> bool { - self.groups.get(group).map_or(false, |g| g.availability_guarantors.contains(authority)) - } - - fn requisite_votes(&self, group: &ParaId) -> (usize, usize) { - self.groups.get(group).map_or( - (usize::max_value(), usize::max_value()), - |g| (g.needed_validity, g.needed_availability), - ) - } -} - -impl TableContext { - fn local_id(&self) -> AuthorityId { - self.key.public().0 - } - - fn sign_statement(&self, statement: table::Statement) -> table::SignedStatement { - let signature = sign_table_statement(&statement, &self.key, &self.parent_hash).into(); - let local_id = self.key.public().0; - - table::SignedStatement { - statement, - signature, - sender: local_id, - } - } -} - /// Sign a table statement against a parent hash. /// The actual message signed is the encoded statement concatenated with the /// parent hash. @@ -185,247 +160,7 @@ pub fn sign_table_statement(statement: &table::Statement, key: &ed25519::Pair, p key.sign(&encoded) } -// A shared table object. -struct SharedTableInner { - table: Table, - proposed_digest: Option, - checked_validity: HashSet, - checked_availability: HashSet, -} - -impl SharedTableInner { - // Import a single statement. Provide a handle to a table router. - fn import_statement( - &mut self, - context: &TableContext, - router: &R, - statement: table::SignedStatement, - received_from: Option, - ) -> StatementProducer<::Future, ::Future> { - let mut producer = StatementProducer { - fetch_block_data: None, - fetch_extrinsic: None, - produced_statements: Default::default(), - _key: context.key.clone(), - }; - - let summary = match self.table.import_statement(context, statement, received_from) { - Some(summary) => summary, - None => return producer, - }; - - let local_id = context.local_id(); - let is_validity_member = context.is_member_of(&local_id, &summary.group_id); - let is_availability_member = - context.is_availability_guarantor_of(&local_id, &summary.group_id); - - let digest = &summary.candidate; - - // TODO: consider a strategy based on the number of candidate votes as well. - // only check validity if this wasn't locally proposed. - let checking_validity = is_validity_member - && self.proposed_digest.as_ref().map_or(true, |d| d != digest) - && self.checked_validity.insert(digest.clone()); - - let checking_availability = is_availability_member && self.checked_availability.insert(digest.clone()); - - if checking_validity || checking_availability { - match self.table.get_candidate(&digest) { - None => {} // TODO: handle table inconsistency somehow? - Some(candidate) => { - if checking_validity { - producer.fetch_block_data = Some(router.fetch_block_data(candidate).into_future().fuse()); - } - - if checking_availability { - producer.fetch_extrinsic = Some(router.fetch_extrinsic_data(candidate).into_future().fuse()); - } - } - } - } - - producer - } -} - -/// Produced statements about a specific candidate. -/// Both may be `None`. -#[derive(Default)] -pub struct ProducedStatements { - /// A statement about the validity of the candidate. - pub validity: Option, - /// A statement about the availability of the candidate. - pub availability: Option, -} - -/// Future that produces statements about a specific candidate. -pub struct StatementProducer { - fetch_block_data: Option>, - fetch_extrinsic: Option>, - produced_statements: ProducedStatements, - _key: Arc, -} - -impl Future for StatementProducer - where - D: Future, - E: Future, -{ - type Item = ProducedStatements; - type Error = Err; - - fn poll(&mut self) -> Poll { - let mut done = true; - if let Some(ref mut fetch_block_data) = self.fetch_block_data { - match fetch_block_data.poll()? { - Async::Ready(_block_data) => { - // TODO [PoC-2] : validate block data here and make statement. - }, - Async::NotReady => { - done = false; - } - } - } - - if let Some(ref mut fetch_extrinsic) = self.fetch_extrinsic { - match fetch_extrinsic.poll()? { - Async::Ready(_extrinsic) => { - // TODO [PoC-2]: guarantee availability of data and make statment. - } - Async::NotReady => { - done = false; - } - } - } - - if done { - Ok(Async::Ready(::std::mem::replace(&mut self.produced_statements, Default::default()))) - } else { - Ok(Async::NotReady) - } - } -} - -/// A shared table object. -pub struct SharedTable { - context: Arc, - inner: Arc>, -} - -impl Clone for SharedTable { - fn clone(&self) -> Self { - SharedTable { - context: self.context.clone(), - inner: self.inner.clone(), - } - } -} - -impl SharedTable { - /// Create a new shared table. - /// - /// Provide the key to sign with, and the parent hash of the relay chain - /// block being built. - pub fn new(groups: HashMap, key: Arc, parent_hash: Hash) -> Self { - SharedTable { - context: Arc::new(TableContext { groups, key, parent_hash }), - inner: Arc::new(Mutex::new(SharedTableInner { - table: Table::default(), - proposed_digest: None, - checked_validity: HashSet::new(), - checked_availability: HashSet::new(), - })) - } - } - - /// Get group info. - pub fn group_info(&self) -> &HashMap { - &self.context.groups - } - - /// Import a single statement. Provide a handle to a table router - /// for dispatching any other requests which come up. - pub fn import_statement( - &self, - router: &R, - statement: table::SignedStatement, - received_from: Option, - ) -> StatementProducer<::Future, ::Future> { - self.inner.lock().import_statement(&*self.context, router, statement, received_from) - } - - /// Sign and import a local statement. - pub fn sign_and_import( - &self, - router: &R, - statement: table::Statement, - ) -> StatementProducer<::Future, ::Future> { - let proposed_digest = match statement { - GenericStatement::Candidate(ref c) => Some(c.hash()), - _ => None, - }; - - let signed_statement = self.context.sign_statement(statement); - - let mut inner = self.inner.lock(); - if proposed_digest.is_some() { - inner.proposed_digest = proposed_digest; - } - - inner.import_statement(&*self.context, router, signed_statement, None) - } - - /// Import many statements at once. - /// - /// Provide an iterator yielding pairs of (statement, received_from). - pub fn import_statements(&self, router: &R, iterable: I) -> U - where - R: TableRouter, - I: IntoIterator)>, - U: ::std::iter::FromIterator::Future, - ::Future> - >, - { - let mut inner = self.inner.lock(); - - iterable.into_iter().map(move |(statement, received_from)| { - inner.import_statement(&*self.context, router, statement, received_from) - }).collect() - } - - /// Check if a proposal is valid. - pub fn proposal_valid(&self, _proposal: &SubstrateBlock) -> bool { - false // TODO - } - - /// Execute a closure using a specific candidate. - /// - /// Deadlocks if called recursively. - pub fn with_candidate(&self, digest: &Hash, f: F) -> U - where F: FnOnce(Option<&CandidateReceipt>) -> U - { - let inner = self.inner.lock(); - f(inner.table.get_candidate(digest)) - } - - /// Get all witnessed misbehavior. - pub fn get_misbehavior(&self) -> HashMap { - self.inner.lock().table.get_misbehavior().clone() - } - - /// Fill a statement batch. - pub fn fill_batch(&self, batch: &mut B) { - self.inner.lock().table.fill_batch(batch); - } - - /// Get the local proposed block's hash. - pub fn proposed_hash(&self) -> Option { - self.inner.lock().proposed_digest.clone() - } -} - -fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId]) -> Result, Error> { +fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId], local_id: AuthorityId) -> Result<(HashMap, LocalDuty), Error> { if roster.validator_duty.len() != authorities.len() { bail!(ErrorKind::InvalidDutyRosterLength(authorities.len(), roster.validator_duty.len())) } @@ -434,11 +169,14 @@ fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId]) -> Result {}, // does nothing for now. @@ -467,23 +205,45 @@ fn make_group_info(roster: DutyRoster, authorities: &[AuthorityId]) -> Result { + let local_duty = LocalDuty { + validation: local_validation, + }; + + Ok((map, local_duty)) + } + None => bail!(ErrorKind::NotValidator(local_id)), + } +} + +fn timer_error(e: &::std::io::Error) -> Error { + ErrorKind::Timer(format!("{}", e)).into() } /// Polkadot proposer factory. -pub struct ProposerFactory { +pub struct ProposerFactory { /// The client instance. pub client: Arc, /// The transaction pool. pub transaction_pool: Arc>, /// The backing network handle. pub network: N, - /// Handle to the underlying tokio-core. + /// Parachain collators. + pub collators: P, + /// The timer used to schedule proposal intervals. pub handle: Handle, + /// The duration after which parachain-empty blocks will be allowed. + pub parachain_empty_duration: Duration, } -impl bft::ProposerFactory for ProposerFactory { - type Proposer = Proposer; +impl bft::ProposerFactory for ProposerFactory + where + C: PolkadotApi, + N: Network, + P: Collators, +{ + type Proposer = Proposer; type Error = Error; fn init(&self, parent_header: &SubstrateHeader, authorities: &[AuthorityId], sign_with: Arc) -> Result { @@ -497,135 +257,224 @@ impl bft::ProposerFactory for ProposerFactory let duty_roster = self.client.duty_roster(&checked_id)?; let random_seed = self.client.random_seed(&checked_id)?; - let group_info = make_group_info(duty_roster, authorities)?; + let (group_info, local_duty) = make_group_info( + duty_roster, + authorities, + sign_with.public().0, + )?; + + let active_parachains = self.client.active_parachains(&checked_id)?; + + let n_parachains = active_parachains.len(); let table = Arc::new(SharedTable::new(group_info, sign_with.clone(), parent_hash)); let router = self.network.table_router(table.clone()); + let dynamic_inclusion = DynamicInclusion::new( + n_parachains, + Instant::now(), + self.parachain_empty_duration.clone(), + ); - let timeout = Timeout::new(DELAY_UNTIL, &self.handle)?; + let timeout = Timeout::new(DELAY_UNTIL, &self.handle) + .map_err(|e| timer_error(&e))?; debug!(target: "bft", "Initialising consensus proposer. Refusing to evaluate for {:?} from now.", DELAY_UNTIL); // TODO [PoC-2]: kick off collation process. Ok(Proposer { - parent_hash, - parent_number: parent_header.number, - parent_id: checked_id, - random_seed, - local_key: sign_with, client: self.client.clone(), - transaction_pool: self.transaction_pool.clone(), + collators: self.collators.clone(), delay: timeout.shared(), - _table: table, - _router: router, + handle: self.handle.clone(), + dynamic_inclusion, + local_duty, + local_key: sign_with, + parent_hash, + parent_id: checked_id, + parent_number: parent_header.number, + random_seed, + router, + table, + transaction_pool: self.transaction_pool.clone(), }) } } -fn current_timestamp() -> Timestamp { - use std::time; - - time::SystemTime::now().duration_since(time::UNIX_EPOCH) - .expect("now always later than unix epoch; qed") - .as_secs() +struct LocalDuty { + validation: Chain, } /// The Polkadot proposer logic. -pub struct Proposer { - parent_hash: HeaderHash, - parent_number: BlockNumber, - parent_id: C::CheckedBlockId, - random_seed: Hash, +pub struct Proposer { client: Arc, - local_key: Arc, - transaction_pool: Arc>, + collators: P, delay: Shared, - _table: Arc, - _router: R, + dynamic_inclusion: DynamicInclusion, + handle: Handle, + local_duty: LocalDuty, + local_key: Arc, + parent_hash: HeaderHash, + parent_id: C::CheckedBlockId, + parent_number: BlockNumber, + random_seed: Hash, + router: R, + table: Arc, + transaction_pool: Arc>, } -impl bft::Proposer for Proposer { +impl bft::Proposer for Proposer + where + C: PolkadotApi, + R: TableRouter, + P: Collators, +{ type Error = Error; - type Create = Result; + type Create = future::Either< + CreateProposal, + future::FutureResult, + >; type Evaluate = Box>; fn propose(&self) -> Self::Create { - debug!(target: "bft", "proposing block on top of parent ({}, {:?})", self.parent_number, self.parent_hash); + const ATTEMPT_PROPOSE_EVERY: Duration = Duration::from_millis(100); - // TODO: handle case when current timestamp behind that in state. - let mut block_builder = self.client.build_block( - &self.parent_id, - current_timestamp() - )?; + let initial_included = self.table.includable_count(); + let enough_candidates = self.dynamic_inclusion.acceptable_in( + Instant::now(), + initial_included, + ).unwrap_or_default(); - let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); + let timing = { + let delay = self.delay.clone(); + let dynamic_inclusion = self.dynamic_inclusion.clone(); + let make_timing = move |handle| -> Result { + let attempt_propose = Interval::new(ATTEMPT_PROPOSE_EVERY, handle)?; + let enough_candidates = Timeout::new(enough_candidates, handle)?; + Ok(ProposalTiming { + attempt_propose, + enough_candidates, + dynamic_inclusion, + minimum_delay: Some(delay), + last_included: initial_included, + }) + }; - { - let mut pool = self.transaction_pool.lock(); - let mut unqueue_invalid = Vec::new(); - let mut pending_size = 0; - pool.cull(None, readiness_evaluator.clone()); - for pending in pool.pending(readiness_evaluator.clone()) { - // skip and cull transactions which are too large. - if pending.encoded_size() > MAX_TRANSACTIONS_SIZE { - unqueue_invalid.push(pending.hash().clone()); - continue + match make_timing(&self.handle) { + Ok(timing) => timing, + Err(e) => { + return future::Either::B(future::err(timer_error(&e))); } - - if pending_size + pending.encoded_size() >= MAX_TRANSACTIONS_SIZE { break } - - match block_builder.push_extrinsic(pending.as_transaction().clone()) { - Ok(()) => { - pending_size += pending.encoded_size(); - } - Err(_) => { - unqueue_invalid.push(pending.hash().clone()); - } - } - } - - for tx_hash in unqueue_invalid { - pool.remove(&tx_hash, false); - } - } - - 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()), - polkadot_block.header.parent_hash, - polkadot_block.extrinsics.iter() - .map(|xt| format!("{}", Hash::from(xt.blake2_256()))) - .collect::>() - .join(", ") - ); - - let substrate_block = Slicable::decode(&mut polkadot_block.encode().as_slice()) - .expect("polkadot blocks defined to serialize to substrate blocks correctly; qed"); - - assert!(evaluate_proposal(&substrate_block, &*self.client, current_timestamp(), &self.parent_hash, self.parent_number, &self.parent_id).is_ok()); - - Ok(substrate_block) - } - - // TODO: certain kinds of errors here should lead to a misbehavior report. - fn evaluate(&self, proposal: &SubstrateBlock) -> Self::Evaluate { - debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash); - - let evaluated = match evaluate_proposal(proposal, &*self.client, current_timestamp(), &self.parent_hash, self.parent_number, &self.parent_id) { - Ok(x) => Ok(x), - Err(e) => match *e.kind() { - ErrorKind::PolkadotApi(polkadot_api::ErrorKind::Executor(_)) => Ok(false), - ErrorKind::ProposalNotForPolkadot => Ok(false), - ErrorKind::TimestampInFuture => Ok(false), - ErrorKind::WrongParentHash(_, _) => Ok(false), - ErrorKind::ProposalTooLarge(_) => Ok(false), - _ => Err(e), } }; - // delay casting vote until able. - Box::new(self.delay.clone().map_err(Error::from).and_then(move |_| evaluated)) + future::Either::A(CreateProposal { + parent_hash: self.parent_hash.clone(), + parent_number: self.parent_number.clone(), + parent_id: self.parent_id.clone(), + client: self.client.clone(), + transaction_pool: self.transaction_pool.clone(), + collation: CollationFetch::new( + self.local_duty.validation, + self.parent_id.clone(), + self.parent_hash.clone(), + self.collators.clone(), + self.client.clone() + ), + table: self.table.clone(), + router: self.router.clone(), + timing, + }) + } + + fn evaluate(&self, proposal: &SubstrateBlock) -> 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) { + Ok(x) => x, + Err(e) => return Box::new(future::err(e.into())) as Box<_>, + }; + + let current_timestamp = current_timestamp(); + + // do initial serialization and structural integrity checks. + let maybe_proposal = evaluation::evaluate_initial( + proposal, + current_timestamp, + &self.parent_hash, + self.parent_number, + &active_parachains, + ); + + let proposal = match maybe_proposal { + Ok(p) => p, + Err(e) => { + // TODO: these errors are easily re-checked in runtime. + debug!(target: "bft", "Invalid proposal: {:?}", e); + return Box::new(future::ok(false)); + } + }; + + let vote_delays = { + // delay casting vote until able (according to minimum block time) + let minimum_delay = self.delay.clone() + .map_err(|e| timer_error(&*e)); + + let included_candidate_hashes = proposal + .parachain_heads() + .iter() + .map(|candidate| candidate.hash()); + + // delay casting vote until we have proof that all candidates are + // includable. + let includability_tracker = self.table.track_includability(included_candidate_hashes) + .map_err(|_| ErrorKind::PrematureDestruction.into()); + + // the duration at which the given number of parachains is acceptable. + let count_delay = self.dynamic_inclusion.acceptable_in( + Instant::now(), + proposal.parachain_heads().len(), + ); + + // the duration until the given timestamp is current + let proposed_timestamp = proposal.timestamp(); + let timestamp_delay = if proposed_timestamp > current_timestamp { + Some(Duration::from_secs(proposed_timestamp - current_timestamp)) + } else { + None + }; + + // construct a future from the maximum of the two durations. + let temporary_delay = match ::std::cmp::max(timestamp_delay, count_delay) { + Some(duration) => { + let maybe_timeout = Timeout::new(duration, &self.handle); + + let f = future::result(maybe_timeout) + .and_then(|timeout| timeout) + .map_err(|e| timer_error(&e)); + + future::Either::A(f) + } + None => future::Either::B(future::ok(())), + }; + + minimum_delay.join3(includability_tracker, temporary_delay) + }; + + // 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 future = future::result(evaluated).and_then(move |good| { + let end_result = future::ok(good); + if good { + // delay a "good" vote. + future::Either::A(vote_delays.and_then(|_| end_result)) + } else { + // don't delay a "bad" evaluation. + future::Either::B(end_result) + } + }); + + Box::new(future) as Box<_> } fn round_proposer(&self, round_number: usize, authorities: &[AuthorityId]) -> AuthorityId { @@ -697,45 +546,186 @@ impl bft::Proposer for Proposer { } } -fn evaluate_proposal( - proposal: &SubstrateBlock, - client: &C, - now: Timestamp, - parent_hash: &HeaderHash, - parent_number: BlockNumber, - parent_id: &C::CheckedBlockId, -) -> Result { - const MAX_TIMESTAMP_DRIFT: Timestamp = 4; +fn current_timestamp() -> Timestamp { + use std::time; - let encoded = Slicable::encode(proposal); - let proposal = PolkadotGenericBlock::decode(&mut &encoded[..]) - .and_then(|b| PolkadotBlock::from(b).ok()) - .ok_or_else(|| ErrorKind::ProposalNotForPolkadot)?; - - let transactions_size = proposal.extrinsics.iter().fold(0, |a, tx| { - a + Slicable::encode(tx).len() - }); - - if transactions_size > MAX_TRANSACTIONS_SIZE { - bail!(ErrorKind::ProposalTooLarge(transactions_size)) - } - - if proposal.header.parent_hash != *parent_hash { - bail!(ErrorKind::WrongParentHash(*parent_hash, proposal.header.parent_hash)); - } - - if proposal.header.number != parent_number + 1 { - bail!(ErrorKind::WrongNumber(parent_number + 1, proposal.header.number)) - } - - let block_timestamp = proposal.timestamp(); - - // TODO: just defer using `tokio_timer` to delay prepare vote. - if block_timestamp > now + MAX_TIMESTAMP_DRIFT { - bail!(ErrorKind::TimestampInFuture) - } - - // execute the block. - client.evaluate_block(parent_id, proposal.into())?; - Ok(true) + time::SystemTime::now().duration_since(time::UNIX_EPOCH) + .expect("now always later than unix epoch; qed") + .as_secs() +} + +struct ProposalTiming { + attempt_propose: Interval, + dynamic_inclusion: DynamicInclusion, + enough_candidates: Timeout, + minimum_delay: Option>, + last_included: usize, +} + +impl ProposalTiming { + // whether it's time to attempt a proposal. + // shouldn't be called outside of the context of a task. + fn poll(&mut self, included: usize) -> Poll<(), Error> { + // first drain from the interval so when the minimum delay is up + // we don't have any notifications built up. + // + // this interval is just meant to produce periodic task wakeups + // that lead to the `dynamic_inclusion` getting updated as necessary. + if let Async::Ready(x) = self.attempt_propose.poll() + .map_err(|e| timer_error(&e))? + { + x.expect("timer still alive; intervals never end; qed"); + } + + if let Some(ref mut min) = self.minimum_delay { + try_ready!(min.poll().map_err(|e| timer_error(&*e))); + } + + self.minimum_delay = None; // after this point, the future must have completed. + + if included == self.last_included { + return self.enough_candidates.poll().map_err(|e| timer_error(&e)); + } + + // the amount of includable candidates has changed. schedule a wakeup + // if it's not sufficient anymore. + let now = Instant::now(); + match self.dynamic_inclusion.acceptable_in(now, included) { + Some(duration) => { + self.last_included = included; + self.enough_candidates.reset(now + duration); + self.enough_candidates.poll().map_err(|e| timer_error(&e)) + } + None => { + Ok(Async::Ready(())) + } + } + } +} + +/// Future which resolves upon the creation of a proposal. +pub struct CreateProposal { + parent_hash: HeaderHash, + parent_number: BlockNumber, + parent_id: C::CheckedBlockId, + client: Arc, + transaction_pool: Arc>, + collation: CollationFetch, + router: R, + table: Arc, + timing: ProposalTiming, +} + +impl CreateProposal + where + C: PolkadotApi, + R: TableRouter, + P: Collators, +{ + fn propose_with(&self, candidates: Vec) -> Result { + // 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 readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client); + + { + let mut pool = self.transaction_pool.lock(); + let mut unqueue_invalid = Vec::new(); + let mut pending_size = 0; + + pool.cull(None, readiness_evaluator.clone()); + for pending in pool.pending(readiness_evaluator.clone()) { + // skip and cull transactions which are too large. + if pending.encoded_size() > MAX_TRANSACTIONS_SIZE { + unqueue_invalid.push(pending.hash().clone()); + continue + } + + if pending_size + pending.encoded_size() >= MAX_TRANSACTIONS_SIZE { break } + + match block_builder.push_extrinsic(pending.as_transaction().clone()) { + Ok(()) => { + pending_size += pending.encoded_size(); + } + Err(e) => { + trace!(target: "transaction-pool", "Invalid transaction: {}", e); + unqueue_invalid.push(pending.hash().clone()); + } + } + } + + for tx_hash in unqueue_invalid { + pool.remove(&tx_hash, false); + } + } + + 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()), + polkadot_block.header.parent_hash, + polkadot_block.extrinsics.iter() + .map(|xt| format!("{}", Hash::from(xt.blake2_256()))) + .collect::>() + .join(", ") + ); + + let substrate_block = Slicable::decode(&mut polkadot_block.encode().as_slice()) + .expect("polkadot blocks defined to serialize to substrate blocks correctly; qed"); + + // TODO: full re-evaluation + let active_parachains = self.client.active_parachains(&self.parent_id)?; + assert!(evaluation::evaluate_initial( + &substrate_block, + timestamp, + &self.parent_hash, + self.parent_number, + &active_parachains, + ).is_ok()); + + Ok(substrate_block) + } +} + +impl Future for CreateProposal + where + C: PolkadotApi, + R: TableRouter, + P: Collators, +{ + type Item = SubstrateBlock; + type Error = Error; + + fn poll(&mut self) -> Poll { + // 1. poll local collation future. + match self.collation.poll() { + Ok(Async::Ready((collation, extrinsic))) => { + let hash = collation.receipt.hash(); + self.router.local_candidate_data(hash, collation.block_data, extrinsic); + + // TODO: if we are an availability guarantor also, we should produce an availability statement. + self.table.sign_and_import(&self.router, GenericStatement::Candidate(collation.receipt)); + } + Ok(Async::NotReady) => {}, + Err(_) => {}, // TODO: handle this failure to collate. + } + + // 2. try to propose if we have enough includable candidates and other + // delays have concluded. + let included = self.table.includable_count(); + try_ready!(self.timing.poll(included)); + + // 3. propose + let proposed_candidates = self.table.with_proposal(|proposed_set| { + proposed_set.into_iter().cloned().collect() + }); + + self.propose_with(proposed_candidates).map(Async::Ready) + } } diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 97384040e9..cae27b16fd 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -22,19 +22,23 @@ use std::thread; use std::time::{Duration, Instant}; use std::sync::Arc; -use futures::{future, Future, Stream, Sink, Async, Canceled, Poll}; -use parking_lot::Mutex; -use substrate_network as net; -use tokio_core::reactor; + +use bft::{self, BftService}; use client::{BlockchainEvents, ChainHead}; -use runtime_support::Hashable; +use ed25519; +use futures::prelude::*; +use futures::{future, Canceled}; +use parking_lot::Mutex; +use polkadot_api::PolkadotApi; +use polkadot_primitives::AccountId; +use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt}; use primitives::{Hash, AuthorityId}; use primitives::block::{Id as BlockId, HeaderHash, Header}; -use polkadot_primitives::parachain::{BlockData, Extrinsic, CandidateReceipt}; -use polkadot_api::PolkadotApi; -use bft::{self, BftService}; +use runtime_support::Hashable; +use substrate_network as net; +use tokio_core::reactor; use transaction_pool::TransactionPool; -use ed25519; + use super::{TableRouter, SharedTable, ProposerFactory}; use error; @@ -174,6 +178,15 @@ impl Sink for BftSink { struct Network(Arc); +impl super::Network for Network { + type TableRouter = Router; + fn table_router(&self, _table: Arc) -> Self::TableRouter { + Router { + network: self.0.clone() + } + } +} + fn start_bft( header: &Header, handle: reactor::Handle, @@ -224,6 +237,7 @@ impl Service { client: Arc, network: Arc, transaction_pool: Arc>, + parachain_empty_duration: Duration, key: ed25519::Pair, ) -> Service where @@ -233,10 +247,13 @@ impl Service { let thread = thread::spawn(move || { let mut core = reactor::Core::new().expect("tokio::Core could not be created"); let key = Arc::new(key); + let factory = ProposerFactory { client: client.clone(), transaction_pool: transaction_pool.clone(), network: Network(network.clone()), + collators: NoCollators, + parachain_empty_duration, handle: core.handle(), }; let bft_service = Arc::new(BftService::new(client.clone(), key, factory)); @@ -312,17 +329,25 @@ impl Drop for Service { } } -impl super::Network for Network { - type TableRouter = Router; - fn table_router(&self, _table: Arc) -> Self::TableRouter { - Router { - network: self.0.clone() - } +// Collators implementation which never collates anything. +// TODO: do a real implementation. +#[derive(Clone, Copy)] +struct NoCollators; + +impl ::collation::Collators for NoCollators { + type Error = (); + type Collation = future::Empty<::collation::Collation, ()>; + + fn collate(&self, _parachain: ParaId, _relay_parent: Hash) -> Self::Collation { + future::empty() } + + fn note_bad_collator(&self, _collator: AccountId) { } } type FetchCandidateAdapter = future::Map) -> BlockData>; +#[derive(Clone)] struct Router { network: Arc, } diff --git a/polkadot/consensus/src/shared_table/includable.rs b/polkadot/consensus/src/shared_table/includable.rs new file mode 100644 index 0000000000..873c3af94c --- /dev/null +++ b/polkadot/consensus/src/shared_table/includable.rs @@ -0,0 +1,137 @@ +// 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 . + +//! Implements a future which resolves when all of the candidates referenced are includable. + +use std::collections::HashMap; + +use futures::prelude::*; +use futures::sync::oneshot; + +use polkadot_primitives::Hash; + +/// Track includability of a set of candidates, +pub(super) fn track>(candidates: I) -> (IncludabilitySender, Includable) { + let (tx, rx) = oneshot::channel(); + let tracking: HashMap<_, _> = candidates.into_iter().collect(); + let includable_count = tracking.values().filter(|x| **x).count(); + + let mut sender = IncludabilitySender { + tracking, + includable_count, + sender: Some(tx), + }; + + sender.try_complete(); + + ( + sender, + Includable(rx), + ) +} + +/// The sending end of the includability sender. +pub(super) struct IncludabilitySender { + tracking: HashMap, + includable_count: usize, + sender: Option>, +} + +impl IncludabilitySender { + /// update the inner candidate. wakes up the task as necessary. + /// returns `Err(Canceled)` if the other end has hung up. + /// + /// returns `true` when this is completed and should be destroyed. + pub fn update_candidate(&mut self, candidate: Hash, includable: bool) -> bool { + use std::collections::hash_map::Entry; + + match self.tracking.entry(candidate) { + Entry::Vacant(_) => {} + Entry::Occupied(mut entry) => { + let old = entry.insert(includable); + if !old && includable { + self.includable_count += 1; + } else if old && !includable { + self.includable_count -= 1; + } + } + } + + self.try_complete() + } + + /// whether the sender is completed. + pub fn is_complete(&self) -> bool { + self.sender.is_none() + } + + fn try_complete(&mut self) -> bool { + if self.includable_count == self.tracking.len() { + if let Some(sender) = self.sender.take() { + let _ = sender.send(()); + } + + true + } else { + false + } + } +} + +/// Future that resolves when all the candidates within are includable. +pub struct Includable(oneshot::Receiver<()>); + +impl Future for Includable { + type Item = (); + type Error = oneshot::Canceled; + + fn poll(&mut self) -> Poll<(), oneshot::Canceled> { + self.0.poll() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let hash1 = [1; 32].into(); + let hash2 = [2; 32].into(); + let hash3 = [3; 32].into(); + + let (mut sender, recv) = track([ + (hash1, true), + (hash2, true), + (hash2, false), // overwrite should favor latter. + (hash3, true), + ].iter().cloned()); + + assert!(!sender.is_complete()); + + // true -> false transition is possible and should be handled. + sender.update_candidate(hash1, false); + assert!(!sender.is_complete()); + + sender.update_candidate(hash2, true); + assert!(!sender.is_complete()); + + sender.update_candidate(hash1, true); + assert!(sender.is_complete()); + + recv.wait().unwrap(); + } +} diff --git a/polkadot/consensus/src/shared_table/mod.rs b/polkadot/consensus/src/shared_table/mod.rs new file mode 100644 index 0000000000..23e936eefe --- /dev/null +++ b/polkadot/consensus/src/shared_table/mod.rs @@ -0,0 +1,566 @@ +// 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 . + +//! Parachain statement table meant to to shared with a message router +//! and a consensus proposer. + +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + +use table::{self, Table, Context as TableContextTrait}; +use table::generic::Statement as GenericStatement; +use collation::Collation; +use polkadot_primitives::Hash; +use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt}; +use primitives::AuthorityId; + +use parking_lot::Mutex; +use futures::{future, prelude::*}; + +use super::{GroupInfo, TableRouter}; +use self::includable::IncludabilitySender; + +mod includable; + +pub use self::includable::Includable; + +struct TableContext { + parent_hash: Hash, + key: Arc<::ed25519::Pair>, + groups: HashMap, +} + +impl table::Context for TableContext { + fn is_member_of(&self, authority: &AuthorityId, group: &ParaId) -> bool { + self.groups.get(group).map_or(false, |g| g.validity_guarantors.contains(authority)) + } + + fn is_availability_guarantor_of(&self, authority: &AuthorityId, group: &ParaId) -> bool { + self.groups.get(group).map_or(false, |g| g.availability_guarantors.contains(authority)) + } + + fn requisite_votes(&self, group: &ParaId) -> (usize, usize) { + self.groups.get(group).map_or( + (usize::max_value(), usize::max_value()), + |g| (g.needed_validity, g.needed_availability), + ) + } +} + +impl TableContext { + fn local_id(&self) -> AuthorityId { + self.key.public().0 + } + + fn sign_statement(&self, statement: table::Statement) -> table::SignedStatement { + let signature = ::sign_table_statement(&statement, &self.key, &self.parent_hash).into(); + let local_id = self.key.public().0; + + table::SignedStatement { + statement, + signature, + sender: local_id, + } + } +} + +/// Source of statements +pub enum StatementSource { + /// Locally produced statement. + Local, + /// Received statement from remote source, with optional sender. + Remote(Option), +} + +// A shared table object. +struct SharedTableInner { + table: Table, + proposed_digest: Option, + checked_validity: HashSet, + checked_availability: HashSet, + trackers: Vec, +} + +impl SharedTableInner { + // Import a single statement. Provide a handle to a table router and a function + // used to determine if a referenced candidate is valid. + fn import_statement bool>( + &mut self, + context: &TableContext, + router: &R, + statement: table::SignedStatement, + statement_source: StatementSource, + check_candidate: C, + ) -> StatementProducer< + ::Future, + ::Future, + C, + > { + // this blank producer does nothing until we attach some futures + // and set a candidate digest. + let received_from = match statement_source { + StatementSource::Local => return Default::default(), + StatementSource::Remote(from) => from, + }; + + let summary = match self.table.import_statement(context, statement, received_from) { + Some(summary) => summary, + None => return Default::default(), + }; + + self.update_trackers(&summary.candidate, context); + + let local_id = context.local_id(); + + let is_validity_member = context.is_member_of(&local_id, &summary.group_id); + let is_availability_member = + context.is_availability_guarantor_of(&local_id, &summary.group_id); + + let digest = &summary.candidate; + + // TODO: consider a strategy based on the number of candidate votes as well. + // only check validity if this wasn't locally proposed. + let checking_validity = is_validity_member + && self.proposed_digest.as_ref().map_or(true, |d| d != digest) + && self.checked_validity.insert(digest.clone()); + + let checking_availability = is_availability_member + && self.checked_availability.insert(digest.clone()); + + let work = if checking_validity || checking_availability { + match self.table.get_candidate(&digest) { + None => None, // TODO: handle table inconsistency somehow? + Some(candidate) => { + let fetch_block_data = + router.fetch_block_data(candidate).into_future().fuse(); + + let fetch_extrinsic = if checking_availability { + Some( + router.fetch_extrinsic_data(candidate).into_future().fuse() + ) + } else { + None + }; + + Some(Work { + candidate_receipt: candidate.clone(), + fetch_block_data, + fetch_extrinsic, + evaluate: checking_validity, + check_candidate, + }) + } + } + } else { + None + }; + + StatementProducer { + produced_statements: Default::default(), + work, + } + } + + fn update_trackers(&mut self, candidate: &Hash, context: &TableContext) { + let includable = self.table.candidate_includable(candidate, context); + for i in (0..self.trackers.len()).rev() { + if self.trackers[i].update_candidate(candidate.clone(), includable) { + self.trackers.swap_remove(i); + } + } + } +} + +/// Produced statements about a specific candidate. +/// Both may be `None`. +#[derive(Default)] +pub struct ProducedStatements { + /// A statement about the validity of the candidate. + pub validity: Option, + /// A statement about availability of data. If this is `Some`, + /// then `block_data` and `extrinsic` should be `Some` as well. + pub availability: Option, + /// Block data to ensure availability of. + pub block_data: Option, + /// Extrinsic data to ensure availability of. + pub extrinsic: Option, +} + +/// Future that produces statements about a specific candidate. +pub struct StatementProducer { + produced_statements: ProducedStatements, + work: Option>, +} + +struct Work { + candidate_receipt: CandidateReceipt, + fetch_block_data: future::Fuse, + fetch_extrinsic: Option>, + evaluate: bool, + check_candidate: C +} + +impl Default for StatementProducer { + fn default() -> Self { + StatementProducer { + produced_statements: Default::default(), + work: None, + } + } +} + +impl Future for StatementProducer + where + D: Future, + E: Future, + C: FnMut(Collation) -> bool, +{ + type Item = ProducedStatements; + type Error = Err; + + fn poll(&mut self) -> Poll { + let work = match self.work { + Some(ref mut work) => work, + None => return Ok(Async::Ready(::std::mem::replace(&mut self.produced_statements, Default::default()))), + }; + + if let Async::Ready(block_data) = work.fetch_block_data.poll()? { + self.produced_statements.block_data = Some(block_data.clone()); + if work.evaluate { + let is_good = (work.check_candidate)(Collation { + block_data, + receipt: work.candidate_receipt.clone(), + }); + + let hash = work.candidate_receipt.hash(); + self.produced_statements.validity = Some(if is_good { + GenericStatement::Valid(hash) + } else { + GenericStatement::Invalid(hash) + }); + } + } + + if let Some(ref mut fetch_extrinsic) = work.fetch_extrinsic { + if let Async::Ready(extrinsic) = fetch_extrinsic.poll()? { + self.produced_statements.extrinsic = Some(extrinsic); + } + } + + let done = self.produced_statements.block_data.is_some() && { + if work.evaluate { + true + } else if self.produced_statements.extrinsic.is_some() { + self.produced_statements.availability = + Some(GenericStatement::Available(work.candidate_receipt.hash())); + + true + } else { + false + } + }; + + if done { + Ok(Async::Ready(::std::mem::replace(&mut self.produced_statements, Default::default()))) + } else { + Ok(Async::NotReady) + } + } +} + +/// A shared table object. +pub struct SharedTable { + context: Arc, + inner: Arc>, +} + +impl Clone for SharedTable { + fn clone(&self) -> Self { + SharedTable { + context: self.context.clone(), + inner: self.inner.clone(), + } + } +} + +impl SharedTable { + /// Create a new shared table. + /// + /// Provide the key to sign with, and the parent hash of the relay chain + /// block being built. + pub fn new(groups: HashMap, key: Arc<::ed25519::Pair>, parent_hash: Hash) -> Self { + SharedTable { + context: Arc::new(TableContext { groups, key, parent_hash }), + inner: Arc::new(Mutex::new(SharedTableInner { + table: Table::default(), + proposed_digest: None, + checked_validity: HashSet::new(), + checked_availability: HashSet::new(), + trackers: Vec::new(), + })) + } + } + + /// Get group info. + pub fn group_info(&self) -> &HashMap { + &self.context.groups + } + + /// Import a single statement. Provide a handle to a table router + /// for dispatching any other requests which come up. + pub fn import_statement bool>( + &self, + router: &R, + statement: table::SignedStatement, + received_from: StatementSource, + check_candidate: C, + ) -> StatementProducer<::Future, ::Future, C> { + self.inner.lock().import_statement(&*self.context, router, statement, received_from, check_candidate) + } + + /// Sign and import a local statement. + pub fn sign_and_import( + &self, + router: &R, + statement: table::Statement, + ) { + let proposed_digest = match statement { + GenericStatement::Candidate(ref c) => Some(c.hash()), + _ => None, + }; + + let signed_statement = self.context.sign_statement(statement); + + let mut inner = self.inner.lock(); + if proposed_digest.is_some() { + inner.proposed_digest = proposed_digest; + } + + let producer = inner.import_statement( + &*self.context, + router, + signed_statement, + StatementSource::Local, + |_| true, + ); + + assert!(producer.work.is_none(), "local statement import never leads to additional work; qed"); + } + + /// Import many statements at once. + /// + /// Provide an iterator yielding pairs of (statement, statement_source). + pub fn import_statements(&self, router: &R, iterable: I) -> U + where + R: TableRouter, + I: IntoIterator, + C: FnMut(Collation) -> bool, + U: ::std::iter::FromIterator::Future, + ::Future, + C, + >>, + { + let mut inner = self.inner.lock(); + + iterable.into_iter().map(move |(statement, statement_source, check_candidate)| { + inner.import_statement(&*self.context, router, statement, statement_source, check_candidate) + }).collect() + } + + /// Execute a closure using a specific candidate. + /// + /// Deadlocks if called recursively. + pub fn with_candidate(&self, digest: &Hash, f: F) -> U + where F: FnOnce(Option<&CandidateReceipt>) -> U + { + let inner = self.inner.lock(); + f(inner.table.get_candidate(digest)) + } + + /// Execute a closure using the current proposed set. + /// + /// Deadlocks if called recursively. + pub fn with_proposal(&self, f: F) -> U + where F: FnOnce(Vec<&CandidateReceipt>) -> U + { + let inner = self.inner.lock(); + f(inner.table.proposed_candidates(&*self.context)) + } + + /// Get the number of parachains which have available candidates. + pub fn includable_count(&self) -> usize { + self.inner.lock().table.includable_count() + } + + /// Get all witnessed misbehavior. + pub fn get_misbehavior(&self) -> HashMap { + self.inner.lock().table.get_misbehavior().clone() + } + + /// Fill a statement batch. + pub fn fill_batch(&self, batch: &mut B) { + self.inner.lock().table.fill_batch(batch); + } + + /// Track includability of a given set of candidate hashes. + pub fn track_includability(&self, iterable: I) -> Includable + where I: IntoIterator + { + let mut inner = self.inner.lock(); + + let (tx, rx) = includable::track(iterable.into_iter().map(|x| { + let includable = inner.table.candidate_includable(&x, &*self.context); + (x, includable) + })); + + if !tx.is_complete() { + inner.trackers.push(tx); + } + + rx + } +} + +#[cfg(test)] +mod tests { + use super::*; + use substrate_keyring::Keyring; + + #[derive(Clone)] + struct DummyRouter; + impl TableRouter for DummyRouter { + type Error = (); + type FetchCandidate = ::futures::future::Empty; + type FetchExtrinsic = ::futures::future::Empty; + + /// 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) { + + } + + /// Fetch block data for a specific candidate. + fn fetch_block_data(&self, _candidate: &CandidateReceipt) -> Self::FetchCandidate { + ::futures::future::empty() + } + + /// Fetch extrinsic data for a specific candidate. + fn fetch_extrinsic_data(&self, _candidate: &CandidateReceipt) -> Self::FetchExtrinsic { + ::futures::future::empty() + } + } + + #[test] + fn statement_triggers_fetch_and_evaluate() { + let mut groups = HashMap::new(); + + let para_id = ParaId::from(1); + let local_id = Keyring::Alice.to_raw_public(); + let local_key = Arc::new(Keyring::Alice.pair()); + + let validity_other = Keyring::Bob.to_raw_public(); + let validity_other_key = Keyring::Bob.pair(); + let parent_hash = Default::default(); + + groups.insert(para_id, GroupInfo { + validity_guarantors: [local_id, validity_other].iter().cloned().collect(), + availability_guarantors: Default::default(), + needed_validity: 2, + needed_availability: 0, + }); + + let shared_table = SharedTable::new(groups, local_key.clone(), parent_hash); + + let candidate = CandidateReceipt { + parachain_index: para_id, + collator: [1; 32], + head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]), + balance_uploads: Vec::new(), + egress_queue_roots: Vec::new(), + fees: 1_000_000, + }; + + let candidate_statement = GenericStatement::Candidate(candidate); + + let signature = ::sign_table_statement(&candidate_statement, &validity_other_key, &parent_hash); + let signed_statement = ::table::generic::SignedStatement { + statement: candidate_statement, + signature: signature.into(), + sender: validity_other, + }; + + let producer = shared_table.import_statement( + &DummyRouter, + signed_statement, + StatementSource::Remote(None), + |_| true, + ); + + assert!(producer.work.is_some(), "candidate and local validity group are same"); + assert!(producer.work.as_ref().unwrap().evaluate, "should evaluate validity"); + } + + #[test] + fn statement_triggers_fetch_and_availability() { + let mut groups = HashMap::new(); + + let para_id = ParaId::from(1); + let local_id = Keyring::Alice.to_raw_public(); + let local_key = Arc::new(Keyring::Alice.pair()); + + let validity_other = Keyring::Bob.to_raw_public(); + let validity_other_key = Keyring::Bob.pair(); + let parent_hash = Default::default(); + + groups.insert(para_id, GroupInfo { + validity_guarantors: [validity_other].iter().cloned().collect(), + availability_guarantors: [local_id].iter().cloned().collect(), + needed_validity: 1, + needed_availability: 1, + }); + + let shared_table = SharedTable::new(groups, local_key.clone(), parent_hash); + + let candidate = CandidateReceipt { + parachain_index: para_id, + collator: [1; 32], + head_data: ::polkadot_primitives::parachain::HeadData(vec![1, 2, 3, 4]), + balance_uploads: Vec::new(), + egress_queue_roots: Vec::new(), + fees: 1_000_000, + }; + + let candidate_statement = GenericStatement::Candidate(candidate); + + let signature = ::sign_table_statement(&candidate_statement, &validity_other_key, &parent_hash); + let signed_statement = ::table::generic::SignedStatement { + statement: candidate_statement, + signature: signature.into(), + sender: validity_other, + }; + + let producer = shared_table.import_statement( + &DummyRouter, + signed_statement, + StatementSource::Remote(None), + |_| true, + ); + + assert!(producer.work.is_some(), "candidate and local availability group are same"); + assert!(producer.work.as_ref().unwrap().fetch_extrinsic.is_some(), "should fetch extrinsic when guaranteeing availability"); + assert!(!producer.work.as_ref().unwrap().evaluate, "should not evaluate validity"); + } +} diff --git a/polkadot/parachain/Cargo.toml b/polkadot/parachain/Cargo.toml new file mode 100644 index 0000000000..47cde571e1 --- /dev/null +++ b/polkadot/parachain/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "polkadot-parachain" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Types and utilities for creating and working with parachains" + +[dependencies] +substrate-codec = { path = "../../substrate/codec", default-features = false } +wasmi = { version = "0.1", optional = true } +error-chain = { version = "0.11", optional = true } + +[dev-dependencies] +tiny-keccak = "1.4" + +[features] +default = ["std"] +std = ["substrate-codec/std", "wasmi", "error-chain"] diff --git a/polkadot/parachain/src/lib.rs b/polkadot/parachain/src/lib.rs new file mode 100644 index 0000000000..2f3c064f33 --- /dev/null +++ b/polkadot/parachain/src/lib.rs @@ -0,0 +1,146 @@ +// 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 . + +//! Defines primitive types for creating or validating a parachain. +//! +//! When compiled with standard library support, this crate exports a `wasm` +//! module that can be used to validate parachain WASM. +//! +//! ## Parachain WASM +//! +//! Polkadot parachain WASM is in the form of a module which imports a memory +//! instance and exports a function `validate`. +//! +//! `validate` accepts as input two `i32` values, representing a pointer/length pair +//! respectively, that encodes `ValidationParams`. +//! +//! `validate` returns an `i32` which is a pointer to a little-endian 32-bit integer denoting a length. +//! Subtracting the length from the initial pointer will give a new pointer to the actual return data, +//! +//! ASCII-diagram demonstrating the return data format: +//! +//! ```ignore +//! [return data][len (LE-u32)] +//! ^~~returned pointer +//! ``` +//! +//! The `load_params` and `write_result` functions provide utilities for setting up +//! a parachain WASM module in Rust. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc))] + +/// Re-export of substrate-codec. +pub extern crate substrate_codec as codec; + +#[cfg(not(feature = "std"))] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate core; + +#[cfg(feature = "std")] +extern crate wasmi; + +#[cfg(feature = "std")] +#[macro_use] +extern crate error_chain; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; +use codec::Slicable; + +#[cfg(feature = "std")] +pub mod wasm; + +/// Validation parameters for evaluating the parachain validity function. +// TODO: consolidated ingress and balance downloads +#[derive(PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct ValidationParams { + /// The collation body. + pub block_data: Vec, + /// Previous head-data. + pub parent_head: Vec, +} + +impl Slicable for ValidationParams { + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + self.block_data.using_encoded(|s| v.extend(s)); + self.parent_head.using_encoded(|s| v.extend(s)); + + v + } + + fn decode(input: &mut I) -> Option { + Some(ValidationParams { + block_data: Slicable::decode(input)?, + parent_head: Slicable::decode(input)?, + }) + } +} + +/// The result of parachain validation. +// TODO: egress and balance uploads +#[derive(PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct ValidationResult { + /// New head data that should be included in the relay chain state. + pub head_data: Vec +} + +impl Slicable for ValidationResult { + fn encode(&self) -> Vec { + self.head_data.encode() + } + + fn decode(input: &mut I) -> Option { + Some(ValidationResult { + head_data: Slicable::decode(input)?, + }) + } +} + +/// Load the validation params from memory when implementing a Rust parachain. +/// +/// Offset and length must have been provided by the validation +/// function's entry point. +pub unsafe fn load_params(offset: usize, len: usize) -> ValidationParams { + let mut slice = ::core::slice::from_raw_parts(offset as *const u8, len); + + ValidationParams::decode(&mut slice).expect("Invalid input data") +} + +/// Allocate the validation result in memory, getting the return-pointer back. +/// +/// As described in the crate docs, this is a pointer to the appended length +/// of the vector. +pub fn write_result(result: ValidationResult) -> usize { + let mut encoded = result.encode(); + let len = encoded.len(); + + assert!(len <= u32::max_value() as usize, "Len too large for parachain-WASM abi"); + (len as u32).using_encoded(|s| encoded.extend(s)); + + // do not alter `encoded` beyond this point. may reallocate. + let end_ptr = &encoded[len] as *const u8 as usize; + + // leak so it doesn't get zeroed. + ::core::mem::forget(encoded); + end_ptr +} diff --git a/polkadot/parachain/src/wasm.rs b/polkadot/parachain/src/wasm.rs new file mode 100644 index 0000000000..a16383acb9 --- /dev/null +++ b/polkadot/parachain/src/wasm.rs @@ -0,0 +1,166 @@ +// 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 . + +//! WASM re-execution of a parachain candidate. +//! In the context of relay-chain candidate evaluation, there are some additional +//! steps to ensure that the provided input parameters are correct. +//! Assuming the parameters are correct, this module provides a wrapper around +//! a WASM VM for re-execution of a parachain candidate. + +use codec::Slicable; + +use wasmi::{self, Module, ModuleInstance, MemoryInstance, MemoryDescriptor, MemoryRef, ModuleImportResolver}; +use wasmi::{memory_units, RuntimeValue}; +use wasmi::Error as WasmError; + +use super::{ValidationParams, ValidationResult}; + +use std::cell::RefCell; + +error_chain! { + types { Error, ErrorKind, ResultExt; } + foreign_links { + Wasm(WasmError); + } + errors { + /// Call data too big. WASM32 only has a 32-bit address space. + ParamsTooLarge(len: usize) { + description("Validation parameters took up too much space to execute in WASM"), + display("Validation parameters took up {} bytes, max allowed by WASM is {}", len, i32::max_value()), + } + /// Bad return data or type. + BadReturn { + description("Validation function returned invalid data."), + display("Validation function returned invalid data."), + } + } +} + +struct Resolver { + max_memory: u32, // in pages. + memory: RefCell>, +} + +impl ModuleImportResolver for Resolver { + fn resolve_memory( + &self, + field_name: &str, + descriptor: &MemoryDescriptor, + ) -> Result { + if field_name == "memory" { + let effective_max = descriptor.maximum().unwrap_or(self.max_memory); + if descriptor.initial() > self.max_memory || effective_max > self.max_memory { + Err(WasmError::Instantiation("Module requested too much memory".to_owned())) + } else { + let mem = MemoryInstance::alloc( + memory_units::Pages(descriptor.initial() as usize), + descriptor.maximum().map(|x| memory_units::Pages(x as usize)), + )?; + *self.memory.borrow_mut() = Some(mem.clone()); + Ok(mem) + } + } else { + Err(WasmError::Instantiation("Memory imported under unknown name".to_owned())) + } + } +} + +/// Validate a candidate under the given validation code. +/// +/// This will fail if the validation code is not a proper parachain validation module. +pub fn validate_candidate(validation_code: &[u8], params: ValidationParams) -> Result { + use wasmi::LINEAR_MEMORY_PAGE_SIZE; + + // maximum memory in bytes + const MAX_MEM: u32 = 1024 * 1024 * 1024; // 1 GiB + + // instantiate the module. + let (module, memory) = { + let module = Module::from_buffer(validation_code)?; + + let module_resolver = Resolver { + max_memory: MAX_MEM / LINEAR_MEMORY_PAGE_SIZE.0 as u32, + memory: RefCell::new(None), + }; + + let module = ModuleInstance::new( + &module, + &wasmi::ImportsBuilder::new().with_resolver("env", &module_resolver), + )?.run_start(&mut wasmi::NopExternals).map_err(WasmError::Trap)?; + + let memory = module_resolver.memory.borrow_mut() + .as_ref() + .ok_or_else(|| WasmError::Instantiation("No imported memory instance".to_owned()))? + .clone(); + + (module, memory) + }; + + // allocate call data in memory. + let (offset, len) = { + let encoded_call_data = params.encode(); + + // hard limit from WASM. + if encoded_call_data.len() > i32::max_value() as usize { + bail!(ErrorKind::ParamsTooLarge(encoded_call_data.len())); + } + + let call_data_pages = (encoded_call_data.len() / LINEAR_MEMORY_PAGE_SIZE.0) + + (encoded_call_data.len() % LINEAR_MEMORY_PAGE_SIZE.0); + + let call_data_pages = wasmi::memory_units::Pages(call_data_pages); + + if memory.current_size() < call_data_pages { + memory.grow(call_data_pages - memory.current_size())?; + } + + memory.set(0, &encoded_call_data).expect("enough memory allocated just before this; \ + copying never fails if memory is large enough; qed"); + + (0, encoded_call_data.len() as i32) + }; + + let output = module.invoke_export( + "validate", + &[RuntimeValue::I32(offset), RuntimeValue::I32(len)], + &mut wasmi::NopExternals, + )?; + + match output { + Some(RuntimeValue::I32(len_offset)) => { + let len_offset = len_offset as u32; + + let mut len_bytes = [0u8; 4]; + memory.get_into(len_offset, &mut len_bytes)?; + + let len = u32::decode(&mut &len_bytes[..]) + .ok_or_else(|| ErrorKind::BadReturn)?; + + let return_offset = if len > len_offset { + bail!(ErrorKind::BadReturn); + } else { + len_offset - len + }; + + // TODO: optimize when `wasmi` lets you inspect memory with a closure. + let raw_return = memory.get(return_offset, len as usize)?; + ValidationResult::decode(&mut &raw_return[..]) + .ok_or_else(|| ErrorKind::BadReturn) + .map_err(Into::into) + } + _ => bail!(ErrorKind::BadReturn), + } +} diff --git a/polkadot/parachain/test-chains/.gitignore b/polkadot/parachain/test-chains/.gitignore new file mode 100644 index 0000000000..2c96eb1b65 --- /dev/null +++ b/polkadot/parachain/test-chains/.gitignore @@ -0,0 +1,2 @@ +target/ +Cargo.lock diff --git a/polkadot/parachain/test-chains/basic_add/Cargo.toml b/polkadot/parachain/test-chains/basic_add/Cargo.toml new file mode 100644 index 0000000000..afc9e9f131 --- /dev/null +++ b/polkadot/parachain/test-chains/basic_add/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "basic_add" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Test parachain which adds to a number as its state transition" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +polkadot-parachain = { path = "../../", default-features = false } +wee_alloc = "0.2.0" +tiny-keccak = "1.4" +pwasm-libc = "0.2" + +[features] +default = ["std"] +std = ["polkadot-parachain/std"] + +[profile.release] +panic = "abort" +lto = true + +[workspace] +members = [] diff --git a/polkadot/parachain/test-chains/basic_add/src/lib.rs b/polkadot/parachain/test-chains/basic_add/src/lib.rs new file mode 100644 index 0000000000..3f877b16d1 --- /dev/null +++ b/polkadot/parachain/test-chains/basic_add/src/lib.rs @@ -0,0 +1,143 @@ +// 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 . + +//! Basic parachain that adds a number as part of its state. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc, core_intrinsics, global_allocator, lang_items))] + +#[cfg(not(feature = "std"))] +extern crate alloc; + +extern crate polkadot_parachain as parachain; +extern crate wee_alloc; +extern crate tiny_keccak; +extern crate pwasm_libc; + +use parachain::codec::{Slicable, Input}; + +#[cfg(not(feature = "std"))] +mod wasm; + +#[cfg(not(feature = "std"))] +pub use wasm::*; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +// Define global allocator. +#[cfg(not(feature = "std"))] +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +// Head data for this parachain. +#[derive(Default, Clone)] +struct HeadData { + // Block number + number: u64, + // parent block keccak256 + parent_hash: [u8; 32], + // hash of post-execution state. + post_state: [u8; 32], +} + +impl Slicable for HeadData { + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + self.number.using_encoded(|s| v.extend(s)); + self.parent_hash.using_encoded(|s| v.extend(s)); + self.post_state.using_encoded(|s| v.extend(s)); + + v + } + + fn decode(input: &mut I) -> Option { + Some(HeadData { + number: Slicable::decode(input)?, + parent_hash: Slicable::decode(input)?, + post_state: Slicable::decode(input)?, + }) + } +} + +// Block data for this parachain. +#[derive(Default, Clone)] +struct BlockData { + // State to begin from. + state: u64, + // Amount to add (overflowing) + add: u64, +} + +impl Slicable for BlockData { + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + self.state.using_encoded(|s| v.extend(s)); + self.add.using_encoded(|s| v.extend(s)); + + v + } + + fn decode(input: &mut I) -> Option { + Some(BlockData { + state: Slicable::decode(input)?, + add: Slicable::decode(input)?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use parachain::ValidationParams; + + const TEST_CODE: &[u8] = include_bytes!("../wasm/test.wasm"); + + fn hash_state(state: u64) -> [u8; 32] { + ::tiny_keccak::keccak256(state.encode().as_slice()) + } + + fn hash_head(head: &HeadData) -> [u8; 32] { + ::tiny_keccak::keccak256(head.encode().as_slice()) + } + + #[test] + fn execute_good_on_parent() { + let parent_head = HeadData { + number: 0, + parent_hash: [0; 32], + post_state: hash_state(0), + }; + + let block_data = BlockData { + state: 0, + add: 512, + }; + + let ret = parachain::wasm::validate_candidate(TEST_CODE, ValidationParams { + parent_head: parent_head.encode(), + block_data: block_data.encode(), + }).unwrap(); + + let new_head = HeadData::decode(&mut &ret.head_data[..]).unwrap(); + + assert_eq!(new_head.number, 1); + assert_eq!(new_head.parent_hash, hash_head(&parent_head)); + assert_eq!(new_head.post_state, hash_state(512)); + } +} diff --git a/polkadot/parachain/test-chains/basic_add/src/src b/polkadot/parachain/test-chains/basic_add/src/src new file mode 120000 index 0000000000..e8310385c5 --- /dev/null +++ b/polkadot/parachain/test-chains/basic_add/src/src @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/polkadot/parachain/test-chains/basic_add/src/wasm.rs b/polkadot/parachain/test-chains/basic_add/src/wasm.rs new file mode 100644 index 0000000000..fa1bf64f43 --- /dev/null +++ b/polkadot/parachain/test-chains/basic_add/src/wasm.rs @@ -0,0 +1,58 @@ +// 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 . + +//! Defines WASM module logic. + +use parachain::{self, ValidationResult}; +use parachain::codec::Slicable; +use super::{HeadData, BlockData}; + +#[lang = "panic_fmt"] +#[no_mangle] +pub extern fn panic_fmt( + _args: ::core::fmt::Arguments, + _file: &'static str, + _line: u32, + _col: u32, +) -> ! { + use core::intrinsics; + unsafe { + intrinsics::abort(); + } +} + +#[no_mangle] +pub extern fn validate(offset: usize, len: usize) -> usize { + let hash_state = |state: u64| ::tiny_keccak::keccak256(state.encode().as_slice()); + + let params = unsafe { ::parachain::load_params(offset, len) }; + let parent_head = HeadData::decode(&mut ¶ms.parent_head[..]) + .expect("invalid parent head format."); + + let block_data = BlockData::decode(&mut ¶ms.block_data[..]) + .expect("invalid block data format."); + + assert_eq!(hash_state(block_data.state), parent_head.post_state, "wrong post-state proof"); + let new_state = block_data.state.saturating_add(block_data.add); + + let new_head = HeadData { + number: parent_head.number + 1, + parent_hash: ::tiny_keccak::keccak256(¶ms.parent_head[..]), + post_state: hash_state(new_state), + }; + + parachain::write_result(ValidationResult { head_data: new_head.encode() }) +} diff --git a/polkadot/parachain/test-chains/build_test_chains.sh b/polkadot/parachain/test-chains/build_test_chains.sh new file mode 100755 index 0000000000..6523e46f14 --- /dev/null +++ b/polkadot/parachain/test-chains/build_test_chains.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +rm -rf ./target +for i in */ +do + i=${i%/} + cd $i + + # TODO: stop using exact nightly when wee-alloc works on normal nightly. + RUSTFLAGS="-C link-arg=--import-memory" cargo +nightly-2018-03-07 build --target=wasm32-unknown-unknown --release --no-default-features + wasm-gc target/wasm32-unknown-unknown/release/$i.wasm ../../tests/res/$i.wasm + cd .. +done diff --git a/polkadot/parachain/tests/basic_add.rs b/polkadot/parachain/tests/basic_add.rs new file mode 100644 index 0000000000..c5fbe467a4 --- /dev/null +++ b/polkadot/parachain/tests/basic_add.rs @@ -0,0 +1,170 @@ +// 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 . + +//! Basic parachain that adds a number as part of its state. + +extern crate polkadot_parachain as parachain; +extern crate tiny_keccak; + +use parachain::ValidationParams; +use parachain::codec::{Slicable, Input}; + +// Head data for this parachain. +#[derive(Default, Clone)] +struct HeadData { + // Block number + number: u64, + // parent block keccak256 + parent_hash: [u8; 32], + // hash of post-execution state. + post_state: [u8; 32], +} + +impl Slicable for HeadData { + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + self.number.using_encoded(|s| v.extend(s)); + self.parent_hash.using_encoded(|s| v.extend(s)); + self.post_state.using_encoded(|s| v.extend(s)); + + v + } + + fn decode(input: &mut I) -> Option { + Some(HeadData { + number: Slicable::decode(input)?, + parent_hash: Slicable::decode(input)?, + post_state: Slicable::decode(input)?, + }) + } +} + +// Block data for this parachain. +#[derive(Default, Clone)] +struct BlockData { + // State to begin from. + state: u64, + // Amount to add (overflowing) + add: u64, +} + +impl Slicable for BlockData { + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + self.state.using_encoded(|s| v.extend(s)); + self.add.using_encoded(|s| v.extend(s)); + + v + } + + fn decode(input: &mut I) -> Option { + Some(BlockData { + state: Slicable::decode(input)?, + add: Slicable::decode(input)?, + }) + } +} + +const TEST_CODE: &[u8] = include_bytes!("res/basic_add.wasm"); + +fn hash_state(state: u64) -> [u8; 32] { + ::tiny_keccak::keccak256(state.encode().as_slice()) +} + +fn hash_head(head: &HeadData) -> [u8; 32] { + ::tiny_keccak::keccak256(head.encode().as_slice()) +} + +#[test] +fn execute_good_on_parent() { + let parent_head = HeadData { + number: 0, + parent_hash: [0; 32], + post_state: hash_state(0), + }; + + let block_data = BlockData { + state: 0, + add: 512, + }; + + let ret = parachain::wasm::validate_candidate(TEST_CODE, ValidationParams { + parent_head: parent_head.encode(), + block_data: block_data.encode(), + }).unwrap(); + + let new_head = HeadData::decode(&mut &ret.head_data[..]).unwrap(); + + assert_eq!(new_head.number, 1); + assert_eq!(new_head.parent_hash, hash_head(&parent_head)); + assert_eq!(new_head.post_state, hash_state(512)); +} + +#[test] +fn execute_good_chain_on_parent() { + let mut number = 0; + let mut parent_hash = [0; 32]; + let mut last_state = 0; + + for add in 0..10 { + let parent_head = HeadData { + number, + parent_hash, + post_state: hash_state(last_state), + }; + + let block_data = BlockData { + state: last_state, + add, + }; + + let ret = parachain::wasm::validate_candidate(TEST_CODE, ValidationParams { + parent_head: parent_head.encode(), + block_data: block_data.encode(), + }).unwrap(); + + let new_head = HeadData::decode(&mut &ret.head_data[..]).unwrap(); + + assert_eq!(new_head.number, number + 1); + assert_eq!(new_head.parent_hash, hash_head(&parent_head)); + assert_eq!(new_head.post_state, hash_state(last_state + add)); + + number += 1; + parent_hash = hash_head(&new_head); + last_state += add; + } +} + +#[test] +fn execute_bad_on_parent() { + let parent_head = HeadData { + number: 0, + parent_hash: [0; 32], + post_state: hash_state(0), + }; + + let block_data = BlockData { + state: 256, // start state is wrong. + add: 256, + }; + + let _ret = parachain::wasm::validate_candidate(TEST_CODE, ValidationParams { + parent_head: parent_head.encode(), + block_data: block_data.encode(), + }).unwrap_err(); +} diff --git a/polkadot/parachain/tests/res/basic_add.wasm b/polkadot/parachain/tests/res/basic_add.wasm new file mode 100755 index 0000000000000000000000000000000000000000..83f52db817f81cf088221070e7db06d3a9ea8765 GIT binary patch literal 44941 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 X{Ls~5O8(frTX~$XF7(Rv(PRG)^`N<2 literal 0 HcmV?d00001 diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index 1db009c735..b9a636162c 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -36,7 +36,6 @@ extern crate substrate_serializer; extern crate substrate_codec as codec; pub mod parachain; -pub mod validator; /// 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 diff --git a/polkadot/primitives/src/parachain.rs b/polkadot/primitives/src/parachain.rs index 1dde3b508d..3a87b1faa2 100644 --- a/polkadot/primitives/src/parachain.rs +++ b/polkadot/primitives/src/parachain.rs @@ -37,6 +37,13 @@ impl From for Id { fn from(x: u32) -> Self { Id(x) } } +impl Id { + /// Convert this Id into its inner representation. + pub fn into_inner(self) -> u32 { + self.0 + } +} + impl Slicable for Id { fn decode(input: &mut I) -> Option { u32::decode(input).map(Id) @@ -86,8 +93,6 @@ impl Slicable for Chain { } } - - /// The duty roster specifying what jobs each validator must do. #[derive(Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Default, Debug))] diff --git a/polkadot/primitives/src/validator.rs b/polkadot/primitives/src/validator.rs deleted file mode 100644 index 0bac607594..0000000000 --- a/polkadot/primitives/src/validator.rs +++ /dev/null @@ -1,76 +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 . - -//! Validator primitives. - -#[cfg(feature = "std")] -use primitives::bytes; -use rstd::vec::Vec; -use parachain; - -/// Parachain outgoing message. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -pub struct EgressPost(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -/// Balance upload. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -pub struct BalanceUpload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -/// Balance download. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -pub struct BalanceDownload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -/// The result of parachain validation. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct ValidationResult { - /// New head data that should be included in the relay chain state. - pub head_data: parachain::HeadData, - /// Outgoing messages (a vec for each parachain). - pub egress_queues: Vec>, - /// Balance uploads - pub balance_uploads: Vec, -} - -#[cfg(test)] -mod tests { - use super::*; - use substrate_serializer as ser; - - #[test] - fn test_validation_result() { - assert_eq!(ser::to_string_pretty(&ValidationResult { - head_data: parachain::HeadData(vec![1]), - egress_queues: vec![vec![EgressPost(vec![1])]], - balance_uploads: vec![BalanceUpload(vec![2])], - }), r#"{ - "headData": "0x01", - "egressQueues": [ - [ - "0x01" - ] - ], - "balanceUploads": [ - "0x02" - ] -}"#); - } -} diff --git a/polkadot/runtime/Cargo.toml b/polkadot/runtime/Cargo.toml index cb6c99de35..95044242fe 100644 --- a/polkadot/runtime/Cargo.toml +++ b/polkadot/runtime/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Parity Technologies "] [dependencies] rustc-hex = "1.0" -hex-literal = "0.1.0" log = { version = "0.3", optional = true } serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } @@ -28,6 +27,9 @@ 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" + [features] default = ["std"] std = [ diff --git a/polkadot/runtime/src/lib.rs b/polkadot/runtime/src/lib.rs index 1cfcd31497..9b86eb91cb 100644 --- a/polkadot/runtime/src/lib.rs +++ b/polkadot/runtime/src/lib.rs @@ -27,7 +27,7 @@ extern crate substrate_runtime_support as runtime_support; #[macro_use] extern crate substrate_runtime_primitives as runtime_primitives; -#[cfg(feature = "std")] +#[cfg(test)] #[macro_use] extern crate hex_literal; @@ -55,7 +55,19 @@ 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}; -#[cfg(feature = "std")] pub use runtime_primitives::BuildExternalities; + +#[cfg(feature = "std")] +pub use runtime_primitives::BuildExternalities; + +pub use consensus::Call as ConsensusCall; +pub use timestamp::Call as TimestampCall; +pub use parachains::Call as ParachainsCall; + + +/// 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; /// Concrete runtime type used to parameterize the various modules. pub struct Concrete; @@ -77,19 +89,18 @@ impl system::Trait for Concrete { pub type System = system::Module; impl consensus::Trait for Concrete { - type PublicAux = ::PublicAux; + type PublicAux = ::PublicAux; type SessionKey = SessionKey; } /// Consensus module for this concrete runtime. pub type Consensus = consensus::Module; -pub use consensus::Call as ConsensusCall; impl timestamp::Trait for Concrete { + const SET_POSITION: u32 = TIMESTAMP_SET_POSITION; type Value = u64; } /// Timestamp module for this concrete runtime. pub type Timestamp = timestamp::Module; -pub use timestamp::Call as TimestampCall; impl session::Trait for Concrete { type ConvertAccountIdToSessionKey = Identity; @@ -116,7 +127,11 @@ pub type Council = council::Module; /// Council voting module for this concrete runtime. pub type CouncilVoting = council::voting::Module; -impl parachains::Trait for Concrete {} +impl parachains::Trait for Concrete { + const SET_POSITION: u32 = PARACHAINS_SET_POSITION; + + type PublicAux = ::PublicAux; +} pub type Parachains = parachains::Module; impl_outer_dispatch! { @@ -128,6 +143,7 @@ impl_outer_dispatch! { Democracy = 5, Council = 6, CouncilVoting = 7, + Parachains = 8, } pub enum PrivCall { diff --git a/polkadot/runtime/src/parachains.rs b/polkadot/runtime/src/parachains.rs index ef46a25146..1a6a77d7fe 100644 --- a/polkadot/runtime/src/parachains.rs +++ b/polkadot/runtime/src/parachains.rs @@ -17,44 +17,70 @@ //! Main parachains logic. For now this is just the determination of which validators do what. use polkadot_primitives; -#[cfg(any(feature = "std", test))] use {runtime_io, runtime_primitives}; use rstd::prelude::*; -#[cfg(any(feature = "std", test))] use rstd::marker::PhantomData; use codec::{Slicable, Joiner}; use runtime_support::Hashable; -#[cfg(any(feature = "std", test))] use runtime_support::StorageValue; -use runtime_primitives::traits::Executable; -use polkadot_primitives::parachain::{Id, Chain, DutyRoster}; + +use runtime_primitives::traits::{Executable, RefInto, MaybeEmpty}; +use polkadot_primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt}; use {system, session}; -pub trait Trait: system::Trait + session::Trait {} +use runtime_support::{StorageValue, StorageMap}; + +#[cfg(any(feature = "std", test))] +use rstd::marker::PhantomData; + +#[cfg(any(feature = "std", test))] +use {runtime_io, runtime_primitives}; + +pub trait Trait: system::Trait + session::Trait { + /// The position of the set_heads call in the block. + const SET_POSITION: u32; + + type PublicAux: RefInto + MaybeEmpty; +} decl_module! { pub struct Module; + pub enum Call where aux: ::PublicAux { + // provide candidate receipts for parachains, in ascending order by id. + fn set_heads(aux, heads: Vec) = 0; + } } decl_storage! { - pub trait Store for Module; - // The number of parachains registered at present. - pub Count get(count): b"para:count" => default u32; + trait Store for Module; + // Vector of all parachain IDs. + pub Parachains get(active_parachains): b"para:chains" => default Vec; + // The parachains registered at present. + pub Code get(parachain_code): b"para:code" => map [ Id => Vec ]; + // The heads of the parachains registered at present. these are kept sorted. + pub Heads get(parachain_head): b"para:head" => map [ Id => Vec ]; + + // Did the parachain heads get updated in this block? + DidUpdate: b"para:did" => default bool; } impl Module { - /// Calculate the current block's duty roster. + /// Calculate the current block's duty roster using system's random seed. pub fn calculate_duty_roster() -> DutyRoster { - let parachain_count = Self::count(); - let validator_count = >::validator_count(); + let parachains = Self::active_parachains(); + let parachain_count = parachains.len(); + let validator_count = >::validator_count() as usize; let validators_per_parachain = if parachain_count != 0 { (validator_count - 1) / parachain_count } else { 0 }; let mut roles_val = (0..validator_count).map(|i| match i { - i if i < parachain_count * validators_per_parachain => - Chain::Parachain(Id::from(i / validators_per_parachain as u32)), + i if i < parachain_count * validators_per_parachain => { + let idx = i / validators_per_parachain; + Chain::Parachain(parachains[idx].clone()) + } _ => Chain::Relay, }).collect::>(); + let mut roles_gua = roles_val.clone(); - let h = >::random_seed(); - let mut seed = h.to_vec().and(b"validator_role_pairs").blake2_256(); + let random_seed = system::Module::::random_seed(); + let mut seed = random_seed.to_vec().and(b"validator_role_pairs").blake2_256(); // shuffle for i in 0..(validator_count - 1) { @@ -83,16 +109,76 @@ impl Module { guarantor_duty: roles_gua, } } + + /// Register a parachain with given code. + /// Fails if given ID is already used. + pub fn register_parachain(id: Id, code: Vec, initial_head_data: Vec) { + let mut parachains = Self::active_parachains(); + match parachains.binary_search(&id) { + Ok(_) => panic!("Parachain with id {} already exists", id.into_inner()), + Err(idx) => parachains.insert(idx, id), + } + + >::insert(id, code); + >::put(parachains); + >::insert(id, initial_head_data); + } + + /// Deregister a parachain with given id + pub fn deregister_parachain(id: Id) { + let mut parachains = Self::active_parachains(); + match parachains.binary_search(&id) { + Ok(idx) => { parachains.remove(idx); } + Err(_) => {} + } + + >::remove(id); + >::remove(id); + >::put(parachains); + } + + fn set_heads(aux: &::PublicAux, heads: Vec) { + assert!(aux.is_empty()); + assert!(!>::exists(), "Parachain heads must be updated only once in the block"); + assert!( + >::extrinsic_index() == T::SET_POSITION, + "Parachain heads update extrinsic must be at position {} in the block", + T::SET_POSITION + ); + + let active_parachains = Self::active_parachains(); + let mut iter = active_parachains.iter(); + + // perform this check before writing to storage. + for head in &heads { + assert!( + iter.find(|&p| p == &head.parachain_index).is_some(), + "Submitted candidate for unregistered or out-of-order parachain {}", + head.parachain_index.into_inner() + ); + } + + for head in heads { + let id = head.parachain_index.clone(); + >::insert(id, head.head_data.0); + } + + >::put(true); + } } impl Executable for Module { fn execute() { + assert!(::DidUpdate::take(), "Parachain heads must be updated once in the block"); } } +/// Parachains module genesis configuration. #[cfg(any(feature = "std", test))] pub struct GenesisConfig { - pub count: u32, + /// The initial parachains, mapped to code. + pub parachains: Vec<(Id, Vec)>, + /// Phantom data. pub phantom: PhantomData, } @@ -100,7 +186,7 @@ pub struct GenesisConfig { impl Default for GenesisConfig { fn default() -> Self { GenesisConfig { - count: 0, + parachains: Vec::new(), phantom: PhantomData, } } @@ -109,12 +195,26 @@ impl Default for GenesisConfig { #[cfg(any(feature = "std", test))] impl runtime_primitives::BuildExternalities for GenesisConfig { - fn build_externalities(self) -> runtime_io::TestExternalities { + fn build_externalities(mut self) -> runtime_io::TestExternalities { + use std::collections::HashMap; use runtime_io::twox_128; use codec::Slicable; - map![ - twox_128(>::key()).to_vec() => self.count.encode() - ] + + self.parachains.sort_unstable_by_key(|&(ref id, _)| id.clone()); + self.parachains.dedup_by_key(|&mut (ref id, _)| id.clone()); + + let only_ids: Vec<_> = self.parachains.iter().map(|&(ref id, _)| id).cloned().collect(); + + let mut map: HashMap<_, _> = map![ + twox_128(>::key()).to_vec() => only_ids.encode() + ]; + + for (id, code) in self.parachains { + let key = twox_128(&>::key_for(&id)).to_vec(); + map.insert(key, code.encode()); + } + + map.into() } } @@ -148,12 +248,15 @@ mod tests { impl session::Trait for Test { type ConvertAccountIdToSessionKey = Identity; } - impl Trait for Test {} + impl Trait for Test { + const SET_POSITION: u32 = 0; + + type PublicAux = ::PublicAux; + } - type System = system::Module; type Parachains = Module; - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext(parachains: Vec<(Id, Vec)>) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_externalities(); t.extend(consensus::GenesisConfig::{ code: vec![], @@ -164,22 +267,59 @@ mod tests { validators: vec![1, 2, 3, 4, 5, 6, 7, 8], }.build_externalities()); t.extend(GenesisConfig::{ - count: 2, + parachains: parachains, phantom: PhantomData, }.build_externalities()); t } #[test] - fn simple_setup_should_work() { - with_externalities(&mut new_test_ext(), || { - assert_eq!(Parachains::count(), 2); + fn active_parachains_should_work() { + let parachains = vec![ + (5u32.into(), vec![1,2,3]), + (100u32.into(), vec![4,5,6]), + ]; + + with_externalities(&mut new_test_ext(parachains), || { + assert_eq!(Parachains::active_parachains(), vec![5u32.into(), 100u32.into()]); + assert_eq!(Parachains::parachain_code(&5u32.into()), Some(vec![1,2,3])); + assert_eq!(Parachains::parachain_code(&100u32.into()), Some(vec![4,5,6])); }); } #[test] - fn should_work() { - with_externalities(&mut new_test_ext(), || { + fn register_deregister() { + let parachains = vec![ + (5u32.into(), vec![1,2,3]), + (100u32.into(), vec![4,5,6]), + ]; + + with_externalities(&mut new_test_ext(parachains), || { + assert_eq!(Parachains::active_parachains(), vec![5u32.into(), 100u32.into()]); + + assert_eq!(Parachains::parachain_code(&5u32.into()), Some(vec![1,2,3])); + assert_eq!(Parachains::parachain_code(&100u32.into()), Some(vec![4,5,6])); + + Parachains::register_parachain(99u32.into(), vec![7,8,9], vec![1, 1, 1]); + + assert_eq!(Parachains::active_parachains(), vec![5u32.into(), 99u32.into(), 100u32.into()]); + assert_eq!(Parachains::parachain_code(&99u32.into()), Some(vec![7,8,9])); + + Parachains::deregister_parachain(5u32.into()); + + assert_eq!(Parachains::active_parachains(), vec![99u32.into(), 100u32.into()]); + assert_eq!(Parachains::parachain_code(&5u32.into()), None); + }); + } + + #[test] + fn duty_roster_works() { + let parachains = vec![ + (0u32.into(), vec![]), + (1u32.into(), vec![]), + ]; + + with_externalities(&mut new_test_ext(parachains), || { let check_roster = |duty_roster: &DutyRoster| { assert_eq!(duty_roster.validator_duty.len(), 8); assert_eq!(duty_roster.guarantor_duty.len(), 8); @@ -191,16 +331,17 @@ mod tests { assert_eq!(duty_roster.guarantor_duty.iter().filter(|&&j| j == Chain::Relay).count(), 2); }; - System::set_random_seed([0u8; 32].into()); + system::Module::::set_random_seed([0u8; 32].into()); let duty_roster_0 = Parachains::calculate_duty_roster(); check_roster(&duty_roster_0); - System::set_random_seed([1u8; 32].into()); + system::Module::::set_random_seed([1u8; 32].into()); let duty_roster_1 = Parachains::calculate_duty_roster(); check_roster(&duty_roster_1); assert!(duty_roster_0 != duty_roster_1); - System::set_random_seed([2u8; 32].into()); + + system::Module::::set_random_seed([2u8; 32].into()); let duty_roster_2 = Parachains::calculate_duty_roster(); check_roster(&duty_roster_2); assert!(duty_roster_0 != duty_roster_2); diff --git a/polkadot/runtime/wasm/Cargo.lock b/polkadot/runtime/wasm/Cargo.lock index 77658199f1..bc00ce5ccd 100644 --- a/polkadot/runtime/wasm/Cargo.lock +++ b/polkadot/runtime/wasm/Cargo.lock @@ -498,9 +498,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "substrate-codec" version = "0.1.0" -dependencies = [ - "substrate-runtime-std 0.1.0", -] [[package]] name = "substrate-keyring" diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index 134df026b54534d6ec84e85bf60c1a8a2ee8651a..35f1cfd18b2c55732ede75049b876d94ba9d76e1 100644 GIT binary patch delta 139463 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%0Dc>LbnxP{k%_;b9$Q>`y=SdNL8Un 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 z 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 diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm index 6c962c62d8156b4026a958286fb6d7bbd6cbc0f0..7bc43f97d55204d60854c78bd42f5c0f5adb81c8 100755 GIT binary patch delta 145198 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

TtpOrY$y$OF z5cfvC>ND7uubI@wFmXw?rpUKIFNb$ddC{IE9ow?a>Ka%R?ibd8^2a718FoKw-28i# zP+RmpO0E4|qXgokXN7x7I#j5Hu4vmP*n!U$bZ!%*vPg`p>)EX%&oymdASx%j(~x zhtKG4e9_){oSvlMau=dJqty#9+Br66?(~v<7+d&`f63l$?C5^hN{!$#vfVWGR80_2(23gsM~wP9F@f3A+6aG5e=(>IwFZ=9B^Pu^iamp|!a z)eA3+Rt7g=t)|HgI5vj4r&AK;n)tDN@h{~W1>Ct?h(-isG?;=VRxB~$o~0J1oWZwp zwuQwSNUFMqe#&#B4t4S4O1UA%>fef581vhl4ICxUwlK@j58-8AG+1LI?_?f{^?q@$}7j8o>*GDDz_ZOg~ zzzqD^>>v3x_JA+Wexg2opgmWWpN}4G-L+ZGYC?$Bok&*Qi8Q#NDY8pgwf#Oirp|hk zzmI;{k8h4wCtVU*7=BzmeMw}a`t8U*4cm#--RIjkhBv6y7uXkb;AHcK z_6gzelj;i>*}vj(^u?S|x8*&GQBhrhKd8T>_cm19`29)!U7U)+ag{GM?qceH>Ar^C z9OJ+nL7IB1if*var-vIh*bBo?sdqNmePN|`Q+9Fm9X}v1s*6&KmAzo#(hun9wI9&Y zdXu^XYlnquhrMl`#gcod*jL}bCaTW) znmx6}a50l`GYNCo5R#~$jTG%KX#Gy_EC$!PK>8PVb=b9_LEiYI*CzM2`j z^Xs&~LB05Od*6Yr!6{itnkU6&F#_(S)B*UC{{H>|d`o|Se*m7X=QYBy7j*#ly+4He zhe7|s(_ZN4vY08>u;(M|qUO1Vr_9(tzCnCKCdfGa#>jCAB+t0iK9Tc)F1ys;U>@D- zh;Q0QprBcE>bnrM#}X$s=YdJB`1#hFTE&GM`1zs;A5u9&kAw7%8-776Woefa%A}Z) zgC?i&T+*Z~A~rxkC>NNgMl^}HwxP+uTdSLt!$71_b=bG;qXwh}B(5BkrdyJ?Yq*5Q zXUV+5l3AiIsl9Mcb|(frIT|P5alMT4nlRi^Tg`RTg#z$fSt;I8N1fhLM&{}HX6&uZ zkooA#^7>eVbIBTpN(<(5T^s8R>haTcRVw^~-Dw+Gef=_f8uu~$e+9%yIQ0GpfH-EO zedPZKKy?1U0>qy01qcWyP`kt}!Oggs2%3a8UT*JK;fyXHb@hy~+M!>Ft$w(fV-7ci z4$w0=kId0$n;A%Nue&&+{p-WW`AF4&Da~B_IMiT>#My9#y+0(T`meAjbW7z(&!`*( zACaL(g~UB4yV6%$>Bzim$#2>M*Vc2xJ7Ye#jT z*J&F<2nRA{F$;Jo`B{u5^(^*D;)CH}rxyd$*>H%>uzaS@N;C3oX-JXd_M-haHKeT5 zDc26A06?gk{4q0V$XN%$pdvD{u|iQx~b@Y3^qOA zbqJ0Co9Led{}J5&-+|3sjt2t&Te$u2gUyFmyhB4zz}9ZS2JF}2x0)S58w%2}Yq&WL zIuJQ0o&$cai9%iih=OD!d+d63$JKUxZ;VIzzE&Susx$g3GwD8S9cwtM%s=qPcOlpk zdq(wKWA}BKfom###&2DBTLU_RDpRvk&quAKd{_UfW?_Y3&TJYa? zTMi5>Kt15(Aot2c%AV9F9V#Tb_JzoG)nm}o8L7{Msu z#HtNUF{YkfXwYD9Gi(Y=s7F?=vhEwrQmTo_VMaI=buihI9W|I%12FpDF|-j}9n5lf zZJEh~Sz^!4SZuNpSo15|;d(Z0SVss9nE%Af+KJYI$&9^YwA#@|s~yd8BwF0O z0uK`2vx8?pht85!-TPg;dp^H?osFAw*)JdMX&V}NpBZ>u0uX`{cuR;w3@JNtlcpWM zz4UrCqvptvp;3=kW4;EbY0_6CkBMV>%KcwFa0@WOGQKEWk#+vT5dGamg6^`&0m%3x zipYp8IjB0+j}ME2j9MpPVmFC))Q>A;C^Oer2U*oSU$>os=|WBQQ!k`62S~tPm{UVF za(d#WAE1F>`vDsGmiN`bxzxys3g zpgP(0lj2AccCw82@n#(Ohy$1UjZ3J#DN{4ix>=ZI#{?>CUMT^t`nXuU4+B#pXI z7ltKK9W)mt8T2R8h;O6r$A_x??_=UEjXB>SfWIS(6%*JLKEH*}uCw9;Y$43E`H}v} zc6Kp+jnf8f<1>HPTfOaA1Ae1S3fhSd?e{jbADk5+?SkWC*O(rXLyP|4E<8shz8;~J zm1@>;Fw!QuijR^5>!oQb)axzltvBmeOx}9^(v?l4aUYqkB*YJ@8wHX+V=zftk&u7KBpKq=1NjgIe#v0_8fgX{MY!4&4 zaLu9bAoO@UIz$5ffMSE90P8Y{-61F3wb|h5DEzQ=jZ&mXTj%>7$w1nVAd43EqWbJ)N+hvH1|L^BJL0J>z+6%ZJb*24KlO z6XF(X19YLU*=&`hiO8uAlQf-K?IQ`P2qYv|U#L%fuyX1Y=_m}a!Vn@jK9Lg^m?pV{ zcfCBv(=T~W&_{nym}?z5MqCPX@shAP6mNjvm+J6UeI=NNw+tlCd5Ktt8A=PTA*NXVRTv=^EYFlH5Ej zSz|l1&&lQn8m3K+?0|^7LjB|bEbwT9Ky+)ULxMMSh_2Lids661&f7QI1ikPzCt!~SSdA3#fZX3I@c#5hxpcyd)_L#5``emvxMqM{~ z;MHqHY>I!KW;CwDi5iGNK8XAyPo3@RuE+x}fbbi+*!$C>2;(n` zSU&2yFA|Ry+~S3wJNPN%fw^c+m{mAt-kBMF!jA5dq1OiCx{eTYU2;hlABS@Dx&3ln|8aa*5OWP7$M30ZO6VQNxnulzYuxhxh_hsX1yR z=?-VzcFiJ|6wtQ%@r5@=UAk=8#1>*`EgQ*fPT^_vVygI8myPppyz zvKWfyH)x`%TGBg`R2QMnP0V(%{m1WBX8=+T7=K4a{Rue3L~K{37Q_Cm?tojtl3ITIyUV>}v!( zMIZ&@ITldAUQD5Fcyq2alOfA8ABI-v;{1DzH2|opi6v~r_v@yGhmrPy6qBAbO0kf1 zk4t0gR3P0!UPL({tB$=pbgs-$!gig&6*mFebLT5X>IX(fKj|xy^`oLR+>zBXFZ72d z=&#_I40MO-enf^L!+DLT%!|qEd;PRzh>0tv%Mqh$TS$F|-{Ywf5KNcMT4c%yUsPYY z+0IR2ZCxEdZZuw&08cJdPu^@#Q*YjE$MeRb!&ZsN_MScrXUBLxdbwcZT#InH9KBn| zCC&zt8h#YW*$t?5bWEw5K;s=pV<+F5ER`cg)RmcAGZ3zrX5r2u}1dI5J#J10Ulx9(K$E#}c$?YHd3t=8Tj;o}tCZ~bSRL`RhD z_7X=zH%t9YWjp6hH_LG(fscMPNzEipY6(CPC!8$yu{e7Kg!;r37U7Otr-P_m@Fg?U z8q+#@e-mZLtA)4PN6V?^95S9~F*4>AyrO?J-#XNzx7yR&WIU9R-V-|%2>AyllR#T8EpyDJWvn^~E-iE9(lYYNN)9;_A3|=D)2*6x zoYj##%c8-ZWwLV7xW@Jjg&OZHYo^OFM=mX6cP7A^ZVWcg!oO&I{NVH@hgPW!(m+|**rD)2Tr0y*G=8zbs_x7$;~ z>(tw?*^>`g7p5?B#nPTv;|s+S(BerioYCw_H!P{58IfI>r*XKGS8ci{GCrJ8U*8&; zJdiLo@fQz^K3ChCBgzyJL-fKUG24WbGGA8zM!3gx32s;tpU`f~CvhH1hwuUuc42bO z&xDYP`N`=U&HO}7ggW%PUa=+mxA89Pga+7HjQ)(N>T?P4%SUG?~G|35_1thn>6?Qq&O@FLRd}B6vbT9xBN^nHv&yG zHv)ChB!|UHb(7*9KC9MseNtZ$V)gIfE4}WB2UjYYB>LDLAG%9Pa#2Uj9CQKq)paaF zHQ(V+AL2uo9I_6z2tp@W=ZB!gMHU~&A01+9158mlb*xR!!jK1c*r<4$uwuA9;(UV0 zxi&i2!}f1EI-{$1oS5P5W_h9f92dh6sAYe9e4^lGdwhbRPFuW-^>H9_7yQ=r3-plS zRv@m-C=pkq#Jy*Pkx7e7TK%}r4qkwy$!Sp>`cjszXhp?##P@%v6MY6F+FT2$fJzR||&6 zP;OI8y+fv)FU{*CHT|iRTt~fwJ~DRu3C2&w00f84fJ_ctBhufESYUeSJ1{A9?Xl-X zYzi&nfeOzO<77_l5^tNelkK{Ks$!l2!GQC8ls)C1?VQ@$t+%Jg9bzNRW(#LC zLPxGge^$Lc>#k@`N;sm$tr+<-sQg)9ucEmj8*fJ?o#Idt$J4yfejW-`W}(tru?k z%Qm-%)wp@~KFc;l4~K3wONXy;>0&&hFIH)ic(Jbm>#wkwQLwmchNl8^xjAa%P%3W- zOQXu zLNGAx`uC5@*Vj?_gXn1?DrJy7$|zLJ!CYEy`upzQHk+Q({?%p+yd~xWF})rXR;`tT z@Vak)r*sG9t6ZBXy_a#I_u_|vuQOB;#^}>{h|IgjVSWD``+~u9_}m_Bq>?*?B8}(^ z&;?bvQf~;QB@H1EX(S2WhR_@qsZkm-)hjaI3!y0xzwqR)kL=rogfPoZ`?Q`TmPN zDI5>_GsluWkUlSbICOlkJzc9NsyNA68Q!X{o#b?d=cxN8IfoVJu;abHUQe$!Ab^n* z%9iDN2cl4K1^Pp)^&ogn_4Cvr-Oi+W^F-tJLCmLlGCN#nHX}m42~!yAzC;uw;S~p> z=}HYm$)#Kzr;1LWr>^aG4*a;JN^^oSb2YEho0;c`B4R%I3*`Jp>pZL8q|mPUPd6~M zWnlnXV^~-hx@^pEX=q72w!K~w-y}=o^$iAddPyPd5@%ZQL->wY^aoKdG5Ukm@Them zshri`+Bt`=M-nv$O^HKbpC%T^^Uo}fC-%yUaI-cZHY8P2;dR7FVUnZQ8mmw*3;=n; z>SvRk8R3U7+MN&#PFeT9gi1~^0n95D?CzNmdqiFS|21sV!w8>Aq;e)@hy z=0nZ^CQ<&W^GNSJz6N*B#BeOQv^}KfPc%5Mp}8yf>3cb-{hg^_ws2*IWiWt4FL_AKYsyM-PO5 zH+W>P^LqHG%VJi`5bj z7Pmo*+)_SEtvEfBA7~jnxp{O;>zF3vpmFT6-EFbX2@}V6O==(4(IMBcG;7C<+#in7 z-h+svo`m>7Xp(6FsL~L}bMxPrLnfO&xxHiEF_Zg8lXVtH!uC%+sefQqzjcD#*20d9 z={P-FTDci+faM$qjoAtBLrd$Pa*;WlOH5LnI0VlQ8Z#MZ3Cw~8FjD!4C(GXtP44AP zwSGK0tuuuzaOz0RYft`S5Kj&|B%4NPL4?M7y|0bQ86%#o zW}Gn0N^76moUl8~U2i8>H^z?#&qKqY-wdF zhAahQDtVgqo~Fk}lIhi#prk)~J;%QK+ehO=OEC-lz7kj603;*6)qAzu4sAon+Nc3k zr0Gj#3swLsjq0*8LsYqL{E{u=SsXJ9QH#$+4-G(rZ$NDbBV-DQrLLB1#U}Spq7ZIJ z8(P{btV-m6K=(Z7A`I0lR*ioag8KB=Sqk%xKUfgNomS6vszfRO0NZnfY?w+e2s>@ z8VGWUTQJ!(B7Mf2ZTviB(J<)^R3D9vg?wZf#94wd1ajGr6nlF(*vH|)Z4tMrrTr3q zbF6j+1?p`ZAB8~JT=*c+74q^A)z<7#0P52m<$AdTO8_~58+rl_OlmRk(BKf?^h6Sw zH3YUURF6lDSdT0jW>|~z5+i3hwIyh2TwlIA?TA}}#5Y2Lg6;HQqf=04bqJbCcKSEz zq;I(xxN-`ftZx)UtnF@yJg~5|cgF2XbVW9p>Jbe*#vvkF8hra0L8^J^y{sdFk zo#L!8e@y|L0iteWiU%gv6`rUZ$YPXB9MvMR#*5p!1!pqe`WEpW3#Zmj@D@D7S{P|x zc#C+ph4XWNm=wU-EUdW|w>1ye>xsl^W=k6nyx!6-UT=9crCR#CdE)jK%Eaw0w1wMS zNCLO_cpf;Rgg6nOf)k+@^`Ys`>{jF972&`Iisw#u4rAxalhd73$NP&{f5N8Wz*S7h zZ22zE>;ZV2m`D1wXA>TaXnKP0HiXPf8WS&-`;G<9WzoOpiIU<6(R9A|38I-g>PQ>b zK{S@z@WVvW^g=unLld_Fz?CJYXe{zeG(5xwE-6vfB!;Hz<1daZ-_>SXHy$BjpgNRJ zO+8`3$}WkDM43U#fcg9-qBh{8km+2Xq}D@f5zYQ1tg7{Gr%3;HU9KKdi-^pi$n>Ec z*pejFBWkFnGb|lZ(;WqEjoz;nNIYdZt$50){E%AXsPsa5G|7e$X!S65qZ-@ie5ebj znZeDLmm@>LP|o$x!B8Rj;gB_KU^rwY%>+Xi!K(a7C`I1~h^C4WKx}{^dY;%k28yC! z2<${$>7|>p*+Iq$FBBlo#*~scs1Ab;_`7zTxVQc?Zl8`Bj)7G>R$4u@E zI$sa~Rk!Z$>^$ZbtIjrJHxB+`cV}(X+VX^2KFb+zz4pZ5mu5Nb_Q4nZT5A&x9={-E zY~2UAR_Ez%$P=Ut<=OJY;BPa|`F7`P+Pm1?keN?s?d?pr!havUcD6I0r)u5bnH~Oz z`r}+@=HTl69WQL1eTMqY9B0AAb!SL_^kPjY27AL?X)^fHe&^6IMJ}7`9BfJ+Yu@?> zPdLE2*W&h&+=rZZIKei1kh7eflixYW*+JsD^PInsc-n`Z#U#G?Vdurpe`y!04LZyn zm^&abMb5DOrB}xPw za2i~~|D>~?DCZ!tp8Ui>N?D6AD})4 zt`pAUrkwqI#0-l^&k}=|X2rXRphBZ#U8bBZlWEGyxk7R0EVbqcXV;1UZZMhu@nBj`4>z>k6Q=?> zQ-St$`(`#AGaC-GvEd`muIj2IoM%ACCqL%QQ$IV>c_{qP!Eb%k**9#`ZV3NV@j9oa z<;IV~z}AdvIeqrvFOPDrww#sA%ihY>gQtDM`B-?&tfNilDz z4HnVfLl-)GstTpkvd_SGewx zR!1*%rVl<*az1ORkIZ)#zHga9%B&7gTv1wC+Pk{AdIZnPqSE4J@kL&#x=MXziPM`| zwX!lxGUyMh_FB10=QeNpr{o=3a>i0;H}$gT9NjF%mn<$*PJMofQ+(g9s9!E|I-5e~ ze`8J-=cHBV@y=)8ulQtj{qfG!?qRd~t|{6{edbuF>;0;jqP}*l zGv4{!s=b$;xKv$ttaEwODqfZ^sj3^6I{oigY$r8-nX`-9f3Y*`{jy9^7c6#OQx6{R z9Q*-2>{B0E;_UGOnf6i}mpS>t$Cf!`IedMEbAMDOP4HwNl|R9mruJU;@A|U5<~*hB z70&Fz!xq9=)o+(OJFDA{bB>W3c2lcPa2D@%Z>VMCgb?-aM9s&H3WeHuE{}vlqj}y= z`gESDmQbjJ=Ni?#(wRK4ke_|wP^g{fY9|!hh3C%!sJuVVQ>wU%XEV=DJUe;b>!*ik z;uzk~<=;5|E#`d+&!FkcXi}O!lk}+#=?D2;TF@LiHq^_9IJtBKJeTpljek<%RV32g z(0L4~kLPzMghC(VxsrcU@yPU3{PeAqo5b(!%39^@Hp!(9sV*4$^AM=b`vNt0m6I6g zF{65zUP|g+{`=$p``_rgl)ivo%lDwsW5$F+^LY38#{`Dnh=)Qu^BkG}R4f$Qt0Db& z{HCgUzJcfbgh4Xy+VJ5GKmBsj8F;VC4$$t8H(z_b+Pw~^=roqPaX@2^1qzib=Obq~k|HJ)! zXzck6KmD2!>AU;s7m(gKGqe2kV5GZ(BxCChg+d4V-)B><4iefA9qfOY#D_*09_FY2 zj#_dJ6&*o3$Q=qAnhi!txrafNBF~LHWvaVL-;?JW-etr=`hAp_bit(o!R*BV;t-yb z`Ny|9GL1|>57L!8s+wkqT_#jhug!vG9VUiIULHZ~C z^be6PJrB|^_0u1tydZOsex;wjh5WlWq@T%e2r6_g>3a$Mg92YAQIi!NI*i{>@DF?p zt?=J}J>va0yo1Q~?@x|+zms>`sDHm}#QRp>JB0p&2JV)GhIheoVKBk>>-gQ+A?a}A z_p^Ct66*N{>l^DknRl3F9n?=VumPFM3jYKL7Qg_CJU8-eg!Ovl>NL`&faHIee}bgP zlfFws`qTWD8GIvd$TG+u)PErPcWcOBuz-wI^bZ;o*arpnftDow$D|A0>vT2t6eqp! z&D0^d7Gy2?Sx44A)lYw=v5)Fhsu&m#-y^kN#ZHV}TAM?<3_DN=g7<)tui(2(!;Mre zs2sfifOp|40SOI~PevnCDbqTKLh^eJPwF42Gv=5{2n7uM0csWQ5eWUmDGeV8ok6#WNnp;6w+tLN8N zdS1AhU+SA*a2_~pjHIntxp>*?`HQ@h+hX#%YW4D!rG?)7mCKi}jRKz zyp@Y(b{lbDZCETGlebMO}->D0(@-r=7cGB|W zz3~^GZ%s{3c(39Mz10)nD}9x>x=XF!?j&QGYOd&I%9T{6k|^bpd3Elo&VgOUTCq~} zyhJUL&83UwlG}a4{9`^+NUHD!&hBc(4hklcm1MS*FY%|4E~jhi=mDpvy;iPzd9Pgd z5~-9|OC;T$)a7?LUVEjStQIRdFI7w=3R%x{r>gB2I@8({#dM*XC?wK}TDp|4$a1`)+2i2`^vq(&a?0 z>Qxe%e97&T>OZ08uXS2t#eAhu@CxNpHdo1{+!^&x%@eaJ##KmE6Nzf2T&}vikC^m6 zb=aBC=y)RI6^pr?mr0c~1+P?gXF6aDAl>6+0a8|g)TJICbjB%lrc;b1GNoEMQ%ogO zxl*d^<<<5xo!w)(LMfLn=e#TclP{|KOHM6TsU&KtbS0O_)@oj*R8{N0)iM z=DgZ{owF)dOvp$I#ayY9&j3a>@2k#9v5M!F^TlGKoGuiS$$VD*?5oZRF_1l3OQ!R= zT&hw{k$U*q&cU;Dl|;(Rrb-Ogt5j<|TfTB>X>~Hc2%Ic= zfU%rPfk|G{ovp@QggN`h+0IAXYqfl)M*p&zbRK*!y8Ei_>z&VcgRq%0*p*0ng<7Rn zbN9PAO#R7ZLT&!CGfPc7*Eu{^V2&xBDrK^%8rZB(J=fU-7$i!WaxR<86q1>2p{Q;< z*V+A`L@txhR;q<^s#q;mb4j;<59-TQmap`RD@w~2SA>^k^)LENrbMNd%oL%2=Az=x zJx!V~CRK7BUYx_f?AQXRgWJKEYPpiErYhM?$;%bo0}OeT%lUFSS;*AVg-p3z%DV@u zNA7p#j`Q;Q49RIPmr52&N!L~V-*IZYS3wyDQ%$7P&&JsX93?vKSv=|rxUgh(@9u3RjZ)YBI_J#CpRjnY#ANUd5?V=r<} zj@7(Wu97a*3Z-J+t7VF6!$r>Cu~IEntrU}0FIn~ql|)u;zsNaYzf7XSY%!DRYA&70 z*W4p^55SgQwR&Z-wsQH>`6sTf!O9j@lb{$)G0MfqDUqALb+ITkG@vDxWPGnk5UQFo=De9$qZmC%Fv~*GJ=X7YwaoYu zWJK~6L6`X^J%a#2S^x{Ei=n#<)aLIw3)&E~sS><2R|FXfDfQ4doKkxQyobY9D#=Q& zl*{GZvKe@)R4P`O$XYR#%XnTvZN8M;`BJ5ngi+@z$#S7o&A3(d$Tyt%?dejQ8j{Iu zx|qtOGfCG|o3}X&#$^g{%33Xvs}{29Qpv5E?3rw}l*#9F$wZ}G@+zLY(4?n|X%MKG z^3v5}Ia|uQi%fbgSAh_-2`^bgd}b@|Vv}C1Fp_e*TFr}4E>+#*{PaRPmnnJ)BzPrJ zE|=Zo^$d(-{JA`E&!v;8Y`NerF}c zxS&@{B1TgcFI#k%>-1RGtCk87Z@Q4=Z$6=pxWeg~If67R0gfg>HYNpOk<@4h*HM>V z;k?$CEvAuR8K%;!!SK~(-**1hPELALLv9wbSwP^fHVmx>`-K74Qps!q1tsOzo-M-A zieP50Sj=R>)>J{w`Hr)2cNlFdmq4PWa=ApM^zZUNLjIZga=Ma)A*Ax9S~6R%y?_0m z)g7AYrNEaO?dQC73f=7e3!H2UfOl26bUs(jCTqED_WcWdPB3#W@;qIrrJ%4Zd>AVG zya8e6{sm*R$!sNAsN~ROYWYgK;C|8M zPi69Dx}T{QDpgdRvU{q@Uo95lOxaw?%NM*{Dd7$nrk4Xl_+J@HEArW0qc-1$vREnQ z^Xa4qv^)^KQgBaG4@1f0iY2hbOQQ|IW{PR|be+AUoXqA+=rahOTCG@3xo3n;cQT12 zQ}21yoq=T++_kzuj0vFMxm;Rvr(90OuXPS=M|CKn4N*tR%Ot?qFPZ8S*-Wm0URTOi z5YFXui6t>0$!)ESZAi!tAr| zIevjsx}1WYCu-}8XQM5&f2q%)avUcGaJ49Y^M%VB<$O3Ywcy|Ni)H>5kLRS<=>JhHin&{5yJ(U})R@+VUaITA?;IJcpy4I*$wVIZ z41Y?fwws*WI%)+E{1=TOn=2#1-EW4~f(slkhT>L*jB3KTV7+N|oKasT}-6sVgQZg$9z(sJDKAXew2~6k5wx>2}hqs>5$~4sOe(Fiz62WlWSb zy3jQ@JIM~{AcfMB219{MKJR|J4)$C*QA!jOr6OouNxD}Wuvef#F&_~AC~IC#-7x5U zY*M;V&Q{>mg;E}sHCc793ZE|Ww4g433FBkIElyPBZ;=keL=)&ID5RwfAW@gx;#AsG z=mpX>4-EjdI^}*>H`WPbM8!yhzi2D9eA@k9_#AclJI;jNF{YO;UcLAvZ`EFV`R4Cl zd%4R_TD)@kvZda#)dzaD#mmUBeA&g}rU~kyGo0P_NaoS5iseGSSg7V1gnMmRETziQ z71!}YYwy>Gqhh+>5Y}dAM+$=wMYEQxR!Rv>5_b~;Ep*nIN$liQ8K5RHY~igwgDm6{ zg3k(qxqL|IriY50(J;2!+s)lpr&@ro-a<$@qKfG&Q$HS7y zes<;J)gJm?37t1tNfdLUT<3}@_olFV=yy(UJK9UShS7o{fB>nb-5;paZg+Y*F=Ub` zM1U}l;#)1cH;2zu`)_e-YRVR;t=&r`F_b)1#cT~TuHX);eYZF#jRTdEm^ZmXBA3f& zGwv;tyu2HAlTM^z&@~te(8ypdRoz>|N2)--K5} zg<_l~_YPA@p^}2-v7GwaEVp*ylC(E)~DeSrmiC=dk2!SZ;_} zcdKr)Ese#HM76D!%auZ{s*b(eSv)RZ&SYvCl#N6(onxT)n3|LLB&u-2Vyc`?(}Md$ z(`^Jz5|xJD7rbh=;NEMpm(!wkmdn^`l~fk%{yvjlDu7k;E{QsWh$~_a~-$geN9e5j(Y-PG=JCgMKw+rj8mDk1A9ZIdsspOneTx^00-WA;w??)l#We zaUb#d4$L;6EJF|ZG~&`rxsPf}X%ojxK9x=|kI4*{@U$O0Zo42*zEZ{*OxH4W%zaE} zZpZQzJtv)ov7w&T++Ub`l`Wl#8h7bQMdWe#z7;Uh`Azc$r_wdoY9FQT+q zs}>XPZvrNpO%#fmd?uaDR4S-}?vthfC`vC4@+w>|whpfXx8AFQ>{0gbi}Webz64?TtwQ8W_e1bP;y^2Dp5zGgxJ8QF2Eo&_`Y1$K!~o?fm=~PUn#6{vtoxe(0S1xe1FB|H)TzAtH~#}VM;^Y9XQ5Cm6sn&4y7@2(rvwTGw3^7^ zG(h70J-kBXcuIxWJA0|WKjQ4s;UzM)GR`GDFgRV)NtbK#a2}^7d*w_X*C$Rl<~~_+ z-weMaN(Sbg&f=dbNZ2L@6ur117a#|if>HRtEfn;jLTZncO2WE#NGjQe&_00%J4 zsD?}dwtRR;7wFD_Xek^^UMY4j5_}@XA0$a>P@Z0mw%Es|D@%sJ&~%o z>|mtjVgX+lF6<)q$NblwZZ-A^bYApdTqV^E4&^MgS8~s=j+Lr*Qd{3~MyW%8?R2Uy zJ>hh=<8{H&NP}geP-Ns<>CnPXL<;Ul%nwk2Pf7Po)0d$Nrgv6wu+oEMx>(3$aHqRp zvOY7ikvnLq1NS)|>0%8*l1~*Y?pfCSU|gxrQVFde^uxE0yiXL}bq%9d1HW-%?N|lq z+?W@+vZ&}u_siS?H>sVUa?b6%Ua;Wv8I} ze&NJADU~gh${rSLt(+_s+;gpu4IguddiyD-WgHfVm?v0#unz!mp6)^?Y^R3ot^hZj zBDJKu-de2w^^&uP}>nDaQg&)EutL7WX8Qf*V&F; z2Dni=QII|Sr0#{PdpqiJtz5>whSw0B0hB5CB6S}0)(IOxXUwDhAVyJ1+>5OR(uaLi z>{+L?lX_4{5G6SbUcw>n1}meUz0jFDEmOjCCIKCc5G)IPbSR4%WnIvK>*^yfIOE42 zxOkzrYW4I(kDC7B)!tIo^LuCRq)g32$E#vCClQ+|_Y&(yT`r?~o`%S!oVxCLXL)-T zy&2huGrNL?=w;lm$#{;Dz{lv$j0XozBL?6@)RT3;?)R?i-Mz~o)4pMuP|&-+UaIzb z!MO`woxsgw`lfy4-sr2?gQ?FI~n&onoG1}#OGnaIkdL~9_*xhl_5Z|r;KE^wx*^?!Bt zP~W}4nLG)l96^mc8MV5AQsZ80EfmlsH~basJL6SnZ=BPKB5^t3PDlvEzs|Z^on|$C zHC`YBI=`|UuMO4=6M!Qvg{uL#L?Po|ZxO(F-APQqosJ(B{})obh*F-)x;I#7>+wy_ zF7;L})Wu;6HR2Ej3AZ{W_eWNO zVr3Fo#X=)y=Ou8>-fXF^Upk*|N9`x>hgF|W;79O^SbbmoEqoSVUj{=8jWbP{&Z}Ye ziSTGIR8f@@1$b=|hD{{rR+FB=$(_j*LCGxYb+YW70t(f^^()kA>rD52I-PV zI^wi;@3hpNk2?o->S$3Fe@ULMZrJ`&A3~wqed|Io$|!e z=X)zlU;>sm(V!}NFd9(;AN1Wazh`xWEPQ3`X^+SP{G~_~E#ux}5kz<$T-)ytPO2Rr zXOc2bo^kew6Otq{R1mi%zKEK8pVd-2 zarL6*So@2;Rrg!!Q;$1GbRw4FDp^k)YrQ9^^{eQSsyZU*8dl0r}i=dc-(Ec z*HAOc?LmNUs{Jqt+UjNe{)*eJ$M!Z zpo}vS=LshIuLRb4wg2nR*mg`)0wP4#p|K)p<~|`G-A-b|6_4OLCbL(=jq3i|I#TLP zs2#7vMDwuZJU(e+7kJEY8U4mO+cWOmh6gNat6h5Xjjp;aGHC?D){=3tR;H5JO zB8&uD2=Qgzr{v>#YTzAbY-b7U4expm23xA6Gimo}uu601v_W_eRWymhiBPWK3@W(K zSXXNHImG<3N$hq4Ed-}0+V6!0Z#Cw`@)bwa@4opU{c7AqZx9-NJ-;ia(}Nbd&fBqMFc|tw_FvQs|K%e zclbrsAO7x)8<)lZ%!&>y(sYs#v-<}rb<)NAH??$@5?SaA35Zh@dc)2PO14ItV(nGr z3N|hts0>^^RdZidkGulgLgyhonycWZLLtF5_fnvd`S+c_iJix$1-Gr2U=C7!rBK^>6fLBZ;h)Z;NTdc z;wa7&AAUvc6=~{ghjD;s5Pr3cr?{ARUsa1DO+DzZMOah?&qo@S0TKEa^^HhVasW3% zkwq~yk7mxgn!j43=g&W}y7;73i_@>^-%FQQ`TaMm)uij!%f-d@8$MMRXWj@( z@#)PV+v>&Xe>7xUy*Tqv{b@AS@$D^ZuDaZA>Q>95O%pp4U_}8=NJtGx5}|mz;q$nU zVQw*Na6)|Yq8SO|);#weYt;PtOHW)vv;XpcQuCS!;~{nVs>PYpg5UJ=^x!vLIU}Mr z+D*HveQj_6*G{G^(gCL%YM|$?jp)8jQ>WNX?Hv*vCqha*F`2C3t8&lOg_E855Lg$0 zwX@ zFIlxn($5ZllYUM_o!~U3+r^2-TB}+Xe*#KDp0LitO-+feCCf$Rp}L{cVB#RtkZTQYmGBWye8m`Nh^F;Ye1=-m)YRGmexqV|ga>e2<1BE`*TrW|5OcSX z0o8ClN#s7uAB-PLW;=*K6W__=g(OOcYtg-Ms7*L5Sc)$+}z;*WHyxllgYS5ej0@Rn*WmwU-y5K;Tw?_U4y~m zONZV-iEl>c&R191O_S8r(M??)HPl4>N9bqxVsk0?TLzxp@^#!qgM_SI!vrp5;B`r~ H7SH`(8D*y_ delta 134078 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 RB@5hSUAYup()WjB`FnG@|( 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

J*5B_ohI|mGagxj9CWsdov+}k`9`9>UTE!qywJT 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 { authority_data: HashMap>, detected_misbehavior: HashMap::Misbehavior>, candidate_votes: HashMap>, + includable_count: HashMap, } impl Default for Table { @@ -276,6 +277,7 @@ impl Default for Table { authority_data: HashMap::new(), detected_misbehavior: HashMap::new(), candidate_votes: HashMap::new(), + includable_count: HashMap::new(), } } } @@ -294,6 +296,11 @@ impl Table { let mut best_candidates = BTreeMap::new(); for candidate_data in self.candidate_votes.values() { let group_id = &candidate_data.group_id; + + if !self.includable_count.contains_key(group_id) { + continue + } + let (validity_t, availability_t) = context.requisite_votes(group_id); if !candidate_data.can_be_included(validity_t, availability_t) { continue } @@ -394,6 +401,11 @@ impl Table { &self.detected_misbehavior } + /// Get the current number of parachains with includable candidates. + pub fn includable_count(&self) -> usize { + self.includable_count.len() + } + /// Fill a statement batch and note messages as seen by the targets. pub fn fill_batch(&mut self, batch: &mut B) where B: StatementBatch< @@ -622,6 +634,9 @@ impl Table { Some(votes) => votes, }; + let (v_threshold, a_threshold) = context.requisite_votes(&votes.group_id); + let was_includable = votes.can_be_included(v_threshold, a_threshold); + // check that this authority actually can vote in this group. if !context.is_member_of(&from, &votes.group_id) { let (sig, valid) = match vote { @@ -686,6 +701,9 @@ impl Table { } } + let is_includable = votes.can_be_included(v_threshold, a_threshold); + update_includable_count(&mut self.includable_count, &votes.group_id, was_includable, is_includable); + (None, Some(votes.summary(digest))) } @@ -701,6 +719,9 @@ impl Table { Some(votes) => votes, }; + let (v_threshold, a_threshold) = context.requisite_votes(&votes.group_id); + let was_includable = votes.can_be_included(v_threshold, a_threshold); + // check that this authority actually can vote in this group. if !context.is_availability_guarantor_of(&from, &votes.group_id) { return ( @@ -716,10 +737,29 @@ impl Table { } votes.availability_votes.insert(from, signature); + + let is_includable = votes.can_be_included(v_threshold, a_threshold); + update_includable_count(&mut self.includable_count, &votes.group_id, was_includable, is_includable); + (None, Some(votes.summary(digest))) } } +fn update_includable_count(map: &mut HashMap, group_id: &G, was_includable: bool, is_includable: bool) { + if was_includable && !is_includable { + if let Entry::Occupied(mut entry) = map.entry(group_id.clone()) { + *entry.get_mut() -= 1; + if *entry.get() == 0 { + entry.remove(); + } + } + } + + if !was_includable && is_includable { + *map.entry(group_id.clone()).or_insert(0) += 1; + } +} + #[cfg(test)] mod tests { use super::*; @@ -746,11 +786,7 @@ mod tests { } fn create() -> Table { - Table { - authority_data: HashMap::default(), - detected_misbehavior: HashMap::default(), - candidate_votes: HashMap::default(), - } + Table::default() } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -806,8 +842,16 @@ mod tests { self.authorities.get(authority).map(|v| &v.1 == group).unwrap_or(false) } - fn requisite_votes(&self, _id: &GroupId) -> (usize, usize) { - (6, 34) + fn requisite_votes(&self, id: &GroupId) -> (usize, usize) { + let mut total_validity = 0; + let mut total_availability = 0; + + for &(ref validity, ref availability) in self.authorities.values() { + if validity == id { total_validity += 1 } + if availability == id { total_availability += 1 } + } + + (total_validity / 2 + 1, total_availability / 2 + 1) } } @@ -1067,6 +1111,69 @@ mod tests { assert!(!candidate.can_be_included(validity_threshold, availability_threshold)); } + #[test] + fn includability_counter() { + let context = TestContext { + authorities: { + let mut map = HashMap::new(); + map.insert(AuthorityId(1), (GroupId(2), GroupId(455))); + map.insert(AuthorityId(2), (GroupId(2), GroupId(455))); + map.insert(AuthorityId(3), (GroupId(2), GroupId(455))); + map.insert(AuthorityId(4), (GroupId(455), GroupId(2))); + map + } + }; + + // have 2/3 validity guarantors note validity. + let mut table = create(); + let statement = SignedStatement { + statement: Statement::Candidate(Candidate(2, 100)), + signature: Signature(1), + sender: AuthorityId(1), + }; + let candidate_digest = Digest(100); + + table.import_statement(&context, statement, None); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); + assert!(!table.candidate_includable(&candidate_digest, &context)); + assert!(table.includable_count.is_empty()); + + let vote = SignedStatement { + statement: Statement::Valid(candidate_digest.clone()), + signature: Signature(2), + sender: AuthorityId(2), + }; + + table.import_statement(&context, vote, None); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); + assert!(!table.candidate_includable(&candidate_digest, &context)); + assert!(table.includable_count.is_empty()); + + // have the availability guarantor note validity. + let vote = SignedStatement { + statement: Statement::Available(candidate_digest.clone()), + signature: Signature(4), + sender: AuthorityId(4), + }; + + table.import_statement(&context, vote, None); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(4))); + assert!(table.candidate_includable(&candidate_digest, &context)); + assert!(table.includable_count.get(&GroupId(2)).is_some()); + + // have the last validity guarantor note invalidity. now it is unincludable. + let vote = SignedStatement { + statement: Statement::Invalid(candidate_digest.clone()), + signature: Signature(3), + sender: AuthorityId(3), + }; + + table.import_statement(&context, vote, None); + assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); + assert!(!table.candidate_includable(&candidate_digest, &context)); + assert!(table.includable_count.is_empty()); + } + #[test] fn candidate_import_gives_summary() { let context = TestContext { diff --git a/polkadot/transaction-pool/src/lib.rs b/polkadot/transaction-pool/src/lib.rs index 68166288b0..d375c7c371 100644 --- a/polkadot/transaction-pool/src/lib.rs +++ b/polkadot/transaction-pool/src/lib.rs @@ -36,7 +36,8 @@ use std::sync::Arc; use polkadot_api::PolkadotApi; use primitives::{AccountId, Timestamp}; -use runtime::{Block, UncheckedExtrinsic, TimestampCall, Call}; +use primitives::parachain::CandidateReceipt; +use runtime::{Block, UncheckedExtrinsic, TimestampCall, ParachainsCall, Call}; use substrate_runtime_primitives::traits::{Bounded, Checkable}; use transaction_pool::{Pool, Readiness}; use transaction_pool::scoring::{Change, Choice}; @@ -59,17 +60,26 @@ pub struct PolkadotBlock { impl PolkadotBlock { /// Create a new block, checking high-level well-formedness. pub fn from(unchecked: Block) -> ::std::result::Result { - if unchecked.extrinsics.len() < 1 { + 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 }) } @@ -92,6 +102,19 @@ impl PolkadotBlock { } } } + + /// 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] diff --git a/polkadot/validator/Cargo.toml b/polkadot/validator/Cargo.toml deleted file mode 100644 index 204c356a99..0000000000 --- a/polkadot/validator/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "polkadot-validator" -version = "0.1.0" -authors = ["Parity Technologies "] - -[dependencies] -error-chain = "0.11" -serde = "1.0" -substrate-primitives = { path = "../../substrate/primitives" } -substrate-serializer = { path = "../../substrate/serializer" } -polkadot-primitives = { path = "../primitives" } diff --git a/polkadot/validator/src/error.rs b/polkadot/validator/src/error.rs deleted file mode 100644 index 1c8caf739f..0000000000 --- a/polkadot/validator/src/error.rs +++ /dev/null @@ -1,33 +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 . - -use serializer; - -error_chain! { - foreign_links { - Serialization(serializer::Error); - } - errors { - Timeout { - description("Validation task has timed-out."), - display("Validation timeout."), - } - InvalidCode(details: String) { - description("The code is invalid."), - display("invalid code: '{}'", details), - } - } -} diff --git a/polkadot/validator/src/lib.rs b/polkadot/validator/src/lib.rs deleted file mode 100644 index dc139e77d5..0000000000 --- a/polkadot/validator/src/lib.rs +++ /dev/null @@ -1,34 +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 . - -//! Validator implementation. - -#[warn(missing_docs)] - -extern crate substrate_primitives as primitives; -extern crate substrate_serializer as serializer; -extern crate polkadot_primitives; -extern crate serde; - -#[macro_use] -extern crate error_chain; - -mod error; -mod parachains; -mod validator; - -pub use error::{Error, ErrorKind, Result}; -pub use validator::Validator; diff --git a/polkadot/validator/src/parachains.rs b/polkadot/validator/src/parachains.rs deleted file mode 100644 index 67ba56ed1f..0000000000 --- a/polkadot/validator/src/parachains.rs +++ /dev/null @@ -1,68 +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 . - -use std::fmt; - -use polkadot_primitives::validator; -use serde::de::DeserializeOwned; - -use error::Result; - -/// Parachain code implementation. -pub trait ParachainCode: fmt::Debug { - /// Deserialized message type. - type Message: DeserializeOwned; - /// Balance download. - type Download: DeserializeOwned; - /// Deserialized block data type. - type BlockData: DeserializeOwned; - /// Parachain head data. - type HeadData: DeserializeOwned; - /// Result - type Result: Into; - - /// Given decoded messages and proof validate it and return egress posts. - fn check( - &self, - messages: Vec<(u64, Vec)>, - downloads: Vec, - block_data: Self::BlockData, - head_data: Self::HeadData, - ) -> Result; -} - -/// Dummy implementation of the first parachain validation. -#[derive(Debug)] -pub struct ParaChain1; - -impl ParachainCode for ParaChain1 { - type Message = (); - type Download = (); - type BlockData = (); - type HeadData = (); - type Result = validator::ValidationResult; - - fn check( - &self, - _messages: Vec<(u64, Vec)>, - _downloads: Vec, - _block_data: Self::BlockData, - _head_data: Self::HeadData, - ) -> Result - { - unimplemented!() - } -} diff --git a/polkadot/validator/src/validator.rs b/polkadot/validator/src/validator.rs deleted file mode 100644 index 354bbf73dc..0000000000 --- a/polkadot/validator/src/validator.rs +++ /dev/null @@ -1,101 +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 . - -use std::fmt; - -use polkadot_primitives::{validator, parachain}; -use serde::de::DeserializeOwned; -use serializer; - -use error::{ErrorKind, Result}; -use parachains::{ParachainCode, ParaChain1}; - -/// A dummy validator implementation. -#[derive(Debug)] -pub struct Validator { - codes: Vec>, -} - -impl Validator { - /// Create a new validator. - pub fn new() -> Self { - Validator { - codes: vec![ - Box::new(ParaChain1) as Box - ], - } - } -} - -impl Validator { - pub fn validate( - &self, - code: &[u8], - consolidated_ingress: &[(u64, Vec)], - balance_downloads: &[validator::BalanceDownload], - block_data: ¶chain::BlockData, - previous_head_data: ¶chain::HeadData, - ) -> Result { - ensure!(code.len() == 1, ErrorKind::InvalidCode(format!("The code should be a single byte."))); - - match self.codes.get(code[0] as usize) { - Some(code) => code.check(consolidated_ingress, balance_downloads, block_data, previous_head_data), - None => bail!(ErrorKind::InvalidCode(format!("Unknown parachain code."))), - } - } -} - -/// Simplified parachain code verification -trait Code: fmt::Debug { - /// Given parachain candidate block data returns it's validity - /// and possible generated egress posts. - fn check( - &self, - consolidated_ingress: &[(u64, Vec)], - balance_downloads: &[validator::BalanceDownload], - block_data: ¶chain::BlockData, - previous_head_data: ¶chain::HeadData, - ) -> Result; -} - -impl Code for T where - M: DeserializeOwned, - B: DeserializeOwned, - R: Into, - T: ParachainCode, -{ - fn check( - &self, - consolidated_ingress: &[(u64, Vec)], - balance_downloads: &[validator::BalanceDownload], - block_data: ¶chain::BlockData, - previous_head_data: ¶chain::HeadData, - ) -> Result { - let messages = consolidated_ingress.iter() - .map(|&(ref block, ref vec)| Ok((*block, vec.iter() - .map(|msg| serializer::from_slice(&msg.0).map_err(Into::into)) - .collect::>>()? - ))) - .collect::>>()?; - let downloads = balance_downloads.iter() - .map(|download| serializer::from_slice(&download.0).map_err(Into::into)) - .collect::>>()?; - let block_data = serializer::from_slice(&block_data.0)?; - let head_data = serializer::from_slice(&previous_head_data.0)?; - - Ok(self.check(messages, downloads, block_data, head_data)?.into()) - } -}