mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 04:41: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" }
|
||||
parking_lot = "0.9.0"
|
||||
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" }
|
||||
kvdb = { 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.
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
use kvdb_rocksdb::{Database, DatabaseConfig};
|
||||
use polkadot_primitives::Hash;
|
||||
|
||||
@@ -26,15 +26,15 @@ pub enum ChainSpec {
|
||||
Development,
|
||||
/// Whatever the current runtime is, with simple Alice/Bob auths.
|
||||
LocalTestnet,
|
||||
/// The PoC-3 era testnet.
|
||||
Alexander,
|
||||
/// The Kusama network.
|
||||
Kusama,
|
||||
/// Whatever the current runtime is with the "global testnet" defaults.
|
||||
StagingTestnet,
|
||||
}
|
||||
|
||||
impl Default for ChainSpec {
|
||||
fn default() -> Self {
|
||||
ChainSpec::Alexander
|
||||
ChainSpec::Kusama
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ impl Default for ChainSpec {
|
||||
impl ChainSpec {
|
||||
pub(crate) fn load(self) -> Result<service::ChainSpec, String> {
|
||||
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::LocalTestnet => service::chain_spec::local_testnet_config(),
|
||||
ChainSpec::StagingTestnet => service::chain_spec::staging_testnet_config(),
|
||||
@@ -53,7 +53,7 @@ impl ChainSpec {
|
||||
match s {
|
||||
"dev" => Some(ChainSpec::Development),
|
||||
"local" => Some(ChainSpec::LocalTestnet),
|
||||
"poc-3" | "alex" | "alexander" => Some(ChainSpec::Alexander),
|
||||
"kusama" => Some(ChainSpec::Kusama),
|
||||
"staging" => Some(ChainSpec::StagingTestnet),
|
||||
"" => Some(ChainSpec::default()),
|
||||
_ => None,
|
||||
|
||||
@@ -9,11 +9,9 @@ edition = "2018"
|
||||
futures = "0.1.17"
|
||||
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" }
|
||||
parity-codec = "4.1"
|
||||
primitives = { package = "substrate-primitives", 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" }
|
||||
aura = { package = "substrate-consensus-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
polkadot-runtime = { path = "../runtime", version = "0.1" }
|
||||
polkadot-primitives = { path = "../primitives", version = "0.1" }
|
||||
polkadot-cli = { path = "../cli" }
|
||||
|
||||
@@ -53,12 +53,12 @@ use futures::{future, Stream, Future, IntoFuture};
|
||||
use futures03::{TryStreamExt as _, StreamExt as _};
|
||||
use log::{info, warn};
|
||||
use client::BlockchainEvents;
|
||||
use primitives::{ed25519, Pair};
|
||||
use primitives::Pair;
|
||||
use polkadot_primitives::{
|
||||
BlockId, SessionKey, Hash, Block,
|
||||
BlockId, Hash, Block,
|
||||
parachain::{
|
||||
self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId, Extrinsic,
|
||||
PoVBlock, Status as ParachainStatus,
|
||||
PoVBlock, Status as ParachainStatus, ValidatorId, CollatorPair,
|
||||
}
|
||||
};
|
||||
use polkadot_cli::{
|
||||
@@ -69,7 +69,6 @@ use polkadot_network::validation::{SessionParams, ValidationNetwork};
|
||||
use polkadot_network::NetworkService;
|
||||
use tokio::timer::Timeout;
|
||||
use consensus_common::SelectChain;
|
||||
use aura::AuraApi;
|
||||
|
||||
pub use polkadot_cli::VersionInfo;
|
||||
pub use polkadot_network::validation::Incoming;
|
||||
@@ -177,7 +176,7 @@ pub fn collate<'a, R, P>(
|
||||
parachain_status: ParachainStatus,
|
||||
relay_context: R,
|
||||
para_context: P,
|
||||
key: Arc<ed25519::Pair>,
|
||||
key: Arc<CollatorPair>,
|
||||
)
|
||||
-> impl Future<Item=parachain::Collation, Error=Error<R::Error>> + 'a
|
||||
where
|
||||
@@ -230,7 +229,7 @@ pub fn collate<'a, R, P>(
|
||||
struct ApiContext<P, E> {
|
||||
network: Arc<ValidationNetwork<P, E, NetworkService, TaskExecutor>>,
|
||||
parent_hash: Hash,
|
||||
authorities: Vec<SessionKey>,
|
||||
validators: Vec<ValidatorId>,
|
||||
}
|
||||
|
||||
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 {
|
||||
local_session_key: None,
|
||||
parent_hash: self.parent_hash,
|
||||
authorities: self.authorities.clone(),
|
||||
authorities: self.validators.clone(),
|
||||
}).map_err(|e| format!("unable to instantiate validation session: {:?}", e));
|
||||
|
||||
Box::new(future::ok(ConsolidatedIngress(Vec::new())))
|
||||
@@ -259,7 +258,7 @@ struct CollationNode<P, E> {
|
||||
build_parachain_context: P,
|
||||
exit: E,
|
||||
para_id: ParaId,
|
||||
key: Arc<ed25519::Pair>,
|
||||
key: Arc<CollatorPair>,
|
||||
}
|
||||
|
||||
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(())),
|
||||
};
|
||||
|
||||
let authorities = try_fr!(api.authorities(&id));
|
||||
let validators = try_fr!(api.validators(&id));
|
||||
|
||||
let targets = compute_targets(
|
||||
para_id,
|
||||
authorities.as_slice(),
|
||||
validators.as_slice(),
|
||||
try_fr!(api.duty_roster(&id)),
|
||||
);
|
||||
|
||||
let context = ApiContext {
|
||||
network: validation_network,
|
||||
parent_hash: relay_parent,
|
||||
authorities,
|
||||
validators,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
roster.validator_duty.iter().enumerate()
|
||||
@@ -433,7 +432,7 @@ pub fn run_collator<P, E>(
|
||||
build_parachain_context: P,
|
||||
para_id: ParaId,
|
||||
exit: E,
|
||||
key: Arc<ed25519::Pair>,
|
||||
key: Arc<CollatorPair>,
|
||||
version: VersionInfo,
|
||||
) -> polkadot_cli::error::Result<()> where
|
||||
P: BuildParachainContext + Send + 'static,
|
||||
@@ -450,7 +449,7 @@ pub fn run_collator<P, E>(
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
use polkadot_primitives::parachain::{OutgoingMessage, FeeSchedule};
|
||||
use keyring::Ed25519Keyring;
|
||||
use keyring::Sr25519Keyring;
|
||||
use super::*;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
@@ -540,7 +539,7 @@ mod tests {
|
||||
},
|
||||
context.clone(),
|
||||
DummyParachainContext,
|
||||
Ed25519Keyring::Alice.pair().into(),
|
||||
Arc::new(Sr25519Keyring::Alice.pair().into()),
|
||||
).wait().unwrap();
|
||||
|
||||
// ascending order by root.
|
||||
|
||||
@@ -7,6 +7,6 @@ edition = "2018"
|
||||
[dependencies]
|
||||
primitives = { package = "polkadot-primitives", path = "../primitives" }
|
||||
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" }
|
||||
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.
|
||||
//! 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 primitives::{Hash as H256, BlakeTwo256, HashT};
|
||||
use primitives::parachain::{BlockData, Extrinsic};
|
||||
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;
|
||||
|
||||
@@ -187,13 +187,14 @@ pub fn reconstruct<'a, I: 'a>(n_validators: usize, chunks: I)
|
||||
|
||||
// lazily decode from the data shards.
|
||||
Decode::decode(&mut ShardInput {
|
||||
remaining_len: shard_len.map(|s| s * params.data_shards).unwrap_or(0),
|
||||
cur_shard: None,
|
||||
shards: shards.iter()
|
||||
.map(|x| x.as_ref())
|
||||
.take(params.data_shards)
|
||||
.map(|x| x.expect("all data shards have been recovered; qed"))
|
||||
.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
|
||||
@@ -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> {
|
||||
let mut trie_storage: MemoryDB<Blake2Hasher> = MemoryDB::default();
|
||||
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)?;
|
||||
@@ -278,21 +279,26 @@ pub fn branch_hash(root: &H256, branch_nodes: &[Vec<u8>], index: usize) -> Resul
|
||||
);
|
||||
|
||||
match res {
|
||||
Ok(Some(Some(hash))) => Ok(hash),
|
||||
Ok(Some(None)) => Err(Error::InvalidBranchProof), // hash failed to decode
|
||||
Ok(Some(Ok(hash))) => Ok(hash),
|
||||
Ok(Some(Err(_))) => Err(Error::InvalidBranchProof), // hash failed to decode
|
||||
Ok(None) => Err(Error::BranchOutOfBounds),
|
||||
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> {
|
||||
remaining_len: usize,
|
||||
shards: I,
|
||||
cur_shard: Option<(&'a [u8], usize)>,
|
||||
}
|
||||
|
||||
impl<'a, I: Iterator<Item=&'a [u8]>> parity_codec::Input for ShardInput<'a, I> {
|
||||
fn read(&mut self, into: &mut [u8]) -> usize {
|
||||
impl<'a, I: Iterator<Item=&'a [u8]>> codec::Input for ShardInput<'a, I> {
|
||||
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;
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
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" }
|
||||
polkadot-validation = { path = "../validation" }
|
||||
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-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.
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
use polkadot_primitives::Hash;
|
||||
use polkadot_primitives::parachain::{CollatorId, Id as ParaId, Collation};
|
||||
use substrate_network::PeerId;
|
||||
|
||||
@@ -22,8 +22,8 @@ use substrate_network::consensus_gossip::{
|
||||
ValidatorContext, MessageIntent, ConsensusMessage,
|
||||
};
|
||||
use polkadot_validation::{GenericStatement, SignedStatement};
|
||||
use polkadot_primitives::{Block, Hash, SessionKey, parachain::ValidatorIndex};
|
||||
use parity_codec::{Decode, Encode};
|
||||
use polkadot_primitives::{Block, Hash, parachain::{ValidatorIndex, ValidatorId}};
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
@@ -218,9 +218,9 @@ impl RegisteredMessageValidator {
|
||||
#[derive(Default)]
|
||||
pub(crate) struct MessageValidationData {
|
||||
/// The authorities at a block.
|
||||
pub(crate) authorities: Vec<SessionKey>,
|
||||
/// Mapping from validator index to `SessionKey`.
|
||||
pub(crate) index_mapping: HashMap<ValidatorIndex, SessionKey>,
|
||||
pub(crate) authorities: Vec<ValidatorId>,
|
||||
/// Mapping from validator index to `ValidatorId`.
|
||||
pub(crate) index_mapping: HashMap<ValidatorIndex, ValidatorId>,
|
||||
}
|
||||
|
||||
impl MessageValidationData {
|
||||
@@ -481,15 +481,15 @@ impl<O: KnownOracle + ?Sized> network_gossip::Validator<Block> for MessageValida
|
||||
-> GossipValidationResult<Hash>
|
||||
{
|
||||
let (res, cost_benefit) = match GossipMessage::decode(&mut data) {
|
||||
None => (GossipValidationResult::Discard, cost::MALFORMED_MESSAGE),
|
||||
Some(GossipMessage::Neighbor(VersionedNeighborPacket::V1(packet))) => {
|
||||
Err(_) => (GossipValidationResult::Discard, cost::MALFORMED_MESSAGE),
|
||||
Ok(GossipMessage::Neighbor(VersionedNeighborPacket::V1(packet))) => {
|
||||
let (res, cb, topics) = self.inner.write().validate_neighbor_packet(sender, packet);
|
||||
for new_topic in topics {
|
||||
context.send_topic(sender, new_topic, false);
|
||||
}
|
||||
(res, cb)
|
||||
}
|
||||
Some(GossipMessage::Statement(statement)) => {
|
||||
Ok(GossipMessage::Statement(statement)) => {
|
||||
let (res, cb) = self.inner.write().validate_statement(statement);
|
||||
if let GossipValidationResult::ProcessAndKeep(ref topic) = res {
|
||||
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[..]) {
|
||||
Some(GossipMessage::Statement(statement)) => {
|
||||
Ok(GossipMessage::Statement(statement)) => {
|
||||
let signed = statement.signed_statement;
|
||||
|
||||
match signed.statement {
|
||||
@@ -573,7 +573,7 @@ mod tests {
|
||||
use parking_lot::Mutex;
|
||||
use polkadot_primitives::parachain::{CandidateReceipt, HeadData};
|
||||
use substrate_primitives::crypto::UncheckedInto;
|
||||
use substrate_primitives::ed25519::Signature as Ed25519Signature;
|
||||
use substrate_primitives::sr25519::Signature as Sr25519Signature;
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
enum ContextEvent {
|
||||
@@ -669,7 +669,7 @@ mod tests {
|
||||
relay_parent: hash_a,
|
||||
signed_statement: SignedStatement {
|
||||
statement: GenericStatement::Candidate(candidate_receipt),
|
||||
signature: Ed25519Signature([255u8; 64]),
|
||||
signature: Sr25519Signature([255u8; 64]).into(),
|
||||
sender: 1,
|
||||
}
|
||||
});
|
||||
@@ -786,7 +786,7 @@ mod tests {
|
||||
relay_parent: hash_a,
|
||||
signed_statement: SignedStatement {
|
||||
statement: GenericStatement::Valid(c_hash),
|
||||
signature: Ed25519Signature([255u8; 64]),
|
||||
signature: Sr25519Signature([255u8; 64]).into(),
|
||||
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 gossip;
|
||||
|
||||
use parity_codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode};
|
||||
use futures::sync::oneshot;
|
||||
use polkadot_primitives::{Block, SessionKey, Hash, Header};
|
||||
use polkadot_primitives::{Block, Hash, Header};
|
||||
use polkadot_primitives::parachain::{
|
||||
Id as ParaId, BlockData, CollatorId, CandidateReceipt, Collation, PoVBlock,
|
||||
StructuredUnroutedIngress,
|
||||
StructuredUnroutedIngress, ValidatorId
|
||||
};
|
||||
use substrate_network::{
|
||||
PeerId, RequestId, Context, StatusMessage as GenericFullStatus,
|
||||
@@ -78,7 +78,7 @@ pub struct Status {
|
||||
}
|
||||
|
||||
struct PoVBlockRequest {
|
||||
attempted_peers: HashSet<SessionKey>,
|
||||
attempted_peers: HashSet<ValidatorId>,
|
||||
validation_session_parent: Hash,
|
||||
candidate_hash: Hash,
|
||||
block_data_hash: Hash,
|
||||
@@ -115,8 +115,8 @@ enum CollatorState {
|
||||
}
|
||||
|
||||
impl CollatorState {
|
||||
fn send_key<F: FnMut(Message)>(&mut self, key: SessionKey, mut f: F) {
|
||||
f(Message::SessionKey(key));
|
||||
fn send_key<F: FnMut(Message)>(&mut self, key: ValidatorId, mut f: F) {
|
||||
f(Message::ValidatorId(key));
|
||||
if let CollatorState::RolePending(role) = *self {
|
||||
f(Message::CollatorRole(role));
|
||||
*self = CollatorState::Primed(Some(role));
|
||||
@@ -160,7 +160,7 @@ pub enum Message {
|
||||
/// As a validator, tell the peer your current session key.
|
||||
// TODO: do this with a cryptographic proof of some kind
|
||||
// https://github.com/paritytech/polkadot/issues/47
|
||||
SessionKey(SessionKey),
|
||||
ValidatorId(ValidatorId),
|
||||
/// Requesting parachain proof-of-validation block (relay_parent, candidate_hash).
|
||||
RequestPovBlock(RequestId, Hash, Hash),
|
||||
/// 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>,
|
||||
collating_for: Option<(CollatorId, ParaId)>,
|
||||
collators: CollatorPool,
|
||||
validators: HashMap<SessionKey, PeerId>,
|
||||
validators: HashMap<ValidatorId, PeerId>,
|
||||
local_collations: LocalCollations<Collation>,
|
||||
live_validation_sessions: LiveValidationSessions,
|
||||
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) {
|
||||
trace!(target: "p_net", "Polkadot message from {}: {:?}", who, 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) => {
|
||||
let pov_block = self.live_validation_sessions.with_pov_block(
|
||||
&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) {
|
||||
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) {
|
||||
let local_status = match Status::decode(&mut &status.chain_status[..]) {
|
||||
Some(status) => status,
|
||||
None => {
|
||||
Status { collating_for: None }
|
||||
}
|
||||
};
|
||||
let local_status = Status::decode(&mut &status.chain_status[..])
|
||||
.unwrap_or_else(|_| Status { collating_for: None });
|
||||
|
||||
let validator = status.roles.contains(substrate_network::config::Roles::AUTHORITY);
|
||||
|
||||
@@ -575,11 +571,11 @@ impl Specialization<Block> for PolkadotProtocol {
|
||||
message: Vec<u8>,
|
||||
) {
|
||||
match Message::decode(&mut &message[..]) {
|
||||
Some(msg) => {
|
||||
Ok(msg) => {
|
||||
ctx.report_peer(who.clone(), benefit::VALID_FORMAT);
|
||||
self.on_polkadot_message(ctx, who, msg)
|
||||
},
|
||||
None => {
|
||||
Err(_) => {
|
||||
trace!(target: "p_net", "Bad message from {}", who);
|
||||
ctx.report_peer(who, cost::INVALID_FORMAT);
|
||||
}
|
||||
@@ -684,7 +680,7 @@ impl PolkadotProtocol {
|
||||
&mut self,
|
||||
ctx: &mut dyn Context<Block>,
|
||||
relay_parent: Hash,
|
||||
targets: HashSet<SessionKey>,
|
||||
targets: HashSet<ValidatorId>,
|
||||
collation: Collation,
|
||||
) {
|
||||
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,
|
||||
//! 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 std::collections::{HashMap, HashSet};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
const LIVE_FOR: Duration = Duration::from_secs(60 * 5);
|
||||
|
||||
struct LocalCollation<C> {
|
||||
targets: HashSet<SessionKey>,
|
||||
targets: HashSet<ValidatorId>,
|
||||
collation: C,
|
||||
live_since: Instant,
|
||||
}
|
||||
|
||||
/// Tracker for locally collated values and which validators to send them to.
|
||||
pub struct LocalCollations<C> {
|
||||
primary_for: HashSet<SessionKey>,
|
||||
primary_for: HashSet<ValidatorId>,
|
||||
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
|
||||
/// 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 {
|
||||
Role::Backup => {
|
||||
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
|
||||
/// 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) {
|
||||
self.primary_for.insert(new_key.clone());
|
||||
|
||||
@@ -81,7 +79,7 @@ impl<C: Clone> LocalCollations<C> {
|
||||
}
|
||||
|
||||
/// Validator disconnected.
|
||||
pub fn on_disconnect(&mut self, key: &SessionKey) {
|
||||
pub fn on_disconnect(&mut self, key: &ValidatorId) {
|
||||
self.primary_for.remove(key);
|
||||
}
|
||||
|
||||
@@ -99,10 +97,10 @@ impl<C: Clone> LocalCollations<C> {
|
||||
pub fn add_collation<'a>(
|
||||
&'a mut self,
|
||||
relay_parent: Hash,
|
||||
targets: HashSet<SessionKey>,
|
||||
targets: HashSet<ValidatorId>,
|
||||
collation: C
|
||||
)
|
||||
-> impl Iterator<Item=(SessionKey, C)> + 'a
|
||||
-> impl Iterator<Item=(ValidatorId, C)> + 'a
|
||||
{
|
||||
self.local_collations.insert(relay_parent, LocalCollation {
|
||||
targets,
|
||||
@@ -119,7 +117,7 @@ impl<C: Clone> LocalCollations<C> {
|
||||
.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()
|
||||
.filter(|&(_, ref v)| v.targets.contains(key))
|
||||
.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(),
|
||||
);
|
||||
|
||||
|
||||
// propagate the statement.
|
||||
// consider something more targeted than gossip in the future.
|
||||
let statement = GossipStatement::new(
|
||||
parent_hash,
|
||||
table.import_validated(validated),
|
||||
match table.import_validated(validated) {
|
||||
None => return,
|
||||
Some(s) => s,
|
||||
}
|
||||
);
|
||||
|
||||
network.gossip_message(attestation_topic, statement.into());
|
||||
})
|
||||
.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) {
|
||||
// produce a signed statement
|
||||
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(
|
||||
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.
|
||||
|
||||
@@ -21,13 +21,13 @@ use super::{PolkadotProtocol, Status, Message, FullStatus};
|
||||
use crate::validation::SessionParams;
|
||||
|
||||
use polkadot_validation::GenericStatement;
|
||||
use polkadot_primitives::{Block, Hash, SessionKey};
|
||||
use polkadot_primitives::{Block, Hash};
|
||||
use polkadot_primitives::parachain::{
|
||||
CandidateReceipt, HeadData, PoVBlock, BlockData, CollatorId, ValidatorId,
|
||||
StructuredUnroutedIngress,
|
||||
StructuredUnroutedIngress
|
||||
};
|
||||
use substrate_primitives::crypto::UncheckedInto;
|
||||
use parity_codec::Encode;
|
||||
use codec::Encode;
|
||||
use substrate_network::{
|
||||
PeerId, Context, config::Roles, message::generic::ConsensusMessage,
|
||||
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 {
|
||||
local_session_key: Some(local_key),
|
||||
parent_hash,
|
||||
@@ -131,13 +131,13 @@ fn sends_session_key() {
|
||||
let mut ctx = TestContext::default();
|
||||
let params = make_validation_session(parent_hash, local_key.clone());
|
||||
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();
|
||||
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();
|
||||
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.
|
||||
{
|
||||
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!(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();
|
||||
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)));
|
||||
|
||||
}
|
||||
@@ -340,8 +340,8 @@ fn many_session_keys() {
|
||||
let status = Status { collating_for: None };
|
||||
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, Message::SessionKey(local_key_b.clone())));
|
||||
assert!(ctx.has_message(peer_a.clone(), Message::ValidatorId(local_key_a.clone())));
|
||||
assert!(ctx.has_message(peer_a, Message::ValidatorId(local_key_b.clone())));
|
||||
}
|
||||
|
||||
let peer_b = PeerId::random();
|
||||
@@ -354,7 +354,7 @@ fn many_session_keys() {
|
||||
let status = Status { collating_for: None };
|
||||
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, Message::SessionKey(local_key_b.clone())));
|
||||
assert!(!ctx.has_message(peer_b.clone(), Message::ValidatorId(local_key_a.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::consensus_gossip::TopicNotification;
|
||||
use substrate_primitives::{NativeOrEncoded, ExecutionContext};
|
||||
use substrate_keyring::Ed25519Keyring;
|
||||
use substrate_keyring::Sr25519Keyring;
|
||||
use crate::PolkadotProtocol;
|
||||
|
||||
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::{
|
||||
Id as ParaId, Chain, DutyRoster, ParachainHost, OutgoingMessage,
|
||||
ValidatorId, StructuredUnroutedIngress, BlockIngressRoots, Status,
|
||||
@@ -41,7 +41,7 @@ use sr_primitives::traits::{ApiRef, ProvideRuntimeApi};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use futures::{prelude::*, sync::mpsc};
|
||||
use parity_codec::Encode;
|
||||
use codec::Encode;
|
||||
|
||||
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 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 (group_info, _) = ::polkadot_validation::make_group_info(
|
||||
DutyRoster { validator_duty: data.duties.clone() },
|
||||
&data.validators, // only possible as long as parachain crypto === aura crypto
|
||||
SessionKey::from(*local_key)
|
||||
Some(sr_pair.public().into()),
|
||||
).unwrap();
|
||||
|
||||
Arc::new(SharedTable::new(
|
||||
data.validators.as_slice(),
|
||||
data.validators.clone(),
|
||||
group_info,
|
||||
Arc::new(local_key.pair()),
|
||||
Some(Arc::new(local_key)),
|
||||
parent_hash,
|
||||
store,
|
||||
None,
|
||||
|
||||
@@ -28,10 +28,10 @@ use substrate_network::consensus_gossip::{
|
||||
use polkadot_validation::{
|
||||
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::{
|
||||
Id as ParaId, Collation, Extrinsic, ParachainHost, CandidateReceipt, CollatorId,
|
||||
ValidatorId, PoVBlock, ValidatorIndex,
|
||||
ValidatorId, PoVBlock, ValidatorIndex
|
||||
};
|
||||
|
||||
use futures::prelude::*;
|
||||
@@ -54,7 +54,7 @@ use super::PolkadotProtocol;
|
||||
|
||||
pub use polkadot_validation::Incoming;
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// An executor suitable for dispatching async consensus tasks.
|
||||
pub trait Executor {
|
||||
@@ -120,7 +120,7 @@ impl Stream for GossipMessageStream {
|
||||
};
|
||||
|
||||
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))))
|
||||
}
|
||||
}
|
||||
@@ -186,11 +186,11 @@ impl NetworkService for super::NetworkService {
|
||||
/// Params to a current validation session.
|
||||
pub struct SessionParams {
|
||||
/// The local session key.
|
||||
pub local_session_key: Option<SessionKey>,
|
||||
pub local_session_key: Option<ValidatorId>,
|
||||
/// The parent hash.
|
||||
pub parent_hash: Hash,
|
||||
/// The authorities.
|
||||
pub authorities: Vec<SessionKey>,
|
||||
pub authorities: Vec<ValidatorId>,
|
||||
}
|
||||
|
||||
/// 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 build_fetcher = self.instantiate_session(SessionParams {
|
||||
local_session_key: Some(local_session_key),
|
||||
local_session_key,
|
||||
parent_hash,
|
||||
authorities: authorities.to_vec(),
|
||||
});
|
||||
|
||||
@@ -6,11 +6,10 @@ description = "Types and utilities for creating and working with parachains"
|
||||
edition = "2018"
|
||||
|
||||
[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 }
|
||||
derive_more = { version = "0.14", optional = true }
|
||||
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 }
|
||||
lazy_static = { version = "1.3.0", optional = true }
|
||||
parking_lot = { version = "0.7.1", optional = true }
|
||||
@@ -27,4 +26,14 @@ halt = { path = "../test-parachains/halt" }
|
||||
[features]
|
||||
default = ["std"]
|
||||
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")]
|
||||
pub mod wasm_api;
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
use rstd::vec::Vec;
|
||||
|
||||
struct TrailingZeroInput<'a>(&'a [u8]);
|
||||
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
|
||||
}
|
||||
}
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Validation parameters for evaluating the parachain validity function.
|
||||
// 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 {
|
||||
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.
|
||||
#[derive(PartialEq, Eq, Decode)]
|
||||
#[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 = 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 {
|
||||
return Err(Error::BadReturn);
|
||||
@@ -445,8 +445,7 @@ pub fn validate_candidate_internal<E: Externalities>(
|
||||
}
|
||||
|
||||
ValidationResult::decode(&mut &mem[return_offset..][..len])
|
||||
.ok_or_else(|| Error::BadReturn)
|
||||
.map_err(Into::into)
|
||||
.map_err(|_| Error::BadReturn.into())
|
||||
})
|
||||
}
|
||||
_ => 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 mut header_buf: &[u8] = 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);
|
||||
let (code, rest) = rest.split_at_mut(MAX_CODE_MEM);
|
||||
let (code, _) = code.split_at_mut(header.code_size as usize);
|
||||
|
||||
@@ -169,7 +169,7 @@ fn processes_messages() {
|
||||
};
|
||||
|
||||
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(
|
||||
TEST_CODE,
|
||||
|
||||
@@ -6,14 +6,16 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" }
|
||||
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]
|
||||
substrate-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
@@ -22,7 +24,7 @@ pretty_assertions = "0.5.1"
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"parity-codec/std",
|
||||
"parity-scale-codec/std",
|
||||
"primitives/std",
|
||||
"substrate-client/std",
|
||||
"rstd/std",
|
||||
@@ -30,5 +32,6 @@ std = [
|
||||
"runtime_primitives/std",
|
||||
"serde",
|
||||
"polkadot-parachain/std",
|
||||
"bitvec/std"
|
||||
"bitvec/std",
|
||||
"babe/std"
|
||||
]
|
||||
|
||||
@@ -21,18 +21,19 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use runtime_primitives::{generic, AnySignature};
|
||||
use primitives::ed25519;
|
||||
|
||||
pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT, Verify};
|
||||
|
||||
pub mod parachain;
|
||||
|
||||
pub use parity_codec::Compact;
|
||||
pub use parity_scale_codec::Compact;
|
||||
|
||||
/// An index to a block.
|
||||
/// 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 = u64;
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
/// 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.
|
||||
/// Equipped with logic for possibly "unsigned" messages.
|
||||
@@ -41,8 +42,7 @@ pub type Signature = AnySignature;
|
||||
/// Alias to an sr25519 or ed25519 key.
|
||||
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
|
||||
/// never know...
|
||||
/// The type for looking up accounts. We don't expect more than 4 billion of them.
|
||||
pub type AccountIndex = u32;
|
||||
|
||||
/// Identifier for a chain. 32-bit should be plenty.
|
||||
@@ -52,13 +52,7 @@ pub type ChainId = u32;
|
||||
pub type Hash = primitives::H256;
|
||||
|
||||
/// Index of a transaction in the relay chain. 32-bit should be plenty.
|
||||
pub type Nonce = u64;
|
||||
|
||||
/// Signature with which authorities sign blocks.
|
||||
pub type SessionSignature = ed25519::Signature;
|
||||
|
||||
/// Identity that authorities use.
|
||||
pub type SessionKey = ed25519::Public;
|
||||
pub type Nonce = u32;
|
||||
|
||||
/// The balance of an account.
|
||||
/// 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.
|
||||
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.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Block type.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::cmp::Ordering;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use parity_scale_codec::{Encode, Decode};
|
||||
use bitvec::vec::BitVec;
|
||||
use super::{Hash, Balance, BlockNumber};
|
||||
|
||||
@@ -27,32 +27,56 @@ use serde::{Serialize, Deserialize};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use primitives::bytes;
|
||||
use primitives::ed25519;
|
||||
use application_crypto::KeyTypeId;
|
||||
|
||||
pub use polkadot_parachain::{
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
///
|
||||
/// 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.
|
||||
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.
|
||||
pub type ValidatorIndex = u32;
|
||||
|
||||
/// A Parachain validator keypair.
|
||||
#[cfg(feature = "std")]
|
||||
pub type ValidatorPair = validator_app::Pair;
|
||||
|
||||
/// Signature with which parachain validators sign blocks.
|
||||
///
|
||||
/// 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.
|
||||
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.
|
||||
#[derive(Copy, Clone, PartialEq, Encode, Decode)]
|
||||
@@ -143,7 +167,7 @@ impl CandidateReceipt {
|
||||
|
||||
/// Check integrity vs. provided block data.
|
||||
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) {
|
||||
Ok(())
|
||||
@@ -292,11 +316,11 @@ pub enum ValidityAttestation {
|
||||
/// implicit validity attestation by issuing.
|
||||
/// This corresponds to issuance of a `Candidate` statement.
|
||||
#[codec(index = "1")]
|
||||
Implicit(CollatorSignature),
|
||||
Implicit(ValidatorSignature),
|
||||
/// An explicit attestation. This corresponds to issuance of a
|
||||
/// `Valid` statement.
|
||||
#[codec(index = "2")]
|
||||
Explicit(CollatorSignature),
|
||||
Explicit(ValidatorSignature),
|
||||
}
|
||||
|
||||
/// An attested candidate.
|
||||
|
||||
@@ -6,14 +6,14 @@ edition = "2018"
|
||||
build = "build.rs"
|
||||
|
||||
[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 }
|
||||
log = { version = "0.3", optional = true }
|
||||
serde = { version = "1.0", default-features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", 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" }
|
||||
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" }
|
||||
@@ -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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
@@ -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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
@@ -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" }
|
||||
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" }
|
||||
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]
|
||||
hex-literal = "0.2.0"
|
||||
@@ -48,7 +51,7 @@ libsecp256k1 = "0.2.1"
|
||||
tiny-keccak = "1.4.2"
|
||||
keyring = { package = "substrate-keyring", 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]
|
||||
wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.1" }
|
||||
@@ -60,7 +63,7 @@ std = [
|
||||
"bitvec/std",
|
||||
"primitives/std",
|
||||
"rustc-hex/std",
|
||||
"parity-codec/std",
|
||||
"codec/std",
|
||||
"inherents/std",
|
||||
"substrate-primitives/std",
|
||||
"client/std",
|
||||
@@ -68,7 +71,6 @@ std = [
|
||||
"rstd/std",
|
||||
"sr-io/std",
|
||||
"srml-support/std",
|
||||
"aura/std",
|
||||
"authorship/std",
|
||||
"balances/std",
|
||||
"collective/std",
|
||||
@@ -77,7 +79,9 @@ std = [
|
||||
"executive/std",
|
||||
"finality-tracker/std",
|
||||
"grandpa/std",
|
||||
"im-online/std",
|
||||
"indices/std",
|
||||
"membership/std",
|
||||
"sr-primitives/std",
|
||||
"session/std",
|
||||
"staking/std",
|
||||
@@ -90,5 +94,6 @@ std = [
|
||||
"serde/std",
|
||||
"log",
|
||||
"safe-mix/std",
|
||||
"consensus_aura/std",
|
||||
"babe/std",
|
||||
"babe-primitives/std",
|
||||
]
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
//! as well.
|
||||
|
||||
use rstd::prelude::*;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
use srml_support::{decl_storage, decl_module, ensure};
|
||||
|
||||
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::traits::{Currency, Get};
|
||||
use system::ensure_none;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
#[cfg(feature = "std")]
|
||||
use sr_primitives::traits::Zero;
|
||||
use sr_primitives::{
|
||||
@@ -200,7 +200,7 @@ mod tests {
|
||||
|
||||
use sr_io::with_externalities;
|
||||
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
|
||||
// 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};
|
||||
@@ -210,20 +210,20 @@ mod tests {
|
||||
impl_outer_origin! {
|
||||
pub enum Origin for Test {}
|
||||
}
|
||||
|
||||
// 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
|
||||
// configuration traits of modules we want to use.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const BlockHashCount: u32 = 250;
|
||||
pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024;
|
||||
pub const MaximumBlockLength: u32 = 4 * 1024 * 1024;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Call = ();
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
@@ -305,12 +305,12 @@ mod tests {
|
||||
// This function basically just builds a genesis storage key/value store according to
|
||||
// our desired mockup.
|
||||
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.
|
||||
t.extend(balances::GenesisConfig::<Test>::default().build_storage().unwrap().0);
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
balances::GenesisConfig::<Test>::default().assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::<Test>{
|
||||
claims: vec![(alice_eth(), 100)],
|
||||
}.build_storage().unwrap().0);
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,17 +19,31 @@ pub mod currency {
|
||||
use primitives::Balance;
|
||||
|
||||
pub const DOTS: Balance = 1_000_000_000_000;
|
||||
pub const BUCKS: Balance = DOTS / 100;
|
||||
pub const CENTS: Balance = BUCKS / 100;
|
||||
pub const DOLLARS: Balance = DOTS / 100;
|
||||
pub const CENTS: Balance = DOLLARS / 100;
|
||||
pub const MILLICENTS: Balance = CENTS / 1_000;
|
||||
}
|
||||
|
||||
|
||||
/// Time.
|
||||
pub mod time {
|
||||
pub const SECS_PER_BLOCK: u64 = 6;
|
||||
pub const MINUTES: u64 = 60 / SECS_PER_BLOCK;
|
||||
pub const HOURS: u64 = MINUTES * 60;
|
||||
pub const DAYS: u64 = HOURS * 24;
|
||||
use primitives::{Moment, BlockNumber};
|
||||
pub const MILLISECS_PER_BLOCK: Moment = 6000;
|
||||
pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000;
|
||||
|
||||
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.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! A module for manually curated GRANDPA set.
|
||||
|
||||
use {grandpa, system};
|
||||
use parity_codec::Decode;
|
||||
use codec::Decode;
|
||||
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Zero};
|
||||
use sr_primitives::weights::SimpleDispatchInfo;
|
||||
use rstd::prelude::*;
|
||||
@@ -79,7 +79,7 @@ decl_module! {
|
||||
let offset = (i * 4 % 32) as usize;
|
||||
|
||||
// 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.
|
||||
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 substrate_primitives::u32_trait::{_1, _2, _3, _4};
|
||||
use primitives::{
|
||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, SessionKey, Signature,
|
||||
parachain, AuraId
|
||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
|
||||
parachain,
|
||||
};
|
||||
use client::{
|
||||
block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult},
|
||||
@@ -44,6 +44,7 @@ use sr_primitives::{
|
||||
};
|
||||
use version::RuntimeVersion;
|
||||
use grandpa::{AuthorityId as GrandpaId, fg_primitives::{self, ScheduledChange}};
|
||||
use babe_primitives::AuthorityId as BabeId;
|
||||
use elections::VoteIndex;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use version::NativeVersion;
|
||||
@@ -51,6 +52,7 @@ use substrate_primitives::OpaqueMetadata;
|
||||
use srml_support::{
|
||||
parameter_types, construct_runtime, traits::{SplitTwoWays, Currency}
|
||||
};
|
||||
use im_online::AuthorityId as ImOnlineId;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use staking::StakerStatus;
|
||||
@@ -97,7 +99,7 @@ pub fn native_version() -> NativeVersion {
|
||||
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const BlockHashCount: BlockNumber = 250;
|
||||
pub const MaximumBlockWeight: Weight = 1_000_000_000;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
|
||||
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
|
||||
@@ -105,6 +107,7 @@ parameter_types! {
|
||||
|
||||
impl system::Trait for Runtime {
|
||||
type Origin = Origin;
|
||||
type Call = Call;
|
||||
type Index = Nonce;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
@@ -120,9 +123,14 @@ impl system::Trait for Runtime {
|
||||
type AvailableBlockRatio = AvailableBlockRatio;
|
||||
}
|
||||
|
||||
impl aura::Trait for Runtime {
|
||||
type HandleReport = aura::StakingSlasher<Runtime>;
|
||||
type AuthorityId = AuraId;
|
||||
parameter_types! {
|
||||
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
|
||||
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
|
||||
}
|
||||
|
||||
impl babe::Trait for Runtime {
|
||||
type EpochDuration = EpochDuration;
|
||||
type ExpectedBlockTime = ExpectedBlockTime;
|
||||
}
|
||||
|
||||
impl indices::Trait for Runtime {
|
||||
@@ -165,22 +173,22 @@ impl balances::Trait for Runtime {
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const MinimumPeriod: u64 = SECS_PER_BLOCK / 2;
|
||||
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
|
||||
}
|
||||
|
||||
impl timestamp::Trait for Runtime {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = Aura;
|
||||
type OnTimestampSet = Babe;
|
||||
type MinimumPeriod = MinimumPeriod;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const UncleGenerations: u64 = 0;
|
||||
pub const UncleGenerations: u32 = 0;
|
||||
}
|
||||
|
||||
// TODO: substrate#2986 implement this properly
|
||||
impl authorship::Trait for Runtime {
|
||||
type FindAuthor = ();
|
||||
type FindAuthor = session::FindAccountFromAuthorIndex<Self, Babe>;
|
||||
type UncleGenerations = UncleGenerations;
|
||||
type FilterUncle = ();
|
||||
type EventHandler = ();
|
||||
@@ -191,11 +199,17 @@ parameter_types! {
|
||||
pub const Offset: BlockNumber = 0;
|
||||
}
|
||||
|
||||
type SessionHandlers = (Grandpa, Aura);
|
||||
type SessionHandlers = (Grandpa, Babe, ImOnline, Parachains);
|
||||
impl_opaque_keys! {
|
||||
pub struct SessionKeys {
|
||||
#[id(key_types::ED25519)]
|
||||
pub ed25519: GrandpaId,
|
||||
#[id(key_types::GRANDPA)]
|
||||
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 {
|
||||
type OnSessionEnding = Staking;
|
||||
type SessionHandler = SessionHandlers;
|
||||
type ShouldEndSession = session::PeriodicSessions<Period, Offset>;
|
||||
type ShouldEndSession = Babe;
|
||||
type Event = Event;
|
||||
type Keys = SessionKeys;
|
||||
type SelectInitialValidators = Staking;
|
||||
@@ -243,11 +257,9 @@ parameter_types! {
|
||||
pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
pub const VotingPeriod: BlockNumber = 28 * 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 CooloffPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
|
||||
|
||||
pub const AttestationPeriod: BlockNumber = 60 * MINUTES * 3;
|
||||
pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
}
|
||||
|
||||
impl democracy::Trait for Runtime {
|
||||
@@ -259,26 +271,35 @@ impl democracy::Trait for Runtime {
|
||||
type VotingPeriod = VotingPeriod;
|
||||
type EmergencyVotingPeriod = EmergencyVotingPeriod;
|
||||
type MinimumDeposit = MinimumDeposit;
|
||||
type ExternalOrigin = collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilInstance>;
|
||||
type ExternalMajorityOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilInstance>;
|
||||
type ExternalPushOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalInstance>;
|
||||
type EmergencyOrigin = collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilInstance>;
|
||||
type CancellationOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilInstance>;
|
||||
type VetoOrigin = collective::EnsureMember<AccountId, CouncilInstance>;
|
||||
/// A straight majority of the council can decide what their next motion is.
|
||||
type ExternalOrigin = collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>;
|
||||
/// A super-majority can have the next scheduled referendum be a straight majority-carries vote.
|
||||
type ExternalMajorityOrigin = collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>;
|
||||
/// A unanimous council can have the next scheduled referendum be a straight default-carries
|
||||
/// (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 CouncilInstance = collective::Instance1;
|
||||
impl collective::Trait<CouncilInstance> for Runtime {
|
||||
type CouncilCollective = collective::Instance1;
|
||||
impl collective::Trait<CouncilCollective> for Runtime {
|
||||
type Origin = Origin;
|
||||
type Proposal = Call;
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const CandidacyBond: Balance = 10 * BUCKS;
|
||||
pub const VotingBond: Balance = 1 * BUCKS;
|
||||
pub const VotingFee: Balance = 2 * BUCKS;
|
||||
pub const CandidacyBond: Balance = 10 * DOLLARS;
|
||||
pub const VotingBond: Balance = 1 * DOLLARS;
|
||||
pub const VotingFee: Balance = 2 * DOLLARS;
|
||||
pub const PresentSlashPerVoter: Balance = 1 * CENTS;
|
||||
pub const CarryCount: u32 = 6;
|
||||
// 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 TechnicalInstance = collective::Instance2;
|
||||
impl collective::Trait<TechnicalInstance> for Runtime {
|
||||
type TechnicalCollective = collective::Instance2;
|
||||
impl collective::Trait<TechnicalCollective> for Runtime {
|
||||
type Origin = Origin;
|
||||
type Proposal = Call;
|
||||
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! {
|
||||
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 Burn: Permill = Permill::from_percent(50);
|
||||
}
|
||||
|
||||
impl treasury::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilInstance>;
|
||||
type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilInstance>;
|
||||
type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilCollective>;
|
||||
type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilCollective>;
|
||||
type Event = Event;
|
||||
type MintedForSpending = ();
|
||||
type ProposalRejection = ();
|
||||
@@ -332,6 +363,12 @@ impl treasury::Trait for Runtime {
|
||||
type Burn = Burn;
|
||||
}
|
||||
|
||||
impl im_online::Trait for Runtime {
|
||||
type Call = Call;
|
||||
type Event = Event;
|
||||
type UncheckedExtrinsic = UncheckedExtrinsic;
|
||||
}
|
||||
|
||||
impl grandpa::Trait for Runtime {
|
||||
type Event = Event;
|
||||
}
|
||||
@@ -347,6 +384,10 @@ impl finality_tracker::Trait for Runtime {
|
||||
type ReportLatency = ReportLatency;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const AttestationPeriod: BlockNumber = 50;
|
||||
}
|
||||
|
||||
impl attestations::Trait for Runtime {
|
||||
type AttestationPeriod = AttestationPeriod;
|
||||
type ValidatorIdentities = parachains::ValidatorIdentities<Runtime>;
|
||||
@@ -395,8 +436,8 @@ construct_runtime!(
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system::{Module, Call, Storage, Config, Event},
|
||||
Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
|
||||
Timestamp: timestamp::{Module, Call, Storage, Inherent},
|
||||
Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
|
||||
Authorship: authorship::{Module, Call, Storage},
|
||||
Indices: indices,
|
||||
Balances: balances,
|
||||
@@ -406,6 +447,7 @@ construct_runtime!(
|
||||
Council: collective::<Instance1>::{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>},
|
||||
TechnicalMembership: membership::<Instance1>::{Module, Call, Storage, Event<T>, Config<T>},
|
||||
FinalityTracker: finality_tracker::{Module, Call, Inherent},
|
||||
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
|
||||
CuratedGrandpa: curated_grandpa::{Module, Call, Config<T>, Storage},
|
||||
@@ -415,6 +457,7 @@ construct_runtime!(
|
||||
Slots: slots::{Module, Call, Storage, Event<T>},
|
||||
Claims: claims::{Module, Call, Storage, Event<T>, Config<T>, ValidateUnsigned},
|
||||
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>;
|
||||
/// The SignedExtension to the basic transaction logic.
|
||||
pub type SignedExtra = (
|
||||
system::CheckGenesis<Runtime>,
|
||||
system::CheckEra<Runtime>,
|
||||
system::CheckNonce<Runtime>,
|
||||
system::CheckWeight<Runtime>,
|
||||
@@ -499,7 +543,7 @@ impl_runtime_apis! {
|
||||
|
||||
impl parachain::ParachainHost<Block> for Runtime {
|
||||
fn validators() -> Vec<parachain::ValidatorId> {
|
||||
Aura::authorities() // only possible as long as parachain validator crypto === aura crypto
|
||||
Parachains::authorities()
|
||||
}
|
||||
fn duty_roster() -> parachain::DutyRoster {
|
||||
Parachains::calculate_duty_roster().0
|
||||
@@ -531,19 +575,40 @@ impl_runtime_apis! {
|
||||
None // disable forced changes.
|
||||
}
|
||||
|
||||
fn grandpa_authorities() -> Vec<(SessionKey, u64)> {
|
||||
fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
|
||||
Grandpa::grandpa_authorities()
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_aura::AuraApi<Block, AuraId> for Runtime {
|
||||
fn slot_duration() -> u64 {
|
||||
Aura::slot_duration()
|
||||
}
|
||||
|
||||
fn authorities() -> Vec<AuraId> {
|
||||
Aura::authorities()
|
||||
impl babe_primitives::BabeApi<Block> for Runtime {
|
||||
fn startup_data() -> babe_primitives::BabeConfiguration {
|
||||
// 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 epoch() -> babe_primitives::Epoch {
|
||||
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::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 sr_primitives::traits::{Hash as HashT, BlakeTwo256, Member, CheckedConversion, Saturating, One};
|
||||
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,
|
||||
ParachainDispatchOrigin, UpwardMessage, BlockIngressRoots,
|
||||
ParachainDispatchOrigin, UpwardMessage, BlockIngressRoots, ValidatorId
|
||||
}};
|
||||
use {system, session};
|
||||
use srml_support::{
|
||||
@@ -33,9 +33,6 @@ use srml_support::{
|
||||
traits::{Currency, Get, WithdrawReason, ExistenceRequirement}
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use srml_support::storage::hashed::generator;
|
||||
|
||||
use inherents::{ProvideInherent, InherentData, RuntimeString, MakeFatalError, InherentIdentifier};
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
@@ -217,7 +214,7 @@ const WATERMARK_QUEUE_SIZE: usize = 20000;
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Parachains {
|
||||
/// 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.
|
||||
pub Parachains get(active_parachains): Vec<ParaId>;
|
||||
/// The parachains registered at present.
|
||||
@@ -252,25 +249,31 @@ decl_storage! {
|
||||
add_extra_genesis {
|
||||
config(parachains): Vec<(ParaId, Vec<u8>, Vec<u8>)>;
|
||||
config(_phdata): PhantomData<T>;
|
||||
build(|storage: &mut StorageOverlay, _: &mut ChildrenStorageOverlay, config: &GenesisConfig<T>| {
|
||||
use sr_primitives::traits::Zero;
|
||||
build(build::<T>);
|
||||
}
|
||||
}
|
||||
|
||||
#[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<_> = p.iter().map(|&(ref id, _, _)| id).cloned().collect();
|
||||
let only_ids: Vec<ParaId> = p.iter().map(|&(ref id, _, _)| id).cloned().collect();
|
||||
|
||||
<Parachains as generator::StorageValue<_>>::put(&only_ids, storage);
|
||||
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 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);
|
||||
Code::insert(&id, &code);
|
||||
Heads::insert(&id, &genesis);
|
||||
<Watermarks<T>>::insert(&id, &sr_primitives::traits::Zero::zero());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
@@ -380,7 +383,7 @@ impl<T: Trait> Module<T> {
|
||||
origin: ParachainDispatchOrigin,
|
||||
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 {
|
||||
ParachainDispatchOrigin::Signed =>
|
||||
system::RawOrigin::Signed(id.into_account()).into(),
|
||||
@@ -528,6 +531,7 @@ impl<T: Trait> Module<T> {
|
||||
pub fn calculate_duty_roster() -> (DutyRoster, [u8; 32]) {
|
||||
let parachains = Self::active_parachains();
|
||||
let parachain_count = parachains.len();
|
||||
// TODO: use decode length. substrate #2794
|
||||
let validator_count = Self::authorities().len();
|
||||
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();
|
||||
|
||||
// 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
|
||||
let offset = (i * 4 % 32) as usize;
|
||||
|
||||
// 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.
|
||||
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>
|
||||
{
|
||||
use primitives::parachain::ValidityAttestation;
|
||||
use sr_primitives::traits::Verify;
|
||||
use sr_primitives::traits::AppVerify;
|
||||
|
||||
// returns groups of slices that have the same chain ID.
|
||||
// assumes the inner slice is sorted by id.
|
||||
@@ -834,7 +838,7 @@ impl<T: Trait> 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)
|
||||
where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
|
||||
@@ -881,10 +885,11 @@ mod tests {
|
||||
testing::{UintAuthorityId, Header},
|
||||
};
|
||||
use primitives::{
|
||||
parachain::{CandidateReceipt, HeadData, ValidityAttestation}, SessionKey,
|
||||
BlockNumber, AuraId,
|
||||
parachain::{CandidateReceipt, HeadData, ValidityAttestation, ValidatorId},
|
||||
BlockNumber,
|
||||
};
|
||||
use keyring::Ed25519Keyring;
|
||||
use crate::constants::time::*;
|
||||
use keyring::Sr25519Keyring;
|
||||
use srml_support::{
|
||||
impl_outer_origin, impl_outer_dispatch, assert_ok, assert_err, parameter_types,
|
||||
};
|
||||
@@ -905,13 +910,14 @@ mod tests {
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const BlockHashCount: u32 = 250;
|
||||
pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024;
|
||||
pub const MaximumBlockLength: u32 = 4 * 1024 * 1024;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Call = Call;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
@@ -957,9 +963,14 @@ mod tests {
|
||||
type MinimumPeriod = MinimumPeriod;
|
||||
}
|
||||
|
||||
impl aura::Trait for Test {
|
||||
type HandleReport = aura::StakingSlasher<Test>;
|
||||
type AuthorityId = AuraId;
|
||||
parameter_types! {
|
||||
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS;
|
||||
pub const ExpectedBlockTime: u64 = MILLISECS_PER_BLOCK;
|
||||
}
|
||||
|
||||
impl babe::Trait for Test {
|
||||
type EpochDuration = EpochDuration;
|
||||
type ExpectedBlockTime = ExpectedBlockTime;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -989,7 +1000,7 @@ mod tests {
|
||||
parameter_types! {
|
||||
pub const SessionsPerEra: session::SessionIndex = 6;
|
||||
pub const BondingDuration: staking::EraIndex = 24 * 28;
|
||||
pub const AttestationPeriod: u64 = 100;
|
||||
pub const AttestationPeriod: BlockNumber = 100;
|
||||
}
|
||||
|
||||
impl staking::Trait for Test {
|
||||
@@ -1021,17 +1032,19 @@ mod tests {
|
||||
|
||||
fn new_test_ext(parachains: Vec<(ParaId, Vec<u8>, Vec<u8>)>) -> TestExternalities<Blake2Hasher> {
|
||||
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 = [
|
||||
Ed25519Keyring::Alice,
|
||||
Ed25519Keyring::Bob,
|
||||
Ed25519Keyring::Charlie,
|
||||
Ed25519Keyring::Dave,
|
||||
Ed25519Keyring::Eve,
|
||||
Ed25519Keyring::Ferdie,
|
||||
Ed25519Keyring::One,
|
||||
Ed25519Keyring::Two,
|
||||
Sr25519Keyring::Alice,
|
||||
Sr25519Keyring::Bob,
|
||||
Sr25519Keyring::Charlie,
|
||||
Sr25519Keyring::Dave,
|
||||
Sr25519Keyring::Eve,
|
||||
Sr25519Keyring::Ferdie,
|
||||
Sr25519Keyring::One,
|
||||
Sr25519Keyring::Two,
|
||||
];
|
||||
|
||||
// stashes are the index.
|
||||
@@ -1039,7 +1052,11 @@ mod tests {
|
||||
.map(|(i, _k)| (i as u64, UintAuthorityId(i as u64)))
|
||||
.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
|
||||
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();
|
||||
|
||||
session::GenesisConfig::<Test> {
|
||||
keys: session_keys,
|
||||
}.assimilate_storage(&mut t, &mut c).unwrap();
|
||||
GenesisConfig::<Test> {
|
||||
parachains,
|
||||
authorities: authorities.clone(),
|
||||
_phdata: Default::default(),
|
||||
}.assimilate_storage(&mut t, &mut c).unwrap();
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
aura::GenesisConfig::<Test> {
|
||||
authorities,
|
||||
}.assimilate_storage(&mut t, &mut c).unwrap();
|
||||
session::GenesisConfig::<Test> {
|
||||
keys: session_keys,
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
babe::GenesisConfig {
|
||||
authorities: babe_authorities,
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
balances::GenesisConfig::<Test> {
|
||||
balances,
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t, &mut c).unwrap();
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
staking::GenesisConfig::<Test> {
|
||||
current_era: 0,
|
||||
@@ -1077,7 +1095,7 @@ mod tests {
|
||||
offline_slash: Perbill::from_percent(5),
|
||||
offline_slash_grace: 0,
|
||||
invulnerables: vec![],
|
||||
}.assimilate_storage(&mut t, &mut c).unwrap();
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
t.into()
|
||||
}
|
||||
@@ -1094,8 +1112,10 @@ mod tests {
|
||||
let candidate_hash = candidate.candidate.hash();
|
||||
|
||||
let authorities = Parachains::authorities();
|
||||
let extract_key = |public: SessionKey| {
|
||||
Ed25519Keyring::from_raw_public(public.0).unwrap()
|
||||
let extract_key = |public: ValidatorId| {
|
||||
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()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
use rstd::{result, ops::Add, convert::{TryFrom, TryInto}};
|
||||
use sr_primitives::traits::CheckedSub;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Total number of possible sub ranges of slots.
|
||||
pub const SLOT_RANGE_COUNT: usize = 10;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
use rstd::{prelude::*, mem::swap, convert::TryInto};
|
||||
use sr_primitives::traits::{CheckedSub, StaticLookup, Zero, One, CheckedConversion, Hash};
|
||||
use sr_primitives::weights::SimpleDispatchInfo;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
use srml_support::{
|
||||
decl_module, decl_storage, decl_event, StorageValue, StorageMap, ensure,
|
||||
traits::{Currency, ReservableCurrency, WithdrawReason, ExistenceRequirement, Get}
|
||||
@@ -813,13 +813,14 @@ mod tests {
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const BlockHashCount: u32 = 250;
|
||||
pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024;
|
||||
pub const MaximumBlockLength: u32 = 4 * 1024 * 1024;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
|
||||
}
|
||||
impl system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Call = ();
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
@@ -926,11 +927,11 @@ mod tests {
|
||||
// This function basically just builds a genesis storage key/value store according to
|
||||
// our desired mock up.
|
||||
fn new_test_ext() -> sr_io::TestExternalities<Blake2Hasher> {
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(balances::GenesisConfig::<Test>{
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
balances::GenesisConfig::<Test>{
|
||||
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
|
||||
vesting: vec![],
|
||||
}.build_storage().unwrap().0);
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ edition = "2018"
|
||||
parking_lot = "0.9.0"
|
||||
lazy_static = "1.0"
|
||||
log = "0.4.6"
|
||||
futures = "0.1"
|
||||
exit-future = "0.1"
|
||||
slog = "^2"
|
||||
hex-literal = "0.2"
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
@@ -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" }
|
||||
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" }
|
||||
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.
|
||||
|
||||
use primitives::{ed25519, sr25519, Pair, crypto::UncheckedInto};
|
||||
use polkadot_primitives::{AccountId, SessionKey};
|
||||
use primitives::{Pair, Public, crypto::UncheckedInto};
|
||||
use polkadot_primitives::{AccountId, parachain::ValidatorId};
|
||||
use polkadot_runtime::{
|
||||
GenesisConfig, CouncilConfig, ElectionsConfig, DemocracyConfig, SystemConfig, AuraConfig,
|
||||
GenesisConfig, CouncilConfig, ElectionsConfig, DemocracyConfig, SystemConfig, BabeConfig,
|
||||
SessionConfig, StakingConfig, BalancesConfig, Perbill, SessionKeys, TechnicalCommitteeConfig,
|
||||
GrandpaConfig, SudoConfig, IndicesConfig, CuratedGrandpaConfig, StakerStatus, WASM_BINARY,
|
||||
ClaimsConfig,
|
||||
ClaimsConfig, ImOnlineConfig, ParachainsConfig
|
||||
};
|
||||
use polkadot_runtime::constants::{currency::DOTS, time::*};
|
||||
use telemetry::TelemetryEndpoints;
|
||||
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 DEFAULT_PROTOCOL_ID: &str = "dot";
|
||||
@@ -34,34 +37,58 @@ const DEFAULT_PROTOCOL_ID: &str = "dot";
|
||||
/// Specialised `ChainSpec`.
|
||||
pub type ChainSpec = ::service::ChainSpec<GenesisConfig>;
|
||||
|
||||
pub fn poc_3_testnet_config() -> Result<ChainSpec, String> {
|
||||
ChainSpec::from_embedded(include_bytes!("../res/alexander.json"))
|
||||
pub fn kusama_config() -> Result<ChainSpec, String> {
|
||||
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 {
|
||||
// subkey inspect "$SECRET"
|
||||
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 session; do subkey -e inspect "$SECRET//$i//$j"; done; done
|
||||
let initial_authorities: Vec<(AccountId, AccountId, SessionKey)> = vec![(
|
||||
hex!["543cf15f6a0289e48eb4f30d451d1731c5fb0e1b2c5a4b99439c11808af3432d"].unchecked_into(), // 5Dy9yz2mjwDmTgjkDFxjPBpovKmKAgTndiRiTp4DfrTEdUvi
|
||||
hex!["8a6ea654337e4a28ce7be124f73ad84702619942722d01cc271e5b421653c56d"].unchecked_into(), // 5FCDLPUMZpZPRfouRfQDZp74typV9SjSxPgG6ymwe5Z3Sbko
|
||||
hex!["03644a181bc4e4197914aa109f3c97b6fe8c4787a82a1ddfab54e4ebedd8ab20"].unchecked_into(), // 5C99nwu8Ucq1yUJfajviwbqMAejpmaERHpmkPVWiFdxiF6yg
|
||||
// for i in 1 2 3 4; do for j in babe; do subkey --sr25519 inspect "$SECRET//$i//$j"; done; done
|
||||
// for i in 1 2 3 4; do for j in grandpa; do subkey --ed25519 inspect "$SECRET//$i//$j"; done; done
|
||||
// for i in 1 2 3 4; do for j in im_online; do subkey --sr25519 inspect "$SECRET//$i//$j"; done; done
|
||||
// for i in 1 2 3 4; do for j in parachains; do subkey --sr25519 inspect "$SECRET//$i//$j"; done; done
|
||||
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!["1adea46f5c3d272cd6426b338dd77d5bca3aff615338c82a0f02f4c62d89280f"].unchecked_into(), // 5CfwEv8TQKnszHNhYPuij6EtLZHCcaN3DgzfPCozcS9oxZzB
|
||||
hex!["d739e1bb4c2b13ea1fff9be72e72d3bb1b364eb3b26176ab9a9512d386b7510b"].unchecked_into(), // 5GvuM53k1Z4nAB5zXJFgkRSHv4Bqo4BsvgbQWNWkiWZTMwWY
|
||||
hex!["b496c98a405ceab59b9e970e59ef61acd7765a19b704e02ab06c1cdfe171e40f"].unchecked_into(), // 5G9VGb8ESBeS8Ca4or43RfhShzk9y7T5iTmxHk5RJsjZwsRx
|
||||
hex!["86d3a7571dd60139d297e55d8238d0c977b2e208c5af088f7f0136b565b0c103"].unchecked_into(), // 5F7V9Y5FcxKXe1aroqvPeRiUmmeQwTFcL3u9rrPXcMuMiCNx
|
||||
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!["7a73b9fcb97cee5c2240d88ca9baea06758fac450efe6f90a72014c939d41857"].unchecked_into(), // 5EqG5RSujgrtSBB5DQvR1Z2EMxAe92sAdWNTNHtX4nL2MkPi
|
||||
hex!["145791f7187d91398d8b445598f62be39b766d6e33e9d57b69c4d23fca218d7f"].unchecked_into(), // 5CXNq1mSKJT4Sc2CbyBBdANeSkbUvdWvE4czJjKXfBHi9sX5
|
||||
hex!["ae12f70078a22882bf5135d134468f77301927aa67c376e8c55b7ff127ace115"].unchecked_into(), // 5FzwpgGvk2kk9agow6KsywLYcPzjYc8suKej2bne5G5b9YU3
|
||||
hex!["7addb914ec8486bbc60643d2647685dcc06373401fa80e09813b630c5831d54b"].unchecked_into(), // 5EqoZhVC2BcsM4WjvZNidu2muKAbu5THQTBKe3EjvxXkdP7A
|
||||
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!["123b9048ba61265547ad3f336dfa48c16851ba1a96691e5d1ab3be1725db0614"].unchecked_into(), // 5CUcQvAgMzXMpQSz8mgzeiswDFHED88NiEK4byfS5TLaTJow
|
||||
hex!["8abecfa66704176be23df099bf441ea65444992d63b3ced3e76a17a4d38b0b0e"].unchecked_into(), // 5FCd9Y7RLNyxz5wnCAErfsLbXGG34L2BaZRHzhiJcMUMd5zd
|
||||
hex!["0867dbb49721126df589db100dda728dc3b475cbf414dad8f72a1d5e84897252"].unchecked_into(), // 5CFj6Kg9rmVn1vrqpyjau2ztyBzKeVdRKwNPiA3tqhB5HPqq
|
||||
hex!["26ab2b4b2eba2263b1e55ceb48f687bb0018130a88df0712fbdaf6a347d50e2a"].unchecked_into(), // 5CwQXP6nvWzigFqNhh2jvCaW9zWVzkdveCJY3tz2MhXMjTon
|
||||
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;
|
||||
@@ -87,7 +114,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
session: Some(SessionConfig {
|
||||
keys: initial_authorities.iter().map(|x| (
|
||||
x.0.clone(),
|
||||
SessionKeys { ed25519: x.2.clone() },
|
||||
session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()),
|
||||
)).collect::<Vec<_>>(),
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
@@ -114,16 +141,25 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
term_duration: 28 * DAYS,
|
||||
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 {
|
||||
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 {
|
||||
shuffle_period: 1024,
|
||||
}),
|
||||
@@ -148,49 +184,53 @@ pub fn staging_testnet_config() -> ChainSpec {
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper function to generate AccountId from seed
|
||||
pub fn get_account_id_from_seed(seed: &str) -> AccountId {
|
||||
sr25519::Pair::from_string(&format!("//{}", seed), None)
|
||||
/// Helper function to generate a crypto pair from seed
|
||||
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
||||
TPublic::Pair::from_string(&format!("//{}", seed), None)
|
||||
.expect("static values are valid; qed")
|
||||
.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
|
||||
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_account_id_from_seed(seed),
|
||||
get_session_key_from_seed(seed),
|
||||
get_from_seed::<AccountId>(&format!("{}//stash", seed)),
|
||||
get_from_seed::<AccountId>(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
|
||||
pub fn testnet_genesis(
|
||||
initial_authorities: Vec<(AccountId, AccountId, SessionKey)>,
|
||||
initial_authorities: Vec<(AccountId, AccountId, BabeId, GrandpaId, ImOnlineId, ValidatorId)>,
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Option<Vec<AccountId>>,
|
||||
) -> GenesisConfig {
|
||||
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(|| {
|
||||
vec![
|
||||
get_account_id_from_seed("Alice"),
|
||||
get_account_id_from_seed("Bob"),
|
||||
get_account_id_from_seed("Charlie"),
|
||||
get_account_id_from_seed("Dave"),
|
||||
get_account_id_from_seed("Eve"),
|
||||
get_account_id_from_seed("Ferdie"),
|
||||
get_account_id_from_seed("Alice//stash"),
|
||||
get_account_id_from_seed("Bob//stash"),
|
||||
get_account_id_from_seed("Charlie//stash"),
|
||||
get_account_id_from_seed("Dave//stash"),
|
||||
get_account_id_from_seed("Eve//stash"),
|
||||
get_account_id_from_seed("Ferdie//stash"),
|
||||
get_from_seed::<AccountId>("Alice"),
|
||||
get_from_seed::<AccountId>("Bob"),
|
||||
get_from_seed::<AccountId>("Charlie"),
|
||||
get_from_seed::<AccountId>("Dave"),
|
||||
get_from_seed::<AccountId>("Eve"),
|
||||
get_from_seed::<AccountId>("Ferdie"),
|
||||
get_from_seed::<AccountId>("Alice//stash"),
|
||||
get_from_seed::<AccountId>("Bob//stash"),
|
||||
get_from_seed::<AccountId>("Charlie//stash"),
|
||||
get_from_seed::<AccountId>("Dave//stash"),
|
||||
get_from_seed::<AccountId>("Eve//stash"),
|
||||
get_from_seed::<AccountId>("Ferdie//stash"),
|
||||
]
|
||||
});
|
||||
|
||||
@@ -214,7 +254,7 @@ pub fn testnet_genesis(
|
||||
session: Some(SessionConfig {
|
||||
keys: initial_authorities.iter().map(|x| (
|
||||
x.0.clone(),
|
||||
SessionKeys { ed25519: x.2.clone() },
|
||||
session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()),
|
||||
)).collect::<Vec<_>>(),
|
||||
}),
|
||||
staking: Some(StakingConfig {
|
||||
@@ -240,22 +280,31 @@ pub fn testnet_genesis(
|
||||
elections: Some(ElectionsConfig {
|
||||
members: endowed_accounts.iter()
|
||||
.filter(|&endowed| initial_authorities.iter()
|
||||
.find(|&(_, controller, _)| controller == endowed)
|
||||
.find(|&(_, controller, _, _, _, _)| controller == endowed)
|
||||
.is_none()
|
||||
).map(|a| (a.clone(), 1000000)).collect(),
|
||||
presentation_duration: 10,
|
||||
term_duration: 1000000,
|
||||
desired_seats,
|
||||
}),
|
||||
parachains: Some(Default::default()),
|
||||
sudo: Some(SudoConfig {
|
||||
key: root_key,
|
||||
}),
|
||||
grandpa: Some(GrandpaConfig {
|
||||
membership_Instance1: Some(Default::default()),
|
||||
babe: Some(BabeConfig {
|
||||
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
|
||||
}),
|
||||
aura: Some(AuraConfig {
|
||||
authorities: initial_authorities.iter().map(|x| x.2.clone()).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 {
|
||||
key: root_key,
|
||||
}),
|
||||
curated_grandpa: Some(CuratedGrandpaConfig {
|
||||
shuffle_period: 1024,
|
||||
@@ -272,7 +321,7 @@ fn development_config_genesis() -> GenesisConfig {
|
||||
vec![
|
||||
get_authority_keys_from_seed("Alice"),
|
||||
],
|
||||
get_account_id_from_seed("Alice"),
|
||||
get_from_seed::<AccountId>("Alice"),
|
||||
None,
|
||||
)
|
||||
}
|
||||
@@ -297,7 +346,7 @@ fn local_testnet_genesis() -> GenesisConfig {
|
||||
get_authority_keys_from_seed("Alice"),
|
||||
get_authority_keys_from_seed("Bob"),
|
||||
],
|
||||
get_account_id_from_seed("Alice"),
|
||||
get_from_seed::<AccountId>("Alice"),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
+192
-121
@@ -18,18 +18,21 @@
|
||||
|
||||
pub mod chain_spec;
|
||||
|
||||
use futures::prelude::*;
|
||||
use client::LongestChain;
|
||||
use consensus_common::SelectChain;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use grandpa_primitives::AuthorityPair as GrandpaPair;
|
||||
use polkadot_primitives::{parachain, Block, Hash, BlockId, AuraPair};
|
||||
use polkadot_primitives::{parachain, Block, Hash, BlockId};
|
||||
use polkadot_runtime::{GenesisConfig, RuntimeApi};
|
||||
use polkadot_network::gossip::{self as network_gossip, Known};
|
||||
use primitives::{ed25519, Pair};
|
||||
use service::{FactoryFullConfiguration, FullBackend, LightBackend, FullExecutor, LightExecutor};
|
||||
use service::{
|
||||
FactoryFullConfiguration, FullBackend, LightBackend, FullExecutor, LightExecutor,
|
||||
error::Error as ServiceError, TelemetryOnConnect
|
||||
};
|
||||
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 log::info;
|
||||
pub use service::{
|
||||
@@ -49,6 +52,20 @@ pub use consensus::run_validation_worker;
|
||||
/// All configuration for the polkadot node.
|
||||
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.
|
||||
pub struct CustomConfiguration {
|
||||
/// 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`.
|
||||
// FIXME: rather than putting this on the config, let's have an actual intermediate setup state
|
||||
// https://github.com/paritytech/substrate/issues/1134
|
||||
pub grandpa_import_setup: Option<(
|
||||
grandpa::BlockImportForService<Factory>,
|
||||
grandpa::LinkHalfForService<Factory>
|
||||
pub import_setup: Option<(
|
||||
BabeBlockImportForService<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.
|
||||
pub max_block_data_size: Option<u64>,
|
||||
|
||||
@@ -73,8 +94,9 @@ impl Default for CustomConfiguration {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
collating_for: None,
|
||||
grandpa_import_setup: None,
|
||||
import_setup: None,
|
||||
inherent_data_providers: InherentDataProviders::new(),
|
||||
tasks_to_spawn: None,
|
||||
max_block_data_size: None,
|
||||
}
|
||||
}
|
||||
@@ -150,93 +172,37 @@ impl PolkadotService for Service<LightComponents<Factory>> {
|
||||
service::construct_service_factory! {
|
||||
struct Factory {
|
||||
Block = Block,
|
||||
ConsensusPair = AuraPair,
|
||||
FinalityPair = GrandpaPair,
|
||||
RuntimeApi = RuntimeApi,
|
||||
NetworkProtocol = PolkadotProtocol {
|
||||
|config: &Configuration| Ok(PolkadotProtocol::new(config.custom.collating_for.clone()))
|
||||
},
|
||||
NetworkProtocol = PolkadotProtocol { |config: &Configuration| Ok(PolkadotProtocol::new(config.custom.collating_for.clone())) },
|
||||
RuntimeDispatch = polkadot_executor::Executor,
|
||||
FullTransactionPoolApi = TxChainApi<FullBackend<Self>, FullExecutor<Self>>
|
||||
{ |config, client| Ok(TransactionPool::new(config, TxChainApi::new(client))) },
|
||||
LightTransactionPoolApi = TxChainApi<LightBackend<Self>, LightExecutor<Self>>
|
||||
{ |config, client| Ok(TransactionPool::new(config, TxChainApi::new(client))) },
|
||||
FullTransactionPoolApi = transaction_pool::ChainApi<client::Client<FullBackend<Self>, FullExecutor<Self>, Block, RuntimeApi>, Block>
|
||||
{ |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) },
|
||||
LightTransactionPoolApi = transaction_pool::ChainApi<client::Client<LightBackend<Self>, LightExecutor<Self>, Block, RuntimeApi>, Block>
|
||||
{ |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) },
|
||||
Genesis = GenesisConfig,
|
||||
Configuration = CustomConfiguration,
|
||||
FullService = FullComponents<Self>
|
||||
{ |config: FactoryFullConfiguration<Self>| {
|
||||
FullComponents::<Factory>::new(config)
|
||||
} },
|
||||
AuthoritySetup = { |mut service: Self::FullService| {
|
||||
use polkadot_network::validation::ValidationNetwork;
|
||||
|
||||
let (block_import, link_half) = service.config.custom.grandpa_import_setup.take()
|
||||
FullService = FullComponents<Self> { |config: FactoryFullConfiguration<Self>| FullComponents::<Factory>::new(config) },
|
||||
AuthoritySetup = {
|
||||
|mut service: Self::FullService| {
|
||||
let (block_import, link_half, babe_link) = service.config_mut().custom.import_setup.take()
|
||||
.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
|
||||
|
||||
// always run GRANDPA in order to sync.
|
||||
{
|
||||
let grandpa_key = if service.config.disable_grandpa {
|
||||
None
|
||||
} else {
|
||||
service.authority_key()
|
||||
};
|
||||
|
||||
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)?);
|
||||
},
|
||||
// spawn any futures that were created in the previous setup steps
|
||||
if let Some(tasks) = service.config_mut().custom.tasks_to_spawn.take() {
|
||||
for task in tasks {
|
||||
service.spawn_task(
|
||||
task.select(service.on_exit())
|
||||
.map(|_| ())
|
||||
.map_err(|_| ())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let extrinsic_store = {
|
||||
use std::path::PathBuf;
|
||||
if service.config().roles != service::Roles::AUTHORITY {
|
||||
return Ok(service);
|
||||
}
|
||||
|
||||
let mut path = PathBuf::from(service.config.database_path.clone());
|
||||
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() {
|
||||
if service.config().custom.collating_for.is_some() {
|
||||
info!(
|
||||
"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
|
||||
let validation_network = ValidationNetwork::new(
|
||||
service.network(),
|
||||
@@ -283,63 +262,150 @@ service::construct_service_factory! {
|
||||
service.client(),
|
||||
polkadot_network::validation::WrappedExecutor(service.spawn_task_handle()),
|
||||
);
|
||||
let proposer_factory = consensus::ProposerFactory::new(
|
||||
let proposer = consensus::ProposerFactory::new(
|
||||
client.clone(),
|
||||
select_chain.clone(),
|
||||
validation_network.clone(),
|
||||
validation_network,
|
||||
service.transaction_pool(),
|
||||
Arc::new(service.spawn_task_handle()),
|
||||
aura_key.clone(),
|
||||
service.keystore(),
|
||||
extrinsic_store,
|
||||
SlotDuration::get_or_compute(&*client)?,
|
||||
service.config.custom.max_block_data_size,
|
||||
polkadot_runtime::constants::time::SLOT_DURATION,
|
||||
service.config().custom.max_block_data_size,
|
||||
);
|
||||
|
||||
info!("Using authority key {}", aura_key.public());
|
||||
let task = start_aura(
|
||||
SlotDuration::get_or_compute(&*client)?,
|
||||
aura_key,
|
||||
client.clone(),
|
||||
let client = service.client();
|
||||
let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?;
|
||||
|
||||
let babe_config = babe::BabeParams {
|
||||
config: Config::get_or_compute(&*client)?,
|
||||
keystore: service.keystore(),
|
||||
client,
|
||||
select_chain,
|
||||
block_import,
|
||||
Arc::new(proposer_factory),
|
||||
service.network(),
|
||||
service.config.custom.inherent_data_providers.clone(),
|
||||
service.config.force_authoring,
|
||||
)?;
|
||||
env: proposer,
|
||||
sync_oracle: service.network(),
|
||||
inherent_data_providers: service.config().custom.inherent_data_providers.clone(),
|
||||
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)
|
||||
}},
|
||||
}
|
||||
},
|
||||
LightService = LightComponents<Self>
|
||||
{ |config| <LightComponents<Factory>>::new(config) },
|
||||
FullImportQueue = AuraImportQueue<
|
||||
Self::Block,
|
||||
>
|
||||
FullImportQueue = BabeImportQueue<Self::Block>
|
||||
{ |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) =
|
||||
grandpa::block_import::<_, _, _, RuntimeApi, FullClient<Self>, _>(
|
||||
client.clone(), client.clone(), select_chain
|
||||
)?;
|
||||
let justification_import = block_import.clone();
|
||||
|
||||
config.custom.grandpa_import_setup = Some((block_import.clone(), link_half));
|
||||
import_queue::<_, _, ed25519::Pair>(
|
||||
slot_duration,
|
||||
Box::new(block_import),
|
||||
let (import_queue, babe_link, babe_block_import, pruning_task) = import_queue(
|
||||
Config::get_or_compute(&*client)?,
|
||||
block_import,
|
||||
Some(Box::new(justification_import)),
|
||||
None,
|
||||
client.clone(),
|
||||
client,
|
||||
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<
|
||||
Self::Block,
|
||||
>
|
||||
{ |config: &mut FactoryFullConfiguration<Self>, client: Arc<LightClient<Self>>| {
|
||||
LightImportQueue = BabeImportQueue<Self::Block>
|
||||
{ |config: &FactoryFullConfiguration<Self>, client: Arc<LightClient<Self>>| {
|
||||
#[allow(deprecated)]
|
||||
let fetch_checker = client.backend().blockchain().fetcher()
|
||||
.upgrade()
|
||||
@@ -348,17 +414,22 @@ service::construct_service_factory! {
|
||||
let block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, LightClient<Self>>(
|
||||
client.clone(), Arc::new(fetch_checker), client.clone()
|
||||
)?;
|
||||
|
||||
let finality_proof_import = block_import.clone();
|
||||
let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder();
|
||||
|
||||
import_queue::<_, _, ed25519::Pair>(
|
||||
SlotDuration::get_or_compute(&*client)?,
|
||||
Box::new(block_import),
|
||||
// FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`.
|
||||
let (import_queue, ..) = import_queue(
|
||||
Config::get_or_compute(&*client)?,
|
||||
block_import,
|
||||
None,
|
||||
Some(Box::new(finality_proof_import)),
|
||||
client.clone(),
|
||||
client,
|
||||
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>
|
||||
{ |config: &FactoryFullConfiguration<Self>, client: Arc<FullClient<Self>>| {
|
||||
@@ -367,7 +438,7 @@ service::construct_service_factory! {
|
||||
}
|
||||
},
|
||||
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"
|
||||
|
||||
[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" }
|
||||
primitives = { package = "polkadot-primitives", path = "../primitives" }
|
||||
|
||||
@@ -28,7 +28,7 @@ use std::collections::hash_map::{HashMap, Entry};
|
||||
use std::hash::Hash;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Context for the statement table.
|
||||
pub trait Context {
|
||||
|
||||
@@ -8,7 +8,7 @@ build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
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"
|
||||
dlmalloc = { version = "0.1.3", features = ["global"], optional = true }
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ impl ParachainContext for AdderContext {
|
||||
) -> Result<(BlockData, HeadData, Extrinsic), InvalidHead>
|
||||
{
|
||||
let adder_head = AdderHead::decode(&mut &status.head_data.0[..])
|
||||
.ok_or(InvalidHead)?;
|
||||
.map_err(|_| InvalidHead)?;
|
||||
|
||||
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))]
|
||||
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
mod wasm_validation;
|
||||
@@ -80,7 +80,7 @@ pub fn process_messages<I, T>(iterable: I) -> u64
|
||||
where I: IntoIterator<Item=T>, T: AsRef<[u8]>
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,24 +13,24 @@ tokio = "0.1.7"
|
||||
derive_more = "0.14.0"
|
||||
log = "0.4.6"
|
||||
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" }
|
||||
parachain = { package = "polkadot-parachain", path = "../parachain" }
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
polkadot-runtime = { path = "../runtime" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
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" }
|
||||
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]
|
||||
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 futures03::{TryStreamExt as _, StreamExt as _};
|
||||
use log::error;
|
||||
use primitives::ed25519;
|
||||
use polkadot_primitives::{Block, BlockId, AuraId};
|
||||
use polkadot_primitives::{Block, BlockId};
|
||||
use polkadot_primitives::parachain::{CandidateReceipt, ParachainHost};
|
||||
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 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)
|
||||
-> ClientResult<Option<impl Iterator<Item=CandidateReceipt>>>
|
||||
{
|
||||
use parity_codec::{Encode, Decode};
|
||||
use codec::{Encode, Decode};
|
||||
use polkadot_runtime::{Call, ParachainsCall, UncheckedExtrinsic as RuntimeExtrinsic};
|
||||
|
||||
let extrinsics = client.block_body(block)?;
|
||||
Ok(match extrinsics {
|
||||
Some(extrinsics) => extrinsics
|
||||
.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 {
|
||||
Call::Parachains(ParachainsCall::set_heads(heads)) => {
|
||||
Some(heads.into_iter().map(|c| c.candidate))
|
||||
@@ -114,7 +114,7 @@ pub(crate) fn start<C, N, P, SC>(
|
||||
select_chain: SC,
|
||||
parachain_validation: Arc<crate::ParachainValidation<C, N, P>>,
|
||||
thread_pool: TaskExecutor,
|
||||
key: Arc<ed25519::Pair>,
|
||||
keystore: KeyStorePtr,
|
||||
extrinsic_store: ExtrinsicStore,
|
||||
max_block_data_size: Option<u64>,
|
||||
) -> ServiceHandle
|
||||
@@ -123,7 +123,7 @@ pub(crate) fn start<C, N, P, SC>(
|
||||
<C::Collation as IntoFuture>::Future: Send + 'static,
|
||||
P: BlockchainEvents<Block> + BlockBody<Block>,
|
||||
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::TableRouter: Send + 'static,
|
||||
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
|
||||
@@ -138,7 +138,8 @@ pub(crate) fn start<C, N, P, SC>(
|
||||
let notifications = {
|
||||
let client = client.clone();
|
||||
let validation = parachain_validation.clone();
|
||||
let key = key.clone();
|
||||
|
||||
let keystore = keystore.clone();
|
||||
|
||||
client.import_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
@@ -148,7 +149,7 @@ pub(crate) fn start<C, N, P, SC>(
|
||||
let res = validation.get_or_instantiate(
|
||||
parent_hash,
|
||||
notification.header.parent_hash().clone(),
|
||||
key.clone(),
|
||||
&keystore,
|
||||
max_block_data_size,
|
||||
);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ use polkadot_primitives::{Block, Hash, BlockId, Balance, parachain::{
|
||||
}};
|
||||
use runtime_primitives::traits::ProvideRuntimeApi;
|
||||
use parachain::{wasm_executor::{self, ExternalitiesError, ExecutionMode}, MessageRef, UpwardMessageRef};
|
||||
|
||||
use trie::TrieConfiguration;
|
||||
use futures::prelude::*;
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Errors that can occur during the validation process.
|
||||
|
||||
use runtime_primitives::RuntimeString;
|
||||
use primitives::ed25519::Public as AuthorityId;
|
||||
use polkadot_primitives::parachain::ValidatorId;
|
||||
|
||||
/// Error type for validation
|
||||
#[derive(Debug, derive_more::Display, derive_more::From)]
|
||||
@@ -35,7 +35,7 @@ pub enum Error {
|
||||
},
|
||||
/// Local account not a validator at this block
|
||||
#[display(fmt = "Local account ID ({:?}) not a validator at this block.", _0)]
|
||||
NotValidator(AuthorityId),
|
||||
NotValidator(ValidatorId),
|
||||
/// Unexpected error checking inherents
|
||||
#[display(fmt = "Unexpected error while checking inherents: {}", _0)]
|
||||
InherentError(RuntimeString),
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use super::MAX_TRANSACTIONS_SIZE;
|
||||
|
||||
use parity_codec::Encode;
|
||||
use codec::Encode;
|
||||
use polkadot_primitives::{Block, Hash, BlockNumber};
|
||||
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 aura::{SlotDuration, AuraApi};
|
||||
use babe_primitives::BabeApi;
|
||||
use client::{BlockchainEvents, BlockBody};
|
||||
use client::blockchain::HeaderBackend;
|
||||
use client::block_builder::api::BlockBuilder as BlockBuilderApi;
|
||||
use parity_codec::Encode;
|
||||
use codec::Encode;
|
||||
use consensus::SelectChain;
|
||||
use extrinsic_store::Store as ExtrinsicStore;
|
||||
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::{
|
||||
Id as ParaId, Chain, DutyRoster, Extrinsic as ParachainExtrinsic, CandidateReceipt,
|
||||
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::{
|
||||
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 dynamic_inclusion::DynamicInclusion;
|
||||
use inherents::InherentData;
|
||||
use runtime_aura::timestamp::TimestampInherentData;
|
||||
use runtime_babe::timestamp::TimestampInherentData;
|
||||
use log::{info, debug, warn, trace, error};
|
||||
|
||||
use ed25519::Public as AuthorityId;
|
||||
use keystore::KeyStorePtr;
|
||||
|
||||
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(
|
||||
&self,
|
||||
table: Arc<SharedTable>,
|
||||
authorities: &[SessionKey],
|
||||
authorities: &[ValidatorId],
|
||||
exit: exit_future::Exit,
|
||||
) -> Self::BuildTableRouter;
|
||||
}
|
||||
@@ -154,7 +153,7 @@ pub trait Network {
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct GroupInfo {
|
||||
/// Authorities meant to check validity of candidates.
|
||||
validity_guarantors: HashSet<SessionKey>,
|
||||
validity_guarantors: HashSet<ValidatorId>,
|
||||
/// Number of votes needed for validity.
|
||||
needed_validity: usize,
|
||||
}
|
||||
@@ -162,32 +161,32 @@ pub struct GroupInfo {
|
||||
/// Sign a table statement against a parent hash.
|
||||
/// The actual message signed is the encoded statement concatenated with the
|
||||
/// 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
|
||||
// expects. These types probably encode the same way so this clone could be optimized
|
||||
// out in the future.
|
||||
let mut encoded = PrimitiveStatement::from(statement.clone()).encode();
|
||||
encoded.extend(parent_hash.as_ref());
|
||||
|
||||
key.sign(&encoded).into()
|
||||
key.sign(&encoded)
|
||||
}
|
||||
|
||||
/// Check signature on table statement.
|
||||
pub fn check_statement(statement: &Statement, signature: &CollatorSignature, signer: SessionKey, parent_hash: &Hash) -> bool {
|
||||
use runtime_primitives::traits::Verify;
|
||||
pub fn check_statement(statement: &Statement, signature: &ValidatorSignature, signer: ValidatorId, parent_hash: &Hash) -> bool {
|
||||
use runtime_primitives::traits::AppVerify;
|
||||
|
||||
let mut encoded = PrimitiveStatement::from(statement.clone()).encode();
|
||||
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.
|
||||
pub fn make_group_info(
|
||||
roster: DutyRoster,
|
||||
authorities: &[AuthorityId],
|
||||
local_id: AuthorityId,
|
||||
) -> Result<(HashMap<ParaId, GroupInfo>, LocalDuty), Error> {
|
||||
authorities: &[ValidatorId],
|
||||
local_id: Option<ValidatorId>,
|
||||
) -> Result<(HashMap<ParaId, GroupInfo>, Option<LocalDuty>), Error> {
|
||||
if roster.validator_duty.len() != authorities.len() {
|
||||
return Err(Error::InvalidDutyRosterLength {
|
||||
expected: authorities.len(),
|
||||
@@ -200,7 +199,7 @@ pub fn make_group_info(
|
||||
|
||||
let duty_iter = authorities.iter().zip(&roster.validator_duty);
|
||||
for (authority, v_duty) in duty_iter {
|
||||
if authority == &local_id {
|
||||
if Some(authority) == local_id.as_ref() {
|
||||
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;
|
||||
}
|
||||
|
||||
match local_validation {
|
||||
Some(local_validation) => {
|
||||
let local_duty = LocalDuty {
|
||||
validation: local_validation,
|
||||
};
|
||||
|
||||
let local_duty = local_validation.map(|v| LocalDuty {
|
||||
validation: v
|
||||
});
|
||||
|
||||
Ok((map, local_duty))
|
||||
}
|
||||
None => return Err(Error::NotValidator(local_id)),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -252,7 +259,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
|
||||
C: Collators + Send + 'static,
|
||||
N: Network,
|
||||
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,
|
||||
N::TableRouter: Send + 'static,
|
||||
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
|
||||
@@ -268,7 +275,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
|
||||
&self,
|
||||
parent_hash: Hash,
|
||||
grandparent_hash: Hash,
|
||||
sign_with: Arc<ed25519::Pair>,
|
||||
keystore: &KeyStorePtr,
|
||||
max_block_data_size: Option<u64>,
|
||||
)
|
||||
-> Result<Arc<AttestationTracker>, Error>
|
||||
@@ -280,7 +287,8 @@ impl<C, N, P> ParachainValidation<C, N, P> where
|
||||
|
||||
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.
|
||||
// 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(
|
||||
duty_roster,
|
||||
&authorities,
|
||||
sign_with.public(),
|
||||
&validators,
|
||||
sign_with.as_ref().map(|k| k.public()),
|
||||
)?;
|
||||
|
||||
info!(
|
||||
"Starting parachain attestation session on top of parent {:?}. Local parachain duty is {:?}",
|
||||
parent_hash,
|
||||
local_duty.validation,
|
||||
local_duty,
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
let table = Arc::new(SharedTable::new(
|
||||
&authorities,
|
||||
validators.clone(),
|
||||
group_info,
|
||||
sign_with.clone(),
|
||||
sign_with,
|
||||
parent_hash,
|
||||
self.extrinsic_store.clone(),
|
||||
max_block_data_size,
|
||||
@@ -339,11 +347,11 @@ impl<C, N, P> ParachainValidation<C, N, P> where
|
||||
|
||||
let router = self.network.communication_for(
|
||||
table.clone(),
|
||||
&authorities,
|
||||
&validators,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -446,9 +454,9 @@ struct AttestationTracker {
|
||||
pub struct ProposerFactory<C, N, P, SC, TxApi: PoolChainApi> {
|
||||
parachain_validation: Arc<ParachainValidation<C, N, P>>,
|
||||
transaction_pool: Arc<Pool<TxApi>>,
|
||||
key: Arc<ed25519::Pair>,
|
||||
keystore: KeyStorePtr,
|
||||
_service_handle: ServiceHandle,
|
||||
aura_slot_duration: SlotDuration,
|
||||
babe_slot_duration: u64,
|
||||
_select_chain: SC,
|
||||
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,
|
||||
P: BlockchainEvents<Block> + BlockBody<Block>,
|
||||
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::TableRouter: 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,
|
||||
transaction_pool: Arc<Pool<TxApi>>,
|
||||
thread_pool: TaskExecutor,
|
||||
key: Arc<ed25519::Pair>,
|
||||
keystore: KeyStorePtr,
|
||||
extrinsic_store: ExtrinsicStore,
|
||||
aura_slot_duration: SlotDuration,
|
||||
babe_slot_duration: u64,
|
||||
max_block_data_size: Option<u64>,
|
||||
) -> Self {
|
||||
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(),
|
||||
parachain_validation.clone(),
|
||||
thread_pool,
|
||||
key.clone(),
|
||||
keystore.clone(),
|
||||
extrinsic_store,
|
||||
max_block_data_size,
|
||||
);
|
||||
@@ -500,9 +508,9 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
|
||||
ProposerFactory {
|
||||
parachain_validation,
|
||||
transaction_pool,
|
||||
key,
|
||||
keystore,
|
||||
_service_handle: service_handle,
|
||||
aura_slot_duration,
|
||||
babe_slot_duration,
|
||||
_select_chain,
|
||||
max_block_data_size,
|
||||
}
|
||||
@@ -514,7 +522,7 @@ impl<C, N, P, SC, TxApi> consensus::Environment<Block> for ProposerFactory<C, N,
|
||||
N: Network,
|
||||
TxApi: PoolChainApi<Block=Block>,
|
||||
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,
|
||||
N::TableRouter: 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;
|
||||
|
||||
fn init(
|
||||
&self,
|
||||
&mut self,
|
||||
parent_header: &Header,
|
||||
) -> Result<Self::Proposer, Error> {
|
||||
let parent_hash = parent_header.hash();
|
||||
let parent_id = BlockId::hash(parent_hash);
|
||||
let sign_with = self.key.clone();
|
||||
|
||||
let tracker = self.parachain_validation.get_or_instantiate(
|
||||
parent_hash,
|
||||
parent_header.parent_hash().clone(),
|
||||
sign_with,
|
||||
&self.keystore,
|
||||
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_number: parent_header.number,
|
||||
transaction_pool: self.transaction_pool.clone(),
|
||||
slot_duration: self.aura_slot_duration,
|
||||
slot_duration: self.babe_slot_duration,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The local duty of a validator.
|
||||
#[derive(Debug)]
|
||||
pub struct LocalDuty {
|
||||
validation: Chain,
|
||||
}
|
||||
@@ -564,7 +573,7 @@ pub struct Proposer<C: Send + Sync, TxApi: PoolChainApi> where
|
||||
parent_number: BlockNumber,
|
||||
tracker: Arc<AttestationTracker>,
|
||||
transaction_pool: Arc<Pool<TxApi>>,
|
||||
slot_duration: SlotDuration,
|
||||
slot_duration: u64,
|
||||
}
|
||||
|
||||
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 Create = Either<CreateProposal<C, TxApi>, future::Ready<Result<Block, Error>>>;
|
||||
|
||||
fn propose(&self,
|
||||
fn propose(&mut self,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
max_duration: Duration,
|
||||
@@ -589,7 +598,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
|
||||
let dynamic_inclusion = DynamicInclusion::new(
|
||||
self.tracker.table.num_parachains(),
|
||||
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(
|
||||
@@ -607,7 +616,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
|
||||
let delay_future = if current_timestamp >= believed_timestamp {
|
||||
None
|
||||
} else {
|
||||
Some(Delay::new(Duration::from_secs(current_timestamp - believed_timestamp)))
|
||||
Some(Delay::new(Duration::from_millis (current_timestamp - believed_timestamp)))
|
||||
};
|
||||
|
||||
let timing = ProposalTiming {
|
||||
@@ -638,8 +647,7 @@ impl<C, TxApi> consensus::Proposer<Block> for Proposer<C, TxApi> where
|
||||
fn current_timestamp() -> u64 {
|
||||
time::SystemTime::now().duration_since(time::UNIX_EPOCH)
|
||||
.expect("now always later than unix epoch; qed")
|
||||
.as_secs()
|
||||
.into()
|
||||
.as_millis() as u64
|
||||
}
|
||||
|
||||
struct ProposalTiming {
|
||||
@@ -811,17 +819,17 @@ impl<C, TxApi> futures03::Future for CreateProposal<C, TxApi> where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_keyring::Ed25519Keyring;
|
||||
use substrate_keyring::Sr25519Keyring;
|
||||
|
||||
#[test]
|
||||
fn sign_and_check_statement() {
|
||||
let statement: Statement = GenericStatement::Valid([1; 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, Ed25519Keyring::Alice.into(), &[0xff; 32].into()));
|
||||
assert!(!check_statement(&statement, &sig, Ed25519Keyring::Bob.into(), &parent_hash));
|
||||
assert!(check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &parent_hash));
|
||||
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &[0xff; 32].into()));
|
||||
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 table::{self, Table, Context as TableContextTrait};
|
||||
use polkadot_primitives::{Block, BlockId, Hash, SessionKey};
|
||||
use polkadot_primitives::parachain::{Id as ParaId, Collation, Extrinsic, CandidateReceipt,
|
||||
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex,
|
||||
use polkadot_primitives::{Block, BlockId, Hash};
|
||||
use polkadot_primitives::parachain::{
|
||||
Id as ParaId, Collation, Extrinsic, CandidateReceipt, ValidatorPair, ValidatorId,
|
||||
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex
|
||||
};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
@@ -34,7 +35,7 @@ use bitvec::bitvec;
|
||||
|
||||
use super::{GroupInfo, TableRouter};
|
||||
use self::includable::IncludabilitySender;
|
||||
use primitives::{ed25519, Pair};
|
||||
use primitives::Pair;
|
||||
use runtime_primitives::traits::ProvideRuntimeApi;
|
||||
|
||||
mod includable;
|
||||
@@ -45,14 +46,14 @@ pub use table::generic::Statement as GenericStatement;
|
||||
|
||||
struct TableContext {
|
||||
parent_hash: Hash,
|
||||
key: Arc<ed25519::Pair>,
|
||||
key: Option<Arc<ValidatorPair>>,
|
||||
groups: HashMap<ParaId, GroupInfo>,
|
||||
index_mapping: HashMap<ValidatorIndex, SessionKey>,
|
||||
validators: Vec<ValidatorId>,
|
||||
}
|
||||
|
||||
impl table::Context for TableContext {
|
||||
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,
|
||||
None => return false,
|
||||
};
|
||||
@@ -66,28 +67,26 @@ impl table::Context for TableContext {
|
||||
}
|
||||
|
||||
impl TableContext {
|
||||
fn local_id(&self) -> SessionKey {
|
||||
self.key.public().into()
|
||||
fn local_id(&self) -> Option<ValidatorId> {
|
||||
self.key.as_ref().map(|k| k.public())
|
||||
}
|
||||
|
||||
fn local_index(&self) -> ValidatorIndex {
|
||||
let id = self.local_id();
|
||||
self
|
||||
.index_mapping
|
||||
fn local_index(&self) -> Option<ValidatorIndex> {
|
||||
self.local_id().and_then(|id|
|
||||
self.validators
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, k)| k == &&id)
|
||||
.map(|(i, _)| *i)
|
||||
.unwrap()
|
||||
.map(|(i, _)| i as ValidatorIndex)
|
||||
)
|
||||
}
|
||||
|
||||
fn sign_statement(&self, statement: table::Statement) -> table::SignedStatement {
|
||||
let signature = crate::sign_table_statement(&statement, &self.key, &self.parent_hash).into();
|
||||
|
||||
table::SignedStatement {
|
||||
statement,
|
||||
signature,
|
||||
sender: self.local_index(),
|
||||
}
|
||||
fn sign_statement(&self, statement: table::Statement) -> Option<table::SignedStatement> {
|
||||
self.local_index().and_then(move |sender|
|
||||
self.key.as_ref()
|
||||
.map(|key| crate::sign_table_statement(&statement, key, &self.parent_hash).into())
|
||||
.map(move |signature| table::SignedStatement { statement, signature, sender })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,15 +141,10 @@ impl SharedTableInner {
|
||||
) -> Option<ParachainWork<
|
||||
<R::FetchValidationProof as IntoFuture>::Future,
|
||||
>> {
|
||||
let summary = match self.table.import_statement(context, statement) {
|
||||
Some(summary) => summary,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let summary = self.table.import_statement(context, statement)?;
|
||||
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 digest = &summary.candidate;
|
||||
@@ -399,16 +393,15 @@ impl SharedTable {
|
||||
/// Provide the key to sign with, and the parent hash of the relay chain
|
||||
/// block being built.
|
||||
pub fn new(
|
||||
authorities: &[ed25519::Public],
|
||||
validators: Vec<ValidatorId>,
|
||||
groups: HashMap<ParaId, GroupInfo>,
|
||||
key: Arc<ed25519::Pair>,
|
||||
key: Option<Arc<ValidatorPair>>,
|
||||
parent_hash: Hash,
|
||||
extrinsic_store: ExtrinsicStore,
|
||||
max_block_data_size: Option<u64>,
|
||||
) -> Self {
|
||||
let index_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect();
|
||||
Self {
|
||||
context: Arc::new(TableContext { groups, key, parent_hash, index_mapping, }),
|
||||
SharedTable {
|
||||
context: Arc::new(TableContext { groups, key, parent_hash, validators: validators.clone(), }),
|
||||
max_block_data_size,
|
||||
inner: Arc::new(Mutex::new(SharedTableInner {
|
||||
table: Table::default(),
|
||||
@@ -425,7 +418,7 @@ impl SharedTable {
|
||||
}
|
||||
|
||||
/// Get the local validator session key.
|
||||
pub fn session_key(&self) -> SessionKey {
|
||||
pub fn session_key(&self) -> Option<ValidatorId> {
|
||||
self.context.local_id()
|
||||
}
|
||||
|
||||
@@ -482,9 +475,10 @@ impl SharedTable {
|
||||
}).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)
|
||||
-> SignedStatement
|
||||
-> Option<SignedStatement>
|
||||
{
|
||||
let digest = match validated.statement {
|
||||
GenericStatement::Candidate(ref c) => c.hash(),
|
||||
@@ -493,9 +487,11 @@ impl SharedTable {
|
||||
|
||||
let signed_statement = self.context.sign_statement(validated.statement);
|
||||
|
||||
if let Some(ref signed) = signed_statement {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.table.import_statement(&*self.context, signed_statement.clone());
|
||||
inner.table.import_statement(&*self.context, signed.clone());
|
||||
inner.validated.insert(digest, ValidationWork::Done(validated.result));
|
||||
}
|
||||
|
||||
signed_statement
|
||||
}
|
||||
@@ -576,15 +572,15 @@ impl SharedTable {
|
||||
}
|
||||
|
||||
/// Returns id of the validator corresponding to the given index.
|
||||
pub fn index_to_id(&self, index: ValidatorIndex) -> Option<SessionKey> {
|
||||
self.context.index_mapping.get(&index).cloned()
|
||||
pub fn index_to_id(&self, index: ValidatorIndex) -> Option<ValidatorId> {
|
||||
self.context.validators.get(index as usize).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_keyring::Ed25519Keyring;
|
||||
use substrate_keyring::Sr25519Keyring;
|
||||
use primitives::crypto::UncheckedInto;
|
||||
use polkadot_primitives::parachain::{BlockData, ConsolidatedIngress};
|
||||
use futures::future;
|
||||
@@ -617,11 +613,12 @@ mod tests {
|
||||
let para_id = ParaId::from(1);
|
||||
let parent_hash = Default::default();
|
||||
|
||||
let local_key = Arc::new(Ed25519Keyring::Alice.pair());
|
||||
let local_id = local_key.public();
|
||||
let local_key = Sr25519Keyring::Alice.pair();
|
||||
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 = validity_other_key.public();
|
||||
let validity_other_key = Sr25519Keyring::Bob.pair();
|
||||
let validity_other: ValidatorId = validity_other_key.public().into();
|
||||
let validity_other_index = 1;
|
||||
|
||||
groups.insert(para_id, GroupInfo {
|
||||
@@ -630,9 +627,9 @@ mod tests {
|
||||
});
|
||||
|
||||
let shared_table = SharedTable::new(
|
||||
&[local_id, validity_other],
|
||||
[local_id, validity_other].to_vec(),
|
||||
groups,
|
||||
local_key.clone(),
|
||||
Some(local_key.clone()),
|
||||
parent_hash,
|
||||
ExtrinsicStore::new_in_memory(),
|
||||
None,
|
||||
@@ -651,7 +648,7 @@ mod tests {
|
||||
|
||||
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 {
|
||||
statement: candidate_statement,
|
||||
signature: signature.into(),
|
||||
@@ -671,11 +668,12 @@ mod tests {
|
||||
let para_id = ParaId::from(1);
|
||||
let parent_hash = Default::default();
|
||||
|
||||
let local_key = Arc::new(Ed25519Keyring::Alice.pair());
|
||||
let local_id = local_key.public();
|
||||
let local_key = Sr25519Keyring::Alice.pair();
|
||||
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 = validity_other_key.public();
|
||||
let validity_other_key = Sr25519Keyring::Bob.pair();
|
||||
let validity_other: ValidatorId = validity_other_key.public().into();
|
||||
let validity_other_index = 1;
|
||||
|
||||
groups.insert(para_id, GroupInfo {
|
||||
@@ -684,9 +682,9 @@ mod tests {
|
||||
});
|
||||
|
||||
let shared_table = SharedTable::new(
|
||||
&[local_id, validity_other],
|
||||
[local_id, validity_other].to_vec(),
|
||||
groups,
|
||||
local_key.clone(),
|
||||
Some(local_key.clone()),
|
||||
parent_hash,
|
||||
ExtrinsicStore::new_in_memory(),
|
||||
None,
|
||||
@@ -705,7 +703,7 @@ mod tests {
|
||||
|
||||
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 {
|
||||
statement: candidate_statement,
|
||||
signature: signature.into(),
|
||||
@@ -806,11 +804,12 @@ mod tests {
|
||||
let para_id = ParaId::from(1);
|
||||
let parent_hash = Default::default();
|
||||
|
||||
let local_key = Arc::new(Ed25519Keyring::Alice.pair());
|
||||
let local_id = local_key.public();
|
||||
let local_key = Sr25519Keyring::Alice.pair();
|
||||
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 = validity_other_key.public();
|
||||
let validity_other_key = Sr25519Keyring::Bob.pair();
|
||||
let validity_other: ValidatorId = validity_other_key.public().into();
|
||||
let validity_other_index = 1;
|
||||
|
||||
groups.insert(para_id, GroupInfo {
|
||||
@@ -819,9 +818,9 @@ mod tests {
|
||||
});
|
||||
|
||||
let shared_table = SharedTable::new(
|
||||
&[local_id, validity_other],
|
||||
[local_id, validity_other].to_vec(),
|
||||
groups,
|
||||
local_key.clone(),
|
||||
Some(local_key.clone()),
|
||||
parent_hash,
|
||||
ExtrinsicStore::new_in_memory(),
|
||||
None,
|
||||
@@ -841,7 +840,7 @@ mod tests {
|
||||
let hash = candidate.hash();
|
||||
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 {
|
||||
statement: candidate_statement,
|
||||
signature: signature.into(),
|
||||
@@ -872,11 +871,12 @@ mod tests {
|
||||
let extrinsic = Extrinsic { outgoing_messages: Vec::new() };
|
||||
let parent_hash = Default::default();
|
||||
|
||||
let local_key = Arc::new(Ed25519Keyring::Alice.pair());
|
||||
let local_id = local_key.public();
|
||||
let local_key = Sr25519Keyring::Alice.pair();
|
||||
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 = validity_other_key.public();
|
||||
let validity_other_key = Sr25519Keyring::Bob.pair();
|
||||
let validity_other: ValidatorId = validity_other_key.public().into();
|
||||
|
||||
groups.insert(para_id, GroupInfo {
|
||||
validity_guarantors: [local_id.clone(), validity_other.clone()].iter().cloned().collect(),
|
||||
@@ -884,9 +884,9 @@ mod tests {
|
||||
});
|
||||
|
||||
let shared_table = SharedTable::new(
|
||||
&[local_id, validity_other],
|
||||
[local_id, validity_other].to_vec(),
|
||||
groups,
|
||||
local_key.clone(),
|
||||
Some(local_key.clone()),
|
||||
parent_hash,
|
||||
ExtrinsicStore::new_in_memory(),
|
||||
None,
|
||||
@@ -908,7 +908,7 @@ mod tests {
|
||||
candidate,
|
||||
pov_block,
|
||||
extrinsic,
|
||||
));
|
||||
)).unwrap();
|
||||
|
||||
assert!(shared_table.inner.lock().validated.get(&hash).expect("validation has started").is_done());
|
||||
|
||||
@@ -919,29 +919,4 @@ mod tests {
|
||||
|
||||
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