mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
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:
Generated
+756
-536
File diff suppressed because it is too large
Load Diff
@@ -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" }
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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 {:?}",
|
||||||
|
|||||||
@@ -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()))
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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,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))]
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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}};
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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
@@ -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 _))
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user