Update to latest Substrate master. (#353)

* Integrate srml/im-online

* Fix all build errors with old aura.

* Fix most of the build errors.

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

* Apply suggestions from code review

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

* Kill some warnings.

* fix panics on 0 validators

* Fix dev chain.

* Fix author stuff

* fix im online integration.

* Some tweaks

* Introduce app-crypto

* Initial build work

* codec update / tweaks

* patch polkadot-erasure-coding input

* More fixes for new crypto

* More fixes

* Update parachains module

* evamp parachain crypto

* More crypto work.

* Chain spec and service.

* ChainSpec stuff

* Last bits for a clean build

* Tweak coment

* adapt polkadot-validation to the new keystore

* polkadot-network compiles, but tests don't

* Integrate the new parachain validation stuff

* delete message_routing file

* make polkadot-network tests compile and pass

* runtime tests compile and pass

* update substrate ref

* service compiles

* all tests pass

* Add TODO, change branch back to polkadot-master

* Lock file

* TODOs done

* Issue number

* Remove old tODO

* Remove commented code
This commit is contained in:
Kian Paimani
2019-08-12 15:48:29 +02:00
committed by Gavin Wood
parent 9b6e630816
commit 10fc88f6b1
51 changed files with 1719 additions and 1513 deletions
+10 -9
View File
@@ -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,
);
+2 -2
View File
@@ -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.
+2 -2
View File
@@ -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),
+1 -1
View File
@@ -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;
+70 -62
View File
@@ -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,
};
Ok((map, local_duty))
}
None => return Err(Error::NotValidator(local_id)),
}
let local_duty = local_validation.map(|v| LocalDuty {
validation: v
});
Ok((map, local_duty))
}
// finds the first key we are capable of signing with out of the given set of validators,
// if any.
fn signing_key(validators: &[ValidatorId], keystore: &KeyStorePtr) -> Option<Arc<ValidatorPair>> {
let keystore = keystore.read();
validators.iter()
.find_map(|v| {
keystore.key_pair::<ValidatorPair>(&v).ok()
})
.map(|pair| Arc::new(pair))
}
/// Constructs parachain-agreement instances.
@@ -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));
}
}
+74 -99
View File
@@ -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
.iter()
.find(|(_, k)| k == &&id)
.map(|(i, _)| *i)
.unwrap()
fn local_index(&self) -> Option<ValidatorIndex> {
self.local_id().and_then(|id|
self.validators
.iter()
.enumerate()
.find(|(_, k)| k == &&id)
.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);
let mut inner = self.inner.lock();
inner.table.import_statement(&*self.context, signed_statement.clone());
inner.validated.insert(digest, ValidationWork::Done(validated.result));
if let Some(ref signed) = signed_statement {
let mut inner = self.inner.lock();
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);
}
}
}