Fix tracking validator set in ImOnline (#3596)

* Use session::validators instead of staking::current_elected

* Basic test framework.

* Initialize validators, attempt to heartbeat.

* Use dummy crypto for im-online testing.

* Remove printlns.

* Finish test, make it invalid.

* Add reporting test.

* Finalize the test.

* Remove dumbness.

* Updates.

* Update AuRa

* Update srml/im-online/src/tests.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Derive Ord

* Add some more tests.

* Remove stray todo.

* Bump runtime version.

* Bump impl-trait-for-tuples.

* Enforce new version of trait-for-tuples.
This commit is contained in:
Tomasz Drwięga
2019-09-13 14:55:33 +02:00
committed by Gavin Wood
parent a7f35680b4
commit b7c6bc1ed5
26 changed files with 493 additions and 133 deletions
@@ -213,6 +213,7 @@ macro_rules! app_crypto {
}
impl $crate::RuntimeAppPublic for Public where $public: $crate::RuntimePublic<Signature=$sig> {
const ID: $crate::KeyTypeId = $key_type;
type Signature = Signature;
fn all() -> $crate::Vec<Self> {
@@ -96,7 +96,10 @@ pub trait RuntimePublic: Sized {
}
/// A runtime interface for an application's public key.
pub trait RuntimeAppPublic: Sized {
pub trait RuntimeAppPublic: Sized {
/// An identifier for this application-specific key type.
const ID: KeyTypeId;
/// The signature that will be generated when signing with the corresponding private key.
type Signature: Codec + MaybeDebugHash + Eq + PartialEq + Clone;
@@ -15,7 +15,6 @@ client = { package = "substrate-client", path = "../../core/client" }
codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" }
derive_more = "0.14.0"
futures = "0.1"
keystore = { package = "substrate-keystore", path = "../../core/keystore" }
libp2p = { version = "0.12.0", default-features = false, features = ["secp256k1", "libp2p-websocket"] }
log = "0.4"
network = { package = "substrate-network", path = "../../core/network" }
+10 -3
View File
@@ -67,6 +67,8 @@ pub struct State {
pub persistent_storage: client::in_mem::OffchainStorage,
/// Local storage
pub local_storage: client::in_mem::OffchainStorage,
/// A vector of transactions submitted from the runtime.
pub transactions: Vec<Vec<u8>>,
}
impl State {
@@ -138,12 +140,17 @@ impl offchain::Externalities for TestOffchainExt {
unimplemented!("not needed in tests so far")
}
fn submit_transaction(&mut self, _ex: Vec<u8>) -> Result<(), ()> {
unimplemented!("not needed in tests so far")
fn submit_transaction(&mut self, ex: Vec<u8>) -> Result<(), ()> {
let mut state = self.0.write();
state.transactions.push(ex);
Ok(())
}
fn network_state(&self) -> Result<OpaqueNetworkState, ()> {
unimplemented!("not needed in tests so far")
Ok(OpaqueNetworkState {
peer_id: Default::default(),
external_addresses: vec![],
})
}
fn timestamp(&mut self) -> Timestamp {
+1 -1
View File
@@ -160,7 +160,7 @@ pub struct OpaqueNetworkState {
}
/// Simple blob to hold a `PeerId` without committing to its format.
#[derive(Clone, Eq, PartialEq, Encode, Decode)]
#[derive(Default, Clone, Eq, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct OpaquePeerId(pub Vec<u8>);
+1 -1
View File
@@ -16,7 +16,7 @@ runtime_io = { package = "sr-io", path = "../sr-io", default-features = false }
log = { version = "0.4", optional = true }
paste = { version = "0.1"}
rand = { version = "0.7.0", optional = true }
impl-trait-for-tuples = "0.1"
impl-trait-for-tuples = "0.1.1"
[dev-dependencies]
serde_json = "1.0"
+1 -1
View File
@@ -56,7 +56,7 @@ pub use generic::{DigestItem, Digest};
/// Re-export this since it's part of the API of this crate.
pub use primitives::crypto::{key_types, KeyTypeId, CryptoType};
pub use app_crypto::AppKey;
pub use app_crypto::RuntimeAppPublic;
/// Justification type.
pub type Justification = Vec<u8>;
+35 -22
View File
@@ -17,7 +17,7 @@
//! Testing utilities.
use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer};
use std::{fmt::Debug, ops::Deref, fmt};
use std::{fmt::Debug, ops::Deref, fmt, cell::RefCell};
use crate::codec::{Codec, Encode, Decode};
use crate::traits::{
self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, ValidateUnsigned,
@@ -30,9 +30,15 @@ use primitives::{crypto::{CryptoType, Dummy, key_types, Public}, U256};
use crate::transaction_validity::{TransactionValidity, TransactionValidityError};
/// Authority Id
#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize)]
#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct UintAuthorityId(pub u64);
impl From<u64> for UintAuthorityId {
fn from(id: u64) -> Self {
UintAuthorityId(id)
}
}
impl UintAuthorityId {
/// Convert this authority id into a public key.
pub fn to_public_key<T: Public>(&self) -> T {
@@ -47,34 +53,44 @@ impl CryptoType for UintAuthorityId {
impl AsRef<[u8]> for UintAuthorityId {
fn as_ref(&self) -> &[u8] {
// Unsafe, i know, but it's test code and it's just there because it's really convenient to
// keep `UintAuthorityId` as a u64 under the hood.
unsafe {
std::slice::from_raw_parts(&self.0 as *const u64 as *const _, std::mem::size_of::<u64>())
}
}
}
thread_local! {
/// A list of all UintAuthorityId keys returned to the runtime.
static ALL_KEYS: RefCell<Vec<UintAuthorityId>> = RefCell::new(vec![]);
}
impl UintAuthorityId {
/// Set the list of keys returned by the runtime call for all keys of that type.
pub fn set_all_keys<T: Into<UintAuthorityId>>(keys: impl IntoIterator<Item=T>) {
ALL_KEYS.with(|l| *l.borrow_mut() = keys.into_iter().map(Into::into).collect())
}
}
impl app_crypto::RuntimeAppPublic for UintAuthorityId {
const ID: KeyTypeId = key_types::DUMMY;
type Signature = u64;
fn all() -> Vec<Self> {
unimplemented!("`all()` not available for `UintAuthorityId`.")
ALL_KEYS.with(|l| l.borrow().clone())
}
#[cfg(feature = "std")]
fn generate_pair(_: Option<&str>) -> Self {
use rand::RngCore;
UintAuthorityId(rand::thread_rng().next_u64())
}
#[cfg(not(feature = "std"))]
fn generate_pair(_: Option<&str>) -> Self {
unimplemented!("`generate_pair` not implemented for `UIntAuthorityId` on `no_std`.")
}
fn sign<M: AsRef<[u8]>>(&self, msg: &M) -> Option<Self::Signature> {
let mut signature = [0u8; 8];
msg.as_ref().iter()
.chain(rstd::iter::repeat(&42u8))
.chain(std::iter::repeat(&42u8))
.take(8)
.enumerate()
.for_each(|(i, v)| { signature[i] = *v; });
@@ -85,7 +101,7 @@ impl app_crypto::RuntimeAppPublic for UintAuthorityId {
fn verify<M: AsRef<[u8]>>(&self, msg: &M, signature: &Self::Signature) -> bool {
let mut msg_signature = [0u8; 8];
msg.as_ref().iter()
.chain(rstd::iter::repeat(&42))
.chain(std::iter::repeat(&42))
.take(8)
.enumerate()
.for_each(|(i, v)| { msg_signature[i] = *v; });
@@ -97,19 +113,16 @@ impl app_crypto::RuntimeAppPublic for UintAuthorityId {
impl OpaqueKeys for UintAuthorityId {
type KeyTypeIds = std::iter::Cloned<std::slice::Iter<'static, KeyTypeId>>;
fn key_ids() -> Self::KeyTypeIds { [key_types::DUMMY].iter().cloned() }
// Unsafe, i know, but it's test code and it's just there because it's really convenient to
// keep `UintAuthorityId` as a u64 under the hood.
fn get_raw(&self, _: KeyTypeId) -> &[u8] {
unsafe {
std::slice::from_raw_parts(
&self.0 as *const _ as *const u8,
std::mem::size_of::<u64>(),
)
}
fn key_ids() -> Self::KeyTypeIds {
[key_types::DUMMY].iter().cloned()
}
fn get_raw(&self, _: KeyTypeId) -> &[u8] {
self.as_ref()
}
fn get<T: Decode>(&self, _: KeyTypeId) -> Option<T> {
self.0.using_encoded(|mut x| T::decode(&mut x)).ok()
self.using_encoded(|mut x| T::decode(&mut x)).ok()
}
}
+1 -1
View File
@@ -39,7 +39,7 @@ use rstd::ops::{
Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
RemAssign, Shl, Shr
};
use crate::AppKey;
use app_crypto::AppKey;
use impl_trait_for_tuples::impl_for_tuples;
/// A lazy value.
@@ -17,16 +17,7 @@
//! A crate which contains primitives that are useful for implementation that uses staking
//! approaches in general. Definitions related to sessions, slashing, etc go here.
use rstd::vec::Vec;
pub mod offence;
/// Simple index type with which we can count sessions.
pub type SessionIndex = u32;
/// A trait for getting the currently elected validator set without coupling to the module that
/// provides this information.
pub trait CurrentElectedSet<ValidatorId> {
/// Returns the validator ids for the currently elected validator set.
fn current_elected_set() -> Vec<ValidatorId>;
}