Slash and prove membership of prior sessions (#2970)

* skeleton for tracking historical sessions

* refactor OpaqueKeys

* some more skeleton work

* adjust session to new OpaqueKeys API

* further refactoring of key-type-ids

* session gets validator ID parameter

* run up against compiler

* tweak staking to support new session changes

* first run at child storage for deduplication

* Make session use `AccountId` as `ValidatorId`

* run up against child trie issues

* switch to using normal trie but with a fixed prefix

* clear out some println

* add dedup test

* flesh out historical module more

* introduce ExposureOf for staking

* test the historical module

* WASM compiles

* tests all compile

* do some mock change

* fix bulk of tests

* fix staking tests

* test obsolecence mechanic

* Apply suggestions from code review

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

* some more style nits

* a couple more nits

* tweak tries

* fix typo thie -> this
This commit is contained in:
Robert Habermeier
2019-07-08 14:36:46 +02:00
committed by GitHub
parent bb7ff32e77
commit 7df8e52cfe
23 changed files with 1188 additions and 341 deletions
+3
View File
@@ -51,6 +51,9 @@ pub mod transaction_validity;
/// Re-export these since they're only "kind of" generic.
pub use generic::{DigestItem, Digest};
/// Re-export this since it's part of the API of this crate.
pub use substrate_primitives::crypto::{key_types, KeyTypeId};
/// A message indicating an invalid signature in extrinsic.
pub const BAD_SIGNATURE: &str = "bad signature in extrinsic";
+21 -5
View File
@@ -19,8 +19,8 @@
use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer};
use std::{fmt::Debug, ops::Deref, fmt};
use crate::codec::{Codec, Encode, Decode};
use crate::traits::{self, Checkable, Applyable, BlakeTwo256, OpaqueKeys};
use crate::generic;
use crate::traits::{self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, TypedKey};
use crate::{generic, KeyTypeId};
use crate::weights::{Weighable, Weight};
pub use substrate_primitives::H256;
use substrate_primitives::U256;
@@ -37,12 +37,28 @@ impl Into<AuthorityId> for UintAuthorityId {
}
}
/// The key-type of the `UintAuthorityId`
pub const UINT_DUMMY_KEY: KeyTypeId = 0xdeadbeef;
impl TypedKey for UintAuthorityId {
const KEY_TYPE: KeyTypeId = UINT_DUMMY_KEY;
}
impl OpaqueKeys for UintAuthorityId {
fn count() -> usize { 1 }
type KeyTypeIds = std::iter::Cloned<std::slice::Iter<'static, KeyTypeId>>;
fn key_ids() -> Self::KeyTypeIds { [UINT_DUMMY_KEY].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, _: usize) -> &[u8] { unsafe { &std::mem::transmute::<_, &[u8; 8]>(&self.0)[..] } }
fn get<T: Decode>(&self, _: usize) -> Option<T> { self.0.using_encoded(|mut x| T::decode(&mut x)) }
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 get<T: Decode>(&self, _: KeyTypeId) -> Option<T> { self.0.using_encoded(|mut x| T::decode(&mut x)) }
}
/// Digest item
+62 -30
View File
@@ -25,6 +25,7 @@ use substrate_primitives::{self, Hasher, Blake2Hasher};
use crate::codec::{Codec, Encode, Decode, HasCompact};
use crate::transaction_validity::TransactionValidity;
use crate::generic::{Digest, DigestItem};
pub use substrate_primitives::crypto::TypedKey;
pub use integer_sqrt::IntegerSquareRoot;
pub use num_traits::{
Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
@@ -162,6 +163,13 @@ impl<T> Convert<T, T> for Identity {
fn convert(a: T) -> T { a }
}
/// A structure that performs standard conversion using the standard Rust conversion traits.
pub struct ConvertInto;
impl<A, B: From<A>> Convert<A, B> for ConvertInto {
fn convert(a: A) -> B { a.into() }
}
/// A meta trait for arithmetic.
///
/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to
@@ -835,12 +843,15 @@ pub trait ValidateUnsigned {
/// Opaque datatype that may be destructured into a series of raw byte slices (which represent
/// individual keys).
pub trait OpaqueKeys: Clone {
/// Return the number of encoded keys.
fn count() -> usize { 0 }
/// Get the raw bytes of key with index `i`.
fn get_raw(&self, i: usize) -> &[u8];
/// An iterator over the type IDs of keys that this holds.
type KeyTypeIds: IntoIterator<Item=super::KeyTypeId>;
/// Return an iterator over the key-type IDs supported by this set.
fn key_ids() -> Self::KeyTypeIds;
/// Get the raw bytes of key with key-type ID `i`.
fn get_raw(&self, i: super::KeyTypeId) -> &[u8];
/// Get the decoded key with index `i`.
fn get<T: Decode>(&self, i: usize) -> Option<T> { T::decode(&mut self.get_raw(i)) }
fn get<T: Decode>(&self, i: super::KeyTypeId) -> Option<T> { T::decode(&mut self.get_raw(i)) }
/// Verify a proof of ownership for the keys.
fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool { true }
}
@@ -969,41 +980,62 @@ macro_rules! count {
};
}
#[macro_export]
/// Just implement `OpaqueKeys` for a given tuple-struct.
/// Implement `OpaqueKeys` for a described struct.
/// Would be much nicer for this to be converted to `derive` code.
///
/// Every field type must be equivalent implement `as_ref()`, which is expected
/// to hold the standard SCALE-encoded form of that key. This is typically
/// just the bytes of the key.
///
/// ```rust
/// use sr_primitives::{impl_opaque_keys, key_types, KeyTypeId};
///
/// impl_opaque_keys! {
/// pub struct Keys {
/// #[id(key_types::ED25519)]
/// pub ed25519: [u8; 32],
/// #[id(key_types::SR25519)]
/// pub sr25519: [u8; 32],
/// }
/// }
/// ```
#[macro_export]
macro_rules! impl_opaque_keys {
(
pub struct $name:ident ( $( $t:ty ),* $(,)* );
) => {
impl_opaque_keys! {
pub struct $name ( $( $t ,)* );
impl OpaqueKeys for _ {}
}
};
(
pub struct $name:ident ( $( $t:ty ),* $(,)* );
impl OpaqueKeys for _ {
$($rest:tt)*
pub struct $name:ident {
$(
#[id($key_id:expr)]
pub $field:ident: $type:ty,
)*
}
) => {
#[derive(Default, Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)]
#[cfg_attr(feature = "std", derive(Debug, $crate::serde::Serialize, $crate::serde::Deserialize))]
pub struct $name($( pub $t ,)*);
pub struct $name {
$(
pub $field: $type,
)*
}
impl $crate::traits::OpaqueKeys for $name {
fn count() -> usize {
let mut c = 0;
$( let _: $t; c += 1; )*
c
type KeyTypeIds = $crate::rstd::iter::Cloned<
$crate::rstd::slice::Iter<'static, $crate::KeyTypeId>
>;
fn key_ids() -> Self::KeyTypeIds {
[
$($key_id),*
].iter().cloned()
}
fn get_raw(&self, i: usize) -> &[u8] {
$crate::count!(impl_opaque_keys (!! self i) $($t),*);
&[]
fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] {
match i {
$(
i if i == $key_id => self.$field.as_ref(),
)*
_ => &[],
}
}
$($rest)*
}
};
( !! $self:ident $param_i:ident $i:tt) => {
if $param_i == $i { return $self.$i.as_ref() }
}
}