Update to latest Substrate master. (#353)

* Integrate srml/im-online

* Fix all build errors with old aura.

* Fix most of the build errors.

* Builds and tests seem to pass (I will not trust this commit yet)

* Apply suggestions from code review

Co-Authored-By: Robert Habermeier <rphmeier@gmail.com>

* Kill some warnings.

* fix panics on 0 validators

* Fix dev chain.

* Fix author stuff

* fix im online integration.

* Some tweaks

* Introduce app-crypto

* Initial build work

* codec update / tweaks

* patch polkadot-erasure-coding input

* More fixes for new crypto

* More fixes

* Update parachains module

* evamp parachain crypto

* More crypto work.

* Chain spec and service.

* ChainSpec stuff

* Last bits for a clean build

* Tweak coment

* adapt polkadot-validation to the new keystore

* polkadot-network compiles, but tests don't

* Integrate the new parachain validation stuff

* delete message_routing file

* make polkadot-network tests compile and pass

* runtime tests compile and pass

* update substrate ref

* service compiles

* all tests pass

* Add TODO, change branch back to polkadot-master

* Lock file

* TODOs done

* Issue number

* Remove old tODO

* Remove commented code
This commit is contained in:
Kian Paimani
2019-08-12 15:48:29 +02:00
committed by Gavin Wood
parent 9b6e630816
commit 10fc88f6b1
51 changed files with 1719 additions and 1513 deletions
+756 -536
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -9,7 +9,7 @@ edition = "2018"
polkadot-primitives = { path = "../primitives" } polkadot-primitives = { path = "../primitives" }
parking_lot = "0.9.0" parking_lot = "0.9.0"
log = "0.4.6" log = "0.4.6"
parity-codec = "4.1" codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
kvdb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } kvdb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" }
kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" }
+1 -1
View File
@@ -16,7 +16,7 @@
//! Persistent database for parachain data. //! Persistent database for parachain data.
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
use kvdb::{KeyValueDB, DBTransaction}; use kvdb::{KeyValueDB, DBTransaction};
use kvdb_rocksdb::{Database, DatabaseConfig}; use kvdb_rocksdb::{Database, DatabaseConfig};
use polkadot_primitives::Hash; use polkadot_primitives::Hash;
+5 -5
View File
@@ -26,15 +26,15 @@ pub enum ChainSpec {
Development, Development,
/// Whatever the current runtime is, with simple Alice/Bob auths. /// Whatever the current runtime is, with simple Alice/Bob auths.
LocalTestnet, LocalTestnet,
/// The PoC-3 era testnet. /// The Kusama network.
Alexander, Kusama,
/// Whatever the current runtime is with the "global testnet" defaults. /// Whatever the current runtime is with the "global testnet" defaults.
StagingTestnet, StagingTestnet,
} }
impl Default for ChainSpec { impl Default for ChainSpec {
fn default() -> Self { fn default() -> Self {
ChainSpec::Alexander ChainSpec::Kusama
} }
} }
@@ -42,7 +42,7 @@ impl Default for ChainSpec {
impl ChainSpec { impl ChainSpec {
pub(crate) fn load(self) -> Result<service::ChainSpec, String> { pub(crate) fn load(self) -> Result<service::ChainSpec, String> {
Ok(match self { Ok(match self {
ChainSpec::Alexander => service::chain_spec::poc_3_testnet_config()?, ChainSpec::Kusama => service::chain_spec::kusama_config()?,
ChainSpec::Development => service::chain_spec::development_config(), ChainSpec::Development => service::chain_spec::development_config(),
ChainSpec::LocalTestnet => service::chain_spec::local_testnet_config(), ChainSpec::LocalTestnet => service::chain_spec::local_testnet_config(),
ChainSpec::StagingTestnet => service::chain_spec::staging_testnet_config(), ChainSpec::StagingTestnet => service::chain_spec::staging_testnet_config(),
@@ -53,7 +53,7 @@ impl ChainSpec {
match s { match s {
"dev" => Some(ChainSpec::Development), "dev" => Some(ChainSpec::Development),
"local" => Some(ChainSpec::LocalTestnet), "local" => Some(ChainSpec::LocalTestnet),
"poc-3" | "alex" | "alexander" => Some(ChainSpec::Alexander), "kusama" => Some(ChainSpec::Kusama),
"staging" => Some(ChainSpec::StagingTestnet), "staging" => Some(ChainSpec::StagingTestnet),
"" => Some(ChainSpec::default()), "" => Some(ChainSpec::default()),
_ => None, _ => None,
-2
View File
@@ -9,11 +9,9 @@ edition = "2018"
futures = "0.1.17" futures = "0.1.17"
futures03 = { package = "futures-preview", version = "0.3.0-alpha.17", features = ["compat"] } futures03 = { package = "futures-preview", version = "0.3.0-alpha.17", features = ["compat"] }
client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
parity-codec = "4.1"
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
substrate-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
consensus_common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } consensus_common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
aura = { package = "substrate-consensus-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
polkadot-runtime = { path = "../runtime", version = "0.1" } polkadot-runtime = { path = "../runtime", version = "0.1" }
polkadot-primitives = { path = "../primitives", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" }
polkadot-cli = { path = "../cli" } polkadot-cli = { path = "../cli" }
+14 -15
View File
@@ -53,12 +53,12 @@ use futures::{future, Stream, Future, IntoFuture};
use futures03::{TryStreamExt as _, StreamExt as _}; use futures03::{TryStreamExt as _, StreamExt as _};
use log::{info, warn}; use log::{info, warn};
use client::BlockchainEvents; use client::BlockchainEvents;
use primitives::{ed25519, Pair}; use primitives::Pair;
use polkadot_primitives::{ use polkadot_primitives::{
BlockId, SessionKey, Hash, Block, BlockId, Hash, Block,
parachain::{ parachain::{
self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId, Extrinsic, self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId, Extrinsic,
PoVBlock, Status as ParachainStatus, PoVBlock, Status as ParachainStatus, ValidatorId, CollatorPair,
} }
}; };
use polkadot_cli::{ use polkadot_cli::{
@@ -69,7 +69,6 @@ use polkadot_network::validation::{SessionParams, ValidationNetwork};
use polkadot_network::NetworkService; use polkadot_network::NetworkService;
use tokio::timer::Timeout; use tokio::timer::Timeout;
use consensus_common::SelectChain; use consensus_common::SelectChain;
use aura::AuraApi;
pub use polkadot_cli::VersionInfo; pub use polkadot_cli::VersionInfo;
pub use polkadot_network::validation::Incoming; pub use polkadot_network::validation::Incoming;
@@ -177,7 +176,7 @@ pub fn collate<'a, R, P>(
parachain_status: ParachainStatus, parachain_status: ParachainStatus,
relay_context: R, relay_context: R,
para_context: P, para_context: P,
key: Arc<ed25519::Pair>, key: Arc<CollatorPair>,
) )
-> impl Future<Item=parachain::Collation, Error=Error<R::Error>> + 'a -> impl Future<Item=parachain::Collation, Error=Error<R::Error>> + 'a
where where
@@ -230,7 +229,7 @@ pub fn collate<'a, R, P>(
struct ApiContext<P, E> { struct ApiContext<P, E> {
network: Arc<ValidationNetwork<P, E, NetworkService, TaskExecutor>>, network: Arc<ValidationNetwork<P, E, NetworkService, TaskExecutor>>,
parent_hash: Hash, parent_hash: Hash,
authorities: Vec<SessionKey>, validators: Vec<ValidatorId>,
} }
impl<P: 'static, E: 'static> RelayChainContext for ApiContext<P, E> where impl<P: 'static, E: 'static> RelayChainContext for ApiContext<P, E> where
@@ -248,7 +247,7 @@ impl<P: 'static, E: 'static> RelayChainContext for ApiContext<P, E> where
let _session = self.network.instantiate_session(SessionParams { let _session = self.network.instantiate_session(SessionParams {
local_session_key: None, local_session_key: None,
parent_hash: self.parent_hash, parent_hash: self.parent_hash,
authorities: self.authorities.clone(), authorities: self.validators.clone(),
}).map_err(|e| format!("unable to instantiate validation session: {:?}", e)); }).map_err(|e| format!("unable to instantiate validation session: {:?}", e));
Box::new(future::ok(ConsolidatedIngress(Vec::new()))) Box::new(future::ok(ConsolidatedIngress(Vec::new())))
@@ -259,7 +258,7 @@ struct CollationNode<P, E> {
build_parachain_context: P, build_parachain_context: P,
exit: E, exit: E,
para_id: ParaId, para_id: ParaId,
key: Arc<ed25519::Pair>, key: Arc<CollatorPair>,
} }
impl<P, E> IntoExit for CollationNode<P, E> where impl<P, E> IntoExit for CollationNode<P, E> where
@@ -364,18 +363,18 @@ impl<P, E> Worker for CollationNode<P, E> where
None => return future::Either::A(future::ok(())), None => return future::Either::A(future::ok(())),
}; };
let authorities = try_fr!(api.authorities(&id)); let validators = try_fr!(api.validators(&id));
let targets = compute_targets( let targets = compute_targets(
para_id, para_id,
authorities.as_slice(), validators.as_slice(),
try_fr!(api.duty_roster(&id)), try_fr!(api.duty_roster(&id)),
); );
let context = ApiContext { let context = ApiContext {
network: validation_network, network: validation_network,
parent_hash: relay_parent, parent_hash: relay_parent,
authorities, validators,
}; };
let collation_work = collate( let collation_work = collate(
@@ -414,7 +413,7 @@ impl<P, E> Worker for CollationNode<P, E> where
} }
} }
fn compute_targets(para_id: ParaId, session_keys: &[SessionKey], roster: DutyRoster) -> HashSet<SessionKey> { fn compute_targets(para_id: ParaId, session_keys: &[ValidatorId], roster: DutyRoster) -> HashSet<ValidatorId> {
use polkadot_primitives::parachain::Chain; use polkadot_primitives::parachain::Chain;
roster.validator_duty.iter().enumerate() roster.validator_duty.iter().enumerate()
@@ -433,7 +432,7 @@ pub fn run_collator<P, E>(
build_parachain_context: P, build_parachain_context: P,
para_id: ParaId, para_id: ParaId,
exit: E, exit: E,
key: Arc<ed25519::Pair>, key: Arc<CollatorPair>,
version: VersionInfo, version: VersionInfo,
) -> polkadot_cli::error::Result<()> where ) -> polkadot_cli::error::Result<()> where
P: BuildParachainContext + Send + 'static, P: BuildParachainContext + Send + 'static,
@@ -450,7 +449,7 @@ pub fn run_collator<P, E>(
mod tests { mod tests {
use std::collections::HashMap; use std::collections::HashMap;
use polkadot_primitives::parachain::{OutgoingMessage, FeeSchedule}; use polkadot_primitives::parachain::{OutgoingMessage, FeeSchedule};
use keyring::Ed25519Keyring; use keyring::Sr25519Keyring;
use super::*; use super::*;
#[derive(Default, Clone)] #[derive(Default, Clone)]
@@ -540,7 +539,7 @@ mod tests {
}, },
context.clone(), context.clone(),
DummyParachainContext, DummyParachainContext,
Ed25519Keyring::Alice.pair().into(), Arc::new(Sr25519Keyring::Alice.pair().into()),
).wait().unwrap(); ).wait().unwrap();
// ascending order by root. // ascending order by root.
+1 -1
View File
@@ -7,6 +7,6 @@ edition = "2018"
[dependencies] [dependencies]
primitives = { package = "polkadot-primitives", path = "../primitives" } primitives = { package = "polkadot-primitives", path = "../primitives" }
reed_solomon = { package = "reed-solomon-erasure", git = "https://github.com/paritytech/reed-solomon-erasure" } reed_solomon = { package = "reed-solomon-erasure", git = "https://github.com/paritytech/reed-solomon-erasure" }
parity-codec = "4.1" codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
trie = { package = "substrate-trie", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } trie = { package = "substrate-trie", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
+21 -10
View File
@@ -24,12 +24,12 @@
//! f is the maximum number of faulty validators in the system. //! f is the maximum number of faulty validators in the system.
//! The data is coded so any f+1 chunks can be used to reconstruct the full data. //! The data is coded so any f+1 chunks can be used to reconstruct the full data.
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
use reed_solomon::galois_16::{self, ReedSolomon}; use reed_solomon::galois_16::{self, ReedSolomon};
use primitives::{Hash as H256, BlakeTwo256, HashT}; use primitives::{Hash as H256, BlakeTwo256, HashT};
use primitives::parachain::{BlockData, Extrinsic}; use primitives::parachain::{BlockData, Extrinsic};
use substrate_primitives::Blake2Hasher; use substrate_primitives::Blake2Hasher;
use trie::{MemoryDB, Trie, TrieMut, TrieDB, TrieDBMut}; use trie::{EMPTY_PREFIX, MemoryDB, Trie, TrieMut, trie_types::{TrieDBMut, TrieDB}};
use self::wrapped_shard::WrappedShard; use self::wrapped_shard::WrappedShard;
@@ -187,13 +187,14 @@ pub fn reconstruct<'a, I: 'a>(n_validators: usize, chunks: I)
// lazily decode from the data shards. // lazily decode from the data shards.
Decode::decode(&mut ShardInput { Decode::decode(&mut ShardInput {
remaining_len: shard_len.map(|s| s * params.data_shards).unwrap_or(0),
cur_shard: None, cur_shard: None,
shards: shards.iter() shards: shards.iter()
.map(|x| x.as_ref()) .map(|x| x.as_ref())
.take(params.data_shards) .take(params.data_shards)
.map(|x| x.expect("all data shards have been recovered; qed")) .map(|x| x.expect("all data shards have been recovered; qed"))
.map(|x| x.as_ref()), .map(|x| x.as_ref()),
}).ok_or_else(|| Error::BadPayload) }).or_else(|_| Err(Error::BadPayload))
} }
/// An iterator that yields merkle branches and chunk data for all chunks to /// An iterator that yields merkle branches and chunk data for all chunks to
@@ -269,7 +270,7 @@ pub fn branches<'a>(chunks: Vec<&'a [u8]>) -> Branches<'a> {
pub fn branch_hash(root: &H256, branch_nodes: &[Vec<u8>], index: usize) -> Result<H256, Error> { pub fn branch_hash(root: &H256, branch_nodes: &[Vec<u8>], index: usize) -> Result<H256, Error> {
let mut trie_storage: MemoryDB<Blake2Hasher> = MemoryDB::default(); let mut trie_storage: MemoryDB<Blake2Hasher> = MemoryDB::default();
for node in branch_nodes.iter() { for node in branch_nodes.iter() {
(&mut trie_storage as &mut trie::HashDB<_>).insert(&[], node.as_slice()); (&mut trie_storage as &mut trie::HashDB<_>).insert(EMPTY_PREFIX, node.as_slice());
} }
let trie = TrieDB::new(&trie_storage, &root).map_err(|_| Error::InvalidBranchProof)?; let trie = TrieDB::new(&trie_storage, &root).map_err(|_| Error::InvalidBranchProof)?;
@@ -278,21 +279,26 @@ pub fn branch_hash(root: &H256, branch_nodes: &[Vec<u8>], index: usize) -> Resul
); );
match res { match res {
Ok(Some(Some(hash))) => Ok(hash), Ok(Some(Ok(hash))) => Ok(hash),
Ok(Some(None)) => Err(Error::InvalidBranchProof), // hash failed to decode Ok(Some(Err(_))) => Err(Error::InvalidBranchProof), // hash failed to decode
Ok(None) => Err(Error::BranchOutOfBounds), Ok(None) => Err(Error::BranchOutOfBounds),
Err(_) => Err(Error::InvalidBranchProof), Err(_) => Err(Error::InvalidBranchProof),
} }
} }
// input for `parity_codec` which draws data from the data shards // input for `codec` which draws data from the data shards
struct ShardInput<'a, I> { struct ShardInput<'a, I> {
remaining_len: usize,
shards: I, shards: I,
cur_shard: Option<(&'a [u8], usize)>, cur_shard: Option<(&'a [u8], usize)>,
} }
impl<'a, I: Iterator<Item=&'a [u8]>> parity_codec::Input for ShardInput<'a, I> { impl<'a, I: Iterator<Item=&'a [u8]>> codec::Input for ShardInput<'a, I> {
fn read(&mut self, into: &mut [u8]) -> usize { fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
Ok(Some(self.remaining_len))
}
fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
let mut read_bytes = 0; let mut read_bytes = 0;
loop { loop {
@@ -320,7 +326,12 @@ impl<'a, I: Iterator<Item=&'a [u8]>> parity_codec::Input for ShardInput<'a, I> {
self.cur_shard = Some((active_shard, in_shard)) self.cur_shard = Some((active_shard, in_shard))
} }
read_bytes self.remaining_len -= read_bytes;
if read_bytes == into.len() {
Ok(())
} else {
Err("slice provided too big for input".into())
}
} }
} }
+1 -1
View File
@@ -11,7 +11,7 @@ parking_lot = "0.9.0"
av_store = { package = "polkadot-availability-store", path = "../availability-store" } av_store = { package = "polkadot-availability-store", path = "../availability-store" }
polkadot-validation = { path = "../validation" } polkadot-validation = { path = "../validation" }
polkadot-primitives = { path = "../primitives" } polkadot-primitives = { path = "../primitives" }
parity-codec = { version = "4.1", features = ["derive"] } codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
substrate-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
sr-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } sr-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
+1 -1
View File
@@ -16,7 +16,7 @@
//! Bridge between the network and consensus service for getting collations to it. //! Bridge between the network and consensus service for getting collations to it.
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
use polkadot_primitives::Hash; use polkadot_primitives::Hash;
use polkadot_primitives::parachain::{CollatorId, Id as ParaId, Collation}; use polkadot_primitives::parachain::{CollatorId, Id as ParaId, Collation};
use substrate_network::PeerId; use substrate_network::PeerId;
+12 -12
View File
@@ -22,8 +22,8 @@ use substrate_network::consensus_gossip::{
ValidatorContext, MessageIntent, ConsensusMessage, ValidatorContext, MessageIntent, ConsensusMessage,
}; };
use polkadot_validation::{GenericStatement, SignedStatement}; use polkadot_validation::{GenericStatement, SignedStatement};
use polkadot_primitives::{Block, Hash, SessionKey, parachain::ValidatorIndex}; use polkadot_primitives::{Block, Hash, parachain::{ValidatorIndex, ValidatorId}};
use parity_codec::{Decode, Encode}; use codec::{Decode, Encode};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
@@ -218,9 +218,9 @@ impl RegisteredMessageValidator {
#[derive(Default)] #[derive(Default)]
pub(crate) struct MessageValidationData { pub(crate) struct MessageValidationData {
/// The authorities at a block. /// The authorities at a block.
pub(crate) authorities: Vec<SessionKey>, pub(crate) authorities: Vec<ValidatorId>,
/// Mapping from validator index to `SessionKey`. /// Mapping from validator index to `ValidatorId`.
pub(crate) index_mapping: HashMap<ValidatorIndex, SessionKey>, pub(crate) index_mapping: HashMap<ValidatorIndex, ValidatorId>,
} }
impl MessageValidationData { impl MessageValidationData {
@@ -481,15 +481,15 @@ impl<O: KnownOracle + ?Sized> network_gossip::Validator<Block> for MessageValida
-> GossipValidationResult<Hash> -> GossipValidationResult<Hash>
{ {
let (res, cost_benefit) = match GossipMessage::decode(&mut data) { let (res, cost_benefit) = match GossipMessage::decode(&mut data) {
None => (GossipValidationResult::Discard, cost::MALFORMED_MESSAGE), Err(_) => (GossipValidationResult::Discard, cost::MALFORMED_MESSAGE),
Some(GossipMessage::Neighbor(VersionedNeighborPacket::V1(packet))) => { Ok(GossipMessage::Neighbor(VersionedNeighborPacket::V1(packet))) => {
let (res, cb, topics) = self.inner.write().validate_neighbor_packet(sender, packet); let (res, cb, topics) = self.inner.write().validate_neighbor_packet(sender, packet);
for new_topic in topics { for new_topic in topics {
context.send_topic(sender, new_topic, false); context.send_topic(sender, new_topic, false);
} }
(res, cb) (res, cb)
} }
Some(GossipMessage::Statement(statement)) => { Ok(GossipMessage::Statement(statement)) => {
let (res, cb) = self.inner.write().validate_statement(statement); let (res, cb) = self.inner.write().validate_statement(statement);
if let GossipValidationResult::ProcessAndKeep(ref topic) = res { if let GossipValidationResult::ProcessAndKeep(ref topic) = res {
context.broadcast_message(topic.clone(), data.to_vec(), false); context.broadcast_message(topic.clone(), data.to_vec(), false);
@@ -535,7 +535,7 @@ impl<O: KnownOracle + ?Sized> network_gossip::Validator<Block> for MessageValida
}; };
match GossipMessage::decode(&mut &data[..]) { match GossipMessage::decode(&mut &data[..]) {
Some(GossipMessage::Statement(statement)) => { Ok(GossipMessage::Statement(statement)) => {
let signed = statement.signed_statement; let signed = statement.signed_statement;
match signed.statement { match signed.statement {
@@ -573,7 +573,7 @@ mod tests {
use parking_lot::Mutex; use parking_lot::Mutex;
use polkadot_primitives::parachain::{CandidateReceipt, HeadData}; use polkadot_primitives::parachain::{CandidateReceipt, HeadData};
use substrate_primitives::crypto::UncheckedInto; use substrate_primitives::crypto::UncheckedInto;
use substrate_primitives::ed25519::Signature as Ed25519Signature; use substrate_primitives::sr25519::Signature as Sr25519Signature;
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
enum ContextEvent { enum ContextEvent {
@@ -669,7 +669,7 @@ mod tests {
relay_parent: hash_a, relay_parent: hash_a,
signed_statement: SignedStatement { signed_statement: SignedStatement {
statement: GenericStatement::Candidate(candidate_receipt), statement: GenericStatement::Candidate(candidate_receipt),
signature: Ed25519Signature([255u8; 64]), signature: Sr25519Signature([255u8; 64]).into(),
sender: 1, sender: 1,
} }
}); });
@@ -786,7 +786,7 @@ mod tests {
relay_parent: hash_a, relay_parent: hash_a,
signed_statement: SignedStatement { signed_statement: SignedStatement {
statement: GenericStatement::Valid(c_hash), statement: GenericStatement::Valid(c_hash),
signature: Ed25519Signature([255u8; 64]), signature: Sr25519Signature([255u8; 64]).into(),
sender: 1, sender: 1,
} }
}); });
@@ -1,265 +0,0 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Data structures and synchronous logic for ICMP message gossip.
use sr_primitives::traits::{BlakeTwo256, Hash as HashT};
use polkadot_primitives::Hash;
use std::collections::{HashMap, HashSet};
use substrate_client::error::Error as ClientError;
use super::{MAX_CHAIN_HEADS, GossipValidationResult, LeavesVec, ChainContext};
/// Construct a topic for a message queue root deterministically.
pub fn queue_topic(queue_root: Hash) -> Hash {
let mut v = queue_root.as_ref().to_vec();
v.extend(b"message_queue");
BlakeTwo256::hash(&v[..])
}
/// A view of which queue roots are current for a given set of leaves.
#[derive(Default)]
pub struct View {
leaves: LeavesVec,
leaf_topics: HashMap<Hash, HashSet<Hash>>, // leaf_hash -> { topics }
expected_queues: HashMap<Hash, Hash>, // topic -> queue-root
}
impl View {
/// Update the set of current leaves.
pub fn update_leaves<T: ChainContext + ?Sized, I>(&mut self, context: &T, new_leaves: I)
-> Result<(), ClientError>
where I: Iterator<Item=Hash>
{
let new_leaves = new_leaves.take(MAX_CHAIN_HEADS);
let old_leaves = {
let mut new = LeavesVec::new();
for leaf in new_leaves {
new.push(leaf.clone());
}
std::mem::replace(&mut self.leaves, new)
};
let expected_queues = &mut self.expected_queues;
let leaves = &self.leaves;
self.leaf_topics.retain(|l, topics| {
if leaves.contains(l) { return true }
// prune out all data about old leaves we don't follow anymore.
for topic in topics.iter() {
expected_queues.remove(topic);
}
false
});
let mut res = Ok(());
// add in new data about fresh leaves.
for new_leaf in &self.leaves {
if old_leaves.contains(new_leaf) { continue }
let mut this_leaf_topics = HashSet::new();
let r = context.leaf_unrouted_roots(new_leaf, &mut |&queue_root| {
let topic = queue_topic(queue_root);
this_leaf_topics.insert(topic);
expected_queues.insert(topic, queue_root);
});
if r.is_err() {
res = r;
}
self.leaf_topics.insert(*new_leaf, this_leaf_topics);
}
res
}
/// Validate an incoming message queue against this view.
pub fn validate_queue(&self, messages: &super::GossipParachainMessages)
-> (GossipValidationResult<Hash>, i32)
{
let ostensible_topic = queue_topic(messages.queue_root);
if !self.is_topic_live(&ostensible_topic) {
(GossipValidationResult::Discard, super::cost::UNNEEDED_ICMP_MESSAGES)
} else if !messages.queue_root_is_correct() {
(
GossipValidationResult::Discard,
super::cost::icmp_messages_root_mismatch(messages.messages.len()),
)
} else {
(
GossipValidationResult::ProcessAndKeep(ostensible_topic),
super::benefit::NEW_ICMP_MESSAGES,
)
}
}
/// Whether a message with given topic is live.
pub fn is_topic_live(&self, topic: &Hash) -> bool {
self.expected_queues.get(topic).is_some()
}
/// Whether a message is allowed under the intersection of the given leaf-set
/// and our own.
pub fn allowed_intersecting(&self, other_leaves: &LeavesVec, topic: &Hash) -> bool {
for i in other_leaves {
for j in &self.leaves {
if i == j {
let leaf_topics = self.leaf_topics.get(i)
.expect("leaf_topics are mutated only in update_leaves; \
we have an entry for each item in self.leaves; \
i is in self.leaves; qed");
if leaf_topics.contains(topic) {
return true;
}
}
}
}
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::TestChainContext;
use crate::gossip::{Known, GossipParachainMessages};
use polkadot_primitives::parachain::Message as ParachainMessage;
fn hash(x: u8) -> Hash {
[x; 32].into()
}
fn message_queue(from: u8, to: u8) -> Option<[[u8; 2]; 1]> {
if from == to {
None
} else {
Some([[from, to]])
}
}
fn message_queue_root(from: u8, to: u8) -> Option<Hash> {
message_queue(from, to).map(
|q| polkadot_validation::message_queue_root(q.iter())
)
}
fn check_roots(view: &View, i: u8, max: u8) -> bool {
for j in 0..max {
if let Some(messages) = message_queue(i, j) {
let queue_root = message_queue_root(i, j).unwrap();
let messages = GossipParachainMessages {
queue_root,
messages: messages.iter().map(|m| ParachainMessage(m.to_vec())).collect(),
};
match view.validate_queue(&messages).0 {
GossipValidationResult::ProcessAndKeep(topic) => if topic != queue_topic(queue_root) {
return false
},
_ => return false,
}
}
}
true
}
#[test]
fn update_leaves_none_in_common() {
let mut ctx = TestChainContext::default();
let max = 5;
for i in 0..max {
ctx.known_map.insert(hash(i as u8), Known::Leaf);
let messages_out: Vec<_> = (0..max).filter_map(|j| message_queue_root(i, j)).collect();
if !messages_out.is_empty() {
ctx.ingress_roots.insert(hash(i as u8), messages_out);
}
}
let mut view = View::default();
view.update_leaves(
&ctx,
[hash(0), hash(1)].iter().cloned(),
).unwrap();
assert!(check_roots(&view, 0, max));
assert!(check_roots(&view, 1, max));
assert!(!check_roots(&view, 2, max));
assert!(!check_roots(&view, 3, max));
assert!(!check_roots(&view, 4, max));
assert!(!check_roots(&view, 5, max));
view.update_leaves(
&ctx,
[hash(2), hash(3), hash(4)].iter().cloned(),
).unwrap();
assert!(!check_roots(&view, 0, max));
assert!(!check_roots(&view, 1, max));
assert!(check_roots(&view, 2, max));
assert!(check_roots(&view, 3, max));
assert!(check_roots(&view, 4, max));
assert!(!check_roots(&view, 5, max));
}
#[test]
fn update_leaves_overlapping() {
let mut ctx = TestChainContext::default();
let max = 5;
for i in 0..max {
ctx.known_map.insert(hash(i as u8), Known::Leaf);
let messages_out: Vec<_> = (0..max).filter_map(|j| message_queue_root(i, j)).collect();
if !messages_out.is_empty() {
ctx.ingress_roots.insert(hash(i as u8), messages_out);
}
}
let mut view = View::default();
view.update_leaves(
&ctx,
[hash(0), hash(1), hash(2)].iter().cloned(),
).unwrap();
view.update_leaves(
&ctx,
[hash(2), hash(3), hash(4)].iter().cloned(),
).unwrap();
assert!(!check_roots(&view, 0, max));
assert!(!check_roots(&view, 1, max));
assert!(check_roots(&view, 2, max));
assert!(check_roots(&view, 3, max));
assert!(check_roots(&view, 4, max));
assert!(!check_roots(&view, 5, max));
}
}
+15 -19
View File
@@ -25,12 +25,12 @@ mod router;
pub mod validation; pub mod validation;
pub mod gossip; pub mod gossip;
use parity_codec::{Decode, Encode}; use codec::{Decode, Encode};
use futures::sync::oneshot; use futures::sync::oneshot;
use polkadot_primitives::{Block, SessionKey, Hash, Header}; use polkadot_primitives::{Block, Hash, Header};
use polkadot_primitives::parachain::{ use polkadot_primitives::parachain::{
Id as ParaId, BlockData, CollatorId, CandidateReceipt, Collation, PoVBlock, Id as ParaId, BlockData, CollatorId, CandidateReceipt, Collation, PoVBlock,
StructuredUnroutedIngress, StructuredUnroutedIngress, ValidatorId
}; };
use substrate_network::{ use substrate_network::{
PeerId, RequestId, Context, StatusMessage as GenericFullStatus, PeerId, RequestId, Context, StatusMessage as GenericFullStatus,
@@ -78,7 +78,7 @@ pub struct Status {
} }
struct PoVBlockRequest { struct PoVBlockRequest {
attempted_peers: HashSet<SessionKey>, attempted_peers: HashSet<ValidatorId>,
validation_session_parent: Hash, validation_session_parent: Hash,
candidate_hash: Hash, candidate_hash: Hash,
block_data_hash: Hash, block_data_hash: Hash,
@@ -115,8 +115,8 @@ enum CollatorState {
} }
impl CollatorState { impl CollatorState {
fn send_key<F: FnMut(Message)>(&mut self, key: SessionKey, mut f: F) { fn send_key<F: FnMut(Message)>(&mut self, key: ValidatorId, mut f: F) {
f(Message::SessionKey(key)); f(Message::ValidatorId(key));
if let CollatorState::RolePending(role) = *self { if let CollatorState::RolePending(role) = *self {
f(Message::CollatorRole(role)); f(Message::CollatorRole(role));
*self = CollatorState::Primed(Some(role)); *self = CollatorState::Primed(Some(role));
@@ -160,7 +160,7 @@ pub enum Message {
/// As a validator, tell the peer your current session key. /// As a validator, tell the peer your current session key.
// TODO: do this with a cryptographic proof of some kind // TODO: do this with a cryptographic proof of some kind
// https://github.com/paritytech/polkadot/issues/47 // https://github.com/paritytech/polkadot/issues/47
SessionKey(SessionKey), ValidatorId(ValidatorId),
/// Requesting parachain proof-of-validation block (relay_parent, candidate_hash). /// Requesting parachain proof-of-validation block (relay_parent, candidate_hash).
RequestPovBlock(RequestId, Hash, Hash), RequestPovBlock(RequestId, Hash, Hash),
/// Provide requested proof-of-validation block data by candidate hash or nothing if unknown. /// Provide requested proof-of-validation block data by candidate hash or nothing if unknown.
@@ -186,7 +186,7 @@ pub struct PolkadotProtocol {
peers: HashMap<PeerId, PeerInfo>, peers: HashMap<PeerId, PeerInfo>,
collating_for: Option<(CollatorId, ParaId)>, collating_for: Option<(CollatorId, ParaId)>,
collators: CollatorPool, collators: CollatorPool,
validators: HashMap<SessionKey, PeerId>, validators: HashMap<ValidatorId, PeerId>,
local_collations: LocalCollations<Collation>, local_collations: LocalCollations<Collation>,
live_validation_sessions: LiveValidationSessions, live_validation_sessions: LiveValidationSessions,
in_flight: HashMap<(RequestId, PeerId), PoVBlockRequest>, in_flight: HashMap<(RequestId, PeerId), PoVBlockRequest>,
@@ -319,7 +319,7 @@ impl PolkadotProtocol {
fn on_polkadot_message(&mut self, ctx: &mut dyn Context<Block>, who: PeerId, msg: Message) { fn on_polkadot_message(&mut self, ctx: &mut dyn Context<Block>, who: PeerId, msg: Message) {
trace!(target: "p_net", "Polkadot message from {}: {:?}", who, msg); trace!(target: "p_net", "Polkadot message from {}: {:?}", who, msg);
match msg { match msg {
Message::SessionKey(key) => self.on_session_key(ctx, who, key), Message::ValidatorId(key) => self.on_session_key(ctx, who, key),
Message::RequestPovBlock(req_id, relay_parent, candidate_hash) => { Message::RequestPovBlock(req_id, relay_parent, candidate_hash) => {
let pov_block = self.live_validation_sessions.with_pov_block( let pov_block = self.live_validation_sessions.with_pov_block(
&relay_parent, &relay_parent,
@@ -352,7 +352,7 @@ impl PolkadotProtocol {
} }
} }
fn on_session_key(&mut self, ctx: &mut dyn Context<Block>, who: PeerId, key: SessionKey) { fn on_session_key(&mut self, ctx: &mut dyn Context<Block>, who: PeerId, key: ValidatorId) {
{ {
let info = match self.peers.get_mut(&who) { let info = match self.peers.get_mut(&who) {
Some(peer) => peer, Some(peer) => peer,
@@ -473,12 +473,8 @@ impl Specialization<Block> for PolkadotProtocol {
} }
fn on_connect(&mut self, ctx: &mut dyn Context<Block>, who: PeerId, status: FullStatus) { fn on_connect(&mut self, ctx: &mut dyn Context<Block>, who: PeerId, status: FullStatus) {
let local_status = match Status::decode(&mut &status.chain_status[..]) { let local_status = Status::decode(&mut &status.chain_status[..])
Some(status) => status, .unwrap_or_else(|_| Status { collating_for: None });
None => {
Status { collating_for: None }
}
};
let validator = status.roles.contains(substrate_network::config::Roles::AUTHORITY); let validator = status.roles.contains(substrate_network::config::Roles::AUTHORITY);
@@ -575,11 +571,11 @@ impl Specialization<Block> for PolkadotProtocol {
message: Vec<u8>, message: Vec<u8>,
) { ) {
match Message::decode(&mut &message[..]) { match Message::decode(&mut &message[..]) {
Some(msg) => { Ok(msg) => {
ctx.report_peer(who.clone(), benefit::VALID_FORMAT); ctx.report_peer(who.clone(), benefit::VALID_FORMAT);
self.on_polkadot_message(ctx, who, msg) self.on_polkadot_message(ctx, who, msg)
}, },
None => { Err(_) => {
trace!(target: "p_net", "Bad message from {}", who); trace!(target: "p_net", "Bad message from {}", who);
ctx.report_peer(who, cost::INVALID_FORMAT); ctx.report_peer(who, cost::INVALID_FORMAT);
} }
@@ -684,7 +680,7 @@ impl PolkadotProtocol {
&mut self, &mut self,
ctx: &mut dyn Context<Block>, ctx: &mut dyn Context<Block>,
relay_parent: Hash, relay_parent: Hash,
targets: HashSet<SessionKey>, targets: HashSet<ValidatorId>,
collation: Collation, collation: Collation,
) { ) {
debug!(target: "p_net", "Importing local collation on relay parent {:?} and parachain {:?}", debug!(target: "p_net", "Importing local collation on relay parent {:?} and parachain {:?}",
+9 -11
View File
@@ -19,24 +19,22 @@
//! Collations are attempted to be repropagated when a new validator connects, //! Collations are attempted to be repropagated when a new validator connects,
//! a validator changes his session key, or when they are generated. //! a validator changes his session key, or when they are generated.
use polkadot_primitives::{Hash, SessionKey}; use polkadot_primitives::{Hash, parachain::{ValidatorId}};
use crate::collator_pool::Role; use crate::collator_pool::Role;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
const LIVE_FOR: Duration = Duration::from_secs(60 * 5); const LIVE_FOR: Duration = Duration::from_secs(60 * 5);
struct LocalCollation<C> { struct LocalCollation<C> {
targets: HashSet<SessionKey>, targets: HashSet<ValidatorId>,
collation: C, collation: C,
live_since: Instant, live_since: Instant,
} }
/// Tracker for locally collated values and which validators to send them to. /// Tracker for locally collated values and which validators to send them to.
pub struct LocalCollations<C> { pub struct LocalCollations<C> {
primary_for: HashSet<SessionKey>, primary_for: HashSet<ValidatorId>,
local_collations: HashMap<Hash, LocalCollation<C>>, local_collations: HashMap<Hash, LocalCollation<C>>,
} }
@@ -51,7 +49,7 @@ impl<C: Clone> LocalCollations<C> {
/// Validator gave us a new role. If the new role is "primary", this function might return /// Validator gave us a new role. If the new role is "primary", this function might return
/// a set of collations to send to that validator. /// a set of collations to send to that validator.
pub fn note_validator_role(&mut self, key: SessionKey, role: Role) -> Vec<(Hash, C)> { pub fn note_validator_role(&mut self, key: ValidatorId, role: Role) -> Vec<(Hash, C)> {
match role { match role {
Role::Backup => { Role::Backup => {
self.primary_for.remove(&key); self.primary_for.remove(&key);
@@ -70,7 +68,7 @@ impl<C: Clone> LocalCollations<C> {
/// Fresh session key from a validator. Returns a vector of collations to send /// Fresh session key from a validator. Returns a vector of collations to send
/// to the validator. /// to the validator.
pub fn fresh_key(&mut self, old_key: &SessionKey, new_key: &SessionKey) -> Vec<(Hash, C)> { pub fn fresh_key(&mut self, old_key: &ValidatorId, new_key: &ValidatorId) -> Vec<(Hash, C)> {
if self.primary_for.remove(old_key) { if self.primary_for.remove(old_key) {
self.primary_for.insert(new_key.clone()); self.primary_for.insert(new_key.clone());
@@ -81,7 +79,7 @@ impl<C: Clone> LocalCollations<C> {
} }
/// Validator disconnected. /// Validator disconnected.
pub fn on_disconnect(&mut self, key: &SessionKey) { pub fn on_disconnect(&mut self, key: &ValidatorId) {
self.primary_for.remove(key); self.primary_for.remove(key);
} }
@@ -99,10 +97,10 @@ impl<C: Clone> LocalCollations<C> {
pub fn add_collation<'a>( pub fn add_collation<'a>(
&'a mut self, &'a mut self,
relay_parent: Hash, relay_parent: Hash,
targets: HashSet<SessionKey>, targets: HashSet<ValidatorId>,
collation: C collation: C
) )
-> impl Iterator<Item=(SessionKey, C)> + 'a -> impl Iterator<Item=(ValidatorId, C)> + 'a
{ {
self.local_collations.insert(relay_parent, LocalCollation { self.local_collations.insert(relay_parent, LocalCollation {
targets, targets,
@@ -119,7 +117,7 @@ impl<C: Clone> LocalCollations<C> {
.map(move |k| (k.clone(), borrowed_collation.clone())) .map(move |k| (k.clone(), borrowed_collation.clone()))
} }
fn collations_targeting(&self, key: &SessionKey) -> Vec<(Hash, C)> { fn collations_targeting(&self, key: &ValidatorId) -> Vec<(Hash, C)> {
self.local_collations.iter() self.local_collations.iter()
.filter(|&(_, ref v)| v.targets.contains(key)) .filter(|&(_, ref v)| v.targets.contains(key))
.map(|(h, v)| (*h, v.collation.clone())) .map(|(h, v)| (*h, v.collation.clone()))
+15 -4
View File
@@ -199,13 +199,16 @@ impl<P: ProvideRuntimeApi + Send + Sync + 'static, E, N, T> Router<P, E, N, T> w
validated.extrinsic().cloned(), validated.extrinsic().cloned(),
); );
// propagate the statement. // propagate the statement.
// consider something more targeted than gossip in the future. // consider something more targeted than gossip in the future.
let statement = GossipStatement::new( let statement = GossipStatement::new(
parent_hash, parent_hash,
table.import_validated(validated), match table.import_validated(validated) {
None => return,
Some(s) => s,
}
); );
network.gossip_message(attestation_topic, statement.into()); network.gossip_message(attestation_topic, statement.into());
}) })
.map_err(|e| debug!(target: "p_net", "Failed to produce statements: {:?}", e)) .map_err(|e| debug!(target: "p_net", "Failed to produce statements: {:?}", e))
@@ -224,10 +227,18 @@ impl<P: ProvideRuntimeApi + Send, E, N, T> TableRouter for Router<P, E, N, T> wh
fn local_collation(&self, collation: Collation, extrinsic: Extrinsic) { fn local_collation(&self, collation: Collation, extrinsic: Extrinsic) {
// produce a signed statement // produce a signed statement
let hash = collation.receipt.hash(); let hash = collation.receipt.hash();
let validated = Validated::collated_local(collation.receipt, collation.pov.clone(), extrinsic.clone()); let validated = Validated::collated_local(
collation.receipt,
collation.pov.clone(),
extrinsic.clone(),
);
let statement = GossipStatement::new( let statement = GossipStatement::new(
self.parent_hash(), self.parent_hash(),
self.table.import_validated(validated), match self.table.import_validated(validated) {
None => return,
Some(s) => s,
},
); );
// give to network to make available. // give to network to make available.
+13 -13
View File
@@ -21,13 +21,13 @@ use super::{PolkadotProtocol, Status, Message, FullStatus};
use crate::validation::SessionParams; use crate::validation::SessionParams;
use polkadot_validation::GenericStatement; use polkadot_validation::GenericStatement;
use polkadot_primitives::{Block, Hash, SessionKey}; use polkadot_primitives::{Block, Hash};
use polkadot_primitives::parachain::{ use polkadot_primitives::parachain::{
CandidateReceipt, HeadData, PoVBlock, BlockData, CollatorId, ValidatorId, CandidateReceipt, HeadData, PoVBlock, BlockData, CollatorId, ValidatorId,
StructuredUnroutedIngress, StructuredUnroutedIngress
}; };
use substrate_primitives::crypto::UncheckedInto; use substrate_primitives::crypto::UncheckedInto;
use parity_codec::Encode; use codec::Encode;
use substrate_network::{ use substrate_network::{
PeerId, Context, config::Roles, message::generic::ConsensusMessage, PeerId, Context, config::Roles, message::generic::ConsensusMessage,
specialization::NetworkSpecialization, specialization::NetworkSpecialization,
@@ -96,7 +96,7 @@ fn make_status(status: &Status, roles: Roles) -> FullStatus {
} }
} }
fn make_validation_session(parent_hash: Hash, local_key: SessionKey) -> SessionParams { fn make_validation_session(parent_hash: Hash, local_key: ValidatorId) -> SessionParams {
SessionParams { SessionParams {
local_session_key: Some(local_key), local_session_key: Some(local_key),
parent_hash, parent_hash,
@@ -131,13 +131,13 @@ fn sends_session_key() {
let mut ctx = TestContext::default(); let mut ctx = TestContext::default();
let params = make_validation_session(parent_hash, local_key.clone()); let params = make_validation_session(parent_hash, local_key.clone());
protocol.new_validation_session(&mut ctx, params); protocol.new_validation_session(&mut ctx, params);
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key.clone()))); assert!(ctx.has_message(peer_a, Message::ValidatorId(local_key.clone())));
} }
{ {
let mut ctx = TestContext::default(); let mut ctx = TestContext::default();
protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&collator_status, Roles::NONE)); protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&collator_status, Roles::NONE));
assert!(ctx.has_message(peer_b.clone(), Message::SessionKey(local_key))); assert!(ctx.has_message(peer_b.clone(), Message::ValidatorId(local_key)));
} }
} }
@@ -186,13 +186,13 @@ fn fetches_from_those_with_knowledge() {
{ {
let mut ctx = TestContext::default(); let mut ctx = TestContext::default();
protocol.on_connect(&mut ctx, peer_a.clone(), make_status(&status, Roles::AUTHORITY)); protocol.on_connect(&mut ctx, peer_a.clone(), make_status(&status, Roles::AUTHORITY));
assert!(ctx.has_message(peer_a.clone(), Message::SessionKey(local_key))); assert!(ctx.has_message(peer_a.clone(), Message::ValidatorId(local_key)));
} }
// peer A gives session key and gets asked for data. // peer A gives session key and gets asked for data.
{ {
let mut ctx = TestContext::default(); let mut ctx = TestContext::default();
on_message(&mut protocol, &mut ctx, peer_a.clone(), Message::SessionKey(a_key.clone())); on_message(&mut protocol, &mut ctx, peer_a.clone(), Message::ValidatorId(a_key.clone()));
assert!(protocol.validators.contains_key(&a_key)); assert!(protocol.validators.contains_key(&a_key));
assert!(ctx.has_message(peer_a.clone(), Message::RequestPovBlock(1, parent_hash, candidate_hash))); assert!(ctx.has_message(peer_a.clone(), Message::RequestPovBlock(1, parent_hash, candidate_hash)));
} }
@@ -203,7 +203,7 @@ fn fetches_from_those_with_knowledge() {
{ {
let mut ctx = TestContext::default(); let mut ctx = TestContext::default();
protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&status, Roles::AUTHORITY)); protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&status, Roles::AUTHORITY));
on_message(&mut protocol, &mut ctx, peer_b.clone(), Message::SessionKey(b_key.clone())); on_message(&mut protocol, &mut ctx, peer_b.clone(), Message::ValidatorId(b_key.clone()));
assert!(!ctx.has_message(peer_b.clone(), Message::RequestPovBlock(2, parent_hash, candidate_hash))); assert!(!ctx.has_message(peer_b.clone(), Message::RequestPovBlock(2, parent_hash, candidate_hash)));
} }
@@ -340,8 +340,8 @@ fn many_session_keys() {
let status = Status { collating_for: None }; let status = Status { collating_for: None };
protocol.on_connect(&mut ctx, peer_a.clone(), make_status(&status, Roles::AUTHORITY)); protocol.on_connect(&mut ctx, peer_a.clone(), make_status(&status, Roles::AUTHORITY));
assert!(ctx.has_message(peer_a.clone(), Message::SessionKey(local_key_a.clone()))); assert!(ctx.has_message(peer_a.clone(), Message::ValidatorId(local_key_a.clone())));
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key_b.clone()))); assert!(ctx.has_message(peer_a, Message::ValidatorId(local_key_b.clone())));
} }
let peer_b = PeerId::random(); let peer_b = PeerId::random();
@@ -354,7 +354,7 @@ fn many_session_keys() {
let status = Status { collating_for: None }; let status = Status { collating_for: None };
protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&status, Roles::AUTHORITY)); protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&status, Roles::AUTHORITY));
assert!(!ctx.has_message(peer_b.clone(), Message::SessionKey(local_key_a.clone()))); assert!(!ctx.has_message(peer_b.clone(), Message::ValidatorId(local_key_a.clone())));
assert!(ctx.has_message(peer_b, Message::SessionKey(local_key_b.clone()))); assert!(ctx.has_message(peer_b, Message::ValidatorId(local_key_b.clone())));
} }
} }
+10 -7
View File
@@ -23,11 +23,11 @@ use crate::gossip::GossipMessage;
use substrate_network::Context as NetContext; use substrate_network::Context as NetContext;
use substrate_network::consensus_gossip::TopicNotification; use substrate_network::consensus_gossip::TopicNotification;
use substrate_primitives::{NativeOrEncoded, ExecutionContext}; use substrate_primitives::{NativeOrEncoded, ExecutionContext};
use substrate_keyring::Ed25519Keyring; use substrate_keyring::Sr25519Keyring;
use crate::PolkadotProtocol; use crate::PolkadotProtocol;
use polkadot_validation::{SharedTable, MessagesFrom, Network}; use polkadot_validation::{SharedTable, MessagesFrom, Network};
use polkadot_primitives::{SessionKey, Block, Hash, Header, BlockId}; use polkadot_primitives::{Block, Hash, Header, BlockId};
use polkadot_primitives::parachain::{ use polkadot_primitives::parachain::{
Id as ParaId, Chain, DutyRoster, ParachainHost, OutgoingMessage, Id as ParaId, Chain, DutyRoster, ParachainHost, OutgoingMessage,
ValidatorId, StructuredUnroutedIngress, BlockIngressRoots, Status, ValidatorId, StructuredUnroutedIngress, BlockIngressRoots, Status,
@@ -41,7 +41,7 @@ use sr_primitives::traits::{ApiRef, ProvideRuntimeApi};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use futures::{prelude::*, sync::mpsc}; use futures::{prelude::*, sync::mpsc};
use parity_codec::Encode; use codec::Encode;
use super::TestContext; use super::TestContext;
@@ -398,20 +398,23 @@ impl IngressBuilder {
} }
} }
fn make_table(data: &ApiData, local_key: &Ed25519Keyring, parent_hash: Hash) -> Arc<SharedTable> { fn make_table(data: &ApiData, local_key: &Sr25519Keyring, parent_hash: Hash) -> Arc<SharedTable> {
use av_store::Store; use av_store::Store;
use substrate_primitives::crypto::Pair;
let sr_pair = local_key.pair();
let local_key = polkadot_primitives::parachain::ValidatorPair::from(local_key.pair());
let store = Store::new_in_memory(); let store = Store::new_in_memory();
let (group_info, _) = ::polkadot_validation::make_group_info( let (group_info, _) = ::polkadot_validation::make_group_info(
DutyRoster { validator_duty: data.duties.clone() }, DutyRoster { validator_duty: data.duties.clone() },
&data.validators, // only possible as long as parachain crypto === aura crypto &data.validators, // only possible as long as parachain crypto === aura crypto
SessionKey::from(*local_key) Some(sr_pair.public().into()),
).unwrap(); ).unwrap();
Arc::new(SharedTable::new( Arc::new(SharedTable::new(
data.validators.as_slice(), data.validators.clone(),
group_info, group_info,
Arc::new(local_key.pair()), Some(Arc::new(local_key)),
parent_hash, parent_hash,
store, store,
None, None,
+7 -7
View File
@@ -28,10 +28,10 @@ use substrate_network::consensus_gossip::{
use polkadot_validation::{ use polkadot_validation::{
Network as ParachainNetwork, SharedTable, Collators, Statement, GenericStatement, SignedStatement, Network as ParachainNetwork, SharedTable, Collators, Statement, GenericStatement, SignedStatement,
}; };
use polkadot_primitives::{Block, BlockId, Hash, SessionKey}; use polkadot_primitives::{Block, BlockId, Hash};
use polkadot_primitives::parachain::{ use polkadot_primitives::parachain::{
Id as ParaId, Collation, Extrinsic, ParachainHost, CandidateReceipt, CollatorId, Id as ParaId, Collation, Extrinsic, ParachainHost, CandidateReceipt, CollatorId,
ValidatorId, PoVBlock, ValidatorIndex, ValidatorId, PoVBlock, ValidatorIndex
}; };
use futures::prelude::*; use futures::prelude::*;
@@ -54,7 +54,7 @@ use super::PolkadotProtocol;
pub use polkadot_validation::Incoming; pub use polkadot_validation::Incoming;
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
/// An executor suitable for dispatching async consensus tasks. /// An executor suitable for dispatching async consensus tasks.
pub trait Executor { pub trait Executor {
@@ -120,7 +120,7 @@ impl Stream for GossipMessageStream {
}; };
debug!(target: "validation", "Processing statement for live validation session"); debug!(target: "validation", "Processing statement for live validation session");
if let Some(gmsg) = GossipMessage::decode(&mut &msg.message[..]) { if let Ok(gmsg) = GossipMessage::decode(&mut &msg.message[..]) {
return Ok(Async::Ready(Some((gmsg, msg.sender)))) return Ok(Async::Ready(Some((gmsg, msg.sender))))
} }
} }
@@ -186,11 +186,11 @@ impl NetworkService for super::NetworkService {
/// Params to a current validation session. /// Params to a current validation session.
pub struct SessionParams { pub struct SessionParams {
/// The local session key. /// The local session key.
pub local_session_key: Option<SessionKey>, pub local_session_key: Option<ValidatorId>,
/// The parent hash. /// The parent hash.
pub parent_hash: Hash, pub parent_hash: Hash,
/// The authorities. /// The authorities.
pub authorities: Vec<SessionKey>, pub authorities: Vec<ValidatorId>,
} }
/// Wrapper around the network service /// Wrapper around the network service
@@ -336,7 +336,7 @@ impl<P, E, N, T> ParachainNetwork for ValidationNetwork<P, E, N, T> where
let local_session_key = table.session_key(); let local_session_key = table.session_key();
let build_fetcher = self.instantiate_session(SessionParams { let build_fetcher = self.instantiate_session(SessionParams {
local_session_key: Some(local_session_key), local_session_key,
parent_hash, parent_hash,
authorities: authorities.to_vec(), authorities: authorities.to_vec(),
}); });
+12 -3
View File
@@ -6,11 +6,10 @@ description = "Types and utilities for creating and working with parachains"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
codec = { package = "parity-codec", version = "4.1", default-features = false, features = [ "derive" ] } codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = [ "derive" ] }
wasmi = { version = "0.4.3", optional = true } wasmi = { version = "0.4.3", optional = true }
derive_more = { version = "0.14", optional = true } derive_more = { version = "0.14", optional = true }
serde = { version = "1.0", default-features = false, features = [ "derive" ] } serde = { version = "1.0", default-features = false, features = [ "derive" ] }
rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", default-features = false } rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", default-features = false }
lazy_static = { version = "1.3.0", optional = true } lazy_static = { version = "1.3.0", optional = true }
parking_lot = { version = "0.7.1", optional = true } parking_lot = { version = "0.7.1", optional = true }
@@ -27,4 +26,14 @@ halt = { path = "../test-parachains/halt" }
[features] [features]
default = ["std"] default = ["std"]
wasm-api = [] wasm-api = []
std = [ "codec/std", "wasmi", "derive_more", "serde/std", "rstd/std", "shared_memory", "lazy_static", "parking_lot", "log" ] std = [
"codec/std",
"wasmi",
"derive_more",
"serde/std",
"rstd/std",
"shared_memory",
"lazy_static",
"parking_lot",
"log"
]
+51 -45
View File
@@ -51,22 +51,9 @@ pub mod wasm_executor;
#[cfg(feature = "wasm-api")] #[cfg(feature = "wasm-api")]
pub mod wasm_api; pub mod wasm_api;
use codec::{Encode, Decode};
use rstd::vec::Vec; use rstd::vec::Vec;
struct TrailingZeroInput<'a>(&'a [u8]); use codec::{Encode, Decode};
impl<'a> codec::Input for TrailingZeroInput<'a> {
fn read(&mut self, into: &mut [u8]) -> usize {
let len = into.len().min(self.0.len());
into[..len].copy_from_slice(&self.0[..len]);
for i in &mut into[len..] {
*i = 0;
}
self.0 = &self.0[len..];
len
}
}
/// Validation parameters for evaluating the parachain validity function. /// Validation parameters for evaluating the parachain validity function.
// TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220) // TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220)
@@ -110,37 +97,6 @@ impl From<codec::Compact<Id>> for Id {
} }
} }
/// This type can be converted into and possibly from an AccountId (which itself is generic).
pub trait AccountIdConversion<AccountId>: Sized {
/// Convert into an account ID. This is infallible.
fn into_account(&self) -> AccountId;
/// Try to convert an account ID into this type. Might not succeed.
fn try_from_account(a: &AccountId) -> Option<Self>;
}
/// Format is b"para" ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to fill AccountId.
impl<T: Encode + Decode + Default> AccountIdConversion<T> for Id {
fn into_account(&self) -> T {
(b"para", self).using_encoded(|b|
T::decode(&mut TrailingZeroInput(b))
).unwrap_or_default()
}
fn try_from_account(x: &T) -> Option<Self> {
x.using_encoded(|d| {
if &d[0..4] != b"para" { return None }
let mut cursor = &d[4..];
let result = Decode::decode(&mut cursor)?;
if cursor.iter().all(|x| *x == 0) {
Some(result)
} else {
None
}
})
}
}
impl From<Id> for u32 { impl From<Id> for u32 {
fn from(x: Id) -> Self { x.0 } fn from(x: Id) -> Self { x.0 }
} }
@@ -156,6 +112,56 @@ impl Id {
} }
} }
// TODO: Remove all of this, move sr-primitives::AccountIdConversion to own crate and and use that.
// #360
struct TrailingZeroInput<'a>(&'a [u8]);
impl<'a> codec::Input for TrailingZeroInput<'a> {
fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
Ok(None)
}
fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
let len = into.len().min(self.0.len());
into[..len].copy_from_slice(&self.0[..len]);
for i in &mut into[len..] {
*i = 0;
}
self.0 = &self.0[len..];
Ok(())
}
}
/// This type can be converted into and possibly from an AccountId (which itself is generic).
pub trait AccountIdConversion<AccountId>: Sized {
/// Convert into an account ID. This is infallible.
fn into_account(&self) -> AccountId;
/// Try to convert an account ID into this type. Might not succeed.
fn try_from_account(a: &AccountId) -> Option<Self>;
}
/// Format is b"para" ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to fill AccountId.
impl<T: Encode + Decode + Default> AccountIdConversion<T> for Id {
fn into_account(&self) -> T {
(b"para", self).using_encoded(|b|
T::decode(&mut TrailingZeroInput(b))
).unwrap_or_default()
}
fn try_from_account(x: &T) -> Option<Self> {
x.using_encoded(|d| {
if &d[0..4] != b"para" { return None }
let mut cursor = &d[4..];
let result = Decode::decode(&mut cursor).ok()?;
if cursor.iter().all(|x| *x == 0) {
Some(result)
} else {
None
}
})
}
}
/// An incoming message. /// An incoming message.
#[derive(PartialEq, Eq, Decode)] #[derive(PartialEq, Eq, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Encode))] #[cfg_attr(feature = "std", derive(Debug, Encode))]
+2 -3
View File
@@ -431,7 +431,7 @@ pub fn validate_candidate_internal<E: Externalities>(
let len_offset = len_offset as usize; let len_offset = len_offset as usize;
let len = u32::decode(&mut &len_bytes[..]) let len = u32::decode(&mut &len_bytes[..])
.ok_or_else(|| Error::BadReturn)? as usize; .map_err(|_| Error::BadReturn)? as usize;
let return_offset = if len > len_offset { let return_offset = if len > len_offset {
return Err(Error::BadReturn); return Err(Error::BadReturn);
@@ -445,8 +445,7 @@ pub fn validate_candidate_internal<E: Externalities>(
} }
ValidationResult::decode(&mut &mem[return_offset..][..len]) ValidationResult::decode(&mut &mem[return_offset..][..len])
.ok_or_else(|| Error::BadReturn) .map_err(|_| Error::BadReturn.into())
.map_err(Into::into)
}) })
} }
_ => Err(Error::BadReturn), _ => Err(Error::BadReturn),
@@ -95,7 +95,7 @@ pub fn run_worker(mem_id: &str) -> Result<(), String> {
let (header_buf, rest) = data.split_at_mut(1024); let (header_buf, rest) = data.split_at_mut(1024);
let mut header_buf: &[u8] = header_buf; let mut header_buf: &[u8] = header_buf;
let header = ValidationHeader::decode(&mut header_buf) let header = ValidationHeader::decode(&mut header_buf)
.ok_or_else(|| format!("Error decoding validation request."))?; .map_err(|_| format!("Error decoding validation request."))?;
debug!("Candidate header: {:?}", header); debug!("Candidate header: {:?}", header);
let (code, rest) = rest.split_at_mut(MAX_CODE_MEM); let (code, rest) = rest.split_at_mut(MAX_CODE_MEM);
let (code, _) = code.split_at_mut(header.code_size as usize); let (code, _) = code.split_at_mut(header.code_size as usize);
+1 -1
View File
@@ -169,7 +169,7 @@ fn processes_messages() {
}; };
let bad_message_data = vec![1]; let bad_message_data = vec![1];
assert!(AddMessage::decode(&mut &bad_message_data[..]).is_none()); assert!(AddMessage::decode(&mut &bad_message_data[..]).is_err());
let ret = parachain::wasm_executor::validate_candidate( let ret = parachain::wasm_executor::validate_candidate(
TEST_CODE, TEST_CODE,
+7 -4
View File
@@ -6,14 +6,16 @@ edition = "2018"
[dependencies] [dependencies]
serde = { version = "1.0", optional = true, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] }
parity-codec = { version = "4.1", default-features = false, features = ["bit-vec"] } parity-scale-codec = { version = "1.0.5", default-features = false, features = ["bit-vec", "derive"] }
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
application-crypto = { package = "substrate-application-crypto", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
substrate-client = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } substrate-client = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
sr-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } sr-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
polkadot-parachain = { path = "../parachain", default-features = false } polkadot-parachain = { path = "../parachain", default-features = false }
bitvec = { version = "0.11", default-features = false, features = ["alloc"] } bitvec = { version = "0.14.0", default-features = false, features = ["alloc"] }
babe = { package = "srml-babe", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
[dev-dependencies] [dev-dependencies]
substrate-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
@@ -22,7 +24,7 @@ pretty_assertions = "0.5.1"
[features] [features]
default = ["std"] default = ["std"]
std = [ std = [
"parity-codec/std", "parity-scale-codec/std",
"primitives/std", "primitives/std",
"substrate-client/std", "substrate-client/std",
"rstd/std", "rstd/std",
@@ -30,5 +32,6 @@ std = [
"runtime_primitives/std", "runtime_primitives/std",
"serde", "serde",
"polkadot-parachain/std", "polkadot-parachain/std",
"bitvec/std" "bitvec/std",
"babe/std"
] ]
+7 -27
View File
@@ -21,18 +21,19 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use runtime_primitives::{generic, AnySignature}; use runtime_primitives::{generic, AnySignature};
use primitives::ed25519;
pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT, Verify}; pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT, Verify};
pub mod parachain; pub mod parachain;
pub use parity_codec::Compact; pub use parity_scale_codec::Compact;
/// An index to a block. /// An index to a block.
/// 32-bits will allow for 136 years of blocks assuming 1 block per second. /// 32-bits will allow for 136 years of blocks assuming 1 block per second.
/// TODO: switch to u32 (https://github.com/paritytech/polkadot/issues/221) pub type BlockNumber = u32;
pub type BlockNumber = u64;
/// An instant or duration in time.
pub type Moment = u64;
/// Alias to 512-bit hash when used in the context of a signature on the relay chain. /// Alias to 512-bit hash when used in the context of a signature on the relay chain.
/// Equipped with logic for possibly "unsigned" messages. /// Equipped with logic for possibly "unsigned" messages.
@@ -41,8 +42,7 @@ pub type Signature = AnySignature;
/// Alias to an sr25519 or ed25519 key. /// Alias to an sr25519 or ed25519 key.
pub type AccountId = <Signature as Verify>::Signer; pub type AccountId = <Signature as Verify>::Signer;
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you /// The type for looking up accounts. We don't expect more than 4 billion of them.
/// never know...
pub type AccountIndex = u32; pub type AccountIndex = u32;
/// Identifier for a chain. 32-bit should be plenty. /// Identifier for a chain. 32-bit should be plenty.
@@ -52,13 +52,7 @@ pub type ChainId = u32;
pub type Hash = primitives::H256; pub type Hash = primitives::H256;
/// Index of a transaction in the relay chain. 32-bit should be plenty. /// Index of a transaction in the relay chain. 32-bit should be plenty.
pub type Nonce = u64; pub type Nonce = u32;
/// Signature with which authorities sign blocks.
pub type SessionSignature = ed25519::Signature;
/// Identity that authorities use.
pub type SessionKey = ed25519::Public;
/// The balance of an account. /// The balance of an account.
/// 128-bits (or 38 significant decimal figures) will allow for 10m currency (10^7) at a resolution /// 128-bits (or 38 significant decimal figures) will allow for 10m currency (10^7) at a resolution
@@ -69,20 +63,6 @@ pub type SessionKey = ed25519::Public;
/// that 32 bits may be multiplied with a balance in 128 bits without worrying about overflow. /// that 32 bits may be multiplied with a balance in 128 bits without worrying about overflow.
pub type Balance = u128; pub type Balance = u128;
/// The aura crypto scheme defined via the keypair type.
#[cfg(feature = "std")]
pub type AuraPair = ed25519::Pair;
/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain.
pub type AuraId = ed25519::Public;
/// The Parachain crypto scheme defined via the keypair type.
#[cfg(feature = "std")]
pub type ParachainPair = ed25519::Pair;
/// The Ed25519 public key used to authenticate signatures on parachain data.
pub type ParachainPublic = ed25519::Public;
/// Header type. /// Header type.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>; pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Block type. /// Block type.
+33 -9
View File
@@ -18,7 +18,7 @@
use rstd::prelude::*; use rstd::prelude::*;
use rstd::cmp::Ordering; use rstd::cmp::Ordering;
use parity_codec::{Encode, Decode}; use parity_scale_codec::{Encode, Decode};
use bitvec::vec::BitVec; use bitvec::vec::BitVec;
use super::{Hash, Balance, BlockNumber}; use super::{Hash, Balance, BlockNumber};
@@ -27,32 +27,56 @@ use serde::{Serialize, Deserialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use primitives::bytes; use primitives::bytes;
use primitives::ed25519; use application_crypto::KeyTypeId;
pub use polkadot_parachain::{ pub use polkadot_parachain::{
Id, AccountIdConversion, ParachainDispatchOrigin, UpwardMessage, Id, AccountIdConversion, ParachainDispatchOrigin, UpwardMessage,
}; };
/// The key type ID for a collator key.
pub const COLLATOR_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"coll");
mod collator_app {
use application_crypto::{app_crypto, sr25519};
app_crypto!(sr25519, super::COLLATOR_KEY_TYPE_ID);
}
/// Identity that collators use. /// Identity that collators use.
pub type CollatorId = ed25519::Public; pub type CollatorId = collator_app::Public;
/// A Parachain collator keypair.
#[cfg(feature = "std")]
pub type CollatorPair = collator_app::Pair;
/// Signature on candidate's block data by a collator. /// Signature on candidate's block data by a collator.
pub type CollatorSignature = ed25519::Signature; pub type CollatorSignature = collator_app::Signature;
/// The key type ID for a parachain validator key.
pub const PARACHAIN_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"para");
mod validator_app {
use application_crypto::{app_crypto, sr25519};
app_crypto!(sr25519, super::PARACHAIN_KEY_TYPE_ID);
}
/// Identity that parachain validators use when signing validation messages. /// Identity that parachain validators use when signing validation messages.
/// ///
/// For now we assert that parachain validator set is exactly equivalent to the (Aura) authority set, and /// For now we assert that parachain validator set is exactly equivalent to the (Aura) authority set, and
/// so we define it to be the same type as `SessionKey`. In the future it may have different crypto. /// so we define it to be the same type as `SessionKey`. In the future it may have different crypto.
pub type ValidatorId = super::SessionKey; pub type ValidatorId = validator_app::Public;
/// Index of the validator is used as a lightweight replacement of the `ValidatorId` when appropriate. /// Index of the validator is used as a lightweight replacement of the `ValidatorId` when appropriate.
pub type ValidatorIndex = u32; pub type ValidatorIndex = u32;
/// A Parachain validator keypair.
#[cfg(feature = "std")]
pub type ValidatorPair = validator_app::Pair;
/// Signature with which parachain validators sign blocks. /// Signature with which parachain validators sign blocks.
/// ///
/// For now we assert that parachain validator set is exactly equivalent to the (Aura) authority set, and /// For now we assert that parachain validator set is exactly equivalent to the (Aura) authority set, and
/// so we define it to be the same type as `SessionKey`. In the future it may have different crypto. /// so we define it to be the same type as `SessionKey`. In the future it may have different crypto.
pub type ValidatorSignature = super::SessionSignature; pub type ValidatorSignature = validator_app::Signature;
/// Identifier for a chain, either one of a number of parachains or the relay chain. /// Identifier for a chain, either one of a number of parachains or the relay chain.
#[derive(Copy, Clone, PartialEq, Encode, Decode)] #[derive(Copy, Clone, PartialEq, Encode, Decode)]
@@ -143,7 +167,7 @@ impl CandidateReceipt {
/// Check integrity vs. provided block data. /// Check integrity vs. provided block data.
pub fn check_signature(&self) -> Result<(), ()> { pub fn check_signature(&self) -> Result<(), ()> {
use runtime_primitives::traits::Verify; use runtime_primitives::traits::AppVerify;
if self.signature.verify(self.block_data_hash.as_ref(), &self.collator) { if self.signature.verify(self.block_data_hash.as_ref(), &self.collator) {
Ok(()) Ok(())
@@ -292,11 +316,11 @@ pub enum ValidityAttestation {
/// implicit validity attestation by issuing. /// implicit validity attestation by issuing.
/// This corresponds to issuance of a `Candidate` statement. /// This corresponds to issuance of a `Candidate` statement.
#[codec(index = "1")] #[codec(index = "1")]
Implicit(CollatorSignature), Implicit(ValidatorSignature),
/// An explicit attestation. This corresponds to issuance of a /// An explicit attestation. This corresponds to issuance of a
/// `Valid` statement. /// `Valid` statement.
#[codec(index = "2")] #[codec(index = "2")]
Explicit(CollatorSignature), Explicit(ValidatorSignature),
} }
/// An attested candidate. /// An attested candidate.
+13 -8
View File
@@ -6,14 +6,14 @@ edition = "2018"
build = "build.rs" build = "build.rs"
[dependencies] [dependencies]
bitvec = { version = "0.11", default-features = false, features = ["alloc"] } bitvec = { version = "0.14.0", default-features = false, features = ["alloc"] }
rustc-hex = { version = "2.0.1", default-features = false } rustc-hex = { version = "2.0.1", default-features = false }
log = { version = "0.3", optional = true } log = { version = "0.3", optional = true }
serde = { version = "1.0", default-features = false } serde = { version = "1.0", default-features = false }
serde_derive = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true }
safe-mix = { version = "1.0", default-features = false} safe-mix = { version = "1.0", default-features = false}
primitives = { package = "polkadot-primitives", path = "../primitives", default-features = false } primitives = { package = "polkadot-primitives", path = "../primitives", default-features = false }
parity-codec = { version = "4.1", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
substrate-serializer = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } substrate-serializer = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
sr-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } sr-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
@@ -21,9 +21,7 @@ srml-support = { git = "https://github.com/paritytech/substrate", default-featur
substrate-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } substrate-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
consensus_aura = { package = "substrate-consensus-aura-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
offchain_primitives = { package = "substrate-offchain-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } offchain_primitives = { package = "substrate-offchain-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
aura = { package = "srml-aura", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
authorship = { package = "srml-authorship", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } authorship = { package = "srml-authorship", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
balances = { package = "srml-balances", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } balances = { package = "srml-balances", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
collective = { package = "srml-collective", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } collective = { package = "srml-collective", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
@@ -32,7 +30,9 @@ democracy = { package = "srml-democracy", git = "https://github.com/paritytech/s
executive = { package = "srml-executive", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } executive = { package = "srml-executive", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
finality-tracker = { package = "srml-finality-tracker", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } finality-tracker = { package = "srml-finality-tracker", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
grandpa = { package = "srml-grandpa", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } grandpa = { package = "srml-grandpa", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
im-online = { package = "srml-im-online", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
indices = { package = "srml-indices", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } indices = { package = "srml-indices", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
membership = { package = "srml-membership", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
sr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } sr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
session = { package = "srml-session", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } session = { package = "srml-session", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
staking = { package = "srml-staking", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } staking = { package = "srml-staking", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
@@ -41,6 +41,9 @@ system = { package = "srml-system", git = "https://github.com/paritytech/substra
timestamp = { package = "srml-timestamp", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } timestamp = { package = "srml-timestamp", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
treasury = { package = "srml-treasury", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } treasury = { package = "srml-treasury", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
version = { package = "sr-version", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } version = { package = "sr-version", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
babe = { package = "srml-babe", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
babe-primitives = { package = "substrate-consensus-babe-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
substrate-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
[dev-dependencies] [dev-dependencies]
hex-literal = "0.2.0" hex-literal = "0.2.0"
@@ -48,7 +51,7 @@ libsecp256k1 = "0.2.1"
tiny-keccak = "1.4.2" tiny-keccak = "1.4.2"
keyring = { package = "substrate-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } keyring = { package = "substrate-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
substrate-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
trie-db = "0.14" trie-db = "0.15"
[build-dependencies] [build-dependencies]
wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.1" } wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.1" }
@@ -60,7 +63,7 @@ std = [
"bitvec/std", "bitvec/std",
"primitives/std", "primitives/std",
"rustc-hex/std", "rustc-hex/std",
"parity-codec/std", "codec/std",
"inherents/std", "inherents/std",
"substrate-primitives/std", "substrate-primitives/std",
"client/std", "client/std",
@@ -68,7 +71,6 @@ std = [
"rstd/std", "rstd/std",
"sr-io/std", "sr-io/std",
"srml-support/std", "srml-support/std",
"aura/std",
"authorship/std", "authorship/std",
"balances/std", "balances/std",
"collective/std", "collective/std",
@@ -77,7 +79,9 @@ std = [
"executive/std", "executive/std",
"finality-tracker/std", "finality-tracker/std",
"grandpa/std", "grandpa/std",
"im-online/std",
"indices/std", "indices/std",
"membership/std",
"sr-primitives/std", "sr-primitives/std",
"session/std", "session/std",
"staking/std", "staking/std",
@@ -90,5 +94,6 @@ std = [
"serde/std", "serde/std",
"log", "log",
"safe-mix/std", "safe-mix/std",
"consensus_aura/std", "babe/std",
"babe-primitives/std",
] ]
+1 -1
View File
@@ -20,7 +20,7 @@
//! as well. //! as well.
use rstd::prelude::*; use rstd::prelude::*;
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
use srml_support::{decl_storage, decl_module, ensure}; use srml_support::{decl_storage, decl_module, ensure};
use primitives::{Hash, parachain::{AttestedCandidate, CandidateReceipt, Id as ParaId}}; use primitives::{Hash, parachain::{AttestedCandidate, CandidateReceipt, Id as ParaId}};
+8 -8
View File
@@ -21,7 +21,7 @@ use sr_io::{keccak_256, secp256k1_ecdsa_recover};
use srml_support::{StorageValue, StorageMap, decl_event, decl_storage, decl_module}; use srml_support::{StorageValue, StorageMap, decl_event, decl_storage, decl_module};
use srml_support::traits::{Currency, Get}; use srml_support::traits::{Currency, Get};
use system::ensure_none; use system::ensure_none;
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use sr_primitives::traits::Zero; use sr_primitives::traits::Zero;
use sr_primitives::{ use sr_primitives::{
@@ -200,7 +200,7 @@ mod tests {
use sr_io::with_externalities; use sr_io::with_externalities;
use substrate_primitives::{H256, Blake2Hasher}; use substrate_primitives::{H256, Blake2Hasher};
use parity_codec::{Decode, Encode}; use codec::{Decode, Encode};
// The testing primitives are very useful for avoiding having to work with signatures // The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup, ConvertInto}, testing::Header}; use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup, ConvertInto}, testing::Header};
@@ -210,20 +210,20 @@ mod tests {
impl_outer_origin! { impl_outer_origin! {
pub enum Origin for Test {} pub enum Origin for Test {}
} }
// For testing the module, we construct most of a mock runtime. This means // For testing the module, we construct most of a mock runtime. This means
// first constructing a configuration type (`Test`) which `impl`s each of the // first constructing a configuration type (`Test`) which `impl`s each of the
// configuration traits of modules we want to use. // configuration traits of modules we want to use.
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct Test; pub struct Test;
parameter_types! { parameter_types! {
pub const BlockHashCount: u64 = 250; pub const BlockHashCount: u32 = 250;
pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024;
pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
} }
impl system::Trait for Test { impl system::Trait for Test {
type Origin = Origin; type Origin = Origin;
type Call = ();
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
@@ -305,12 +305,12 @@ mod tests {
// This function basically just builds a genesis storage key/value store according to // This function basically just builds a genesis storage key/value store according to
// our desired mockup. // our desired mockup.
fn new_test_ext() -> sr_io::TestExternalities<Blake2Hasher> { fn new_test_ext() -> sr_io::TestExternalities<Blake2Hasher> {
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0; let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap();
// We use default for brevity, but you can configure as desired if needed. // We use default for brevity, but you can configure as desired if needed.
t.extend(balances::GenesisConfig::<Test>::default().build_storage().unwrap().0); balances::GenesisConfig::<Test>::default().assimilate_storage(&mut t).unwrap();
t.extend(GenesisConfig::<Test>{ GenesisConfig::<Test>{
claims: vec![(alice_eth(), 100)], claims: vec![(alice_eth(), 100)],
}.build_storage().unwrap().0); }.assimilate_storage(&mut t).unwrap();
t.into() t.into()
} }
+20 -6
View File
@@ -19,17 +19,31 @@ pub mod currency {
use primitives::Balance; use primitives::Balance;
pub const DOTS: Balance = 1_000_000_000_000; pub const DOTS: Balance = 1_000_000_000_000;
pub const BUCKS: Balance = DOTS / 100; pub const DOLLARS: Balance = DOTS / 100;
pub const CENTS: Balance = BUCKS / 100; pub const CENTS: Balance = DOLLARS / 100;
pub const MILLICENTS: Balance = CENTS / 1_000; pub const MILLICENTS: Balance = CENTS / 1_000;
} }
/// Time. /// Time.
pub mod time { pub mod time {
pub const SECS_PER_BLOCK: u64 = 6; use primitives::{Moment, BlockNumber};
pub const MINUTES: u64 = 60 / SECS_PER_BLOCK; pub const MILLISECS_PER_BLOCK: Moment = 6000;
pub const HOURS: u64 = MINUTES * 60; pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000;
pub const DAYS: u64 = HOURS * 24;
pub const SLOT_DURATION: Moment = 1650;
pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES;
pub const EPOCH_DURATION_IN_SLOTS: u64 = {
const SLOT_FILL_RATE: f64 = MILLISECS_PER_BLOCK as f64 / SLOT_DURATION as f64;
(EPOCH_DURATION_IN_BLOCKS as f64 * SLOT_FILL_RATE) as u64
};
// These time units are defined in number of blocks.
pub const MINUTES: BlockNumber = 60 / (SECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
} }
/// Fee-related. /// Fee-related.
+2 -2
View File
@@ -17,7 +17,7 @@
//! A module for manually curated GRANDPA set. //! A module for manually curated GRANDPA set.
use {grandpa, system}; use {grandpa, system};
use parity_codec::Decode; use codec::Decode;
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Zero}; use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Zero};
use sr_primitives::weights::SimpleDispatchInfo; use sr_primitives::weights::SimpleDispatchInfo;
use rstd::prelude::*; use rstd::prelude::*;
@@ -79,7 +79,7 @@ decl_module! {
let offset = (i * 4 % 32) as usize; let offset = (i * 4 % 32) as usize;
// number of roles remaining to select from. // number of roles remaining to select from.
let remaining = (voter_count - i) as usize; let remaining = rstd::cmp::max(1, (voter_count - i) as usize);
// 8 32-bit ints per 256-bit seed. // 8 32-bit ints per 256-bit seed.
let voter_index = u32::decode(&mut &seed[offset..offset + 4]).expect("using 4 bytes for a 32-bit quantity") as usize % remaining; let voter_index = u32::decode(&mut &seed[offset..offset + 4]).expect("using 4 bytes for a 32-bit quantity") as usize % remaining;
+109 -44
View File
@@ -30,8 +30,8 @@ mod slots;
use rstd::prelude::*; use rstd::prelude::*;
use substrate_primitives::u32_trait::{_1, _2, _3, _4}; use substrate_primitives::u32_trait::{_1, _2, _3, _4};
use primitives::{ use primitives::{
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, SessionKey, Signature, AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
parachain, AuraId parachain,
}; };
use client::{ use client::{
block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult}, block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult},
@@ -44,6 +44,7 @@ use sr_primitives::{
}; };
use version::RuntimeVersion; use version::RuntimeVersion;
use grandpa::{AuthorityId as GrandpaId, fg_primitives::{self, ScheduledChange}}; use grandpa::{AuthorityId as GrandpaId, fg_primitives::{self, ScheduledChange}};
use babe_primitives::AuthorityId as BabeId;
use elections::VoteIndex; use elections::VoteIndex;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
use version::NativeVersion; use version::NativeVersion;
@@ -51,6 +52,7 @@ use substrate_primitives::OpaqueMetadata;
use srml_support::{ use srml_support::{
parameter_types, construct_runtime, traits::{SplitTwoWays, Currency} parameter_types, construct_runtime, traits::{SplitTwoWays, Currency}
}; };
use im_online::AuthorityId as ImOnlineId;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use staking::StakerStatus; pub use staking::StakerStatus;
@@ -97,7 +99,7 @@ pub fn native_version() -> NativeVersion {
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance; type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
parameter_types! { parameter_types! {
pub const BlockHashCount: u64 = 250; pub const BlockHashCount: BlockNumber = 250;
pub const MaximumBlockWeight: Weight = 1_000_000_000; pub const MaximumBlockWeight: Weight = 1_000_000_000;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
@@ -105,6 +107,7 @@ parameter_types! {
impl system::Trait for Runtime { impl system::Trait for Runtime {
type Origin = Origin; type Origin = Origin;
type Call = Call;
type Index = Nonce; type Index = Nonce;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
type Hash = Hash; type Hash = Hash;
@@ -120,9 +123,14 @@ impl system::Trait for Runtime {
type AvailableBlockRatio = AvailableBlockRatio; type AvailableBlockRatio = AvailableBlockRatio;
} }
impl aura::Trait for Runtime { parameter_types! {
type HandleReport = aura::StakingSlasher<Runtime>; pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
type AuthorityId = AuraId; pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
}
impl babe::Trait for Runtime {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
} }
impl indices::Trait for Runtime { impl indices::Trait for Runtime {
@@ -144,8 +152,8 @@ parameter_types! {
pub type DealWithFees = SplitTwoWays< pub type DealWithFees = SplitTwoWays<
Balance, Balance,
NegativeImbalance, NegativeImbalance,
_4, Treasury, // 4 parts (80%) goes to the treasury. _4, Treasury, // 4 parts (80%) goes to the treasury.
_1, ToAuthor, // 1 part (20%) goes to the block author. _1, ToAuthor, // 1 part (20%) goes to the block author.
>; >;
impl balances::Trait for Runtime { impl balances::Trait for Runtime {
@@ -165,22 +173,22 @@ impl balances::Trait for Runtime {
} }
parameter_types! { parameter_types! {
pub const MinimumPeriod: u64 = SECS_PER_BLOCK / 2; pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
} }
impl timestamp::Trait for Runtime { impl timestamp::Trait for Runtime {
type Moment = u64; type Moment = u64;
type OnTimestampSet = Aura; type OnTimestampSet = Babe;
type MinimumPeriod = MinimumPeriod; type MinimumPeriod = MinimumPeriod;
} }
parameter_types! { parameter_types! {
pub const UncleGenerations: u64 = 0; pub const UncleGenerations: u32 = 0;
} }
// TODO: substrate#2986 implement this properly // TODO: substrate#2986 implement this properly
impl authorship::Trait for Runtime { impl authorship::Trait for Runtime {
type FindAuthor = (); type FindAuthor = session::FindAccountFromAuthorIndex<Self, Babe>;
type UncleGenerations = UncleGenerations; type UncleGenerations = UncleGenerations;
type FilterUncle = (); type FilterUncle = ();
type EventHandler = (); type EventHandler = ();
@@ -191,11 +199,17 @@ parameter_types! {
pub const Offset: BlockNumber = 0; pub const Offset: BlockNumber = 0;
} }
type SessionHandlers = (Grandpa, Aura); type SessionHandlers = (Grandpa, Babe, ImOnline, Parachains);
impl_opaque_keys! { impl_opaque_keys! {
pub struct SessionKeys { pub struct SessionKeys {
#[id(key_types::ED25519)] #[id(key_types::GRANDPA)]
pub ed25519: GrandpaId, pub grandpa: GrandpaId,
#[id(key_types::BABE)]
pub babe: BabeId,
#[id(key_types::IM_ONLINE)]
pub im_online: ImOnlineId,
#[id(parachain::PARACHAIN_KEY_TYPE_ID)]
pub parachain_validator: parachain::ValidatorId,
} }
} }
@@ -208,7 +222,7 @@ impl_opaque_keys! {
impl session::Trait for Runtime { impl session::Trait for Runtime {
type OnSessionEnding = Staking; type OnSessionEnding = Staking;
type SessionHandler = SessionHandlers; type SessionHandler = SessionHandlers;
type ShouldEndSession = session::PeriodicSessions<Period, Offset>; type ShouldEndSession = Babe;
type Event = Event; type Event = Event;
type Keys = SessionKeys; type Keys = SessionKeys;
type SelectInitialValidators = Staking; type SelectInitialValidators = Staking;
@@ -243,11 +257,9 @@ parameter_types! {
pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES;
pub const MinimumDeposit: Balance = 100 * BUCKS; pub const MinimumDeposit: Balance = 100 * DOLLARS;
pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
pub const CooloffPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
pub const AttestationPeriod: BlockNumber = 60 * MINUTES * 3;
} }
impl democracy::Trait for Runtime { impl democracy::Trait for Runtime {
@@ -259,26 +271,35 @@ impl democracy::Trait for Runtime {
type VotingPeriod = VotingPeriod; type VotingPeriod = VotingPeriod;
type EmergencyVotingPeriod = EmergencyVotingPeriod; type EmergencyVotingPeriod = EmergencyVotingPeriod;
type MinimumDeposit = MinimumDeposit; type MinimumDeposit = MinimumDeposit;
type ExternalOrigin = collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilInstance>; /// A straight majority of the council can decide what their next motion is.
type ExternalMajorityOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilInstance>; type ExternalOrigin = collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>;
type ExternalPushOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalInstance>; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote.
type EmergencyOrigin = collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilInstance>; type ExternalMajorityOrigin = collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>;
type CancellationOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilInstance>; /// A unanimous council can have the next scheduled referendum be a straight default-carries
type VetoOrigin = collective::EnsureMember<AccountId, CouncilInstance>; /// (NTB) vote.
type ExternalDefaultOrigin = collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>;
/// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
/// be tabled immediately and with a shorter voting/enactment period.
type FastTrackOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>;
// To cancel a proposal which has been passed, 2/3 of the council must agree to it.
type CancellationOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>;
// Any single technical committee member may veto a coming council proposal, however they can
// only do it once and it lasts only for the cooloff period.
type VetoOrigin = collective::EnsureMember<AccountId, TechnicalCollective>;
type CooloffPeriod = CooloffPeriod; type CooloffPeriod = CooloffPeriod;
} }
type CouncilInstance = collective::Instance1; type CouncilCollective = collective::Instance1;
impl collective::Trait<CouncilInstance> for Runtime { impl collective::Trait<CouncilCollective> for Runtime {
type Origin = Origin; type Origin = Origin;
type Proposal = Call; type Proposal = Call;
type Event = Event; type Event = Event;
} }
parameter_types! { parameter_types! {
pub const CandidacyBond: Balance = 10 * BUCKS; pub const CandidacyBond: Balance = 10 * DOLLARS;
pub const VotingBond: Balance = 1 * BUCKS; pub const VotingBond: Balance = 1 * DOLLARS;
pub const VotingFee: Balance = 2 * BUCKS; pub const VotingFee: Balance = 2 * DOLLARS;
pub const PresentSlashPerVoter: Balance = 1 * CENTS; pub const PresentSlashPerVoter: Balance = 1 * CENTS;
pub const CarryCount: u32 = 6; pub const CarryCount: u32 = 6;
// one additional vote should go by before an inactive voter can be reaped. // one additional vote should go by before an inactive voter can be reaped.
@@ -305,24 +326,34 @@ impl elections::Trait for Runtime {
type DecayRatio = DecayRatio; type DecayRatio = DecayRatio;
} }
type TechnicalInstance = collective::Instance2; type TechnicalCollective = collective::Instance2;
impl collective::Trait<TechnicalInstance> for Runtime { impl collective::Trait<TechnicalCollective> for Runtime {
type Origin = Origin; type Origin = Origin;
type Proposal = Call; type Proposal = Call;
type Event = Event; type Event = Event;
} }
impl membership::Trait<membership::Instance1> for Runtime {
type Event = Event;
type AddOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type RemoveOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type SwapOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type ResetOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type MembershipInitialized = TechnicalCommittee;
type MembershipChanged = TechnicalCommittee;
}
parameter_types! { parameter_types! {
pub const ProposalBond: Permill = Permill::from_percent(5); pub const ProposalBond: Permill = Permill::from_percent(5);
pub const ProposalBondMinimum: Balance = 1 * BUCKS; pub const ProposalBondMinimum: Balance = 1 * DOLLARS;
pub const SpendPeriod: BlockNumber = 1 * DAYS; pub const SpendPeriod: BlockNumber = 1 * DAYS;
pub const Burn: Permill = Permill::from_percent(50); pub const Burn: Permill = Permill::from_percent(50);
} }
impl treasury::Trait for Runtime { impl treasury::Trait for Runtime {
type Currency = Balances; type Currency = Balances;
type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilInstance>; type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilCollective>;
type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilInstance>; type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilCollective>;
type Event = Event; type Event = Event;
type MintedForSpending = (); type MintedForSpending = ();
type ProposalRejection = (); type ProposalRejection = ();
@@ -332,6 +363,12 @@ impl treasury::Trait for Runtime {
type Burn = Burn; type Burn = Burn;
} }
impl im_online::Trait for Runtime {
type Call = Call;
type Event = Event;
type UncheckedExtrinsic = UncheckedExtrinsic;
}
impl grandpa::Trait for Runtime { impl grandpa::Trait for Runtime {
type Event = Event; type Event = Event;
} }
@@ -347,6 +384,10 @@ impl finality_tracker::Trait for Runtime {
type ReportLatency = ReportLatency; type ReportLatency = ReportLatency;
} }
parameter_types! {
pub const AttestationPeriod: BlockNumber = 50;
}
impl attestations::Trait for Runtime { impl attestations::Trait for Runtime {
type AttestationPeriod = AttestationPeriod; type AttestationPeriod = AttestationPeriod;
type ValidatorIdentities = parachains::ValidatorIdentities<Runtime>; type ValidatorIdentities = parachains::ValidatorIdentities<Runtime>;
@@ -395,8 +436,8 @@ construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic UncheckedExtrinsic = UncheckedExtrinsic
{ {
System: system::{Module, Call, Storage, Config, Event}, System: system::{Module, Call, Storage, Config, Event},
Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
Timestamp: timestamp::{Module, Call, Storage, Inherent}, Timestamp: timestamp::{Module, Call, Storage, Inherent},
Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
Authorship: authorship::{Module, Call, Storage}, Authorship: authorship::{Module, Call, Storage},
Indices: indices, Indices: indices,
Balances: balances, Balances: balances,
@@ -406,6 +447,7 @@ construct_runtime!(
Council: collective::<Instance1>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>}, Council: collective::<Instance1>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>},
TechnicalCommittee: collective::<Instance2>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>}, TechnicalCommittee: collective::<Instance2>::{Module, Call, Storage, Origin<T>, Event<T>, Config<T>},
Elections: elections::{Module, Call, Storage, Event<T>, Config<T>}, Elections: elections::{Module, Call, Storage, Event<T>, Config<T>},
TechnicalMembership: membership::<Instance1>::{Module, Call, Storage, Event<T>, Config<T>},
FinalityTracker: finality_tracker::{Module, Call, Inherent}, FinalityTracker: finality_tracker::{Module, Call, Inherent},
Grandpa: grandpa::{Module, Call, Storage, Config, Event}, Grandpa: grandpa::{Module, Call, Storage, Config, Event},
CuratedGrandpa: curated_grandpa::{Module, Call, Config<T>, Storage}, CuratedGrandpa: curated_grandpa::{Module, Call, Config<T>, Storage},
@@ -415,6 +457,7 @@ construct_runtime!(
Slots: slots::{Module, Call, Storage, Event<T>}, Slots: slots::{Module, Call, Storage, Event<T>},
Claims: claims::{Module, Call, Storage, Event<T>, Config<T>, ValidateUnsigned}, Claims: claims::{Module, Call, Storage, Event<T>, Config<T>, ValidateUnsigned},
Sudo: sudo, Sudo: sudo,
ImOnline: im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config<T>},
} }
); );
@@ -430,6 +473,7 @@ pub type SignedBlock = generic::SignedBlock<Block>;
pub type BlockId = generic::BlockId<Block>; pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic. /// The SignedExtension to the basic transaction logic.
pub type SignedExtra = ( pub type SignedExtra = (
system::CheckGenesis<Runtime>,
system::CheckEra<Runtime>, system::CheckEra<Runtime>,
system::CheckNonce<Runtime>, system::CheckNonce<Runtime>,
system::CheckWeight<Runtime>, system::CheckWeight<Runtime>,
@@ -499,7 +543,7 @@ impl_runtime_apis! {
impl parachain::ParachainHost<Block> for Runtime { impl parachain::ParachainHost<Block> for Runtime {
fn validators() -> Vec<parachain::ValidatorId> { fn validators() -> Vec<parachain::ValidatorId> {
Aura::authorities() // only possible as long as parachain validator crypto === aura crypto Parachains::authorities()
} }
fn duty_roster() -> parachain::DutyRoster { fn duty_roster() -> parachain::DutyRoster {
Parachains::calculate_duty_roster().0 Parachains::calculate_duty_roster().0
@@ -531,19 +575,40 @@ impl_runtime_apis! {
None // disable forced changes. None // disable forced changes.
} }
fn grandpa_authorities() -> Vec<(SessionKey, u64)> { fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
Grandpa::grandpa_authorities() Grandpa::grandpa_authorities()
} }
} }
impl consensus_aura::AuraApi<Block, AuraId> for Runtime { impl babe_primitives::BabeApi<Block> for Runtime {
fn slot_duration() -> u64 { fn startup_data() -> babe_primitives::BabeConfiguration {
Aura::slot_duration() // The choice of `c` parameter (where `1 - c` represents the
// probability of a slot being empty), is done in accordance to the
// slot duration and expected target block time, for safely
// resisting network delays of maximum two seconds.
// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
babe_primitives::BabeConfiguration {
median_required_blocks: 1000,
slot_duration: Babe::slot_duration(),
c: (278, 1000),
}
} }
fn authorities() -> Vec<AuraId> { fn epoch() -> babe_primitives::Epoch {
Aura::authorities() babe_primitives::Epoch {
start_slot: Babe::epoch_start_slot(),
authorities: Babe::authorities(),
epoch_index: Babe::epoch_index(),
randomness: Babe::randomness(),
duration: EpochDuration::get(),
}
} }
} }
impl substrate_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string"));
SessionKeys::generate(seed)
}
}
} }
+80 -60
View File
@@ -18,14 +18,14 @@
use rstd::prelude::*; use rstd::prelude::*;
use rstd::collections::btree_map::BTreeMap; use rstd::collections::btree_map::BTreeMap;
use parity_codec::{Encode, Decode, HasCompact}; use codec::{Encode, Decode, HasCompact};
use srml_support::{decl_storage, decl_module, fail, ensure}; use srml_support::{decl_storage, decl_module, fail, ensure};
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Member, CheckedConversion, Saturating, One}; use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Member, CheckedConversion, Saturating, One};
use sr_primitives::weights::SimpleDispatchInfo; use sr_primitives::weights::SimpleDispatchInfo;
use primitives::{Hash, Balance, ParachainPublic, parachain::{ use primitives::{Hash, Balance, parachain::{
self, Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement, AccountIdConversion, self, Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement, AccountIdConversion,
ParachainDispatchOrigin, UpwardMessage, BlockIngressRoots, ParachainDispatchOrigin, UpwardMessage, BlockIngressRoots, ValidatorId
}}; }};
use {system, session}; use {system, session};
use srml_support::{ use srml_support::{
@@ -33,9 +33,6 @@ use srml_support::{
traits::{Currency, Get, WithdrawReason, ExistenceRequirement} traits::{Currency, Get, WithdrawReason, ExistenceRequirement}
}; };
#[cfg(feature = "std")]
use srml_support::storage::hashed::generator;
use inherents::{ProvideInherent, InherentData, RuntimeString, MakeFatalError, InherentIdentifier}; use inherents::{ProvideInherent, InherentData, RuntimeString, MakeFatalError, InherentIdentifier};
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
@@ -217,7 +214,7 @@ const WATERMARK_QUEUE_SIZE: usize = 20000;
decl_storage! { decl_storage! {
trait Store for Module<T: Trait> as Parachains { trait Store for Module<T: Trait> as Parachains {
/// All authorities' keys at the moment. /// All authorities' keys at the moment.
pub Authorities get(authorities) config(authorities): Vec<ParachainPublic>; pub Authorities get(authorities) config(authorities): Vec<ValidatorId>;
/// Vector of all parachain IDs. /// Vector of all parachain IDs.
pub Parachains get(active_parachains): Vec<ParaId>; pub Parachains get(active_parachains): Vec<ParaId>;
/// The parachains registered at present. /// The parachains registered at present.
@@ -252,27 +249,33 @@ decl_storage! {
add_extra_genesis { add_extra_genesis {
config(parachains): Vec<(ParaId, Vec<u8>, Vec<u8>)>; config(parachains): Vec<(ParaId, Vec<u8>, Vec<u8>)>;
config(_phdata): PhantomData<T>; config(_phdata): PhantomData<T>;
build(|storage: &mut StorageOverlay, _: &mut ChildrenStorageOverlay, config: &GenesisConfig<T>| { build(build::<T>);
use sr_primitives::traits::Zero;
let mut p = config.parachains.clone();
p.sort_unstable_by_key(|&(ref id, _, _)| *id);
p.dedup_by_key(|&mut (ref id, _, _)| *id);
let only_ids: Vec<_> = p.iter().map(|&(ref id, _, _)| id).cloned().collect();
<Parachains as generator::StorageValue<_>>::put(&only_ids, storage);
for (id, code, genesis) in p {
// no ingress -- a chain cannot be routed to until it is live.
<Code as generator::StorageMap<_, _>>::insert(&id, &code, storage);
<Heads as generator::StorageMap<_, _>>::insert(&id, &genesis, storage);
<Watermarks<T> as generator::StorageMap<_, _>>::insert(&id, &Zero::zero(), storage);
}
});
} }
} }
#[cfg(feature = "std")]
fn build<T: Trait>(
storage: &mut (StorageOverlay, ChildrenStorageOverlay),
config: &GenesisConfig<T>
) {
let mut p = config.parachains.clone();
p.sort_unstable_by_key(|&(ref id, _, _)| *id);
p.dedup_by_key(|&mut (ref id, _, _)| *id);
let only_ids: Vec<ParaId> = p.iter().map(|&(ref id, _, _)| id).cloned().collect();
sr_io::with_storage(storage, || {
Parachains::put(&only_ids);
for (id, code, genesis) in p {
// no ingress -- a chain cannot be routed to until it is live.
Code::insert(&id, &code);
Heads::insert(&id, &genesis);
<Watermarks<T>>::insert(&id, &sr_primitives::traits::Zero::zero());
}
});
}
decl_module! { decl_module! {
/// Parachains module. /// Parachains module.
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin { pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
@@ -380,7 +383,7 @@ impl<T: Trait> Module<T> {
origin: ParachainDispatchOrigin, origin: ParachainDispatchOrigin,
data: &[u8], data: &[u8],
) { ) {
if let Some(message_call) = T::Call::decode(&mut &data[..]) { if let Ok(message_call) = <T as Trait>::Call::decode(&mut &data[..]) {
let origin: <T as Trait>::Origin = match origin { let origin: <T as Trait>::Origin = match origin {
ParachainDispatchOrigin::Signed => ParachainDispatchOrigin::Signed =>
system::RawOrigin::Signed(id.into_account()).into(), system::RawOrigin::Signed(id.into_account()).into(),
@@ -528,6 +531,7 @@ impl<T: Trait> Module<T> {
pub fn calculate_duty_roster() -> (DutyRoster, [u8; 32]) { pub fn calculate_duty_roster() -> (DutyRoster, [u8; 32]) {
let parachains = Self::active_parachains(); let parachains = Self::active_parachains();
let parachain_count = parachains.len(); let parachain_count = parachains.len();
// TODO: use decode length. substrate #2794
let validator_count = Self::authorities().len(); let validator_count = Self::authorities().len();
let validators_per_parachain = if parachain_count != 0 { (validator_count - 1) / parachain_count } else { 0 }; let validators_per_parachain = if parachain_count != 0 { (validator_count - 1) / parachain_count } else { 0 };
@@ -561,12 +565,12 @@ impl<T: Trait> Module<T> {
let orig_seed = seed.clone().to_fixed_bytes(); let orig_seed = seed.clone().to_fixed_bytes();
// shuffle // shuffle
for i in 0..(validator_count - 1) { for i in 0..(validator_count.saturating_sub(1)) {
// 4 bytes of entropy used per cycle, 32 bytes entropy per hash // 4 bytes of entropy used per cycle, 32 bytes entropy per hash
let offset = (i * 4 % 32) as usize; let offset = (i * 4 % 32) as usize;
// number of roles remaining to select from. // number of roles remaining to select from.
let remaining = (validator_count - i) as usize; let remaining = rstd::cmp::max(1, (validator_count - i) as usize);
// 8 32-bit ints per 256-bit seed. // 8 32-bit ints per 256-bit seed.
let val_index = u32::decode(&mut &seed[offset..offset + 4]) let val_index = u32::decode(&mut &seed[offset..offset + 4])
@@ -656,7 +660,7 @@ impl<T: Trait> Module<T> {
-> rstd::result::Result<IncludedBlocks<T>, &'static str> -> rstd::result::Result<IncludedBlocks<T>, &'static str>
{ {
use primitives::parachain::ValidityAttestation; use primitives::parachain::ValidityAttestation;
use sr_primitives::traits::Verify; use sr_primitives::traits::AppVerify;
// returns groups of slices that have the same chain ID. // returns groups of slices that have the same chain ID.
// assumes the inner slice is sorted by id. // assumes the inner slice is sorted by id.
@@ -801,7 +805,7 @@ impl<T: Trait> Module<T> {
para_block_hashes.push(candidate_hash.unwrap_or_else(|| candidate.candidate().hash())); para_block_hashes.push(candidate_hash.unwrap_or_else(|| candidate.candidate().hash()));
ensure!( ensure!(
candidate.validity_votes.len() == expected_votes_len, candidate.validity_votes.len() == expected_votes_len,
"Extra untagged validity votes along with candidate" "Extra untagged validity votes along with candidate"
); );
@@ -834,7 +838,7 @@ impl<T: Trait> Module<T> {
} }
impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> { impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
type Key = ParachainPublic; type Key = ValidatorId;
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued: I) fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued: I)
where I: Iterator<Item=(&'a T::AccountId, Self::Key)> where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
@@ -881,10 +885,11 @@ mod tests {
testing::{UintAuthorityId, Header}, testing::{UintAuthorityId, Header},
}; };
use primitives::{ use primitives::{
parachain::{CandidateReceipt, HeadData, ValidityAttestation}, SessionKey, parachain::{CandidateReceipt, HeadData, ValidityAttestation, ValidatorId},
BlockNumber, AuraId, BlockNumber,
}; };
use keyring::Ed25519Keyring; use crate::constants::time::*;
use keyring::Sr25519Keyring;
use srml_support::{ use srml_support::{
impl_outer_origin, impl_outer_dispatch, assert_ok, assert_err, parameter_types, impl_outer_origin, impl_outer_dispatch, assert_ok, assert_err, parameter_types,
}; };
@@ -905,13 +910,14 @@ mod tests {
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct Test; pub struct Test;
parameter_types! { parameter_types! {
pub const BlockHashCount: u64 = 250; pub const BlockHashCount: u32 = 250;
pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024;
pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
} }
impl system::Trait for Test { impl system::Trait for Test {
type Origin = Origin; type Origin = Origin;
type Call = Call;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
@@ -957,9 +963,14 @@ mod tests {
type MinimumPeriod = MinimumPeriod; type MinimumPeriod = MinimumPeriod;
} }
impl aura::Trait for Test { parameter_types! {
type HandleReport = aura::StakingSlasher<Test>; pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
type AuthorityId = AuraId; pub const ExpectedBlockTime: u64 = MILLISECS_PER_BLOCK;
}
impl babe::Trait for Test {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
} }
parameter_types! { parameter_types! {
@@ -989,7 +1000,7 @@ mod tests {
parameter_types! { parameter_types! {
pub const SessionsPerEra: session::SessionIndex = 6; pub const SessionsPerEra: session::SessionIndex = 6;
pub const BondingDuration: staking::EraIndex = 24 * 28; pub const BondingDuration: staking::EraIndex = 24 * 28;
pub const AttestationPeriod: u64 = 100; pub const AttestationPeriod: BlockNumber = 100;
} }
impl staking::Trait for Test { impl staking::Trait for Test {
@@ -1021,17 +1032,19 @@ mod tests {
fn new_test_ext(parachains: Vec<(ParaId, Vec<u8>, Vec<u8>)>) -> TestExternalities<Blake2Hasher> { fn new_test_ext(parachains: Vec<(ParaId, Vec<u8>, Vec<u8>)>) -> TestExternalities<Blake2Hasher> {
use staking::StakerStatus; use staking::StakerStatus;
use babe::AuthorityId as BabeAuthorityId;
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap();
let (mut t, mut c) = system::GenesisConfig::default().build_storage::<Test>().unwrap();
let authority_keys = [ let authority_keys = [
Ed25519Keyring::Alice, Sr25519Keyring::Alice,
Ed25519Keyring::Bob, Sr25519Keyring::Bob,
Ed25519Keyring::Charlie, Sr25519Keyring::Charlie,
Ed25519Keyring::Dave, Sr25519Keyring::Dave,
Ed25519Keyring::Eve, Sr25519Keyring::Eve,
Ed25519Keyring::Ferdie, Sr25519Keyring::Ferdie,
Ed25519Keyring::One, Sr25519Keyring::One,
Ed25519Keyring::Two, Sr25519Keyring::Two,
]; ];
// stashes are the index. // stashes are the index.
@@ -1039,7 +1052,11 @@ mod tests {
.map(|(i, _k)| (i as u64, UintAuthorityId(i as u64))) .map(|(i, _k)| (i as u64, UintAuthorityId(i as u64)))
.collect(); .collect();
let authorities: Vec<_> = authority_keys.iter().map(|k| SessionKey::from(*k)).collect(); let authorities: Vec<_> = authority_keys.iter().map(|k| ValidatorId::from(k.public())).collect();
let babe_authorities: Vec<_> = authority_keys.iter()
.map(|k| BabeAuthorityId::from(k.public()))
.map(|k| (k, 1))
.collect();
// controllers are the index + 1000 // controllers are the index + 1000
let stakers: Vec<_> = (0..authority_keys.len()).map(|i| ( let stakers: Vec<_> = (0..authority_keys.len()).map(|i| (
@@ -1051,23 +1068,24 @@ mod tests {
let balances: Vec<_> = (0..authority_keys.len()).map(|i| (i as u64, 10_000_000)).collect(); let balances: Vec<_> = (0..authority_keys.len()).map(|i| (i as u64, 10_000_000)).collect();
session::GenesisConfig::<Test> {
keys: session_keys,
}.assimilate_storage(&mut t, &mut c).unwrap();
GenesisConfig::<Test> { GenesisConfig::<Test> {
parachains, parachains,
authorities: authorities.clone(), authorities: authorities.clone(),
_phdata: Default::default(), _phdata: Default::default(),
}.assimilate_storage(&mut t, &mut c).unwrap(); }.assimilate_storage(&mut t).unwrap();
aura::GenesisConfig::<Test> { session::GenesisConfig::<Test> {
authorities, keys: session_keys,
}.assimilate_storage(&mut t, &mut c).unwrap(); }.assimilate_storage(&mut t).unwrap();
babe::GenesisConfig {
authorities: babe_authorities,
}.assimilate_storage(&mut t).unwrap();
balances::GenesisConfig::<Test> { balances::GenesisConfig::<Test> {
balances, balances,
vesting: vec![], vesting: vec![],
}.assimilate_storage(&mut t, &mut c).unwrap(); }.assimilate_storage(&mut t).unwrap();
staking::GenesisConfig::<Test> { staking::GenesisConfig::<Test> {
current_era: 0, current_era: 0,
@@ -1077,7 +1095,7 @@ mod tests {
offline_slash: Perbill::from_percent(5), offline_slash: Perbill::from_percent(5),
offline_slash_grace: 0, offline_slash_grace: 0,
invulnerables: vec![], invulnerables: vec![],
}.assimilate_storage(&mut t, &mut c).unwrap(); }.assimilate_storage(&mut t).unwrap();
t.into() t.into()
} }
@@ -1094,8 +1112,10 @@ mod tests {
let candidate_hash = candidate.candidate.hash(); let candidate_hash = candidate.candidate.hash();
let authorities = Parachains::authorities(); let authorities = Parachains::authorities();
let extract_key = |public: SessionKey| { let extract_key = |public: ValidatorId| {
Ed25519Keyring::from_raw_public(public.0).unwrap() let mut raw_public = [0; 32];
raw_public.copy_from_slice(public.as_ref());
Sr25519Keyring::from_raw_public(raw_public).unwrap()
}; };
let validation_entries = duty_roster.validator_duty.iter() let validation_entries = duty_roster.validator_duty.iter()
+1 -1
View File
@@ -19,7 +19,7 @@
use rstd::{result, ops::Add, convert::{TryFrom, TryInto}}; use rstd::{result, ops::Add, convert::{TryFrom, TryInto}};
use sr_primitives::traits::CheckedSub; use sr_primitives::traits::CheckedSub;
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
/// Total number of possible sub ranges of slots. /// Total number of possible sub ranges of slots.
pub const SLOT_RANGE_COUNT: usize = 10; pub const SLOT_RANGE_COUNT: usize = 10;
+6 -5
View File
@@ -21,7 +21,7 @@
use rstd::{prelude::*, mem::swap, convert::TryInto}; use rstd::{prelude::*, mem::swap, convert::TryInto};
use sr_primitives::traits::{CheckedSub, StaticLookup, Zero, One, CheckedConversion, Hash}; use sr_primitives::traits::{CheckedSub, StaticLookup, Zero, One, CheckedConversion, Hash};
use sr_primitives::weights::SimpleDispatchInfo; use sr_primitives::weights::SimpleDispatchInfo;
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
use srml_support::{ use srml_support::{
decl_module, decl_storage, decl_event, StorageValue, StorageMap, ensure, decl_module, decl_storage, decl_event, StorageValue, StorageMap, ensure,
traits::{Currency, ReservableCurrency, WithdrawReason, ExistenceRequirement, Get} traits::{Currency, ReservableCurrency, WithdrawReason, ExistenceRequirement, Get}
@@ -813,13 +813,14 @@ mod tests {
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct Test; pub struct Test;
parameter_types! { parameter_types! {
pub const BlockHashCount: u64 = 250; pub const BlockHashCount: u32 = 250;
pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024;
pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
} }
impl system::Trait for Test { impl system::Trait for Test {
type Origin = Origin; type Origin = Origin;
type Call = ();
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
@@ -926,11 +927,11 @@ mod tests {
// This function basically just builds a genesis storage key/value store according to // This function basically just builds a genesis storage key/value store according to
// our desired mock up. // our desired mock up.
fn new_test_ext() -> sr_io::TestExternalities<Blake2Hasher> { fn new_test_ext() -> sr_io::TestExternalities<Blake2Hasher> {
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0; let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap();
t.extend(balances::GenesisConfig::<Test>{ balances::GenesisConfig::<Test>{
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
vesting: vec![], vesting: vec![],
}.build_storage().unwrap().0); }.assimilate_storage(&mut t).unwrap();
t.into() t.into()
} }
+6 -1
View File
@@ -8,6 +8,8 @@ edition = "2018"
parking_lot = "0.9.0" parking_lot = "0.9.0"
lazy_static = "1.0" lazy_static = "1.0"
log = "0.4.6" log = "0.4.6"
futures = "0.1"
exit-future = "0.1"
slog = "^2" slog = "^2"
hex-literal = "0.2" hex-literal = "0.2"
av_store = { package = "polkadot-availability-store", path = "../availability-store" } av_store = { package = "polkadot-availability-store", path = "../availability-store" }
@@ -20,7 +22,6 @@ sr-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-ma
sr-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } sr-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
aura = { package = "substrate-consensus-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
consensus_common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } consensus_common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
grandpa = { package = "substrate-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } grandpa = { package = "substrate-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
grandpa_primitives = { package = "substrate-finality-grandpa-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } grandpa_primitives = { package = "substrate-finality-grandpa-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
@@ -29,3 +30,7 @@ service = { package = "substrate-service", git = "https://github.com/paritytech/
telemetry = { package = "substrate-telemetry", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } telemetry = { package = "substrate-telemetry", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
transaction_pool = { package = "substrate-transaction-pool", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } transaction_pool = { package = "substrate-transaction-pool", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
substrate-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
srml_babe = { package = "srml-babe", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
im-online = { package = "srml-im-online", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
babe = { package = "substrate-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
babe-primitives = { package = "substrate-consensus-babe-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
+115 -66
View File
@@ -16,17 +16,20 @@
//! Polkadot chain configurations. //! Polkadot chain configurations.
use primitives::{ed25519, sr25519, Pair, crypto::UncheckedInto}; use primitives::{Pair, Public, crypto::UncheckedInto};
use polkadot_primitives::{AccountId, SessionKey}; use polkadot_primitives::{AccountId, parachain::ValidatorId};
use polkadot_runtime::{ use polkadot_runtime::{
GenesisConfig, CouncilConfig, ElectionsConfig, DemocracyConfig, SystemConfig, AuraConfig, GenesisConfig, CouncilConfig, ElectionsConfig, DemocracyConfig, SystemConfig, BabeConfig,
SessionConfig, StakingConfig, BalancesConfig, Perbill, SessionKeys, TechnicalCommitteeConfig, SessionConfig, StakingConfig, BalancesConfig, Perbill, SessionKeys, TechnicalCommitteeConfig,
GrandpaConfig, SudoConfig, IndicesConfig, CuratedGrandpaConfig, StakerStatus, WASM_BINARY, GrandpaConfig, SudoConfig, IndicesConfig, CuratedGrandpaConfig, StakerStatus, WASM_BINARY,
ClaimsConfig, ClaimsConfig, ImOnlineConfig, ParachainsConfig
}; };
use polkadot_runtime::constants::{currency::DOTS, time::*}; use polkadot_runtime::constants::{currency::DOTS, time::*};
use telemetry::TelemetryEndpoints; use telemetry::TelemetryEndpoints;
use hex_literal::hex; use hex_literal::hex;
use babe_primitives::AuthorityId as BabeId;
use grandpa::AuthorityId as GrandpaId;
use im_online::AuthorityId as ImOnlineId;
const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
const DEFAULT_PROTOCOL_ID: &str = "dot"; const DEFAULT_PROTOCOL_ID: &str = "dot";
@@ -34,34 +37,58 @@ const DEFAULT_PROTOCOL_ID: &str = "dot";
/// Specialised `ChainSpec`. /// Specialised `ChainSpec`.
pub type ChainSpec = ::service::ChainSpec<GenesisConfig>; pub type ChainSpec = ::service::ChainSpec<GenesisConfig>;
pub fn poc_3_testnet_config() -> Result<ChainSpec, String> { pub fn kusama_config() -> Result<ChainSpec, String> {
ChainSpec::from_embedded(include_bytes!("../res/alexander.json")) ChainSpec::from_json_bytes(&include_bytes!("../res/kusama.json")[..])
}
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
im_online: ImOnlineId,
parachain_validator: ValidatorId
) -> SessionKeys {
SessionKeys { babe, grandpa, im_online, parachain_validator }
} }
fn staging_testnet_config_genesis() -> GenesisConfig { fn staging_testnet_config_genesis() -> GenesisConfig {
// subkey inspect "$SECRET" // subkey inspect "$SECRET"
let endowed_accounts = vec![ let endowed_accounts = vec![
hex!["42d69e4222c08885a4d6ff65f01852ba4a1599b683ad66286e4603d825e26b49"].unchecked_into(), // 5DaLmkrGTFvSTHBpShqqqRYaydw1sT4u3NCogYiE8Q1LqUUp hex!["12b782529c22032ed4694e0f6e7d486be7daa6d12088f6bc74d593b3900b8438"].unchecked_into(), // 5CVFESwfkk7NmhQ6FwHCM9roBvr9BGa4vJHFYU8DnGQxrXvz
]; ];
// for i in 1 2 3 4; do for j in stash controller; do subkey inspect "$SECRET//$i//$j"; done; done // for i in 1 2 3 4; do for j in stash controller; do subkey inspect "$SECRET//$i//$j"; done; done
// for i in 1 2 3 4; do for j in session; do subkey -e inspect "$SECRET//$i//$j"; done; done // for i in 1 2 3 4; do for j in babe; do subkey --sr25519 inspect "$SECRET//$i//$j"; done; done
let initial_authorities: Vec<(AccountId, AccountId, SessionKey)> = vec![( // for i in 1 2 3 4; do for j in grandpa; do subkey --ed25519 inspect "$SECRET//$i//$j"; done; done
hex!["543cf15f6a0289e48eb4f30d451d1731c5fb0e1b2c5a4b99439c11808af3432d"].unchecked_into(), // 5Dy9yz2mjwDmTgjkDFxjPBpovKmKAgTndiRiTp4DfrTEdUvi // for i in 1 2 3 4; do for j in im_online; do subkey --sr25519 inspect "$SECRET//$i//$j"; done; done
hex!["8a6ea654337e4a28ce7be124f73ad84702619942722d01cc271e5b421653c56d"].unchecked_into(), // 5FCDLPUMZpZPRfouRfQDZp74typV9SjSxPgG6ymwe5Z3Sbko // for i in 1 2 3 4; do for j in parachains; do subkey --sr25519 inspect "$SECRET//$i//$j"; done; done
hex!["03644a181bc4e4197914aa109f3c97b6fe8c4787a82a1ddfab54e4ebedd8ab20"].unchecked_into(), // 5C99nwu8Ucq1yUJfajviwbqMAejpmaERHpmkPVWiFdxiF6yg let initial_authorities: Vec<(AccountId, AccountId, BabeId, GrandpaId, ImOnlineId, ValidatorId)> = vec![(
hex!["32a5718e87d16071756d4b1370c411bbbb947eb62f0e6e0b937d5cbfc0ea633b"].unchecked_into(), // 5DD7Q4VEfPTLEdn11CnThoHT5f9xKCrnofWJL5SsvpTghaAT
hex!["bee39fe862c85c91aaf343e130d30b643c6ea0b4406a980206f1df8331f7093b"].unchecked_into(), // 5GNzaEqhrZAtUQhbMe2gn9jBuNWfamWFZHULryFwBUXyd1cG
hex!["a639b507ee1585e0b6498ff141d6153960794523226866d1b44eba3f25f36356"].unchecked_into(), // 5FpewyS2VY8Cj3tKgSckq8ECkjd1HKHvBRnWhiHqRQsWfFC1
hex!["76620f7c98bce8619979c2b58cf2b0aff71824126d2b039358729dad993223db"].unchecked_into(), // 5EjvdwATjyFFikdZibVvx1q5uBHhphS2Mnsq5c7yfaYK25vm
hex!["a639b507ee1585e0b6498ff141d6153960794523226866d1b44eba3f25f36356"].unchecked_into(), // 5FpewyS2VY8Cj3tKgSckq8ECkjd1HKHvBRnWhiHqRQsWfFC1
hex!["a639b507ee1585e0b6498ff141d6153960794523226866d1b44eba3f25f36356"].unchecked_into(), // 5FpewyS2VY8Cj3tKgSckq8ECkjd1HKHvBRnWhiHqRQsWfFC1
),( ),(
hex!["c4957aa922910004f3b006d638b034070407dcb21e0905cb5cca9b58aec7fa3e"].unchecked_into(), // 5GWTeVF49JR9dAMVe4rRAAMXuhEjRAhSiYqQV4LbwpHTDLei hex!["b496c98a405ceab59b9e970e59ef61acd7765a19b704e02ab06c1cdfe171e40f"].unchecked_into(), // 5G9VGb8ESBeS8Ca4or43RfhShzk9y7T5iTmxHk5RJsjZwsRx
hex!["1adea46f5c3d272cd6426b338dd77d5bca3aff615338c82a0f02f4c62d89280f"].unchecked_into(), // 5CfwEv8TQKnszHNhYPuij6EtLZHCcaN3DgzfPCozcS9oxZzB hex!["86d3a7571dd60139d297e55d8238d0c977b2e208c5af088f7f0136b565b0c103"].unchecked_into(), // 5F7V9Y5FcxKXe1aroqvPeRiUmmeQwTFcL3u9rrPXcMuMiCNx
hex!["d739e1bb4c2b13ea1fff9be72e72d3bb1b364eb3b26176ab9a9512d386b7510b"].unchecked_into(), // 5GvuM53k1Z4nAB5zXJFgkRSHv4Bqo4BsvgbQWNWkiWZTMwWY hex!["765e46067adac4d1fe6c783aa2070dfa64a19f84376659e12705d1734b3eae01"].unchecked_into(), // 5GvuM53k1Z4nAB5zXJFgkRSHv4Bqo4BsvgbQWNWkiWZTMwWY
hex!["e2234d661bee4a04c38392c75d1566200aa9e6ae44dd98ee8765e4cc9af63cb7"].unchecked_into(), // 5HBDAaybNqjmY7ww8ZcZZY1L5LHxvpnyfqJwoB7HhR6raTmG
hex!["765e46067adac4d1fe6c783aa2070dfa64a19f84376659e12705d1734b3eae01"].unchecked_into(), // 5GvuM53k1Z4nAB5zXJFgkRSHv4Bqo4BsvgbQWNWkiWZTMwWY
hex!["765e46067adac4d1fe6c783aa2070dfa64a19f84376659e12705d1734b3eae01"].unchecked_into(), // 5GvuM53k1Z4nAB5zXJFgkRSHv4Bqo4BsvgbQWNWkiWZTMwWY
),( ),(
hex!["6c3d14686e97d393814a09bea4246b9f273dcdbdef6731dcab3430b36820f135"].unchecked_into(), // 5EWdAzp9aJseLKVNeWJwE2K8PD47qzMbKVysCXr67xnEohYL hex!["ae12f70078a22882bf5135d134468f77301927aa67c376e8c55b7ff127ace115"].unchecked_into(), // 5FzwpgGvk2kk9agow6KsywLYcPzjYc8suKej2bne5G5b9YU3
hex!["7a73b9fcb97cee5c2240d88ca9baea06758fac450efe6f90a72014c939d41857"].unchecked_into(), // 5EqG5RSujgrtSBB5DQvR1Z2EMxAe92sAdWNTNHtX4nL2MkPi hex!["7addb914ec8486bbc60643d2647685dcc06373401fa80e09813b630c5831d54b"].unchecked_into(), // 5EqoZhVC2BcsM4WjvZNidu2muKAbu5THQTBKe3EjvxXkdP7A
hex!["145791f7187d91398d8b445598f62be39b766d6e33e9d57b69c4d23fca218d7f"].unchecked_into(), // 5CXNq1mSKJT4Sc2CbyBBdANeSkbUvdWvE4czJjKXfBHi9sX5 hex!["664eae1ca4713dd6abf8c15e6c041820cda3c60df97dc476c2cbf7cb82cb2d2e"].unchecked_into(), // 5CXNq1mSKJT4Sc2CbyBBdANeSkbUvdWvE4czJjKXfBHi9sX5
hex!["5b57ed1443c8967f461db1f6eb2ada24794d163a668f1cf9d9ce3235dfad8799"].unchecked_into(), // 5E8ULLQrDAtWhfnVfZmX41Yux86zNAwVJYguWJZVWrJvdhBe
hex!["664eae1ca4713dd6abf8c15e6c041820cda3c60df97dc476c2cbf7cb82cb2d2e"].unchecked_into(), // 5CXNq1mSKJT4Sc2CbyBBdANeSkbUvdWvE4czJjKXfBHi9sX5
hex!["664eae1ca4713dd6abf8c15e6c041820cda3c60df97dc476c2cbf7cb82cb2d2e"].unchecked_into(), // 5CXNq1mSKJT4Sc2CbyBBdANeSkbUvdWvE4czJjKXfBHi9sX5
),( ),(
hex!["be6726c17ad7b5844c9e0ab6a1698d00d88bf183f0f82d8ec9627531c9ddc934"].unchecked_into(), // 5GNMbce1P2FfjvcPcoUxzjj6bYSRdQ2RpsbCyF9ozwMxx3NS hex!["0867dbb49721126df589db100dda728dc3b475cbf414dad8f72a1d5e84897252"].unchecked_into(), // 5CFj6Kg9rmVn1vrqpyjau2ztyBzKeVdRKwNPiA3tqhB5HPqq
hex!["123b9048ba61265547ad3f336dfa48c16851ba1a96691e5d1ab3be1725db0614"].unchecked_into(), // 5CUcQvAgMzXMpQSz8mgzeiswDFHED88NiEK4byfS5TLaTJow hex!["26ab2b4b2eba2263b1e55ceb48f687bb0018130a88df0712fbdaf6a347d50e2a"].unchecked_into(), // 5CwQXP6nvWzigFqNhh2jvCaW9zWVzkdveCJY3tz2MhXMjTon
hex!["8abecfa66704176be23df099bf441ea65444992d63b3ced3e76a17a4d38b0b0e"].unchecked_into(), // 5FCd9Y7RLNyxz5wnCAErfsLbXGG34L2BaZRHzhiJcMUMd5zd hex!["2adb17a5cafbddc7c3e00ec45b6951a8b12ce2264235b4def342513a767e5d3d"].unchecked_into(), // 5FCd9Y7RLNyxz5wnCAErfsLbXGG34L2BaZRHzhiJcMUMd5zd
hex!["e60d23f49e93c1c1f2d7c115957df5bbd7faf5ebf138d1e9d02e8b39a1f63df0"].unchecked_into(), // 5HGLmrZsiTFTPp3QoS1W8w9NxByt8PVq79reqvdxNcQkByqK
hex!["2adb17a5cafbddc7c3e00ec45b6951a8b12ce2264235b4def342513a767e5d3d"].unchecked_into(), // 5FCd9Y7RLNyxz5wnCAErfsLbXGG34L2BaZRHzhiJcMUMd5zd
hex!["2adb17a5cafbddc7c3e00ec45b6951a8b12ce2264235b4def342513a767e5d3d"].unchecked_into(), // 5FCd9Y7RLNyxz5wnCAErfsLbXGG34L2BaZRHzhiJcMUMd5zd
)]; )];
const ENDOWMENT: u128 = 1_000_000 * DOTS; const ENDOWMENT: u128 = 1_000_000 * DOTS;
@@ -87,7 +114,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
session: Some(SessionConfig { session: Some(SessionConfig {
keys: initial_authorities.iter().map(|x| ( keys: initial_authorities.iter().map(|x| (
x.0.clone(), x.0.clone(),
SessionKeys { ed25519: x.2.clone() }, session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()),
)).collect::<Vec<_>>(), )).collect::<Vec<_>>(),
}), }),
staking: Some(StakingConfig { staking: Some(StakingConfig {
@@ -114,16 +141,25 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
term_duration: 28 * DAYS, term_duration: 28 * DAYS,
desired_seats: 0, desired_seats: 0,
}), }),
membership_Instance1: Some(Default::default()),
babe: Some(BabeConfig {
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
}),
grandpa: Some(GrandpaConfig {
authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(),
}),
im_online: Some(ImOnlineConfig {
gossip_at: 0,
keys: initial_authorities.iter().map(|x| x.4.clone()).collect(),
}),
parachains: Some(ParachainsConfig {
authorities: initial_authorities.iter().map(|x| x.5.clone()).collect(),
parachains: vec![],
_phdata: Default::default(),
}),
sudo: Some(SudoConfig { sudo: Some(SudoConfig {
key: endowed_accounts[0].clone(), key: endowed_accounts[0].clone(),
}), }),
grandpa: Some(GrandpaConfig {
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
}),
aura: Some(AuraConfig {
authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
}),
parachains: Some(Default::default()),
curated_grandpa: Some(CuratedGrandpaConfig { curated_grandpa: Some(CuratedGrandpaConfig {
shuffle_period: 1024, shuffle_period: 1024,
}), }),
@@ -148,49 +184,53 @@ pub fn staging_testnet_config() -> ChainSpec {
) )
} }
/// Helper function to generate AccountId from seed /// Helper function to generate a crypto pair from seed
pub fn get_account_id_from_seed(seed: &str) -> AccountId { pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
sr25519::Pair::from_string(&format!("//{}", seed), None) TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed") .expect("static values are valid; qed")
.public() .public()
} }
/// Helper function to generate SessionKey from seed
pub fn get_session_key_from_seed(seed: &str) -> SessionKey {
ed25519::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}
/// Helper function to generate stash, controller and session key from seed /// Helper function to generate stash, controller and session key from seed
pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, SessionKey) { pub fn get_authority_keys_from_seed(seed: &str) -> (
AccountId,
AccountId,
BabeId,
GrandpaId,
ImOnlineId,
ValidatorId
) {
( (
get_account_id_from_seed(&format!("{}//stash", seed)), get_from_seed::<AccountId>(&format!("{}//stash", seed)),
get_account_id_from_seed(seed), get_from_seed::<AccountId>(seed),
get_session_key_from_seed(seed), get_from_seed::<BabeId>(seed),
get_from_seed::<GrandpaId>(seed),
get_from_seed::<ImOnlineId>(seed),
get_from_seed::<ValidatorId>(seed),
) )
} }
/// Helper function to create GenesisConfig for testing /// Helper function to create GenesisConfig for testing
pub fn testnet_genesis( pub fn testnet_genesis(
initial_authorities: Vec<(AccountId, AccountId, SessionKey)>, initial_authorities: Vec<(AccountId, AccountId, BabeId, GrandpaId, ImOnlineId, ValidatorId)>,
root_key: AccountId, root_key: AccountId,
endowed_accounts: Option<Vec<AccountId>>, endowed_accounts: Option<Vec<AccountId>>,
) -> GenesisConfig { ) -> GenesisConfig {
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(|| { let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(|| {
vec![ vec![
get_account_id_from_seed("Alice"), get_from_seed::<AccountId>("Alice"),
get_account_id_from_seed("Bob"), get_from_seed::<AccountId>("Bob"),
get_account_id_from_seed("Charlie"), get_from_seed::<AccountId>("Charlie"),
get_account_id_from_seed("Dave"), get_from_seed::<AccountId>("Dave"),
get_account_id_from_seed("Eve"), get_from_seed::<AccountId>("Eve"),
get_account_id_from_seed("Ferdie"), get_from_seed::<AccountId>("Ferdie"),
get_account_id_from_seed("Alice//stash"), get_from_seed::<AccountId>("Alice//stash"),
get_account_id_from_seed("Bob//stash"), get_from_seed::<AccountId>("Bob//stash"),
get_account_id_from_seed("Charlie//stash"), get_from_seed::<AccountId>("Charlie//stash"),
get_account_id_from_seed("Dave//stash"), get_from_seed::<AccountId>("Dave//stash"),
get_account_id_from_seed("Eve//stash"), get_from_seed::<AccountId>("Eve//stash"),
get_account_id_from_seed("Ferdie//stash"), get_from_seed::<AccountId>("Ferdie//stash"),
] ]
}); });
@@ -214,7 +254,7 @@ pub fn testnet_genesis(
session: Some(SessionConfig { session: Some(SessionConfig {
keys: initial_authorities.iter().map(|x| ( keys: initial_authorities.iter().map(|x| (
x.0.clone(), x.0.clone(),
SessionKeys { ed25519: x.2.clone() }, session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()),
)).collect::<Vec<_>>(), )).collect::<Vec<_>>(),
}), }),
staking: Some(StakingConfig { staking: Some(StakingConfig {
@@ -240,22 +280,31 @@ pub fn testnet_genesis(
elections: Some(ElectionsConfig { elections: Some(ElectionsConfig {
members: endowed_accounts.iter() members: endowed_accounts.iter()
.filter(|&endowed| initial_authorities.iter() .filter(|&endowed| initial_authorities.iter()
.find(|&(_, controller, _)| controller == endowed) .find(|&(_, controller, _, _, _, _)| controller == endowed)
.is_none() .is_none()
).map(|a| (a.clone(), 1000000)).collect(), ).map(|a| (a.clone(), 1000000)).collect(),
presentation_duration: 10, presentation_duration: 10,
term_duration: 1000000, term_duration: 1000000,
desired_seats, desired_seats,
}), }),
parachains: Some(Default::default()), membership_Instance1: Some(Default::default()),
sudo: Some(SudoConfig { babe: Some(BabeConfig {
key: root_key,
}),
grandpa: Some(GrandpaConfig {
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
}), }),
aura: Some(AuraConfig { grandpa: Some(GrandpaConfig {
authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(),
}),
im_online: Some(ImOnlineConfig {
gossip_at: 0,
keys: initial_authorities.iter().map(|x| x.4.clone()).collect(),
}),
parachains: Some(ParachainsConfig {
authorities: initial_authorities.iter().map(|x| x.5.clone()).collect(),
parachains: vec![],
_phdata: Default::default(),
}),
sudo: Some(SudoConfig {
key: root_key,
}), }),
curated_grandpa: Some(CuratedGrandpaConfig { curated_grandpa: Some(CuratedGrandpaConfig {
shuffle_period: 1024, shuffle_period: 1024,
@@ -272,7 +321,7 @@ fn development_config_genesis() -> GenesisConfig {
vec![ vec![
get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Alice"),
], ],
get_account_id_from_seed("Alice"), get_from_seed::<AccountId>("Alice"),
None, None,
) )
} }
@@ -297,7 +346,7 @@ fn local_testnet_genesis() -> GenesisConfig {
get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"), get_authority_keys_from_seed("Bob"),
], ],
get_account_id_from_seed("Alice"), get_from_seed::<AccountId>("Alice"),
None, None,
) )
} }
+192 -121
View File
@@ -18,18 +18,21 @@
pub mod chain_spec; pub mod chain_spec;
use futures::prelude::*;
use client::LongestChain; use client::LongestChain;
use consensus_common::SelectChain; use consensus_common::SelectChain;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use grandpa_primitives::AuthorityPair as GrandpaPair; use polkadot_primitives::{parachain, Block, Hash, BlockId};
use polkadot_primitives::{parachain, Block, Hash, BlockId, AuraPair};
use polkadot_runtime::{GenesisConfig, RuntimeApi}; use polkadot_runtime::{GenesisConfig, RuntimeApi};
use polkadot_network::gossip::{self as network_gossip, Known}; use polkadot_network::gossip::{self as network_gossip, Known};
use primitives::{ed25519, Pair}; use service::{
use service::{FactoryFullConfiguration, FullBackend, LightBackend, FullExecutor, LightExecutor}; FactoryFullConfiguration, FullBackend, LightBackend, FullExecutor, LightExecutor,
error::Error as ServiceError, TelemetryOnConnect
};
use transaction_pool::txpool::{Pool as TransactionPool}; use transaction_pool::txpool::{Pool as TransactionPool};
use aura::{import_queue, start_aura, AuraImportQueue, SlotDuration}; use babe::{import_queue, start_babe, BabeImportQueue, Config};
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
use inherents::InherentDataProviders; use inherents::InherentDataProviders;
use log::info; use log::info;
pub use service::{ pub use service::{
@@ -49,6 +52,20 @@ pub use consensus::run_validation_worker;
/// All configuration for the polkadot node. /// All configuration for the polkadot node.
pub type Configuration = FactoryFullConfiguration<Factory>; pub type Configuration = FactoryFullConfiguration<Factory>;
type BabeBlockImportForService<F> = babe::BabeBlockImport<
FullBackend<F>,
FullExecutor<F>,
<F as crate::ServiceFactory>::Block,
grandpa::BlockImportForService<F>,
<F as crate::ServiceFactory>::RuntimeApi,
client::Client<
FullBackend<F>,
FullExecutor<F>,
<F as crate::ServiceFactory>::Block,
<F as crate::ServiceFactory>::RuntimeApi
>,
>;
/// Polkadot-specific configuration. /// Polkadot-specific configuration.
pub struct CustomConfiguration { pub struct CustomConfiguration {
/// Set to `Some` with a collator `CollatorId` and desired parachain /// Set to `Some` with a collator `CollatorId` and desired parachain
@@ -58,11 +75,15 @@ pub struct CustomConfiguration {
/// Intermediate state during setup. Will be removed in future. Set to `None`. /// Intermediate state during setup. Will be removed in future. Set to `None`.
// FIXME: rather than putting this on the config, let's have an actual intermediate setup state // FIXME: rather than putting this on the config, let's have an actual intermediate setup state
// https://github.com/paritytech/substrate/issues/1134 // https://github.com/paritytech/substrate/issues/1134
pub grandpa_import_setup: Option<( pub import_setup: Option<(
grandpa::BlockImportForService<Factory>, BabeBlockImportForService<Factory>,
grandpa::LinkHalfForService<Factory> grandpa::LinkHalfForService<Factory>,
babe::BabeLink,
)>, )>,
/// Tasks that were created by previous setup steps and should be spawned.
pub tasks_to_spawn: Option<Vec<Box<dyn Future<Item = (), Error = ()> + Send>>>,
/// Maximal `block_data` size. /// Maximal `block_data` size.
pub max_block_data_size: Option<u64>, pub max_block_data_size: Option<u64>,
@@ -73,8 +94,9 @@ impl Default for CustomConfiguration {
fn default() -> Self { fn default() -> Self {
Self { Self {
collating_for: None, collating_for: None,
grandpa_import_setup: None, import_setup: None,
inherent_data_providers: InherentDataProviders::new(), inherent_data_providers: InherentDataProviders::new(),
tasks_to_spawn: None,
max_block_data_size: None, max_block_data_size: None,
} }
} }
@@ -150,93 +172,37 @@ impl PolkadotService for Service<LightComponents<Factory>> {
service::construct_service_factory! { service::construct_service_factory! {
struct Factory { struct Factory {
Block = Block, Block = Block,
ConsensusPair = AuraPair,
FinalityPair = GrandpaPair,
RuntimeApi = RuntimeApi, RuntimeApi = RuntimeApi,
NetworkProtocol = PolkadotProtocol { NetworkProtocol = PolkadotProtocol { |config: &Configuration| Ok(PolkadotProtocol::new(config.custom.collating_for.clone())) },
|config: &Configuration| Ok(PolkadotProtocol::new(config.custom.collating_for.clone()))
},
RuntimeDispatch = polkadot_executor::Executor, RuntimeDispatch = polkadot_executor::Executor,
FullTransactionPoolApi = TxChainApi<FullBackend<Self>, FullExecutor<Self>> FullTransactionPoolApi = transaction_pool::ChainApi<client::Client<FullBackend<Self>, FullExecutor<Self>, Block, RuntimeApi>, Block>
{ |config, client| Ok(TransactionPool::new(config, TxChainApi::new(client))) }, { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) },
LightTransactionPoolApi = TxChainApi<LightBackend<Self>, LightExecutor<Self>> LightTransactionPoolApi = transaction_pool::ChainApi<client::Client<LightBackend<Self>, LightExecutor<Self>, Block, RuntimeApi>, Block>
{ |config, client| Ok(TransactionPool::new(config, TxChainApi::new(client))) }, { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) },
Genesis = GenesisConfig, Genesis = GenesisConfig,
Configuration = CustomConfiguration, Configuration = CustomConfiguration,
FullService = FullComponents<Self> FullService = FullComponents<Self> { |config: FactoryFullConfiguration<Self>| FullComponents::<Factory>::new(config) },
{ |config: FactoryFullConfiguration<Self>| { AuthoritySetup = {
FullComponents::<Factory>::new(config) |mut service: Self::FullService| {
} }, let (block_import, link_half, babe_link) = service.config_mut().custom.import_setup.take()
AuthoritySetup = { |mut service: Self::FullService| {
use polkadot_network::validation::ValidationNetwork;
let (block_import, link_half) = service.config.custom.grandpa_import_setup.take()
.expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); .expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
// always run GRANDPA in order to sync. // spawn any futures that were created in the previous setup steps
{ if let Some(tasks) = service.config_mut().custom.tasks_to_spawn.take() {
let grandpa_key = if service.config.disable_grandpa { for task in tasks {
None service.spawn_task(
} else { task.select(service.on_exit())
service.authority_key() .map(|_| ())
}; .map_err(|_| ())
);
let config = grandpa::Config {
local_key: grandpa_key.map(Arc::new),
// FIXME #1578 make this available through chainspec
gossip_duration: Duration::from_millis(333),
justification_period: 4096,
name: Some(service.config.name.clone())
};
match config.local_key {
None => {
service.spawn_task(grandpa::run_grandpa_observer(
config,
link_half,
service.network(),
service.on_exit(),
)?);
},
Some(_) => {
use service::TelemetryOnConnect;
let telemetry_on_connect = TelemetryOnConnect {
telemetry_connection_sinks: service.telemetry_on_connect_stream(),
};
let grandpa_config = grandpa::GrandpaParams {
config: config,
link: link_half,
network: service.network(),
inherent_data_providers: service.config.custom.inherent_data_providers.clone(),
on_exit: service.on_exit(),
telemetry_on_connect: Some(telemetry_on_connect),
};
service.spawn_task(grandpa::run_grandpa_voter(grandpa_config)?);
},
} }
} }
let extrinsic_store = { if service.config().roles != service::Roles::AUTHORITY {
use std::path::PathBuf; return Ok(service);
}
let mut path = PathBuf::from(service.config.database_path.clone()); if service.config().custom.collating_for.is_some() {
path.push("availability");
av_store::Store::new(::av_store::Config {
cache_size: None,
path,
})?
};
// run authorship only if authority.
let aura_key = match service.authority_key() {
Some(key) => Arc::new(key),
None => return Ok(service),
};
if service.config.custom.collating_for.is_some() {
info!( info!(
"The node cannot start as an authority because it is also configured to run as a collator." "The node cannot start as an authority because it is also configured to run as a collator."
); );
@@ -275,6 +241,19 @@ service::construct_service_factory! {
}, },
); );
use polkadot_network::validation::ValidationNetwork;
let extrinsic_store = {
use std::path::PathBuf;
let mut path = PathBuf::from(service.config().database_path.clone());
path.push("availability");
av_store::Store::new(::av_store::Config {
cache_size: None,
path,
})?
};
// collator connections and validation network both fulfilled by this // collator connections and validation network both fulfilled by this
let validation_network = ValidationNetwork::new( let validation_network = ValidationNetwork::new(
service.network(), service.network(),
@@ -283,63 +262,150 @@ service::construct_service_factory! {
service.client(), service.client(),
polkadot_network::validation::WrappedExecutor(service.spawn_task_handle()), polkadot_network::validation::WrappedExecutor(service.spawn_task_handle()),
); );
let proposer_factory = consensus::ProposerFactory::new( let proposer = consensus::ProposerFactory::new(
client.clone(), client.clone(),
select_chain.clone(), select_chain.clone(),
validation_network.clone(), validation_network.clone(),
validation_network, validation_network,
service.transaction_pool(), service.transaction_pool(),
Arc::new(service.spawn_task_handle()), Arc::new(service.spawn_task_handle()),
aura_key.clone(), service.keystore(),
extrinsic_store, extrinsic_store,
SlotDuration::get_or_compute(&*client)?, polkadot_runtime::constants::time::SLOT_DURATION,
service.config.custom.max_block_data_size, service.config().custom.max_block_data_size,
); );
info!("Using authority key {}", aura_key.public()); let client = service.client();
let task = start_aura( let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?;
SlotDuration::get_or_compute(&*client)?,
aura_key, let babe_config = babe::BabeParams {
client.clone(), config: Config::get_or_compute(&*client)?,
keystore: service.keystore(),
client,
select_chain, select_chain,
block_import, block_import,
Arc::new(proposer_factory), env: proposer,
service.network(), sync_oracle: service.network(),
service.config.custom.inherent_data_providers.clone(), inherent_data_providers: service.config().custom.inherent_data_providers.clone(),
service.config.force_authoring, force_authoring: service.config().force_authoring,
)?; time_source: babe_link,
};
let babe = start_babe(babe_config)?;
let select = babe.select(service.on_exit()).then(|_| Ok(()));
service.spawn_task(Box::new(select));
let config = grandpa::Config {
// FIXME substrate#1578 make this available through chainspec
gossip_duration: Duration::from_millis(333),
justification_period: 4096,
name: Some(service.config().name.clone()),
keystore: Some(service.keystore()),
};
match (service.config().roles.is_authority(), service.config().disable_grandpa) {
(false, false) => {
// start the lightweight GRANDPA observer
service.spawn_task(Box::new(grandpa::run_grandpa_observer(
config,
link_half,
service.network(),
service.on_exit(),
)?));
},
(true, false) => {
// start the full GRANDPA voter
let telemetry_on_connect = TelemetryOnConnect {
telemetry_connection_sinks: service.telemetry_on_connect_stream(),
};
let grandpa_config = grandpa::GrandpaParams {
config: config,
link: link_half,
network: service.network(),
inherent_data_providers: service.config().custom.inherent_data_providers.clone(),
on_exit: service.on_exit(),
telemetry_on_connect: Some(telemetry_on_connect),
};
service.spawn_task(Box::new(grandpa::run_grandpa_voter(grandpa_config)?));
},
(_, true) => {
grandpa::setup_disabled_grandpa(
service.client(),
&service.config().custom.inherent_data_providers,
service.network(),
)?;
},
}
// let config = grandpa::Config {
// // FIXME #1578 make this available through chainspec
// gossip_duration: Duration::from_millis(333),
// justification_period: 4096,
// name: Some(service.config().name.clone()),
// keystore: Some(service.keystore()),
// };
// if !service.config().disable_grandpa {
// if service.config().roles.is_authority() {
// let telemetry_on_connect = TelemetryOnConnect {
// telemetry_connection_sinks: service.telemetry_on_connect_stream(),
// };
// let grandpa_config = grandpa::GrandpaParams {
// config: config,
// link: link_half,
// network: service.network(),
// inherent_data_providers: service.config().custom.inherent_data_providers.clone(),
// on_exit: service.on_exit(),
// telemetry_on_connect: Some(telemetry_on_connect),
// };
// service.spawn_task(Box::new(grandpa::run_grandpa_voter(grandpa_config)?));
// } else {
// service.spawn_task(Box::new(grandpa::run_grandpa_observer(
// config,
// link_half,
// service.network(),
// service.on_exit(),
// )?));
// }
// }
// // regardless of whether grandpa is started or not, when
// // authoring blocks we expect inherent data regarding what our
// // last finalized block is, to be available.
// grandpa::register_finality_tracker_inherent_data_provider(
// service.client(),
// &service.config().custom.inherent_data_providers,
// )?;
service.spawn_task(task);
Ok(service) Ok(service)
}}, }
},
LightService = LightComponents<Self> LightService = LightComponents<Self>
{ |config| <LightComponents<Factory>>::new(config) }, { |config| <LightComponents<Factory>>::new(config) },
FullImportQueue = AuraImportQueue< FullImportQueue = BabeImportQueue<Self::Block>
Self::Block,
>
{ |config: &mut FactoryFullConfiguration<Self>, client: Arc<FullClient<Self>>, select_chain: Self::SelectChain| { { |config: &mut FactoryFullConfiguration<Self>, client: Arc<FullClient<Self>>, select_chain: Self::SelectChain| {
let slot_duration = SlotDuration::get_or_compute(&*client)?;
let (block_import, link_half) = let (block_import, link_half) =
grandpa::block_import::<_, _, _, RuntimeApi, FullClient<Self>, _>( grandpa::block_import::<_, _, _, RuntimeApi, FullClient<Self>, _>(
client.clone(), client.clone(), select_chain client.clone(), client.clone(), select_chain
)?; )?;
let justification_import = block_import.clone(); let justification_import = block_import.clone();
config.custom.grandpa_import_setup = Some((block_import.clone(), link_half)); let (import_queue, babe_link, babe_block_import, pruning_task) = import_queue(
import_queue::<_, _, ed25519::Pair>( Config::get_or_compute(&*client)?,
slot_duration, block_import,
Box::new(block_import),
Some(Box::new(justification_import)), Some(Box::new(justification_import)),
None, None,
client.clone(),
client, client,
config.custom.inherent_data_providers.clone(), config.custom.inherent_data_providers.clone(),
).map_err(Into::into) )?;
config.custom.import_setup = Some((babe_block_import.clone(), link_half, babe_link));
config.custom.tasks_to_spawn = Some(vec![Box::new(pruning_task)]);
Ok(import_queue)
}}, }},
LightImportQueue = AuraImportQueue< LightImportQueue = BabeImportQueue<Self::Block>
Self::Block, { |config: &FactoryFullConfiguration<Self>, client: Arc<LightClient<Self>>| {
>
{ |config: &mut FactoryFullConfiguration<Self>, client: Arc<LightClient<Self>>| {
#[allow(deprecated)] #[allow(deprecated)]
let fetch_checker = client.backend().blockchain().fetcher() let fetch_checker = client.backend().blockchain().fetcher()
.upgrade() .upgrade()
@@ -348,17 +414,22 @@ service::construct_service_factory! {
let block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, LightClient<Self>>( let block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, LightClient<Self>>(
client.clone(), Arc::new(fetch_checker), client.clone() client.clone(), Arc::new(fetch_checker), client.clone()
)?; )?;
let finality_proof_import = block_import.clone(); let finality_proof_import = block_import.clone();
let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder();
import_queue::<_, _, ed25519::Pair>( // FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`.
SlotDuration::get_or_compute(&*client)?, let (import_queue, ..) = import_queue(
Box::new(block_import), Config::get_or_compute(&*client)?,
block_import,
None, None,
Some(Box::new(finality_proof_import)), Some(Box::new(finality_proof_import)),
client.clone(),
client, client,
config.custom.inherent_data_providers.clone(), config.custom.inherent_data_providers.clone(),
).map_err(Into::into).map(|q| (q, finality_proof_request_builder)) )?;
Ok((import_queue, finality_proof_request_builder))
}}, }},
SelectChain = LongestChain<FullBackend<Self>, Self::Block> SelectChain = LongestChain<FullBackend<Self>, Self::Block>
{ |config: &FactoryFullConfiguration<Self>, client: Arc<FullClient<Self>>| { { |config: &FactoryFullConfiguration<Self>, client: Arc<FullClient<Self>>| {
@@ -367,7 +438,7 @@ service::construct_service_factory! {
} }
}, },
FinalityProofProvider = { |client: Arc<FullClient<Self>>| { FinalityProofProvider = { |client: Arc<FullClient<Self>>| {
Ok(Some(Arc::new(grandpa::FinalityProofProvider::new(client.clone(), client)) as _)) Ok(Some(Arc::new(GrandpaFinalityProofProvider::new(client.clone(), client)) as _))
}}, }},
} }
} }
+1 -1
View File
@@ -5,6 +5,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
parity-codec = { version = "4.1", features = ["derive"] } codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
primitives = { package = "polkadot-primitives", path = "../primitives" } primitives = { package = "polkadot-primitives", path = "../primitives" }
+1 -1
View File
@@ -28,7 +28,7 @@ use std::collections::hash_map::{HashMap, Entry};
use std::hash::Hash; use std::hash::Hash;
use std::fmt::Debug; use std::fmt::Debug;
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
/// Context for the statement table. /// Context for the statement table.
pub trait Context { pub trait Context {
+1 -1
View File
@@ -8,7 +8,7 @@ build = "build.rs"
[dependencies] [dependencies]
parachain = { package = "polkadot-parachain", path = "../../parachain/", default-features = false } parachain = { package = "polkadot-parachain", path = "../../parachain/", default-features = false }
parity-codec = { version = "4.1", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
tiny-keccak = "1.5.0" tiny-keccak = "1.5.0"
dlmalloc = { version = "0.1.3", features = ["global"], optional = true } dlmalloc = { version = "0.1.3", features = ["global"], optional = true }
@@ -63,7 +63,7 @@ impl ParachainContext for AdderContext {
) -> Result<(BlockData, HeadData, Extrinsic), InvalidHead> ) -> Result<(BlockData, HeadData, Extrinsic), InvalidHead>
{ {
let adder_head = AdderHead::decode(&mut &status.head_data.0[..]) let adder_head = AdderHead::decode(&mut &status.head_data.0[..])
.ok_or(InvalidHead)?; .map_err(|_| InvalidHead)?;
let mut db = self.db.lock(); let mut db = self.db.lock();
+2 -2
View File
@@ -20,7 +20,7 @@
#![cfg_attr(feature = "no_std", feature(core_intrinsics, lang_items, core_panic_info, alloc_error_handler))] #![cfg_attr(feature = "no_std", feature(core_intrinsics, lang_items, core_panic_info, alloc_error_handler))]
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
mod wasm_validation; mod wasm_validation;
@@ -80,7 +80,7 @@ pub fn process_messages<I, T>(iterable: I) -> u64
where I: IntoIterator<Item=T>, T: AsRef<[u8]> where I: IntoIterator<Item=T>, T: AsRef<[u8]>
{ {
iterable.into_iter() iterable.into_iter()
.filter_map(|data| AddMessage::decode(&mut data.as_ref())) .filter_map(|data| AddMessage::decode(&mut data.as_ref()).ok())
.fold(0u64, |a, c| a.overflowing_add(c.amount).0) .fold(0u64, |a, c| a.overflowing_add(c.amount).0)
} }
+5 -5
View File
@@ -13,24 +13,24 @@ tokio = "0.1.7"
derive_more = "0.14.0" derive_more = "0.14.0"
log = "0.4.6" log = "0.4.6"
exit-future = "0.1" exit-future = "0.1"
parity-codec = "4.1" codec = { package = "parity-scale-codec", version = "~1.0.0", default-features = false, features = ["derive"] }
extrinsic_store = { package = "polkadot-availability-store", path = "../availability-store" } extrinsic_store = { package = "polkadot-availability-store", path = "../availability-store" }
parachain = { package = "polkadot-parachain", path = "../parachain" } parachain = { package = "polkadot-parachain", path = "../parachain" }
polkadot-primitives = { path = "../primitives" } polkadot-primitives = { path = "../primitives" }
polkadot-runtime = { path = "../runtime" } polkadot-runtime = { path = "../runtime" }
table = { package = "polkadot-statement-table", path = "../statement-table" } table = { package = "polkadot-statement-table", path = "../statement-table" }
aura = { package = "substrate-consensus-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
aura_primitives = { package = "substrate-consensus-aura-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
grandpa = { package = "substrate-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } grandpa = { package = "substrate-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
consensus = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } consensus = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
transaction_pool = { package = "substrate-transaction-pool", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } transaction_pool = { package = "substrate-transaction-pool", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
runtime_aura = { package = "srml-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
trie = { package = "substrate-trie", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } trie = { package = "substrate-trie", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
bitvec = { version = "0.11", default-features = false, features = ["alloc"] } bitvec = { version = "0.14.0", default-features = false, features = ["alloc"] }
runtime_babe = { package = "srml-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
babe-primitives = { package = "substrate-consensus-babe-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
keystore = { package = "substrate-keystore", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
[dev-dependencies] [dev-dependencies]
substrate-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } substrate-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
+10 -9
View File
@@ -33,11 +33,11 @@ use extrinsic_store::Store as ExtrinsicStore;
use futures::prelude::*; use futures::prelude::*;
use futures03::{TryStreamExt as _, StreamExt as _}; use futures03::{TryStreamExt as _, StreamExt as _};
use log::error; use log::error;
use primitives::ed25519; use polkadot_primitives::{Block, BlockId};
use polkadot_primitives::{Block, BlockId, AuraId};
use polkadot_primitives::parachain::{CandidateReceipt, ParachainHost}; use polkadot_primitives::parachain::{CandidateReceipt, ParachainHost};
use runtime_primitives::traits::{ProvideRuntimeApi, Header as HeaderT}; use runtime_primitives::traits::{ProvideRuntimeApi, Header as HeaderT};
use aura::AuraApi; use babe_primitives::BabeApi;
use keystore::KeyStorePtr;
use tokio::{timer::Interval, runtime::current_thread::Runtime as LocalRuntime}; use tokio::{timer::Interval, runtime::current_thread::Runtime as LocalRuntime};
use log::{warn, debug}; use log::{warn, debug};
@@ -50,14 +50,14 @@ type TaskExecutor = Arc<dyn futures::future::Executor<Box<dyn Future<Item = (),
pub(crate) fn fetch_candidates<P: BlockBody<Block>>(client: &P, block: &BlockId) pub(crate) fn fetch_candidates<P: BlockBody<Block>>(client: &P, block: &BlockId)
-> ClientResult<Option<impl Iterator<Item=CandidateReceipt>>> -> ClientResult<Option<impl Iterator<Item=CandidateReceipt>>>
{ {
use parity_codec::{Encode, Decode}; use codec::{Encode, Decode};
use polkadot_runtime::{Call, ParachainsCall, UncheckedExtrinsic as RuntimeExtrinsic}; use polkadot_runtime::{Call, ParachainsCall, UncheckedExtrinsic as RuntimeExtrinsic};
let extrinsics = client.block_body(block)?; let extrinsics = client.block_body(block)?;
Ok(match extrinsics { Ok(match extrinsics {
Some(extrinsics) => extrinsics Some(extrinsics) => extrinsics
.into_iter() .into_iter()
.filter_map(|ex| RuntimeExtrinsic::decode(&mut ex.encode().as_slice())) .filter_map(|ex| RuntimeExtrinsic::decode(&mut ex.encode().as_slice()).ok())
.filter_map(|ex| match ex.function { .filter_map(|ex| match ex.function {
Call::Parachains(ParachainsCall::set_heads(heads)) => { Call::Parachains(ParachainsCall::set_heads(heads)) => {
Some(heads.into_iter().map(|c| c.candidate)) Some(heads.into_iter().map(|c| c.candidate))
@@ -114,7 +114,7 @@ pub(crate) fn start<C, N, P, SC>(
select_chain: SC, select_chain: SC,
parachain_validation: Arc<crate::ParachainValidation<C, N, P>>, parachain_validation: Arc<crate::ParachainValidation<C, N, P>>,
thread_pool: TaskExecutor, thread_pool: TaskExecutor,
key: Arc<ed25519::Pair>, keystore: KeyStorePtr,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
max_block_data_size: Option<u64>, max_block_data_size: Option<u64>,
) -> ServiceHandle ) -> ServiceHandle
@@ -123,7 +123,7 @@ pub(crate) fn start<C, N, P, SC>(
<C::Collation as IntoFuture>::Future: Send + 'static, <C::Collation as IntoFuture>::Future: Send + 'static,
P: BlockchainEvents<Block> + BlockBody<Block>, P: BlockchainEvents<Block> + BlockBody<Block>,
P: ProvideRuntimeApi + HeaderBackend<Block> + Send + Sync + 'static, P: ProvideRuntimeApi + HeaderBackend<Block> + Send + Sync + 'static,
P::Api: ParachainHost<Block> + BlockBuilder<Block> + AuraApi<Block, AuraId>, P::Api: ParachainHost<Block> + BlockBuilder<Block> + BabeApi<Block>,
N: Network + Send + Sync + 'static, N: Network + Send + Sync + 'static,
N::TableRouter: Send + 'static, N::TableRouter: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static, <N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
@@ -138,7 +138,8 @@ pub(crate) fn start<C, N, P, SC>(
let notifications = { let notifications = {
let client = client.clone(); let client = client.clone();
let validation = parachain_validation.clone(); let validation = parachain_validation.clone();
let key = key.clone();
let keystore = keystore.clone();
client.import_notification_stream() client.import_notification_stream()
.map(|v| Ok::<_, ()>(v)).compat() .map(|v| Ok::<_, ()>(v)).compat()
@@ -148,7 +149,7 @@ pub(crate) fn start<C, N, P, SC>(
let res = validation.get_or_instantiate( let res = validation.get_or_instantiate(
parent_hash, parent_hash,
notification.header.parent_hash().clone(), notification.header.parent_hash().clone(),
key.clone(), &keystore,
max_block_data_size, max_block_data_size,
); );
+2 -2
View File
@@ -27,7 +27,7 @@ use polkadot_primitives::{Block, Hash, BlockId, Balance, parachain::{
}}; }};
use runtime_primitives::traits::ProvideRuntimeApi; use runtime_primitives::traits::ProvideRuntimeApi;
use parachain::{wasm_executor::{self, ExternalitiesError, ExecutionMode}, MessageRef, UpwardMessageRef}; use parachain::{wasm_executor::{self, ExternalitiesError, ExecutionMode}, MessageRef, UpwardMessageRef};
use trie::TrieConfiguration;
use futures::prelude::*; use futures::prelude::*;
use log::debug; use log::debug;
@@ -186,7 +186,7 @@ impl std::error::Error for Error {
pub fn message_queue_root<A, I: IntoIterator<Item=A>>(messages: I) -> Hash pub fn message_queue_root<A, I: IntoIterator<Item=A>>(messages: I) -> Hash
where A: AsRef<[u8]> where A: AsRef<[u8]>
{ {
::trie::ordered_trie_root::<primitives::Blake2Hasher, _, _>(messages) ::trie::trie_types::Layout::<primitives::Blake2Hasher>::ordered_trie_root(messages)
} }
/// Compute the set of egress roots for all given outgoing messages. /// Compute the set of egress roots for all given outgoing messages.
+2 -2
View File
@@ -17,7 +17,7 @@
//! Errors that can occur during the validation process. //! Errors that can occur during the validation process.
use runtime_primitives::RuntimeString; use runtime_primitives::RuntimeString;
use primitives::ed25519::Public as AuthorityId; use polkadot_primitives::parachain::ValidatorId;
/// Error type for validation /// Error type for validation
#[derive(Debug, derive_more::Display, derive_more::From)] #[derive(Debug, derive_more::Display, derive_more::From)]
@@ -35,7 +35,7 @@ pub enum Error {
}, },
/// Local account not a validator at this block /// Local account not a validator at this block
#[display(fmt = "Local account ID ({:?}) not a validator at this block.", _0)] #[display(fmt = "Local account ID ({:?}) not a validator at this block.", _0)]
NotValidator(AuthorityId), NotValidator(ValidatorId),
/// Unexpected error checking inherents /// Unexpected error checking inherents
#[display(fmt = "Unexpected error while checking inherents: {}", _0)] #[display(fmt = "Unexpected error while checking inherents: {}", _0)]
InherentError(RuntimeString), InherentError(RuntimeString),
+1 -1
View File
@@ -18,7 +18,7 @@
use super::MAX_TRANSACTIONS_SIZE; use super::MAX_TRANSACTIONS_SIZE;
use parity_codec::Encode; use codec::Encode;
use polkadot_primitives::{Block, Hash, BlockNumber}; use polkadot_primitives::{Block, Hash, BlockNumber};
use polkadot_primitives::parachain::Id as ParaId; use polkadot_primitives::parachain::Id as ParaId;
+70 -62
View File
@@ -31,21 +31,21 @@
use std::{collections::{HashMap, HashSet}, pin::Pin, sync::Arc, time::{self, Duration, Instant}}; use std::{collections::{HashMap, HashSet}, pin::Pin, sync::Arc, time::{self, Duration, Instant}};
use aura::{SlotDuration, AuraApi}; use babe_primitives::BabeApi;
use client::{BlockchainEvents, BlockBody}; use client::{BlockchainEvents, BlockBody};
use client::blockchain::HeaderBackend; use client::blockchain::HeaderBackend;
use client::block_builder::api::BlockBuilder as BlockBuilderApi; use client::block_builder::api::BlockBuilder as BlockBuilderApi;
use parity_codec::Encode; use codec::Encode;
use consensus::SelectChain; use consensus::SelectChain;
use extrinsic_store::Store as ExtrinsicStore; use extrinsic_store::Store as ExtrinsicStore;
use parking_lot::Mutex; use parking_lot::Mutex;
use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, SessionKey, AuraId}; use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header};
use polkadot_primitives::parachain::{ use polkadot_primitives::parachain::{
Id as ParaId, Chain, DutyRoster, Extrinsic as ParachainExtrinsic, CandidateReceipt, Id as ParaId, Chain, DutyRoster, Extrinsic as ParachainExtrinsic, CandidateReceipt,
ParachainHost, AttestedCandidate, Statement as PrimitiveStatement, Message, OutgoingMessage, ParachainHost, AttestedCandidate, Statement as PrimitiveStatement, Message, OutgoingMessage,
CollatorSignature, Collation, PoVBlock, Collation, PoVBlock, ValidatorSignature, ValidatorPair, ValidatorId
}; };
use primitives::{Pair, ed25519}; use primitives::Pair;
use runtime_primitives::{ use runtime_primitives::{
traits::{ProvideRuntimeApi, Header as HeaderT, DigestFor}, ApplyError traits::{ProvideRuntimeApi, Header as HeaderT, DigestFor}, ApplyError
}; };
@@ -58,10 +58,9 @@ use futures03::{future::{self, Either, FutureExt}, task::Context, stream::Stream
use collation::CollationFetch; use collation::CollationFetch;
use dynamic_inclusion::DynamicInclusion; use dynamic_inclusion::DynamicInclusion;
use inherents::InherentData; use inherents::InherentData;
use runtime_aura::timestamp::TimestampInherentData; use runtime_babe::timestamp::TimestampInherentData;
use log::{info, debug, warn, trace, error}; use log::{info, debug, warn, trace, error};
use keystore::KeyStorePtr;
use ed25519::Public as AuthorityId;
type TaskExecutor = Arc<dyn futures::future::Executor<Box<dyn Future<Item = (), Error = ()> + Send>> + Send + Sync>; type TaskExecutor = Arc<dyn futures::future::Executor<Box<dyn Future<Item = (), Error = ()> + Send>> + Send + Sync>;
@@ -145,7 +144,7 @@ pub trait Network {
fn communication_for( fn communication_for(
&self, &self,
table: Arc<SharedTable>, table: Arc<SharedTable>,
authorities: &[SessionKey], authorities: &[ValidatorId],
exit: exit_future::Exit, exit: exit_future::Exit,
) -> Self::BuildTableRouter; ) -> Self::BuildTableRouter;
} }
@@ -154,7 +153,7 @@ pub trait Network {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct GroupInfo { pub struct GroupInfo {
/// Authorities meant to check validity of candidates. /// Authorities meant to check validity of candidates.
validity_guarantors: HashSet<SessionKey>, validity_guarantors: HashSet<ValidatorId>,
/// Number of votes needed for validity. /// Number of votes needed for validity.
needed_validity: usize, needed_validity: usize,
} }
@@ -162,32 +161,32 @@ pub struct GroupInfo {
/// Sign a table statement against a parent hash. /// Sign a table statement against a parent hash.
/// The actual message signed is the encoded statement concatenated with the /// The actual message signed is the encoded statement concatenated with the
/// parent hash. /// parent hash.
pub fn sign_table_statement(statement: &Statement, key: &ed25519::Pair, parent_hash: &Hash) -> CollatorSignature { pub fn sign_table_statement(statement: &Statement, key: &ValidatorPair, parent_hash: &Hash) -> ValidatorSignature {
// we sign using the primitive statement type because that's what the runtime // we sign using the primitive statement type because that's what the runtime
// expects. These types probably encode the same way so this clone could be optimized // expects. These types probably encode the same way so this clone could be optimized
// out in the future. // out in the future.
let mut encoded = PrimitiveStatement::from(statement.clone()).encode(); let mut encoded = PrimitiveStatement::from(statement.clone()).encode();
encoded.extend(parent_hash.as_ref()); encoded.extend(parent_hash.as_ref());
key.sign(&encoded).into() key.sign(&encoded)
} }
/// Check signature on table statement. /// Check signature on table statement.
pub fn check_statement(statement: &Statement, signature: &CollatorSignature, signer: SessionKey, parent_hash: &Hash) -> bool { pub fn check_statement(statement: &Statement, signature: &ValidatorSignature, signer: ValidatorId, parent_hash: &Hash) -> bool {
use runtime_primitives::traits::Verify; use runtime_primitives::traits::AppVerify;
let mut encoded = PrimitiveStatement::from(statement.clone()).encode(); let mut encoded = PrimitiveStatement::from(statement.clone()).encode();
encoded.extend(parent_hash.as_ref()); encoded.extend(parent_hash.as_ref());
signature.verify(&encoded[..], &signer.into()) signature.verify(&encoded[..], &signer)
} }
/// Compute group info out of a duty roster and a local authority set. /// Compute group info out of a duty roster and a local authority set.
pub fn make_group_info( pub fn make_group_info(
roster: DutyRoster, roster: DutyRoster,
authorities: &[AuthorityId], authorities: &[ValidatorId],
local_id: AuthorityId, local_id: Option<ValidatorId>,
) -> Result<(HashMap<ParaId, GroupInfo>, LocalDuty), Error> { ) -> Result<(HashMap<ParaId, GroupInfo>, Option<LocalDuty>), Error> {
if roster.validator_duty.len() != authorities.len() { if roster.validator_duty.len() != authorities.len() {
return Err(Error::InvalidDutyRosterLength { return Err(Error::InvalidDutyRosterLength {
expected: authorities.len(), expected: authorities.len(),
@@ -200,7 +199,7 @@ pub fn make_group_info(
let duty_iter = authorities.iter().zip(&roster.validator_duty); let duty_iter = authorities.iter().zip(&roster.validator_duty);
for (authority, v_duty) in duty_iter { for (authority, v_duty) in duty_iter {
if authority == &local_id { if Some(authority) == local_id.as_ref() {
local_validation = Some(v_duty.clone()); local_validation = Some(v_duty.clone());
} }
@@ -219,16 +218,24 @@ pub fn make_group_info(
live_group.needed_validity = validity_len / 2 + validity_len % 2; live_group.needed_validity = validity_len / 2 + validity_len % 2;
} }
match local_validation {
Some(local_validation) => {
let local_duty = LocalDuty {
validation: local_validation,
};
Ok((map, local_duty)) let local_duty = local_validation.map(|v| LocalDuty {
} validation: v
None => return Err(Error::NotValidator(local_id)), });
}
Ok((map, local_duty))
}
// finds the first key we are capable of signing with out of the given set of validators,
// if any.
fn signing_key(validators: &[ValidatorId], keystore: &KeyStorePtr) -> Option<Arc<ValidatorPair>> {
let keystore = keystore.read();
validators.iter()
.find_map(|v| {
keystore.key_pair::<ValidatorPair>(&v).ok()
})
.map(|pair| Arc::new(pair))
} }
/// Constructs parachain-agreement instances. /// Constructs parachain-agreement instances.
@@ -252,7 +259,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
C: Collators + Send + 'static, C: Collators + Send + 'static,
N: Network, N: Network,
P: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + Send + Sync + 'static, P: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + Send + Sync + 'static,
P::Api: ParachainHost<Block> + BlockBuilderApi<Block> + AuraApi<Block, AuraId>, P::Api: ParachainHost<Block> + BlockBuilderApi<Block>,
<C::Collation as IntoFuture>::Future: Send + 'static, <C::Collation as IntoFuture>::Future: Send + 'static,
N::TableRouter: Send + 'static, N::TableRouter: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static, <N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
@@ -268,7 +275,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
&self, &self,
parent_hash: Hash, parent_hash: Hash,
grandparent_hash: Hash, grandparent_hash: Hash,
sign_with: Arc<ed25519::Pair>, keystore: &KeyStorePtr,
max_block_data_size: Option<u64>, max_block_data_size: Option<u64>,
) )
-> Result<Arc<AttestationTracker>, Error> -> Result<Arc<AttestationTracker>, Error>
@@ -280,7 +287,8 @@ impl<C, N, P> ParachainValidation<C, N, P> where
let id = BlockId::hash(parent_hash); let id = BlockId::hash(parent_hash);
let authorities = self.client.runtime_api().authorities(&id)?; let validators = self.client.runtime_api().validators(&id)?;
let sign_with = signing_key(&validators[..], keystore);
// compute the parent candidates, if we know of them. // compute the parent candidates, if we know of them.
// this will allow us to circulate outgoing messages to other peers as necessary. // this will allow us to circulate outgoing messages to other peers as necessary.
@@ -312,14 +320,14 @@ impl<C, N, P> ParachainValidation<C, N, P> where
let (group_info, local_duty) = make_group_info( let (group_info, local_duty) = make_group_info(
duty_roster, duty_roster,
&authorities, &validators,
sign_with.public(), sign_with.as_ref().map(|k| k.public()),
)?; )?;
info!( info!(
"Starting parachain attestation session on top of parent {:?}. Local parachain duty is {:?}", "Starting parachain attestation session on top of parent {:?}. Local parachain duty is {:?}",
parent_hash, parent_hash,
local_duty.validation, local_duty,
); );
let active_parachains = self.client.runtime_api().active_parachains(&id)?; let active_parachains = self.client.runtime_api().active_parachains(&id)?;
@@ -327,9 +335,9 @@ impl<C, N, P> ParachainValidation<C, N, P> where
debug!(target: "validation", "Active parachains: {:?}", active_parachains); debug!(target: "validation", "Active parachains: {:?}", active_parachains);
let table = Arc::new(SharedTable::new( let table = Arc::new(SharedTable::new(
&authorities, validators.clone(),
group_info, group_info,
sign_with.clone(), sign_with,
parent_hash, parent_hash,
self.extrinsic_store.clone(), self.extrinsic_store.clone(),
max_block_data_size, max_block_data_size,
@@ -339,11 +347,11 @@ impl<C, N, P> ParachainValidation<C, N, P> where
let router = self.network.communication_for( let router = self.network.communication_for(
table.clone(), table.clone(),
&authorities, &validators,
exit.clone(), exit.clone(),
); );
if let Chain::Parachain(id) = local_duty.validation { if let Some(Chain::Parachain(id)) = local_duty.as_ref().map(|d| d.validation) {
self.launch_work(parent_hash, id, router, max_block_data_size, exit); self.launch_work(parent_hash, id, router, max_block_data_size, exit);
} }
@@ -446,9 +454,9 @@ struct AttestationTracker {
pub struct ProposerFactory<C, N, P, SC, TxApi: PoolChainApi> { pub struct ProposerFactory<C, N, P, SC, TxApi: PoolChainApi> {
parachain_validation: Arc<ParachainValidation<C, N, P>>, parachain_validation: Arc<ParachainValidation<C, N, P>>,
transaction_pool: Arc<Pool<TxApi>>, transaction_pool: Arc<Pool<TxApi>>,
key: Arc<ed25519::Pair>, keystore: KeyStorePtr,
_service_handle: ServiceHandle, _service_handle: ServiceHandle,
aura_slot_duration: SlotDuration, babe_slot_duration: u64,
_select_chain: SC, _select_chain: SC,
max_block_data_size: Option<u64>, max_block_data_size: Option<u64>,
} }
@@ -458,7 +466,7 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
<C::Collation as IntoFuture>::Future: Send + 'static, <C::Collation as IntoFuture>::Future: Send + 'static,
P: BlockchainEvents<Block> + BlockBody<Block>, P: BlockchainEvents<Block> + BlockBody<Block>,
P: ProvideRuntimeApi + HeaderBackend<Block> + Send + Sync + 'static, P: ProvideRuntimeApi + HeaderBackend<Block> + Send + Sync + 'static,
P::Api: ParachainHost<Block> + BlockBuilderApi<Block> + AuraApi<Block, AuraId>, P::Api: ParachainHost<Block> + BlockBuilderApi<Block> + BabeApi<Block>,
N: Network + Send + Sync + 'static, N: Network + Send + Sync + 'static,
N::TableRouter: Send + 'static, N::TableRouter: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static, <N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
@@ -473,9 +481,9 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
collators: C, collators: C,
transaction_pool: Arc<Pool<TxApi>>, transaction_pool: Arc<Pool<TxApi>>,
thread_pool: TaskExecutor, thread_pool: TaskExecutor,
key: Arc<ed25519::Pair>, keystore: KeyStorePtr,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
aura_slot_duration: SlotDuration, babe_slot_duration: u64,
max_block_data_size: Option<u64>, max_block_data_size: Option<u64>,
) -> Self { ) -> Self {
let parachain_validation = Arc::new(ParachainValidation { let parachain_validation = Arc::new(ParachainValidation {
@@ -492,7 +500,7 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
_select_chain.clone(), _select_chain.clone(),
parachain_validation.clone(), parachain_validation.clone(),
thread_pool, thread_pool,
key.clone(), keystore.clone(),
extrinsic_store, extrinsic_store,
max_block_data_size, max_block_data_size,
); );
@@ -500,9 +508,9 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
ProposerFactory { ProposerFactory {
parachain_validation, parachain_validation,
transaction_pool, transaction_pool,
key, keystore,
_service_handle: service_handle, _service_handle: service_handle,
aura_slot_duration, babe_slot_duration,
_select_chain, _select_chain,
max_block_data_size, max_block_data_size,
} }
@@ -514,7 +522,7 @@ impl<C, N, P, SC, TxApi> consensus::Environment<Block> for ProposerFactory<C, N,
N: Network, N: Network,
TxApi: PoolChainApi<Block=Block>, TxApi: PoolChainApi<Block=Block>,
P: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + Send + Sync + 'static, P: ProvideRuntimeApi + HeaderBackend<Block> + BlockBody<Block> + Send + Sync + 'static,
P::Api: ParachainHost<Block> + BlockBuilderApi<Block> + AuraApi<Block, AuraId>, P::Api: ParachainHost<Block> + BlockBuilderApi<Block> + BabeApi<Block>,
<C::Collation as IntoFuture>::Future: Send + 'static, <C::Collation as IntoFuture>::Future: Send + 'static,
N::TableRouter: Send + 'static, N::TableRouter: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static, <N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
@@ -524,16 +532,16 @@ impl<C, N, P, SC, TxApi> consensus::Environment<Block> for ProposerFactory<C, N,
type Error = Error; type Error = Error;
fn init( fn init(
&self, &mut self,
parent_header: &Header, parent_header: &Header,
) -> Result<Self::Proposer, Error> { ) -> Result<Self::Proposer, Error> {
let parent_hash = parent_header.hash(); let parent_hash = parent_header.hash();
let parent_id = BlockId::hash(parent_hash); let parent_id = BlockId::hash(parent_hash);
let sign_with = self.key.clone();
let tracker = self.parachain_validation.get_or_instantiate( let tracker = self.parachain_validation.get_or_instantiate(
parent_hash, parent_hash,
parent_header.parent_hash().clone(), parent_header.parent_hash().clone(),
sign_with, &self.keystore,
self.max_block_data_size, self.max_block_data_size,
)?; )?;
@@ -544,12 +552,13 @@ impl<C, N, P, SC, TxApi> consensus::Environment<Block> for ProposerFactory<C, N,
parent_id, parent_id,
parent_number: parent_header.number, parent_number: parent_header.number,
transaction_pool: self.transaction_pool.clone(), transaction_pool: self.transaction_pool.clone(),
slot_duration: self.aura_slot_duration, slot_duration: self.babe_slot_duration,
}) })
} }
} }
/// The local duty of a validator. /// The local duty of a validator.
#[derive(Debug)]
pub struct LocalDuty { pub struct LocalDuty {
validation: Chain, validation: Chain,
} }
@@ -564,7 +573,7 @@ pub struct Proposer<C: Send + Sync, TxApi: PoolChainApi> where
parent_number: BlockNumber, parent_number: BlockNumber,
tracker: Arc<AttestationTracker>, tracker: Arc<AttestationTracker>,
transaction_pool: Arc<Pool<TxApi>>, transaction_pool: Arc<Pool<TxApi>>,
slot_duration: SlotDuration, slot_duration: u64,
} }
impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
@@ -575,7 +584,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
type Error = Error; type Error = Error;
type Create = Either<CreateProposal<C, TxApi>, future::Ready<Result<Block, Error>>>; type Create = Either<CreateProposal<C, TxApi>, future::Ready<Result<Block, Error>>>;
fn propose(&self, fn propose(&mut self,
inherent_data: InherentData, inherent_data: InherentData,
inherent_digests: DigestFor<Block>, inherent_digests: DigestFor<Block>,
max_duration: Duration, max_duration: Duration,
@@ -589,7 +598,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
let dynamic_inclusion = DynamicInclusion::new( let dynamic_inclusion = DynamicInclusion::new(
self.tracker.table.num_parachains(), self.tracker.table.num_parachains(),
self.tracker.started, self.tracker.started,
Duration::from_secs(self.slot_duration.get() / SLOT_DURATION_DENOMINATOR), Duration::from_millis(self.slot_duration / SLOT_DURATION_DENOMINATOR),
); );
let enough_candidates = dynamic_inclusion.acceptable_in( let enough_candidates = dynamic_inclusion.acceptable_in(
@@ -607,7 +616,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
let delay_future = if current_timestamp >= believed_timestamp { let delay_future = if current_timestamp >= believed_timestamp {
None None
} else { } else {
Some(Delay::new(Duration::from_secs(current_timestamp - believed_timestamp))) Some(Delay::new(Duration::from_millis (current_timestamp - believed_timestamp)))
}; };
let timing = ProposalTiming { let timing = ProposalTiming {
@@ -638,8 +647,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
fn current_timestamp() -> u64 { fn current_timestamp() -> u64 {
time::SystemTime::now().duration_since(time::UNIX_EPOCH) time::SystemTime::now().duration_since(time::UNIX_EPOCH)
.expect("now always later than unix epoch; qed") .expect("now always later than unix epoch; qed")
.as_secs() .as_millis() as u64
.into()
} }
struct ProposalTiming { struct ProposalTiming {
@@ -811,17 +819,17 @@ impl<C, TxApi> futures03::Future for CreateProposal<C, TxApi> where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use substrate_keyring::Ed25519Keyring; use substrate_keyring::Sr25519Keyring;
#[test] #[test]
fn sign_and_check_statement() { fn sign_and_check_statement() {
let statement: Statement = GenericStatement::Valid([1; 32].into()); let statement: Statement = GenericStatement::Valid([1; 32].into());
let parent_hash = [2; 32].into(); let parent_hash = [2; 32].into();
let sig = sign_table_statement(&statement, &Ed25519Keyring::Alice.pair(), &parent_hash); let sig = sign_table_statement(&statement, &Sr25519Keyring::Alice.pair().into(), &parent_hash);
assert!(check_statement(&statement, &sig, Ed25519Keyring::Alice.into(), &parent_hash)); assert!(check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &parent_hash));
assert!(!check_statement(&statement, &sig, Ed25519Keyring::Alice.into(), &[0xff; 32].into())); assert!(!check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &[0xff; 32].into()));
assert!(!check_statement(&statement, &sig, Ed25519Keyring::Bob.into(), &parent_hash)); assert!(!check_statement(&statement, &sig, Sr25519Keyring::Bob.public().into(), &parent_hash));
} }
} }
+74 -99
View File
@@ -22,9 +22,10 @@ use std::sync::Arc;
use extrinsic_store::{Data, Store as ExtrinsicStore}; use extrinsic_store::{Data, Store as ExtrinsicStore};
use table::{self, Table, Context as TableContextTrait}; use table::{self, Table, Context as TableContextTrait};
use polkadot_primitives::{Block, BlockId, Hash, SessionKey}; use polkadot_primitives::{Block, BlockId, Hash};
use polkadot_primitives::parachain::{Id as ParaId, Collation, Extrinsic, CandidateReceipt, use polkadot_primitives::parachain::{
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex, Id as ParaId, Collation, Extrinsic, CandidateReceipt, ValidatorPair, ValidatorId,
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
@@ -34,7 +35,7 @@ use bitvec::bitvec;
use super::{GroupInfo, TableRouter}; use super::{GroupInfo, TableRouter};
use self::includable::IncludabilitySender; use self::includable::IncludabilitySender;
use primitives::{ed25519, Pair}; use primitives::Pair;
use runtime_primitives::traits::ProvideRuntimeApi; use runtime_primitives::traits::ProvideRuntimeApi;
mod includable; mod includable;
@@ -45,14 +46,14 @@ pub use table::generic::Statement as GenericStatement;
struct TableContext { struct TableContext {
parent_hash: Hash, parent_hash: Hash,
key: Arc<ed25519::Pair>, key: Option<Arc<ValidatorPair>>,
groups: HashMap<ParaId, GroupInfo>, groups: HashMap<ParaId, GroupInfo>,
index_mapping: HashMap<ValidatorIndex, SessionKey>, validators: Vec<ValidatorId>,
} }
impl table::Context for TableContext { impl table::Context for TableContext {
fn is_member_of(&self, authority: ValidatorIndex, group: &ParaId) -> bool { fn is_member_of(&self, authority: ValidatorIndex, group: &ParaId) -> bool {
let key = match self.index_mapping.get(&authority) { let key = match self.validators.get(authority as usize) {
Some(val) => val, Some(val) => val,
None => return false, None => return false,
}; };
@@ -66,28 +67,26 @@ impl table::Context for TableContext {
} }
impl TableContext { impl TableContext {
fn local_id(&self) -> SessionKey { fn local_id(&self) -> Option<ValidatorId> {
self.key.public().into() self.key.as_ref().map(|k| k.public())
} }
fn local_index(&self) -> ValidatorIndex { fn local_index(&self) -> Option<ValidatorIndex> {
let id = self.local_id(); self.local_id().and_then(|id|
self self.validators
.index_mapping .iter()
.iter() .enumerate()
.find(|(_, k)| k == &&id) .find(|(_, k)| k == &&id)
.map(|(i, _)| *i) .map(|(i, _)| i as ValidatorIndex)
.unwrap() )
} }
fn sign_statement(&self, statement: table::Statement) -> table::SignedStatement { fn sign_statement(&self, statement: table::Statement) -> Option<table::SignedStatement> {
let signature = crate::sign_table_statement(&statement, &self.key, &self.parent_hash).into(); self.local_index().and_then(move |sender|
self.key.as_ref()
table::SignedStatement { .map(|key| crate::sign_table_statement(&statement, key, &self.parent_hash).into())
statement, .map(move |signature| table::SignedStatement { statement, signature, sender })
signature, )
sender: self.local_index(),
}
} }
} }
@@ -142,15 +141,10 @@ impl SharedTableInner {
) -> Option<ParachainWork< ) -> Option<ParachainWork<
<R::FetchValidationProof as IntoFuture>::Future, <R::FetchValidationProof as IntoFuture>::Future,
>> { >> {
let summary = match self.table.import_statement(context, statement) { let summary = self.table.import_statement(context, statement)?;
Some(summary) => summary,
None => return None,
};
self.update_trackers(&summary.candidate, context); self.update_trackers(&summary.candidate, context);
let local_index = context.local_index(); let local_index = context.local_index()?;
let para_member = context.is_member_of(local_index, &summary.group_id); let para_member = context.is_member_of(local_index, &summary.group_id);
let digest = &summary.candidate; let digest = &summary.candidate;
@@ -399,16 +393,15 @@ impl SharedTable {
/// Provide the key to sign with, and the parent hash of the relay chain /// Provide the key to sign with, and the parent hash of the relay chain
/// block being built. /// block being built.
pub fn new( pub fn new(
authorities: &[ed25519::Public], validators: Vec<ValidatorId>,
groups: HashMap<ParaId, GroupInfo>, groups: HashMap<ParaId, GroupInfo>,
key: Arc<ed25519::Pair>, key: Option<Arc<ValidatorPair>>,
parent_hash: Hash, parent_hash: Hash,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
max_block_data_size: Option<u64>, max_block_data_size: Option<u64>,
) -> Self { ) -> Self {
let index_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect(); SharedTable {
Self { context: Arc::new(TableContext { groups, key, parent_hash, validators: validators.clone(), }),
context: Arc::new(TableContext { groups, key, parent_hash, index_mapping, }),
max_block_data_size, max_block_data_size,
inner: Arc::new(Mutex::new(SharedTableInner { inner: Arc::new(Mutex::new(SharedTableInner {
table: Table::default(), table: Table::default(),
@@ -425,7 +418,7 @@ impl SharedTable {
} }
/// Get the local validator session key. /// Get the local validator session key.
pub fn session_key(&self) -> SessionKey { pub fn session_key(&self) -> Option<ValidatorId> {
self.context.local_id() self.context.local_id()
} }
@@ -482,9 +475,10 @@ impl SharedTable {
}).collect() }).collect()
} }
/// Sign and import the result of candidate validation. /// Sign and import the result of candidate validation. Returns `None` if the table
/// was instantiated without a local key.
pub fn import_validated(&self, validated: Validated) pub fn import_validated(&self, validated: Validated)
-> SignedStatement -> Option<SignedStatement>
{ {
let digest = match validated.statement { let digest = match validated.statement {
GenericStatement::Candidate(ref c) => c.hash(), GenericStatement::Candidate(ref c) => c.hash(),
@@ -493,9 +487,11 @@ impl SharedTable {
let signed_statement = self.context.sign_statement(validated.statement); let signed_statement = self.context.sign_statement(validated.statement);
let mut inner = self.inner.lock(); if let Some(ref signed) = signed_statement {
inner.table.import_statement(&*self.context, signed_statement.clone()); let mut inner = self.inner.lock();
inner.validated.insert(digest, ValidationWork::Done(validated.result)); inner.table.import_statement(&*self.context, signed.clone());
inner.validated.insert(digest, ValidationWork::Done(validated.result));
}
signed_statement signed_statement
} }
@@ -576,15 +572,15 @@ impl SharedTable {
} }
/// Returns id of the validator corresponding to the given index. /// Returns id of the validator corresponding to the given index.
pub fn index_to_id(&self, index: ValidatorIndex) -> Option<SessionKey> { pub fn index_to_id(&self, index: ValidatorIndex) -> Option<ValidatorId> {
self.context.index_mapping.get(&index).cloned() self.context.validators.get(index as usize).cloned()
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use substrate_keyring::Ed25519Keyring; use substrate_keyring::Sr25519Keyring;
use primitives::crypto::UncheckedInto; use primitives::crypto::UncheckedInto;
use polkadot_primitives::parachain::{BlockData, ConsolidatedIngress}; use polkadot_primitives::parachain::{BlockData, ConsolidatedIngress};
use futures::future; use futures::future;
@@ -617,11 +613,12 @@ mod tests {
let para_id = ParaId::from(1); let para_id = ParaId::from(1);
let parent_hash = Default::default(); let parent_hash = Default::default();
let local_key = Arc::new(Ed25519Keyring::Alice.pair()); let local_key = Sr25519Keyring::Alice.pair();
let local_id = local_key.public(); let local_id: ValidatorId = local_key.public().into();
let local_key: Arc<ValidatorPair> = Arc::new(local_key.into());
let validity_other_key = Ed25519Keyring::Bob.pair(); let validity_other_key = Sr25519Keyring::Bob.pair();
let validity_other = validity_other_key.public(); let validity_other: ValidatorId = validity_other_key.public().into();
let validity_other_index = 1; let validity_other_index = 1;
groups.insert(para_id, GroupInfo { groups.insert(para_id, GroupInfo {
@@ -630,9 +627,9 @@ mod tests {
}); });
let shared_table = SharedTable::new( let shared_table = SharedTable::new(
&[local_id, validity_other], [local_id, validity_other].to_vec(),
groups, groups,
local_key.clone(), Some(local_key.clone()),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None, None,
@@ -651,7 +648,7 @@ mod tests {
let candidate_statement = GenericStatement::Candidate(candidate); let candidate_statement = GenericStatement::Candidate(candidate);
let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key, &parent_hash); let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key.into(), &parent_hash);
let signed_statement = ::table::generic::SignedStatement { let signed_statement = ::table::generic::SignedStatement {
statement: candidate_statement, statement: candidate_statement,
signature: signature.into(), signature: signature.into(),
@@ -671,11 +668,12 @@ mod tests {
let para_id = ParaId::from(1); let para_id = ParaId::from(1);
let parent_hash = Default::default(); let parent_hash = Default::default();
let local_key = Arc::new(Ed25519Keyring::Alice.pair()); let local_key = Sr25519Keyring::Alice.pair();
let local_id = local_key.public(); let local_id: ValidatorId = local_key.public().into();
let local_key: Arc<ValidatorPair> = Arc::new(local_key.into());
let validity_other_key = Ed25519Keyring::Bob.pair(); let validity_other_key = Sr25519Keyring::Bob.pair();
let validity_other = validity_other_key.public(); let validity_other: ValidatorId = validity_other_key.public().into();
let validity_other_index = 1; let validity_other_index = 1;
groups.insert(para_id, GroupInfo { groups.insert(para_id, GroupInfo {
@@ -684,9 +682,9 @@ mod tests {
}); });
let shared_table = SharedTable::new( let shared_table = SharedTable::new(
&[local_id, validity_other], [local_id, validity_other].to_vec(),
groups, groups,
local_key.clone(), Some(local_key.clone()),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None, None,
@@ -705,7 +703,7 @@ mod tests {
let candidate_statement = GenericStatement::Candidate(candidate); let candidate_statement = GenericStatement::Candidate(candidate);
let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key, &parent_hash); let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key.into(), &parent_hash);
let signed_statement = ::table::generic::SignedStatement { let signed_statement = ::table::generic::SignedStatement {
statement: candidate_statement, statement: candidate_statement,
signature: signature.into(), signature: signature.into(),
@@ -806,11 +804,12 @@ mod tests {
let para_id = ParaId::from(1); let para_id = ParaId::from(1);
let parent_hash = Default::default(); let parent_hash = Default::default();
let local_key = Arc::new(Ed25519Keyring::Alice.pair()); let local_key = Sr25519Keyring::Alice.pair();
let local_id = local_key.public(); let local_id: ValidatorId = local_key.public().into();
let local_key: Arc<ValidatorPair> = Arc::new(local_key.into());
let validity_other_key = Ed25519Keyring::Bob.pair(); let validity_other_key = Sr25519Keyring::Bob.pair();
let validity_other = validity_other_key.public(); let validity_other: ValidatorId = validity_other_key.public().into();
let validity_other_index = 1; let validity_other_index = 1;
groups.insert(para_id, GroupInfo { groups.insert(para_id, GroupInfo {
@@ -819,9 +818,9 @@ mod tests {
}); });
let shared_table = SharedTable::new( let shared_table = SharedTable::new(
&[local_id, validity_other], [local_id, validity_other].to_vec(),
groups, groups,
local_key.clone(), Some(local_key.clone()),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None, None,
@@ -841,7 +840,7 @@ mod tests {
let hash = candidate.hash(); let hash = candidate.hash();
let candidate_statement = GenericStatement::Candidate(candidate); let candidate_statement = GenericStatement::Candidate(candidate);
let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key, &parent_hash); let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key.into(), &parent_hash);
let signed_statement = ::table::generic::SignedStatement { let signed_statement = ::table::generic::SignedStatement {
statement: candidate_statement, statement: candidate_statement,
signature: signature.into(), signature: signature.into(),
@@ -872,11 +871,12 @@ mod tests {
let extrinsic = Extrinsic { outgoing_messages: Vec::new() }; let extrinsic = Extrinsic { outgoing_messages: Vec::new() };
let parent_hash = Default::default(); let parent_hash = Default::default();
let local_key = Arc::new(Ed25519Keyring::Alice.pair()); let local_key = Sr25519Keyring::Alice.pair();
let local_id = local_key.public(); let local_id: ValidatorId = local_key.public().into();
let local_key: Arc<ValidatorPair> = Arc::new(local_key.into());
let validity_other_key = Ed25519Keyring::Bob.pair(); let validity_other_key = Sr25519Keyring::Bob.pair();
let validity_other = validity_other_key.public(); let validity_other: ValidatorId = validity_other_key.public().into();
groups.insert(para_id, GroupInfo { groups.insert(para_id, GroupInfo {
validity_guarantors: [local_id.clone(), validity_other.clone()].iter().cloned().collect(), validity_guarantors: [local_id.clone(), validity_other.clone()].iter().cloned().collect(),
@@ -884,9 +884,9 @@ mod tests {
}); });
let shared_table = SharedTable::new( let shared_table = SharedTable::new(
&[local_id, validity_other], [local_id, validity_other].to_vec(),
groups, groups,
local_key.clone(), Some(local_key.clone()),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None, None,
@@ -908,7 +908,7 @@ mod tests {
candidate, candidate,
pov_block, pov_block,
extrinsic, extrinsic,
)); )).unwrap();
assert!(shared_table.inner.lock().validated.get(&hash).expect("validation has started").is_done()); assert!(shared_table.inner.lock().validated.get(&hash).expect("validation has started").is_done());
@@ -919,29 +919,4 @@ mod tests {
assert!(a.is_none()); assert!(a.is_none());
} }
#[test]
fn index_mapping_from_authorities() {
let authorities_set: &[&[_]] = &[
&[],
&[Ed25519Keyring::Alice.pair().public()],
&[Ed25519Keyring::Alice.pair().public(), Ed25519Keyring::Bob.pair().public()],
&[Ed25519Keyring::Bob.pair().public(), Ed25519Keyring::Alice.pair().public()],
&[Ed25519Keyring::Alice.pair().public(), Ed25519Keyring::Bob.pair().public(), Ed25519Keyring::Charlie.pair().public()],
&[Ed25519Keyring::Charlie.pair().public(), Ed25519Keyring::Bob.pair().public(), Ed25519Keyring::Alice.pair().public()],
];
for authorities in authorities_set {
let shared_table = SharedTable::new(
authorities,
HashMap::new(),
Arc::new(Ed25519Keyring::Alice.pair()),
Default::default(),
ExtrinsicStore::new_in_memory(),
None,
);
let expected_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect();
assert_eq!(shared_table.context.index_mapping, expected_mapping);
}
}
} }