Update to Substrate master (#176)

* Update to master

This introduces a new type `CollatorId`, currently just `SessionKey`
but which would forseeably change to its own thing. It seems to work
like this (despite there being a lot of the new-incompatible
`AccountId` replaced). No idea if it does anything sensible, though.

* Cleanups

* Fix tests

* Remove commented code

* Specify commit hash

* Remove commented code

* Correct version

* Update runtime/Cargo.toml

Co-Authored-By: gavofyork <github@gavwood.com>

* PairT instead of _Pair

* Update lock file

* Remove rev causing upset
This commit is contained in:
Gav Wood
2019-03-18 11:29:39 +01:00
committed by GitHub
parent 448c23dc52
commit 67275abe30
23 changed files with 1128 additions and 792 deletions
+35 -36
View File
@@ -16,9 +16,8 @@
//! Bridge between the network and consensus service for getting collations to it.
use polkadot_primitives::{AccountId, Hash};
use polkadot_primitives::{parachain::CollatorId, Hash};
use polkadot_primitives::parachain::{Id as ParaId, Collation};
use futures::sync::oneshot;
use std::collections::hash_map::{HashMap, Entry};
@@ -40,9 +39,9 @@ pub enum Role {
#[allow(dead_code)]
pub enum Action {
/// Disconnect the given collator.
Disconnect(AccountId),
Disconnect(CollatorId),
/// Give the collator a new role.
NewRole(AccountId, Role),
NewRole(CollatorId, Role),
}
struct CollationSlot {
@@ -111,13 +110,13 @@ impl SlotEntries {
}
struct ParachainCollators {
primary: AccountId,
backup: Vec<AccountId>,
primary: CollatorId,
backup: Vec<CollatorId>,
}
/// Manages connected collators and role assignments from the perspective of a validator.
pub struct CollatorPool {
collators: HashMap<AccountId, ParaId>,
collators: HashMap<CollatorId, ParaId>,
parachain_collators: HashMap<ParaId, ParachainCollators>,
collations: HashMap<(Hash, ParaId), CollationSlot>,
}
@@ -133,19 +132,19 @@ impl CollatorPool {
}
/// Call when a new collator is authenticated. Returns the role.
pub fn on_new_collator(&mut self, account_id: AccountId, para_id: ParaId) -> Role {
self.collators.insert(account_id.clone(), para_id);
pub fn on_new_collator(&mut self, collator_id: CollatorId, para_id: ParaId) -> Role {
self.collators.insert(collator_id.clone(), para_id);
match self.parachain_collators.entry(para_id) {
Entry::Vacant(vacant) => {
vacant.insert(ParachainCollators {
primary: account_id,
primary: collator_id,
backup: Vec::new(),
});
Role::Primary
},
Entry::Occupied(mut occupied) => {
occupied.get_mut().backup.push(account_id);
occupied.get_mut().backup.push(collator_id);
Role::Backup
}
@@ -154,21 +153,21 @@ impl CollatorPool {
/// Called when a collator disconnects. If it was the primary, returns a new primary for that
/// parachain.
pub fn on_disconnect(&mut self, account_id: AccountId) -> Option<AccountId> {
self.collators.remove(&account_id).and_then(|para_id| match self.parachain_collators.entry(para_id) {
pub fn on_disconnect(&mut self, collator_id: CollatorId) -> Option<CollatorId> {
self.collators.remove(&collator_id).and_then(|para_id| match self.parachain_collators.entry(para_id) {
Entry::Vacant(_) => None,
Entry::Occupied(mut occ) => {
if occ.get().primary == account_id {
if occ.get().primary == collator_id {
if occ.get().backup.is_empty() {
occ.remove();
None
} else {
let mut collators = occ.get_mut();
collators.primary = collators.backup.pop().expect("backup non-empty; qed");
Some(collators.primary)
Some(collators.primary.clone())
}
} else {
let pos = occ.get().backup.iter().position(|a| a == &account_id)
let pos = occ.get().backup.iter().position(|a| a == &collator_id)
.expect("registered collator always present in backup if not primary; qed");
occ.get_mut().backup.remove(pos);
@@ -181,8 +180,8 @@ impl CollatorPool {
/// Called when a collation is received.
/// The collator should be registered for the parachain of the collation as a precondition of this function.
/// The collation should have been checked for integrity of signature before passing to this function.
pub fn on_collation(&mut self, account_id: AccountId, relay_parent: Hash, collation: Collation) {
if let Some(para_id) = self.collators.get(&account_id) {
pub fn on_collation(&mut self, collator_id: CollatorId, relay_parent: Hash, collation: Collation) {
if let Some(para_id) = self.collators.get(&collator_id) {
debug_assert_eq!(para_id, &collation.receipt.parachain_index);
// TODO: punish if not primary?
@@ -219,20 +218,20 @@ impl CollatorPool {
#[cfg(test)]
mod tests {
use super::*;
use substrate_primitives::crypto::UncheckedInto;
use polkadot_primitives::parachain::{CandidateReceipt, BlockData, HeadData};
use substrate_primitives::H512;
use futures::Future;
#[test]
fn disconnect_primary_gives_new_primary() {
let mut pool = CollatorPool::new();
let para_id: ParaId = 5.into();
let bad_primary = [0; 32].into();
let good_backup = [1; 32].into();
let bad_primary: CollatorId = [0; 32].unchecked_into();
let good_backup: CollatorId = [1; 32].unchecked_into();
assert_eq!(pool.on_new_collator(bad_primary, para_id.clone()), Role::Primary);
assert_eq!(pool.on_new_collator(good_backup, para_id.clone()), Role::Backup);
assert_eq!(pool.on_disconnect(bad_primary), Some(good_backup));
assert_eq!(pool.on_new_collator(bad_primary.clone(), para_id.clone()), Role::Primary);
assert_eq!(pool.on_new_collator(good_backup.clone(), para_id.clone()), Role::Backup);
assert_eq!(pool.on_disconnect(bad_primary), Some(good_backup.clone()));
assert_eq!(pool.on_disconnect(good_backup), None);
}
@@ -240,11 +239,11 @@ mod tests {
fn disconnect_backup_removes_from_pool() {
let mut pool = CollatorPool::new();
let para_id: ParaId = 5.into();
let primary = [0; 32].into();
let backup = [1; 32].into();
let primary = [0; 32].unchecked_into();
let backup: CollatorId = [1; 32].unchecked_into();
assert_eq!(pool.on_new_collator(primary, para_id.clone()), Role::Primary);
assert_eq!(pool.on_new_collator(backup, para_id.clone()), Role::Backup);
assert_eq!(pool.on_new_collator(backup.clone(), para_id.clone()), Role::Backup);
assert_eq!(pool.on_disconnect(backup), None);
assert!(pool.parachain_collators.get(&para_id).unwrap().backup.is_empty());
}
@@ -253,19 +252,19 @@ mod tests {
fn await_before_collation() {
let mut pool = CollatorPool::new();
let para_id: ParaId = 5.into();
let primary = [0; 32].into();
let primary: CollatorId = [0; 32].unchecked_into();
let relay_parent = [1; 32].into();
assert_eq!(pool.on_new_collator(primary, para_id.clone()), Role::Primary);
assert_eq!(pool.on_new_collator(primary.clone(), para_id.clone()), Role::Primary);
let (tx1, rx1) = oneshot::channel();
let (tx2, rx2) = oneshot::channel();
pool.await_collation(relay_parent, para_id, tx1);
pool.await_collation(relay_parent, para_id, tx2);
pool.on_collation(primary, relay_parent, Collation {
pool.on_collation(primary.clone(), relay_parent, Collation {
receipt: CandidateReceipt {
parachain_index: para_id,
collator: primary.into(),
signature: H512::from([2; 64]).into(),
signature: Default::default(),
head_data: HeadData(vec![1, 2, 3]),
balance_uploads: vec![],
egress_queue_roots: vec![],
@@ -283,16 +282,16 @@ mod tests {
fn collate_before_await() {
let mut pool = CollatorPool::new();
let para_id: ParaId = 5.into();
let primary = [0; 32].into();
let primary: CollatorId = [0; 32].unchecked_into();
let relay_parent = [1; 32].into();
assert_eq!(pool.on_new_collator(primary, para_id.clone()), Role::Primary);
assert_eq!(pool.on_new_collator(primary.clone(), para_id.clone()), Role::Primary);
pool.on_collation(primary, relay_parent, Collation {
pool.on_collation(primary.clone(), relay_parent, Collation {
receipt: CandidateReceipt {
parachain_index: para_id,
collator: primary.into(),
signature: H512::from([2; 64]).into(),
collator: primary,
signature: Default::default(),
head_data: HeadData(vec![1, 2, 3]),
balance_uploads: vec![],
egress_queue_roots: vec![],
+1 -1
View File
@@ -128,7 +128,7 @@ impl MessageValidationData {
::polkadot_validation::check_statement(
&statement.statement,
&statement.signature,
statement.sender,
statement.sender.clone(),
relay_parent,
)
}
+19 -19
View File
@@ -54,13 +54,13 @@ pub mod gossip;
use codec::{Decode, Encode};
use futures::sync::oneshot;
use polkadot_primitives::{AccountId, Block, SessionKey, Hash, Header};
use polkadot_primitives::{Block, SessionKey, Hash, Header, parachain::CollatorId};
use polkadot_primitives::parachain::{Id as ParaId, BlockData, CandidateReceipt, Collation};
use substrate_network::{NodeIndex, RequestId, Context, Severity};
use substrate_network::{message, generic_message};
use substrate_network::specialization::NetworkSpecialization as Specialization;
use substrate_network::StatusMessage as GenericFullStatus;
use self::validation::{LiveValidationSessions, RecentSessionKeys, InsertedRecentKey};
use self::validation::{LiveValidationSessions, RecentValidatorIds, InsertedRecentKey};
use self::collator_pool::{CollatorPool, Role, Action};
use self::local_collations::LocalCollations;
@@ -81,7 +81,7 @@ pub type NetworkService = ::substrate_network::Service<Block, PolkadotProtocol>;
/// Status of a Polkadot node.
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct Status {
collating_for: Option<(AccountId, ParaId)>,
collating_for: Option<(CollatorId, ParaId)>,
}
struct BlockDataRequest {
@@ -128,8 +128,8 @@ impl CollatorState {
}
struct PeerInfo {
collating_for: Option<(AccountId, ParaId)>,
validator_keys: RecentSessionKeys,
collating_for: Option<(CollatorId, ParaId)>,
validator_keys: RecentValidatorIds,
claimed_validator: bool,
collator_state: CollatorState,
}
@@ -165,7 +165,7 @@ fn send_polkadot_message(ctx: &mut Context<Block>, to: NodeIndex, message: Messa
/// Polkadot protocol attachment for substrate.
pub struct PolkadotProtocol {
peers: HashMap<NodeIndex, PeerInfo>,
collating_for: Option<(AccountId, ParaId)>,
collating_for: Option<(CollatorId, ParaId)>,
collators: CollatorPool,
validators: HashMap<SessionKey, NodeIndex>,
local_collations: LocalCollations<Collation>,
@@ -178,7 +178,7 @@ pub struct PolkadotProtocol {
impl PolkadotProtocol {
/// Instantiate a polkadot protocol handler.
pub fn new(collating_for: Option<(AccountId, ParaId)>) -> Self {
pub fn new(collating_for: Option<(CollatorId, ParaId)>) -> Self {
PolkadotProtocol {
peers: HashMap::new(),
collators: CollatorPool::new(),
@@ -220,7 +220,7 @@ impl PolkadotProtocol {
for (id, peer_data) in self.peers.iter_mut()
.filter(|&(_, ref info)| info.should_send_key())
{
peer_data.collator_state.send_key(new_local, |msg| send_polkadot_message(
peer_data.collator_state.send_key(new_local.clone(), |msg| send_polkadot_message(
ctx,
*id,
msg
@@ -251,8 +251,8 @@ impl PolkadotProtocol {
}
Err(Some(known_keys)) => {
let next_peer = known_keys.iter()
.filter_map(|x| validator_keys.get(x).map(|id| (*x, *id)))
.find(|&(ref key, _)| pending.attempted_peers.insert(*key))
.filter_map(|x| validator_keys.get(x).map(|id| (x.clone(), *id)))
.find(|&(ref key, _)| pending.attempted_peers.insert(key.clone()))
.map(|(_, id)| id);
// dispatch to peer
@@ -323,14 +323,14 @@ impl PolkadotProtocol {
}
let local_collations = &mut self.local_collations;
let new_collations = match info.validator_keys.insert(key) {
let new_collations = match info.validator_keys.insert(key.clone()) {
InsertedRecentKey::AlreadyKnown => Vec::new(),
InsertedRecentKey::New(Some(old_key)) => {
self.validators.remove(&old_key);
local_collations.fresh_key(&old_key, &key)
}
InsertedRecentKey::New(None) => info.collator_state.role()
.map(|r| local_collations.note_validator_role(key, r))
.map(|r| local_collations.note_validator_role(key.clone(), r))
.unwrap_or_else(Vec::new),
};
@@ -418,7 +418,7 @@ impl Specialization<Block> for PolkadotProtocol {
let validator = status.roles.contains(substrate_network::config::Roles::AUTHORITY);
let mut peer_info = PeerInfo {
collating_for: local_status.collating_for,
collating_for: local_status.collating_for.clone(),
validator_keys: Default::default(),
claimed_validator: validator,
collator_state: CollatorState::Fresh,
@@ -442,7 +442,7 @@ impl Specialization<Block> for PolkadotProtocol {
// send session keys.
if peer_info.should_send_key() {
for local_session_key in self.live_validation_sessions.recent_keys() {
peer_info.collator_state.send_key(*local_session_key, |msg| send_polkadot_message(
peer_info.collator_state.send_key(local_session_key.clone(), |msg| send_polkadot_message(
ctx,
who,
msg,
@@ -544,7 +544,7 @@ impl PolkadotProtocol {
// we received a collation from a peer
fn on_collation(&mut self, ctx: &mut Context<Block>, from: NodeIndex, relay_parent: Hash, collation: Collation) {
let collation_para = collation.receipt.parachain_index;
let collated_acc = collation.receipt.collator;
let collated_acc = collation.receipt.collator.clone();
match self.peers.get(&from) {
None => ctx.report_peer(from, Severity::Useless("Unknown Polkadot specific reason".to_string())),
@@ -571,11 +571,11 @@ impl PolkadotProtocol {
}
// get connected peer with given account ID for collation.
fn collator_peer(&mut self, account_id: AccountId) -> Option<(NodeIndex, &mut PeerInfo)> {
fn collator_peer(&mut self, collator_id: CollatorId) -> Option<(NodeIndex, &mut PeerInfo)> {
let check_info = |info: &PeerInfo| info
.collating_for
.as_ref()
.map_or(false, |&(ref acc_id, _)| acc_id == &account_id);
.map_or(false, |&(ref acc_id, _)| acc_id == &collator_id);
self.peers
.iter_mut()
@@ -585,8 +585,8 @@ impl PolkadotProtocol {
}
// disconnect a collator by account-id.
fn disconnect_bad_collator(&mut self, ctx: &mut Context<Block>, account_id: AccountId) {
if let Some((who, _)) = self.collator_peer(account_id) {
fn disconnect_bad_collator(&mut self, ctx: &mut Context<Block>, collator_id: CollatorId) {
if let Some((who, _)) = self.collator_peer(collator_id) {
ctx.report_peer(who, Severity::Bad("Consensus layer determined the given collator misbehaved".to_string()))
}
}
+14 -12
View File
@@ -58,7 +58,7 @@ impl<C: Clone> LocalCollations<C> {
Vec::new()
}
Role::Primary => {
let new_primary = self.primary_for.insert(key);
let new_primary = self.primary_for.insert(key.clone());
if new_primary {
self.collations_targeting(&key)
} else {
@@ -72,7 +72,7 @@ impl<C: Clone> LocalCollations<C> {
/// to the validator.
pub fn fresh_key(&mut self, old_key: &SessionKey, new_key: &SessionKey) -> Vec<(Hash, C)> {
if self.primary_for.remove(old_key) {
self.primary_for.insert(*new_key);
self.primary_for.insert(new_key.clone());
self.collations_targeting(new_key)
} else {
@@ -116,7 +116,7 @@ impl<C: Clone> LocalCollations<C> {
let borrowed_collation = &local.collation;
local.targets
.intersection(&self.primary_for)
.map(move |k| (*k, borrowed_collation.clone()))
.map(move |k| (k.clone(), borrowed_collation.clone()))
}
fn collations_targeting(&self, key: &SessionKey) -> Vec<(Hash, C)> {
@@ -130,14 +130,16 @@ impl<C: Clone> LocalCollations<C> {
#[cfg(test)]
mod tests {
use super::*;
use substrate_primitives::crypto::UncheckedInto;
use polkadot_primitives::parachain::ValidatorId;
#[test]
fn add_validator_with_ready_collation() {
let key = [1; 32].into();
let key: ValidatorId = [1; 32].unchecked_into();
let relay_parent = [2; 32].into();
let targets = {
let mut set = HashSet::new();
set.insert(key);
set.insert(key.clone());
set
};
@@ -148,18 +150,18 @@ mod tests {
#[test]
fn rename_with_ready() {
let orig_key = [1; 32].into();
let new_key = [2; 32].into();
let orig_key: ValidatorId = [1; 32].unchecked_into();
let new_key: ValidatorId = [2; 32].unchecked_into();
let relay_parent = [255; 32].into();
let targets = {
let mut set = HashSet::new();
set.insert(new_key);
set.insert(new_key.clone());
set
};
let mut tracker: LocalCollations<u8> = LocalCollations::new();
assert!(tracker.add_collation(relay_parent, targets, 5).next().is_none());
assert!(tracker.note_validator_role(orig_key, Role::Primary).is_empty());
assert!(tracker.note_validator_role(orig_key.clone(), Role::Primary).is_empty());
assert_eq!(tracker.fresh_key(&orig_key, &new_key), vec![(relay_parent, 5u8)]);
}
@@ -183,16 +185,16 @@ mod tests {
#[test]
fn add_collation_with_connected_target() {
let key = [1; 32].into();
let key: ValidatorId = [1; 32].unchecked_into();
let relay_parent = [2; 32].into();
let targets = {
let mut set = HashSet::new();
set.insert(key);
set.insert(key.clone());
set
};
let mut tracker = LocalCollations::new();
assert!(tracker.note_validator_role(key, Role::Primary).is_empty());
assert!(tracker.note_validator_role(key.clone(), Role::Primary).is_empty());
assert_eq!(tracker.add_collation(relay_parent, targets, 5).next(), Some((key, 5)));
}
+9 -8
View File
@@ -426,8 +426,8 @@ impl DeferredStatements {
fn push(&mut self, statement: SignedStatement) {
let (hash, trace) = match statement.statement {
GenericStatement::Candidate(_) => return,
GenericStatement::Valid(hash) => (hash, StatementTrace::Valid(statement.sender, hash)),
GenericStatement::Invalid(hash) => (hash, StatementTrace::Invalid(statement.sender, hash)),
GenericStatement::Valid(hash) => (hash, StatementTrace::Valid(statement.sender.clone(), hash)),
GenericStatement::Invalid(hash) => (hash, StatementTrace::Invalid(statement.sender.clone(), hash)),
};
if self.known_traces.insert(trace) {
@@ -443,8 +443,8 @@ impl DeferredStatements {
for statement in deferred.iter() {
let trace = match statement.statement {
GenericStatement::Candidate(_) => continue,
GenericStatement::Valid(hash) => StatementTrace::Valid(statement.sender, hash),
GenericStatement::Invalid(hash) => StatementTrace::Invalid(statement.sender, hash),
GenericStatement::Valid(hash) => StatementTrace::Valid(statement.sender.clone(), hash),
GenericStatement::Invalid(hash) => StatementTrace::Invalid(statement.sender.clone(), hash),
};
self.known_traces.remove(&trace);
@@ -512,19 +512,20 @@ impl<S> Future for ComputeIngress<S> where S: Stream<Item=IngressPair> {
#[cfg(test)]
mod tests {
use super::*;
use substrate_primitives::H512;
use substrate_primitives::crypto::UncheckedInto;
use futures::stream;
use polkadot_primitives::parachain::ValidatorId;
#[test]
fn deferred_statements_works() {
let mut deferred = DeferredStatements::new();
let hash = [1; 32].into();
let sig = H512::from([2; 64]).into();
let sender = [255; 32].into();
let sig = Default::default();
let sender: ValidatorId = [255; 32].unchecked_into();
let statement = SignedStatement {
statement: GenericStatement::Valid(hash),
sender,
sender: sender.clone(),
signature: sig,
};
+27 -27
View File
@@ -22,8 +22,8 @@ use validation::{ValidationSession, Knowledge};
use parking_lot::Mutex;
use polkadot_validation::GenericStatement;
use polkadot_primitives::{Block, SessionKey};
use polkadot_primitives::parachain::{CandidateReceipt, HeadData, BlockData};
use substrate_primitives::H512;
use polkadot_primitives::parachain::{CandidateReceipt, HeadData, BlockData, CollatorId, ValidatorId};
use substrate_primitives::crypto::UncheckedInto;
use codec::Encode;
use substrate_network::{
Severity, NodeIndex, PeerInfo, ClientHandle, Context, config::Roles,
@@ -107,10 +107,10 @@ fn sends_session_key() {
let peer_a = 1;
let peer_b = 2;
let parent_hash = [0; 32].into();
let local_key = [1; 32].into();
let local_key: ValidatorId = [1; 32].unchecked_into();
let validator_status = Status { collating_for: None };
let collator_status = Status { collating_for: Some(([2; 32].into(), 5.into())) };
let collator_status = Status { collating_for: Some(([2; 32].unchecked_into(), 5.into())) };
{
let mut ctx = TestContext::default();
@@ -120,9 +120,9 @@ fn sends_session_key() {
{
let mut ctx = TestContext::default();
let (session, _knowledge) = make_validation_session(local_key);
let (session, _knowledge) = make_validation_session(local_key.clone());
protocol.new_validation_session(&mut ctx, parent_hash, session);
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key)));
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key.clone())));
}
{
@@ -139,15 +139,15 @@ fn fetches_from_those_with_knowledge() {
let peer_a = 1;
let peer_b = 2;
let parent_hash = [0; 32].into();
let local_key = [1; 32].into();
let local_key: ValidatorId = [1; 32].unchecked_into();
let block_data = BlockData(vec![1, 2, 3, 4]);
let block_data_hash = block_data.hash();
let candidate_receipt = CandidateReceipt {
parachain_index: 5.into(),
collator: [255; 32].into(),
collator: [255; 32].unchecked_into(),
head_data: HeadData(vec![9, 9, 9]),
signature: H512::from([1; 64]).into(),
signature: Default::default(),
balance_uploads: Vec::new(),
egress_queue_roots: Vec::new(),
fees: 1_000_000,
@@ -155,15 +155,15 @@ fn fetches_from_those_with_knowledge() {
};
let candidate_hash = candidate_receipt.hash();
let a_key = [3; 32].into();
let b_key = [4; 32].into();
let a_key: ValidatorId = [3; 32].unchecked_into();
let b_key: ValidatorId = [4; 32].unchecked_into();
let status = Status { collating_for: None };
let (session, knowledge) = make_validation_session(local_key);
let (session, knowledge) = make_validation_session(local_key.clone());
protocol.new_validation_session(&mut TestContext::default(), parent_hash, session);
knowledge.lock().note_statement(a_key, &GenericStatement::Valid(candidate_hash));
knowledge.lock().note_statement(a_key.clone(), &GenericStatement::Valid(candidate_hash));
let recv = protocol.fetch_block_data(&mut TestContext::default(), &candidate_receipt, parent_hash);
// connect peer A
@@ -176,12 +176,12 @@ fn fetches_from_those_with_knowledge() {
// peer A gives session key and gets asked for data.
{
let mut ctx = TestContext::default();
on_message(&mut protocol, &mut ctx, peer_a, Message::SessionKey(a_key));
on_message(&mut protocol, &mut ctx, peer_a, Message::SessionKey(a_key.clone()));
assert!(protocol.validators.contains_key(&a_key));
assert!(ctx.has_message(peer_a, Message::RequestBlockData(1, parent_hash, candidate_hash)));
}
knowledge.lock().note_statement(b_key, &GenericStatement::Valid(candidate_hash));
knowledge.lock().note_statement(b_key.clone(), &GenericStatement::Valid(candidate_hash));
// peer B connects and sends session key. request already assigned to A
{
@@ -221,9 +221,9 @@ fn fetches_available_block_data() {
let para_id = 5.into();
let candidate_receipt = CandidateReceipt {
parachain_index: para_id,
collator: [255; 32].into(),
collator: [255; 32].unchecked_into(),
head_data: HeadData(vec![9, 9, 9]),
signature: H512::from([1; 64]).into(),
signature: Default::default(),
balance_uploads: Vec::new(),
egress_queue_roots: Vec::new(),
fees: 1_000_000,
@@ -264,9 +264,9 @@ fn remove_bad_collator() {
let mut protocol = PolkadotProtocol::new(None);
let who = 1;
let account_id = [2; 32].into();
let collator_id: CollatorId = [2; 32].unchecked_into();
let status = Status { collating_for: Some((account_id, 5.into())) };
let status = Status { collating_for: Some((collator_id.clone(), 5.into())) };
{
let mut ctx = TestContext::default();
@@ -275,7 +275,7 @@ fn remove_bad_collator() {
{
let mut ctx = TestContext::default();
protocol.disconnect_bad_collator(&mut ctx, account_id);
protocol.disconnect_bad_collator(&mut ctx, collator_id);
assert!(ctx.disabled.contains(&who));
}
}
@@ -287,16 +287,16 @@ fn many_session_keys() {
let parent_a = [1; 32].into();
let parent_b = [2; 32].into();
let local_key_a = [3; 32].into();
let local_key_b = [4; 32].into();
let local_key_a: ValidatorId = [3; 32].unchecked_into();
let local_key_b: ValidatorId = [4; 32].unchecked_into();
let (session_a, _knowledge_a) = make_validation_session(local_key_a);
let (session_b, _knowledge_b) = make_validation_session(local_key_b);
let (session_a, _knowledge_a) = make_validation_session(local_key_a.clone());
let (session_b, _knowledge_b) = make_validation_session(local_key_b.clone());
protocol.new_validation_session(&mut TestContext::default(), parent_a, session_a);
protocol.new_validation_session(&mut TestContext::default(), parent_b, session_b);
assert_eq!(protocol.live_validation_sessions.recent_keys(), &[local_key_a, local_key_b]);
assert_eq!(protocol.live_validation_sessions.recent_keys(), &[local_key_a.clone(), local_key_b.clone()]);
let peer_a = 1;
@@ -307,8 +307,8 @@ fn many_session_keys() {
let status = Status { collating_for: None };
protocol.on_connect(&mut ctx, peer_a, make_status(&status, Roles::AUTHORITY));
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key_a)));
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key_b)));
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key_a.clone())));
assert!(ctx.has_message(peer_a, Message::SessionKey(local_key_b.clone())));
}
let peer_b = 2;
+22 -22
View File
@@ -18,13 +18,14 @@
use validation::NetworkService;
use substrate_network::Context as NetContext;
use substrate_primitives::{Ed25519AuthorityId, NativeOrEncoded};
use substrate_keyring::Keyring;
use substrate_primitives::NativeOrEncoded;
use substrate_keyring::AuthorityKeyring;
use {PolkadotProtocol};
use polkadot_validation::{SharedTable, MessagesFrom, Network, TableRouter};
use polkadot_primitives::{AccountId, Block, Hash, Header, BlockId};
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, ParachainHost, OutgoingMessage};
use polkadot_primitives::{SessionKey, Block, Hash, Header, BlockId};
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, ParachainHost, OutgoingMessage,
ValidatorId};
use parking_lot::Mutex;
use substrate_client::error::Result as ClientResult;
use substrate_client::runtime_api::{Core, RuntimeVersion, ApiExt};
@@ -154,7 +155,7 @@ impl NetworkService for TestNetwork {
#[derive(Default)]
struct ApiData {
validators: Vec<AccountId>,
validators: Vec<ValidatorId>,
duties: Vec<Chain>,
active_parachains: Vec<ParaId>,
ingress: HashMap<ParaId, Vec<(ParaId, Hash)>>,
@@ -194,7 +195,7 @@ impl Core<Block> for RuntimeApi {
_: ExecutionContext,
_: Option<()>,
_: Vec<u8>,
) -> ClientResult<NativeOrEncoded<Vec<Ed25519AuthorityId>>> {
) -> ClientResult<NativeOrEncoded<Vec<SessionKey>>> {
unimplemented!("Not required for testing!")
}
@@ -239,7 +240,7 @@ impl ParachainHost<Block> for RuntimeApi {
_: ExecutionContext,
_: Option<()>,
_: Vec<u8>,
) -> ClientResult<NativeOrEncoded<Vec<AccountId>>> {
) -> ClientResult<NativeOrEncoded<Vec<ValidatorId>>> {
Ok(NativeOrEncoded::Native(self.data.lock().validators.clone()))
}
@@ -372,15 +373,14 @@ impl IngressBuilder {
}
}
fn make_table(data: &ApiData, local_key: &Keyring, parent_hash: Hash) -> Arc<SharedTable> {
fn make_table(data: &ApiData, local_key: &AuthorityKeyring, parent_hash: Hash) -> Arc<SharedTable> {
use ::av_store::Store;
let store = Store::new_in_memory();
let authorities: Vec<_> = data.validators.iter().map(|v| v.to_fixed_bytes().into()).collect();
let (group_info, _) = ::polkadot_validation::make_group_info(
DutyRoster { validator_duty: data.duties.clone() },
&authorities,
local_key.to_raw_public().into()
&data.validators, // only possible as long as parachain crypto === aura crypto
SessionKey::from(*local_key)
).unwrap();
Arc::new(SharedTable::new(
@@ -400,9 +400,9 @@ fn ingress_fetch_works() {
let id_b: ParaId = 2.into();
let id_c: ParaId = 3.into();
let key_a = Keyring::Alice;
let key_b = Keyring::Bob;
let key_c = Keyring::Charlie;
let key_a = AuthorityKeyring::Alice;
let key_b = AuthorityKeyring::Bob;
let key_c = AuthorityKeyring::Charlie;
let messages_from_a = vec![
OutgoingMessage { target: id_b, data: vec![1, 2, 3] },
@@ -432,16 +432,16 @@ fn ingress_fetch_works() {
let parent_hash = [1; 32].into();
let (router_a, router_b, router_c) = {
let validators: Vec<Hash> = vec![
key_a.to_raw_public().into(),
key_b.to_raw_public().into(),
key_c.to_raw_public().into(),
let validators: Vec<ValidatorId> = vec![
key_a.into(),
key_b.into(),
key_c.into(),
];
let authorities: Vec<_> = validators.iter().cloned()
.map(|h| h.to_fixed_bytes())
.map(Ed25519AuthorityId)
.collect();
// NOTE: this is possible only because we are currently asserting that parachain validators
// share their crypto with the (Aura) authority set. Once that assumption breaks, so will this
// code.
let authorities = validators.clone();
let mut api_handle = built.api_handle.lock();
*api_handle = ApiData {
+37 -35
View File
@@ -22,8 +22,9 @@
use sr_primitives::traits::ProvideRuntimeApi;
use substrate_network::Context as NetContext;
use polkadot_validation::{Network as ParachainNetwork, SharedTable, Collators, Statement, GenericStatement};
use polkadot_primitives::{AccountId, Block, Hash, SessionKey};
use polkadot_primitives::parachain::{Id as ParaId, Collation, Extrinsic, ParachainHost, BlockData};
use polkadot_primitives::{Block, Hash};
use polkadot_primitives::parachain::{Id as ParaId, Collation, Extrinsic, ParachainHost, BlockData, ValidatorId,
CollatorId};
use codec::Decode;
use futures::prelude::*;
@@ -208,7 +209,7 @@ impl<P, E, N, T> ParachainNetwork for ValidationNetwork<P, E, N, T> where
&self,
table: Arc<SharedTable>,
outgoing: polkadot_validation::Outgoing,
authorities: &[SessionKey],
authorities: &[ValidatorId],
) -> Self::TableRouter {
let parent_hash = table.consensus_parent_hash().clone();
@@ -310,15 +311,15 @@ impl<P, E: Clone, N, T: Clone> Collators for ValidationNetwork<P, E, N, T> where
}
fn note_bad_collator(&self, collator: AccountId) {
fn note_bad_collator(&self, collator: CollatorId) {
self.network.with_spec(move |spec, ctx| spec.disconnect_bad_collator(ctx, collator));
}
}
#[derive(Default)]
struct KnowledgeEntry {
knows_block_data: Vec<SessionKey>,
knows_extrinsic: Vec<SessionKey>,
knows_block_data: Vec<ValidatorId>,
knows_extrinsic: Vec<ValidatorId>,
block_data: Option<BlockData>,
extrinsic: Option<Extrinsic>,
}
@@ -337,19 +338,19 @@ impl Knowledge {
}
/// Note a statement seen from another validator.
pub(crate) fn note_statement(&mut self, from: SessionKey, statement: &Statement) {
pub(crate) fn note_statement(&mut self, from: ValidatorId, statement: &Statement) {
// those proposing the candidate or declaring it valid know everything.
// those claiming it invalid do not have the extrinsic data as it is
// generated by valid execution.
match *statement {
GenericStatement::Candidate(ref c) => {
let mut entry = self.candidates.entry(c.hash()).or_insert_with(Default::default);
entry.knows_block_data.push(from);
entry.knows_block_data.push(from.clone());
entry.knows_extrinsic.push(from);
}
GenericStatement::Valid(ref hash) => {
let mut entry = self.candidates.entry(*hash).or_insert_with(Default::default);
entry.knows_block_data.push(from);
entry.knows_block_data.push(from.clone());
entry.knows_extrinsic.push(from);
}
GenericStatement::Invalid(ref hash) => self.candidates.entry(*hash)
@@ -370,12 +371,12 @@ impl Knowledge {
/// A current validation session instance.
pub(crate) struct ValidationSession {
knowledge: Arc<Mutex<Knowledge>>,
local_session_key: SessionKey,
local_session_key: ValidatorId,
}
impl ValidationSession {
#[cfg(test)]
pub(crate) fn new(knowledge: Arc<Mutex<Knowledge>>, local_session_key: SessionKey) -> Self {
pub(crate) fn new(knowledge: Arc<Mutex<Knowledge>>, local_session_key: ValidatorId) -> Self {
ValidationSession {
knowledge,
local_session_key
@@ -385,7 +386,7 @@ impl ValidationSession {
// execute a closure with locally stored block data for a candidate, or a slice of session identities
// we believe should have the data.
fn with_block_data<F, U>(&self, hash: &Hash, f: F) -> U
where F: FnOnce(Result<&BlockData, &[SessionKey]>) -> U
where F: FnOnce(Result<&BlockData, &[ValidatorId]>) -> U
{
let knowledge = self.knowledge.lock();
let res = knowledge.candidates.get(hash)
@@ -407,19 +408,19 @@ pub(crate) enum InsertedRecentKey {
/// Key was already known.
AlreadyKnown,
/// Key was new and pushed out optional old item.
New(Option<SessionKey>),
New(Option<ValidatorId>),
}
/// Wrapper for managing recent session keys.
#[derive(Default)]
pub(crate) struct RecentSessionKeys {
inner: ArrayVec<[SessionKey; RECENT_SESSIONS]>,
pub(crate) struct RecentValidatorIds {
inner: ArrayVec<[ValidatorId; RECENT_SESSIONS]>,
}
impl RecentSessionKeys {
impl RecentValidatorIds {
/// Insert a new session key. This returns one to be pushed out if the
/// set is full.
pub(crate) fn insert(&mut self, key: SessionKey) -> InsertedRecentKey {
pub(crate) fn insert(&mut self, key: ValidatorId) -> InsertedRecentKey {
if self.inner.contains(&key) { return InsertedRecentKey::AlreadyKnown }
let old = if self.inner.len() == RECENT_SESSIONS {
@@ -433,11 +434,11 @@ impl RecentSessionKeys {
}
/// As a slice.
pub(crate) fn as_slice(&self) -> &[SessionKey] {
pub(crate) fn as_slice(&self) -> &[ValidatorId] {
&*self.inner
}
fn remove(&mut self, key: &SessionKey) {
fn remove(&mut self, key: &ValidatorId) {
self.inner.retain(|k| k != key)
}
}
@@ -445,7 +446,7 @@ impl RecentSessionKeys {
/// Manages requests and keys for live validation session instances.
pub(crate) struct LiveValidationSessions {
// recent local session keys.
recent: RecentSessionKeys,
recent: RecentValidatorIds,
// live validation session instances, on `parent_hash`.
live_instances: HashMap<Hash, ValidationSession>,
}
@@ -465,10 +466,10 @@ impl LiveValidationSessions {
&mut self,
parent_hash: Hash,
session: ValidationSession,
) -> Option<SessionKey> {
let inserted_key = self.recent.insert(session.local_session_key);
) -> Option<ValidatorId> {
let inserted_key = self.recent.insert(session.local_session_key.clone());
let maybe_new = if let InsertedRecentKey::New(_) = inserted_key {
Some(session.local_session_key)
Some(session.local_session_key.clone())
} else {
None
};
@@ -491,7 +492,7 @@ impl LiveValidationSessions {
}
/// Recent session keys as a slice.
pub(crate) fn recent_keys(&self) -> &[SessionKey] {
pub(crate) fn recent_keys(&self) -> &[ValidatorId] {
self.recent.as_slice()
}
@@ -501,7 +502,7 @@ impl LiveValidationSessions {
/// `Err(Some(keys))` when the session is live but the data unknown, with a list of keys
/// who have the data, and `Err(None)` where the session is unknown.
pub(crate) fn with_block_data<F, U>(&self, parent_hash: &Hash, c_hash: &Hash, f: F) -> U
where F: FnOnce(Result<&BlockData, Option<&[SessionKey]>>) -> U
where F: FnOnce(Result<&BlockData, Option<&[ValidatorId]>>) -> U
{
match self.live_instances.get(parent_hash) {
Some(c) => c.with_block_data(c_hash, |res| f(res.map_err(Some))),
@@ -513,27 +514,28 @@ impl LiveValidationSessions {
#[cfg(test)]
mod tests {
use super::*;
use substrate_primitives::crypto::UncheckedInto;
#[test]
fn last_keys_works() {
let a = [1; 32].into();
let b = [2; 32].into();
let c = [3; 32].into();
let d = [4; 32].into();
let a: ValidatorId = [1; 32].unchecked_into();
let b: ValidatorId = [2; 32].unchecked_into();
let c: ValidatorId = [3; 32].unchecked_into();
let d: ValidatorId = [4; 32].unchecked_into();
let mut recent = RecentSessionKeys::default();
let mut recent = RecentValidatorIds::default();
match recent.insert(a) {
match recent.insert(a.clone()) {
InsertedRecentKey::New(None) => {},
_ => panic!("is new, not at capacity"),
}
match recent.insert(a) {
match recent.insert(a.clone()) {
InsertedRecentKey::AlreadyKnown => {},
_ => panic!("not new"),
}
match recent.insert(b) {
match recent.insert(b.clone()) {
InsertedRecentKey::New(None) => {},
_ => panic!("is new, not at capacity"),
}
@@ -543,7 +545,7 @@ mod tests {
_ => panic!("not new"),
}
match recent.insert(c) {
match recent.insert(c.clone()) {
InsertedRecentKey::New(None) => {},
_ => panic!("is new, not at capacity"),
}
@@ -553,7 +555,7 @@ mod tests {
_ => panic!("not new"),
}
match recent.insert(d) {
match recent.insert(d.clone()) {
InsertedRecentKey::New(Some(old)) => assert_eq!(old, a),
_ => panic!("is new, and at capacity"),
}