mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 21:51:06 +00:00
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:
@@ -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(¶_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![],
|
||||
|
||||
@@ -128,7 +128,7 @@ impl MessageValidationData {
|
||||
::polkadot_validation::check_statement(
|
||||
&statement.statement,
|
||||
&statement.signature,
|
||||
statement.sender,
|
||||
statement.sender.clone(),
|
||||
relay_parent,
|
||||
)
|
||||
}
|
||||
|
||||
+19
-19
@@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user