Rename folder: primitives/sr-primitives -> primitives/runtime (#4280)

* primitives/sr-primitives -> primitives/runtime

* update
This commit is contained in:
Weiliang Li
2019-12-09 16:49:32 +09:00
committed by Bastian Köcher
parent 94b6921d03
commit 04fcc71809
117 changed files with 845 additions and 765 deletions
+166
View File
@@ -0,0 +1,166 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Provides some utilities to define a piecewise linear function.
use crate::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}};
use core::ops::Sub;
/// Piecewise Linear function in [0, 1] -> [0, 1].
#[derive(PartialEq, Eq, primitives::RuntimeDebug)]
pub struct PiecewiseLinear<'a> {
/// Array of points. Must be in order from the lowest abscissas to the highest.
pub points: &'a [(Perbill, Perbill)],
/// The maximum value that can be returned.
pub maximum: Perbill,
}
fn abs_sub<N: Ord + Sub<Output=N> + Clone>(a: N, b: N) -> N where {
a.clone().max(b.clone()) - a.min(b)
}
impl<'a> PiecewiseLinear<'a> {
/// Compute `f(n/d)*d` with `n <= d`. This is useful to avoid loss of precision.
pub fn calculate_for_fraction_times_denominator<N>(&self, n: N, d: N) -> N where
N: SimpleArithmetic + Clone
{
let n = n.min(d.clone());
if self.points.len() == 0 {
return N::zero()
}
let next_point_index = self.points.iter()
.position(|p| n < p.0 * d.clone());
let (prev, next) = if let Some(next_point_index) = next_point_index {
if let Some(previous_point_index) = next_point_index.checked_sub(1) {
(self.points[previous_point_index], self.points[next_point_index])
} else {
// There is no previous points, take first point ordinate
return self.points.first().map(|p| p.1).unwrap_or_else(Perbill::zero) * d
}
} else {
// There is no next points, take last point ordinate
return self.points.last().map(|p| p.1).unwrap_or_else(Perbill::zero) * d
};
let delta_y = multiply_by_rational_saturating(
abs_sub(n.clone(), prev.0 * d.clone()),
abs_sub(next.1.deconstruct(), prev.1.deconstruct()),
// Must not saturate as prev abscissa > next abscissa
next.0.deconstruct().saturating_sub(prev.0.deconstruct()),
);
// If both substration are same sign then result is positive
if (n > prev.0 * d.clone()) == (next.1.deconstruct() > prev.1.deconstruct()) {
(prev.1 * d).saturating_add(delta_y)
// Otherwise result is negative
} else {
(prev.1 * d).saturating_sub(delta_y)
}
}
}
// Compute value * p / q.
// This is guaranteed not to overflow on whatever values nor lose precision.
// `q` must be superior to zero.
fn multiply_by_rational_saturating<N>(value: N, p: u32, q: u32) -> N
where N: SimpleArithmetic + Clone
{
let q = q.max(1);
// Mul can saturate if p > q
let result_divisor_part = (value.clone() / q.into()).saturating_mul(p.into());
let result_remainder_part = {
let rem = value % q.into();
// Fits into u32 because q is u32 and remainder < q
let rem_u32 = rem.saturated_into::<u32>();
// Multiplication fits into u64 as both term are u32
let rem_part = rem_u32 as u64 * p as u64 / q as u64;
// Can saturate if p > q
rem_part.saturated_into::<N>()
};
// Can saturate if p > q
result_divisor_part.saturating_add(result_remainder_part)
}
#[test]
fn test_multiply_by_rational_saturating() {
use std::convert::TryInto;
let div = 100u32;
for value in 0..=div {
for p in 0..=div {
for q in 1..=div {
let value: u64 = (value as u128 * u64::max_value() as u128 / div as u128)
.try_into().unwrap();
let p = (p as u64 * u32::max_value() as u64 / div as u64)
.try_into().unwrap();
let q = (q as u64 * u32::max_value() as u64 / div as u64)
.try_into().unwrap();
assert_eq!(
multiply_by_rational_saturating(value, p, q),
(value as u128 * p as u128 / q as u128)
.try_into().unwrap_or(u64::max_value())
);
}
}
}
}
#[test]
fn test_calculate_for_fraction_times_denominator() {
use std::convert::TryInto;
let curve = PiecewiseLinear {
points: &[
(Perbill::from_parts(0_000_000_000), Perbill::from_parts(0_500_000_000)),
(Perbill::from_parts(0_500_000_000), Perbill::from_parts(1_000_000_000)),
(Perbill::from_parts(1_000_000_000), Perbill::from_parts(0_000_000_000)),
],
maximum: Perbill::from_parts(1_000_000_000),
};
pub fn formal_calculate_for_fraction_times_denominator(n: u64, d: u64) -> u64 {
if n <= Perbill::from_parts(0_500_000_000) * d.clone() {
n + d / 2
} else {
(d as u128 * 2 - n as u128 * 2).try_into().unwrap()
}
}
let div = 100u32;
for d in 0..=div {
for n in 0..=d {
let d: u64 = (d as u128 * u64::max_value() as u128 / div as u128)
.try_into().unwrap();
let n: u64 = (n as u128 * u64::max_value() as u128 / div as u128)
.try_into().unwrap();
let res = curve.calculate_for_fraction_times_denominator(n, d);
let expected = formal_calculate_for_fraction_times_denominator(n, d);
assert!(abs_sub(res, expected) <= 1);
}
}
}
@@ -0,0 +1,112 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Generic implementation of a block and associated items.
#[cfg(feature = "std")]
use std::fmt;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use rstd::prelude::*;
use primitives::RuntimeDebug;
use crate::codec::{Codec, Encode, Decode};
use crate::traits::{self, Member, Block as BlockT, Header as HeaderT, MaybeSerialize};
use crate::Justification;
/// Something to identify a block.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub enum BlockId<Block: BlockT> {
/// Identify by block header hash.
Hash(<<Block as BlockT>::Header as HeaderT>::Hash),
/// Identify by block number.
Number(<<Block as BlockT>::Header as HeaderT>::Number),
}
impl<Block: BlockT> BlockId<Block> {
/// Create a block ID from a hash.
pub fn hash(hash: Block::Hash) -> Self {
BlockId::Hash(hash)
}
/// Create a block ID from a number.
pub fn number(number: <Block::Header as HeaderT>::Number) -> Self {
BlockId::Number(number)
}
}
impl<Block: BlockT> Copy for BlockId<Block> {}
#[cfg(feature = "std")]
impl<Block: BlockT> fmt::Display for BlockId<Block> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
/// Abstraction over a substrate block.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Block<Header, Extrinsic: MaybeSerialize> {
/// The block header.
pub header: Header,
/// The accompanying extrinsics.
pub extrinsics: Vec<Extrinsic>,
}
impl<Header, Extrinsic: MaybeSerialize> traits::Block for Block<Header, Extrinsic>
where
Header: HeaderT,
Extrinsic: Member + Codec + traits::Extrinsic,
{
type Extrinsic = Extrinsic;
type Header = Header;
type Hash = <Self::Header as traits::Header>::Hash;
fn header(&self) -> &Self::Header {
&self.header
}
fn extrinsics(&self) -> &[Self::Extrinsic] {
&self.extrinsics[..]
}
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>) {
(self.header, self.extrinsics)
}
fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self {
Block { header, extrinsics }
}
fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec<u8> {
(header, extrinsics).encode()
}
}
/// Abstraction over a substrate block and justification.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct SignedBlock<Block> {
/// Full block.
pub block: Block,
/// Block justification.
pub justification: Option<Justification>,
}
@@ -0,0 +1,90 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Generic implementation of an extrinsic that has passed the verification
//! stage.
use crate::traits::{
self, Member, MaybeDisplay, SignedExtension, Dispatchable,
};
#[allow(deprecated)]
use crate::traits::ValidateUnsigned;
use crate::transaction_validity::TransactionValidity;
/// Definition of something that the external world might want to say; its
/// existence implies that it has been checked and is good, particularly with
/// regards to the signature.
#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)]
pub struct CheckedExtrinsic<AccountId, Call, Extra> {
/// Who this purports to be from and the number of extrinsics have come before
/// from the same signer, if anyone (note this is not a signature).
pub signed: Option<(AccountId, Extra)>,
/// The function that should be called.
pub function: Call,
}
impl<AccountId, Call, Extra, Origin, Info> traits::Applyable for
CheckedExtrinsic<AccountId, Call, Extra>
where
AccountId: Member + MaybeDisplay,
Call: Member + Dispatchable<Origin=Origin>,
Extra: SignedExtension<AccountId=AccountId, Call=Call, DispatchInfo=Info>,
Origin: From<Option<AccountId>>,
Info: Clone,
{
type AccountId = AccountId;
type Call = Call;
type DispatchInfo = Info;
fn sender(&self) -> Option<&Self::AccountId> {
self.signed.as_ref().map(|x| &x.0)
}
#[allow(deprecated)] // Allow ValidateUnsigned
fn validate<U: ValidateUnsigned<Call = Self::Call>>(
&self,
info: Self::DispatchInfo,
len: usize,
) -> TransactionValidity {
if let Some((ref id, ref extra)) = self.signed {
Extra::validate(extra, id, &self.function, info.clone(), len)
} else {
let valid = Extra::validate_unsigned(&self.function, info, len)?;
let unsigned_validation = U::validate_unsigned(&self.function)?;
Ok(valid.combine_with(unsigned_validation))
}
}
#[allow(deprecated)] // Allow ValidateUnsigned
fn apply<U: ValidateUnsigned<Call=Self::Call>>(
self,
info: Self::DispatchInfo,
len: usize,
) -> crate::ApplyExtrinsicResult {
let (maybe_who, pre) = if let Some((id, extra)) = self.signed {
let pre = Extra::pre_dispatch(extra, &id, &self.function, info.clone(), len)?;
(Some(id), pre)
} else {
let pre = Extra::pre_dispatch_unsigned(&self.function, info.clone(), len)?;
U::pre_dispatch(&self.function)?;
(None, pre)
};
let res = self.function.dispatch(Origin::from(maybe_who));
Extra::post_dispatch(pre, info.clone(), len);
Ok(res.map_err(Into::into))
}
}
@@ -0,0 +1,376 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Generic implementation of a digest.
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use rstd::prelude::*;
use crate::ConsensusEngineId;
use crate::codec::{Decode, Encode, Input, Error};
use primitives::RuntimeDebug;
/// Generic header digest.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Digest<Hash: Encode + Decode> {
/// A list of logs in the digest.
pub logs: Vec<DigestItem<Hash>>,
}
impl<Item: Encode + Decode> Default for Digest<Item> {
fn default() -> Self {
Digest { logs: Vec::new(), }
}
}
impl<Hash: Encode + Decode> Digest<Hash> {
/// Get reference to all digest items.
pub fn logs(&self) -> &[DigestItem<Hash>] {
&self.logs
}
/// Push new digest item.
pub fn push(&mut self, item: DigestItem<Hash>) {
self.logs.push(item);
}
/// Pop a digest item.
pub fn pop(&mut self) -> Option<DigestItem<Hash>> {
self.logs.pop()
}
/// Get reference to the first digest item that matches the passed predicate.
pub fn log<T: ?Sized, F: Fn(&DigestItem<Hash>) -> Option<&T>>(&self, predicate: F) -> Option<&T> {
self.logs().iter()
.filter_map(predicate)
.next()
}
/// Get a conversion of the first digest item that successfully converts using the function.
pub fn convert_first<T, F: Fn(&DigestItem<Hash>) -> Option<T>>(&self, predicate: F) -> Option<T> {
self.logs().iter()
.filter_map(predicate)
.next()
}
}
/// Digest item that is able to encode/decode 'system' digest items and
/// provide opaque access to other items.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
pub enum DigestItem<Hash> {
/// System digest item that contains the root of changes trie at given
/// block. It is created for every block iff runtime supports changes
/// trie creation.
ChangesTrieRoot(Hash),
/// A pre-runtime digest.
///
/// These are messages from the consensus engine to the runtime, although
/// the consensus engine can (and should) read them itself to avoid
/// code and state duplication. It is erroneous for a runtime to produce
/// these, but this is not (yet) checked.
PreRuntime(ConsensusEngineId, Vec<u8>),
/// A message from the runtime to the consensus engine. This should *never*
/// be generated by the native code of any consensus engine, but this is not
/// checked (yet).
Consensus(ConsensusEngineId, Vec<u8>),
/// Put a Seal on it. This is only used by native code, and is never seen
/// by runtimes.
Seal(ConsensusEngineId, Vec<u8>),
/// Some other thing. Unsupported and experimental.
Other(Vec<u8>),
}
#[cfg(feature = "std")]
impl<Hash: Encode> serde::Serialize for DigestItem<Hash> {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
self.using_encoded(|bytes| {
primitives::bytes::serialize(bytes, seq)
})
}
}
#[cfg(feature = "std")]
impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem<Hash> {
fn deserialize<D>(de: D) -> Result<Self, D::Error> where
D: serde::Deserializer<'a>,
{
let r = primitives::bytes::deserialize(de)?;
Decode::decode(&mut &r[..])
.map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
}
}
/// A 'referencing view' for digest item. Does not own its contents. Used by
/// final runtime implementations for encoding/decoding its log items.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
pub enum DigestItemRef<'a, Hash: 'a> {
/// Reference to `DigestItem::ChangesTrieRoot`.
ChangesTrieRoot(&'a Hash),
/// A pre-runtime digest.
///
/// These are messages from the consensus engine to the runtime, although
/// the consensus engine can (and should) read them itself to avoid
/// code and state duplication. It is erroneous for a runtime to produce
/// these, but this is not (yet) checked.
PreRuntime(&'a ConsensusEngineId, &'a Vec<u8>),
/// A message from the runtime to the consensus engine. This should *never*
/// be generated by the native code of any consensus engine, but this is not
/// checked (yet).
Consensus(&'a ConsensusEngineId, &'a Vec<u8>),
/// Put a Seal on it. This is only used by native code, and is never seen
/// by runtimes.
Seal(&'a ConsensusEngineId, &'a Vec<u8>),
/// Any 'non-system' digest item, opaque to the native code.
Other(&'a Vec<u8>),
}
/// Type of the digest item. Used to gain explicit control over `DigestItem` encoding
/// process. We need an explicit control, because final runtimes are encoding their own
/// digest items using `DigestItemRef` type and we can't auto-derive `Decode`
/// trait for `DigestItemRef`.
#[repr(u32)]
#[derive(Encode, Decode)]
pub enum DigestItemType {
ChangesTrieRoot = 2,
PreRuntime = 6,
Consensus = 4,
Seal = 5,
Other = 0,
}
/// Type of a digest item that contains raw data; this also names the consensus engine ID where
/// applicable. Used to identify one or more digest items of interest.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub enum OpaqueDigestItemId<'a> {
/// Type corresponding to DigestItem::PreRuntime.
PreRuntime(&'a ConsensusEngineId),
/// Type corresponding to DigestItem::Consensus.
Consensus(&'a ConsensusEngineId),
/// Type corresponding to DigestItem::Seal.
Seal(&'a ConsensusEngineId),
/// Some other (non-prescribed) type.
Other,
}
impl<Hash> DigestItem<Hash> {
/// Returns a 'referencing view' for this digest item.
pub fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash> {
match *self {
DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v),
DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s),
DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s),
DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s),
DigestItem::Other(ref v) => DigestItemRef::Other(v),
}
}
/// Returns `Some` if the entry is the `ChangesTrieRoot` entry.
pub fn as_changes_trie_root(&self) -> Option<&Hash> {
self.dref().as_changes_trie_root()
}
/// Returns `Some` if this entry is the `PreRuntime` entry.
pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> {
self.dref().as_pre_runtime()
}
/// Returns `Some` if this entry is the `Consensus` entry.
pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &[u8])> {
self.dref().as_consensus()
}
/// Returns `Some` if this entry is the `Seal` entry.
pub fn as_seal(&self) -> Option<(ConsensusEngineId, &[u8])> {
self.dref().as_seal()
}
/// Returns Some if `self` is a `DigestItem::Other`.
pub fn as_other(&self) -> Option<&[u8]> {
match *self {
DigestItem::Other(ref v) => Some(&v[..]),
_ => None,
}
}
/// Returns the opaque data contained in the item if `Some` if this entry has the id given.
pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&[u8]> {
self.dref().try_as_raw(id)
}
/// Returns the data contained in the item if `Some` if this entry has the id given, decoded
/// to the type provided `T`.
pub fn try_to<T: Decode>(&self, id: OpaqueDigestItemId) -> Option<T> {
self.dref().try_to::<T>(id)
}
}
impl<Hash: Encode> Encode for DigestItem<Hash> {
fn encode(&self) -> Vec<u8> {
self.dref().encode()
}
}
impl<Hash: Encode> codec::EncodeLike for DigestItem<Hash> {}
impl<Hash: Decode> Decode for DigestItem<Hash> {
#[allow(deprecated)]
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
let item_type: DigestItemType = Decode::decode(input)?;
match item_type {
DigestItemType::ChangesTrieRoot => Ok(DigestItem::ChangesTrieRoot(
Decode::decode(input)?,
)),
DigestItemType::PreRuntime => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Ok(DigestItem::PreRuntime(vals.0, vals.1))
},
DigestItemType::Consensus => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Ok(DigestItem::Consensus(vals.0, vals.1))
}
DigestItemType::Seal => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Ok(DigestItem::Seal(vals.0, vals.1))
},
DigestItemType::Other => Ok(DigestItem::Other(
Decode::decode(input)?,
)),
}
}
}
impl<'a, Hash> DigestItemRef<'a, Hash> {
/// Cast this digest item into `ChangesTrieRoot`.
pub fn as_changes_trie_root(&self) -> Option<&'a Hash> {
match *self {
DigestItemRef::ChangesTrieRoot(ref changes_trie_root) => Some(changes_trie_root),
_ => None,
}
}
/// Cast this digest item into `PreRuntime`
pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &'a [u8])> {
match *self {
DigestItemRef::PreRuntime(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)),
_ => None,
}
}
/// Cast this digest item into `Consensus`
pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &'a [u8])> {
match *self {
DigestItemRef::Consensus(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)),
_ => None,
}
}
/// Cast this digest item into `Seal`
pub fn as_seal(&self) -> Option<(ConsensusEngineId, &'a [u8])> {
match *self {
DigestItemRef::Seal(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)),
_ => None,
}
}
/// Cast this digest item into `PreRuntime`
pub fn as_other(&self) -> Option<&'a [u8]> {
match *self {
DigestItemRef::Other(ref data) => Some(data),
_ => None,
}
}
/// Try to match this digest item to the given opaque item identifier; if it matches, then
/// return the opaque data it contains.
pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&'a [u8]> {
match (id, self) {
(OpaqueDigestItemId::Consensus(w), &DigestItemRef::Consensus(v, s)) |
(OpaqueDigestItemId::Seal(w), &DigestItemRef::Seal(v, s)) |
(OpaqueDigestItemId::PreRuntime(w), &DigestItemRef::PreRuntime(v, s))
if v == w => Some(&s[..]),
(OpaqueDigestItemId::Other, &DigestItemRef::Other(s)) => Some(&s[..]),
_ => None,
}
}
/// Try to match this digest item to the given opaque item identifier; if it matches, then
/// try to cast to the given datatype; if that works, return it.
pub fn try_to<T: Decode>(&self, id: OpaqueDigestItemId) -> Option<T> {
self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x).ok())
}
}
impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
match *self {
DigestItemRef::ChangesTrieRoot(changes_trie_root) => {
DigestItemType::ChangesTrieRoot.encode_to(&mut v);
changes_trie_root.encode_to(&mut v);
},
DigestItemRef::Consensus(val, data) => {
DigestItemType::Consensus.encode_to(&mut v);
(val, data).encode_to(&mut v);
},
DigestItemRef::Seal(val, sig) => {
DigestItemType::Seal.encode_to(&mut v);
(val, sig).encode_to(&mut v);
},
DigestItemRef::PreRuntime(val, data) => {
DigestItemType::PreRuntime.encode_to(&mut v);
(val, data).encode_to(&mut v);
},
DigestItemRef::Other(val) => {
DigestItemType::Other.encode_to(&mut v);
val.encode_to(&mut v);
},
}
v
}
}
impl<'a, Hash: Encode> codec::EncodeLike for DigestItemRef<'a, Hash> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_serialize_digest() {
let digest = Digest {
logs: vec![
DigestItem::ChangesTrieRoot(4),
DigestItem::Other(vec![1, 2, 3]),
DigestItem::Seal(*b"test", vec![1, 2, 3])
],
};
assert_eq!(
::serde_json::to_string(&digest).unwrap(),
r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"#
);
}
}
@@ -0,0 +1,206 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Generic implementation of an unchecked (pre-verification) extrinsic.
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use crate::codec::{Decode, Encode, Input, Output, Error};
/// Era period
pub type Period = u64;
/// Era phase
pub type Phase = u64;
/// An era to describe the longevity of a transaction.
#[derive(PartialEq, Eq, Clone, Copy, primitives::RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Era {
/// The transaction is valid forever. The genesis hash must be present in the signed content.
Immortal,
/// Period and phase are encoded:
/// - The period of validity from the block hash found in the signing material.
/// - The phase in the period that this transaction's lifetime begins (and, importantly,
/// implies which block hash is included in the signature material). If the `period` is
/// greater than 1 << 12, then it will be a factor of the times greater than 1<<12 that
/// `period` is.
Mortal(Period, Phase),
}
/*
E.g. with period == 4:
0 10 20 30 40
0123456789012345678901234567890123456789012
|...|
authored -/ \- expiry
phase = 1
n = Q(current - phase, period) + phase
*/
impl Era {
/// Create a new era based on a period (which should be a power of two between 4 and 65536 inclusive)
/// and a block number on which it should start (or, for long periods, be shortly after the start).
pub fn mortal(period: u64, current: u64) -> Self {
let period = period.checked_next_power_of_two()
.unwrap_or(1 << 16)
.max(4)
.min(1 << 16);
let phase = current % period;
let quantize_factor = (period >> 12).max(1);
let quantized_phase = phase / quantize_factor * quantize_factor;
Era::Mortal(period, quantized_phase)
}
/// Create an "immortal" transaction.
pub fn immortal() -> Self {
Era::Immortal
}
/// `true` if this is an immortal transaction.
pub fn is_immortal(&self) -> bool {
match self {
Era::Immortal => true,
_ => false,
}
}
/// Get the block number of the start of the era whose properties this object
/// describes that `current` belongs to.
pub fn birth(self, current: u64) -> u64 {
match self {
Era::Immortal => 0,
Era::Mortal(period, phase) => (current.max(phase) - phase) / period * period + phase,
}
}
/// Get the block number of the first block at which the era has ended.
pub fn death(self, current: u64) -> u64 {
match self {
Era::Immortal => u64::max_value(),
Era::Mortal(period, _) => self.birth(current) + period,
}
}
}
impl Encode for Era {
fn encode_to<T: Output>(&self, output: &mut T) {
match self {
Era::Immortal => output.push_byte(0),
Era::Mortal(period, phase) => {
let quantize_factor = (*period as u64 >> 12).max(1);
let encoded = (period.trailing_zeros() - 1).max(1).min(15) as u16 | ((phase / quantize_factor) << 4) as u16;
output.push(&encoded);
}
}
}
}
impl codec::EncodeLike for Era {}
impl Decode for Era {
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
let first = input.read_byte()?;
if first == 0 {
Ok(Era::Immortal)
} else {
let encoded = first as u64 + ((input.read_byte()? as u64) << 8);
let period = 2 << (encoded % (1 << 4));
let quantize_factor = (period >> 12).max(1);
let phase = (encoded >> 4) * quantize_factor;
if period >= 4 && phase < period {
Ok(Era::Mortal(period, phase))
} else {
Err("Invalid period and phase".into())
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn immortal_works() {
let e = Era::immortal();
assert_eq!(e.birth(0), 0);
assert_eq!(e.death(0), u64::max_value());
assert_eq!(e.birth(1), 0);
assert_eq!(e.death(1), u64::max_value());
assert_eq!(e.birth(u64::max_value()), 0);
assert_eq!(e.death(u64::max_value()), u64::max_value());
assert!(e.is_immortal());
assert_eq!(e.encode(), vec![0u8]);
assert_eq!(e, Era::decode(&mut&[0u8][..]).unwrap());
}
#[test]
fn mortal_codec_works() {
let e = Era::mortal(64, 42);
assert!(!e.is_immortal());
let expected = vec![5 + 42 % 16 * 16, 42 / 16];
assert_eq!(e.encode(), expected);
assert_eq!(e, Era::decode(&mut&expected[..]).unwrap());
}
#[test]
fn long_period_mortal_codec_works() {
let e = Era::mortal(32768, 20000);
let expected = vec![(14 + 2500 % 16 * 16) as u8, (2500 / 16) as u8];
assert_eq!(e.encode(), expected);
assert_eq!(e, Era::decode(&mut&expected[..]).unwrap());
}
#[test]
fn era_initialization_works() {
assert_eq!(Era::mortal(64, 42), Era::Mortal(64, 42));
assert_eq!(Era::mortal(32768, 20000), Era::Mortal(32768, 20000));
assert_eq!(Era::mortal(200, 513), Era::Mortal(256, 1));
assert_eq!(Era::mortal(2, 1), Era::Mortal(4, 1));
assert_eq!(Era::mortal(4, 5), Era::Mortal(4, 1));
}
#[test]
fn quantized_clamped_era_initialization_works() {
// clamp 1000000 to 65536, quantize 1000001 % 65536 to the nearest 4
assert_eq!(Era::mortal(1000000, 1000001), Era::Mortal(65536, 1000001 % 65536 / 4 * 4));
}
#[test]
fn mortal_birth_death_works() {
let e = Era::mortal(4, 6);
for i in 6..10 {
assert_eq!(e.birth(i), 6);
assert_eq!(e.death(i), 10);
}
// wrong because it's outside of the (current...current + period) range
assert_ne!(e.birth(10), 6);
assert_ne!(e.birth(5), 6);
}
#[test]
fn current_less_than_phase() {
// should not panic
Era::mortal(4, 3).birth(1);
}
}
@@ -0,0 +1,199 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Generic implementation of a block header.
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error};
use crate::traits::{
self, Member, SimpleArithmetic, SimpleBitOps, Hash as HashT,
MaybeSerializeDeserialize, MaybeSerialize, MaybeDisplay,
};
use crate::generic::Digest;
use primitives::U256;
use rstd::{
convert::TryFrom,
fmt::Debug,
};
/// Abstraction over a block header for a substrate chain.
#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Header<Number: Copy + Into<U256> + TryFrom<U256>, Hash: HashT> {
/// The parent hash.
pub parent_hash: Hash::Output,
/// The block number.
#[cfg_attr(feature = "std", serde(
serialize_with = "serialize_number",
deserialize_with = "deserialize_number"))]
pub number: Number,
/// The state trie merkle root
pub state_root: Hash::Output,
/// The merkle root of the extrinsics.
pub extrinsics_root: Hash::Output,
/// A chain-specific digest of data useful for light clients or referencing auxiliary data.
pub digest: Digest<Hash::Output>,
}
#[cfg(feature = "std")]
pub fn serialize_number<S, T: Copy + Into<U256> + TryFrom<U256>>(
val: &T, s: S,
) -> Result<S::Ok, S::Error> where S: serde::Serializer {
let u256: U256 = (*val).into();
serde::Serialize::serialize(&u256, s)
}
#[cfg(feature = "std")]
pub fn deserialize_number<'a, D, T: Copy + Into<U256> + TryFrom<U256>>(
d: D,
) -> Result<T, D::Error> where D: serde::Deserializer<'a> {
let u256: U256 = serde::Deserialize::deserialize(d)?;
TryFrom::try_from(u256).map_err(|_| serde::de::Error::custom("Try from failed"))
}
impl<Number, Hash> Decode for Header<Number, Hash> where
Number: HasCompact + Copy + Into<U256> + TryFrom<U256>,
Hash: HashT,
Hash::Output: Decode,
{
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
Ok(Header {
parent_hash: Decode::decode(input)?,
number: <<Number as HasCompact>::Type>::decode(input)?.into(),
state_root: Decode::decode(input)?,
extrinsics_root: Decode::decode(input)?,
digest: Decode::decode(input)?,
})
}
}
impl<Number, Hash> Encode for Header<Number, Hash> where
Number: HasCompact + Copy + Into<U256> + TryFrom<U256>,
Hash: HashT,
Hash::Output: Encode,
{
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.parent_hash);
dest.push(&<<<Number as HasCompact>::Type as EncodeAsRef<_>>::RefType>::from(&self.number));
dest.push(&self.state_root);
dest.push(&self.extrinsics_root);
dest.push(&self.digest);
}
}
impl<Number, Hash> codec::EncodeLike for Header<Number, Hash> where
Number: HasCompact + Copy + Into<U256> + TryFrom<U256>,
Hash: HashT,
Hash::Output: Encode,
{}
impl<Number, Hash> traits::Header for Header<Number, Hash> where
Number: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + MaybeDisplay +
SimpleArithmetic + Codec + Copy + Into<U256> + TryFrom<U256>,
Hash: HashT,
Hash::Output: Default + rstd::hash::Hash + Copy + Member +
MaybeSerialize + Debug + MaybeDisplay + SimpleBitOps + Codec,
{
type Number = Number;
type Hash = <Hash as HashT>::Output;
type Hashing = Hash;
fn number(&self) -> &Self::Number { &self.number }
fn set_number(&mut self, num: Self::Number) { self.number = num }
fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root }
fn set_extrinsics_root(&mut self, root: Self::Hash) { self.extrinsics_root = root }
fn state_root(&self) -> &Self::Hash { &self.state_root }
fn set_state_root(&mut self, root: Self::Hash) { self.state_root = root }
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
fn digest(&self) -> &Digest<Self::Hash> { &self.digest }
fn digest_mut(&mut self) -> &mut Digest<Self::Hash> {
#[cfg(feature = "std")]
log::debug!(target: "header", "Retrieving mutable reference to digest");
&mut self.digest
}
fn new(
number: Self::Number,
extrinsics_root: Self::Hash,
state_root: Self::Hash,
parent_hash: Self::Hash,
digest: Digest<Self::Hash>,
) -> Self {
Header {
number,
extrinsics_root,
state_root,
parent_hash,
digest,
}
}
}
impl<Number, Hash> Header<Number, Hash> where
Number: Member + rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into<U256> + TryFrom<U256>,
Hash: HashT,
Hash::Output: Default + rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec,
{
/// Convenience helper for computing the hash of the header without having
/// to import the trait.
pub fn hash(&self) -> Hash::Output {
Hash::hash_of(self)
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
#[test]
fn should_serialize_numbers() {
fn serialize(num: u128) -> String {
let mut v = vec![];
{
let mut ser = serde_json::Serializer::new(std::io::Cursor::new(&mut v));
serialize_number(&num, &mut ser).unwrap();
}
String::from_utf8(v).unwrap()
}
assert_eq!(serialize(0), "\"0x0\"".to_owned());
assert_eq!(serialize(1), "\"0x1\"".to_owned());
assert_eq!(serialize(u64::max_value() as u128), "\"0xffffffffffffffff\"".to_owned());
assert_eq!(serialize(u64::max_value() as u128 + 1), "\"0x10000000000000000\"".to_owned());
}
#[test]
fn should_deserialize_number() {
fn deserialize(num: &str) -> u128 {
let mut der = serde_json::Deserializer::new(serde_json::de::StrRead::new(num));
deserialize_number(&mut der).unwrap()
}
assert_eq!(deserialize("\"0x0\""), 0);
assert_eq!(deserialize("\"0x1\""), 1);
assert_eq!(deserialize("\"0xffffffffffffffff\""), u64::max_value() as u128);
assert_eq!(deserialize("\"0x10000000000000000\""), u64::max_value() as u128 + 1);
}
}
@@ -0,0 +1,62 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
// tag::description[]
//! Generic implementations of Extrinsic/Header/Block.
// end::description[]
mod unchecked_extrinsic;
mod era;
mod checked_extrinsic;
mod header;
mod block;
mod digest;
#[cfg(test)]
mod tests;
pub use self::unchecked_extrinsic::{UncheckedExtrinsic, SignedPayload};
pub use self::era::{Era, Phase};
pub use self::checked_extrinsic::CheckedExtrinsic;
pub use self::header::Header;
pub use self::block::{Block, SignedBlock, BlockId};
pub use self::digest::{
Digest, DigestItem, DigestItemRef, OpaqueDigestItemId
};
use crate::codec::Encode;
use rstd::prelude::*;
fn encode_with_vec_prefix<T: Encode, F: Fn(&mut Vec<u8>)>(encoder: F) -> Vec<u8> {
let size = ::rstd::mem::size_of::<T>();
let reserve = match size {
0..=0b00111111 => 1,
0..=0b00111111_11111111 => 2,
_ => 4,
};
let mut v = Vec::with_capacity(reserve + size);
v.resize(reserve, 0);
encoder(&mut v);
// need to prefix with the total length to ensure it's binary compatible with
// Vec<u8>.
let mut length: Vec<()> = Vec::new();
length.resize(v.len() - reserve, ());
length.using_encoded(|s| {
v.splice(0..reserve, s.iter().cloned());
});
v
}
@@ -0,0 +1,60 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Tests for the generic implementations of Extrinsic/Header/Block.
use crate::codec::{Decode, Encode};
use primitives::H256;
use super::DigestItem;
#[test]
fn system_digest_item_encoding() {
let item = DigestItem::ChangesTrieRoot::<H256>(H256::default());
let encoded = item.encode();
assert_eq!(encoded, vec![
// type = DigestItemType::ChangesTrieRoot
2,
// trie root
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
]);
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
assert_eq!(item, decoded);
}
#[test]
fn non_system_digest_item_encoding() {
let item = DigestItem::Other::<H256>(vec![10, 20, 30]);
let encoded = item.encode();
assert_eq!(encoded, vec![
// type = DigestItemType::Other
0,
// length of other data
12,
// authorities
10, 20, 30,
]);
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
assert_eq!(item, decoded);
}
@@ -0,0 +1,409 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Generic implementation of an unchecked (pre-verification) extrinsic.
use rstd::{fmt, prelude::*};
use runtime_io::hashing::blake2_256;
use codec::{Decode, Encode, EncodeLike, Input, Error};
use crate::{
traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic, IdentifyAccount},
generic::CheckedExtrinsic, transaction_validity::{TransactionValidityError, InvalidTransaction},
};
const TRANSACTION_VERSION: u8 = 4;
/// A extrinsic right from the external world. This is unchecked and so
/// can contain a signature.
#[derive(PartialEq, Eq, Clone)]
pub struct UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Extra: SignedExtension
{
/// The signature, address, number of extrinsics have come before from
/// the same signer and an era describing the longevity of this transaction,
/// if this is a signed extrinsic.
pub signature: Option<(Address, Signature, Extra)>,
/// The function that should be called.
pub function: Call,
}
impl<Address, Call, Signature, Extra: SignedExtension>
UncheckedExtrinsic<Address, Call, Signature, Extra>
{
/// New instance of a signed extrinsic aka "transaction".
pub fn new_signed(
function: Call,
signed: Address,
signature: Signature,
extra: Extra
) -> Self {
UncheckedExtrinsic {
signature: Some((signed, signature, extra)),
function,
}
}
/// New instance of an unsigned extrinsic aka "inherent".
pub fn new_unsigned(function: Call) -> Self {
UncheckedExtrinsic {
signature: None,
function,
}
}
}
impl<Address, Call, Signature, Extra: SignedExtension> Extrinsic
for UncheckedExtrinsic<Address, Call, Signature, Extra>
{
type Call = Call;
type SignaturePayload = (
Address,
Signature,
Extra,
);
fn is_signed(&self) -> Option<bool> {
Some(self.signature.is_some())
}
fn new(function: Call, signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
Some(if let Some((address, signature, extra)) = signed_data {
UncheckedExtrinsic::new_signed(function, address, signature, extra)
} else {
UncheckedExtrinsic::new_unsigned(function)
})
}
}
impl<Address, AccountId, Call, Signature, Extra, Lookup>
Checkable<Lookup>
for
UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Address: Member + MaybeDisplay,
Call: Encode + Member,
Signature: Member + traits::Verify,
<Signature as traits::Verify>::Signer: IdentifyAccount<AccountId=AccountId>,
Extra: SignedExtension<AccountId=AccountId>,
AccountId: Member + MaybeDisplay,
Lookup: traits::Lookup<Source=Address, Target=AccountId>,
{
type Checked = CheckedExtrinsic<AccountId, Call, Extra>;
fn check(self, lookup: &Lookup) -> Result<Self::Checked, TransactionValidityError> {
Ok(match self.signature {
Some((signed, signature, extra)) => {
let signed = lookup.lookup(signed)?;
let raw_payload = SignedPayload::new(self.function, extra)?;
if !raw_payload.using_encoded(|payload| {
signature.verify(payload, &signed)
}) {
return Err(InvalidTransaction::BadProof.into())
}
let (function, extra, _) = raw_payload.deconstruct();
CheckedExtrinsic {
signed: Some((signed, extra)),
function,
}
}
None => CheckedExtrinsic {
signed: None,
function: self.function,
},
})
}
}
/// A payload that has been signed for an unchecked extrinsics.
///
/// Note that the payload that we sign to produce unchecked extrinsic signature
/// is going to be different than the `SignaturePayload` - so the thing the extrinsic
/// actually contains.
pub struct SignedPayload<Call, Extra: SignedExtension>((
Call,
Extra,
Extra::AdditionalSigned,
));
impl<Call, Extra> SignedPayload<Call, Extra> where
Call: Encode,
Extra: SignedExtension,
{
/// Create new `SignedPayload`.
///
/// This function may fail if `additional_signed` of `Extra` is not available.
pub fn new(call: Call, extra: Extra) -> Result<Self, TransactionValidityError> {
let additional_signed = extra.additional_signed()?;
let raw_payload = (call, extra, additional_signed);
Ok(Self(raw_payload))
}
/// Create new `SignedPayload` from raw components.
pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self {
Self((call, extra, additional_signed))
}
/// Deconstruct the payload into it's components.
pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) {
self.0
}
}
impl<Call, Extra> Encode for SignedPayload<Call, Extra> where
Call: Encode,
Extra: SignedExtension,
{
/// Get an encoded version of this payload.
///
/// Payloads longer than 256 bytes are going to be `blake2_256`-hashed.
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(|payload| {
if payload.len() > 256 {
f(&blake2_256(payload)[..])
} else {
f(payload)
}
})
}
}
impl<Call, Extra> EncodeLike for SignedPayload<Call, Extra>
where
Call: Encode,
Extra: SignedExtension,
{}
impl<Address, Call, Signature, Extra> Decode
for UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Address: Decode,
Signature: Decode,
Call: Decode,
Extra: SignedExtension,
{
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
// This is a little more complicated than usual since the binary format must be compatible
// with substrate's generic `Vec<u8>` type. Basically this just means accepting that there
// will be a prefix of vector length (we don't need
// to use this).
let _length_do_not_remove_me_see_above: Vec<()> = Decode::decode(input)?;
let version = input.read_byte()?;
let is_signed = version & 0b1000_0000 != 0;
let version = version & 0b0111_1111;
if version != TRANSACTION_VERSION {
return Err("Invalid transaction version".into());
}
Ok(UncheckedExtrinsic {
signature: if is_signed { Some(Decode::decode(input)?) } else { None },
function: Decode::decode(input)?,
})
}
}
impl<Address, Call, Signature, Extra> Encode
for UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Address: Encode,
Signature: Encode,
Call: Encode,
Extra: SignedExtension,
{
fn encode(&self) -> Vec<u8> {
super::encode_with_vec_prefix::<Self, _>(|v| {
// 1 byte version id.
match self.signature.as_ref() {
Some(s) => {
v.push(TRANSACTION_VERSION | 0b1000_0000);
s.encode_to(v);
}
None => {
v.push(TRANSACTION_VERSION & 0b0111_1111);
}
}
self.function.encode_to(v);
})
}
}
impl<Address, Call, Signature, Extra> EncodeLike
for UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Address: Encode,
Signature: Encode,
Call: Encode,
Extra: SignedExtension,
{}
#[cfg(feature = "std")]
impl<Address: Encode, Signature: Encode, Call: Encode, Extra: SignedExtension> serde::Serialize
for UncheckedExtrinsic<Address, Call, Signature, Extra>
{
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer {
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
}
}
impl<Address, Call, Signature, Extra> fmt::Debug
for UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Address: fmt::Debug,
Call: fmt::Debug,
Extra: SignedExtension,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"UncheckedExtrinsic({:?}, {:?})",
self.signature.as_ref().map(|x| (&x.0, &x.2)),
self.function,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use runtime_io::hashing::blake2_256;
use crate::codec::{Encode, Decode};
use crate::traits::{SignedExtension, IdentifyAccount, IdentityLookup};
use serde::{Serialize, Deserialize};
type TestContext = IdentityLookup<u64>;
#[derive(Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize, Encode, Decode)]
pub struct TestSigner(pub u64);
impl From<u64> for TestSigner { fn from(x: u64) -> Self { Self(x) } }
impl From<TestSigner> for u64 { fn from(x: TestSigner) -> Self { x.0 } }
impl IdentifyAccount for TestSigner {
type AccountId = u64;
fn into_account(self) -> u64 { self.into() }
}
#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)]
struct TestSig(u64, Vec<u8>);
impl traits::Verify for TestSig {
type Signer = TestSigner;
fn verify<L: traits::Lazy<[u8]>>(&self, mut msg: L, signer: &u64) -> bool {
signer == &self.0 && msg.get() == &self.1[..]
}
}
type TestAccountId = u64;
type TestCall = Vec<u8>;
const TEST_ACCOUNT: TestAccountId = 0;
// NOTE: this is demonstration. One can simply use `()` for testing.
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd)]
struct TestExtra;
impl SignedExtension for TestExtra {
type AccountId = u64;
type Call = ();
type AdditionalSigned = ();
type DispatchInfo = ();
type Pre = ();
fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) }
}
type Ex = UncheckedExtrinsic<TestAccountId, TestCall, TestSig, TestExtra>;
type CEx = CheckedExtrinsic<TestAccountId, TestCall, TestExtra>;
#[test]
fn unsigned_codec_should_work() {
let ux = Ex::new_unsigned(vec![0u8; 0]);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
}
#[test]
fn signed_codec_should_work() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()),
TestExtra
);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
}
#[test]
fn large_signed_codec_should_work() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (vec![0u8; 257], TestExtra)
.using_encoded(blake2_256)[..].to_owned()),
TestExtra
);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
}
#[test]
fn unsigned_check_should_work() {
let ux = Ex::new_unsigned(vec![0u8; 0]);
assert!(!ux.is_signed().unwrap_or(false));
assert!(<Ex as Checkable<TestContext>>::check(ux, &Default::default()).is_ok());
}
#[test]
fn badly_signed_check_should_fail() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, vec![0u8; 0]),
TestExtra,
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
Err(InvalidTransaction::BadProof.into()),
);
}
#[test]
fn signed_check_should_work() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()),
TestExtra,
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }),
);
}
#[test]
fn encoding_matches_vec() {
let ex = Ex::new_unsigned(vec![0u8; 0]);
let encoded = ex.encode();
let decoded = Ex::decode(&mut encoded.as_slice()).unwrap();
assert_eq!(decoded, ex);
let as_vec: Vec<u8> = Decode::decode(&mut encoded.as_slice()).unwrap();
assert_eq!(as_vec.encode(), encoded);
}
}
+685
View File
@@ -0,0 +1,685 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Runtime Modules shared primitive types.
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
// to allow benchmarking
#![cfg_attr(feature = "bench", feature(test))]
#[cfg(feature = "bench")] extern crate test;
#[doc(hidden)]
pub use codec;
#[cfg(feature = "std")]
#[doc(hidden)]
pub use serde;
#[doc(hidden)]
pub use rstd;
#[doc(hidden)]
pub use paste;
#[doc(hidden)]
pub use app_crypto;
#[cfg(feature = "std")]
pub use primitives::storage::{StorageOverlay, ChildrenStorageOverlay};
use rstd::prelude::*;
use rstd::convert::TryFrom;
use primitives::{crypto, ed25519, sr25519, ecdsa, hash::{H256, H512}};
use codec::{Encode, Decode};
pub mod curve;
pub mod generic;
pub mod offchain;
#[cfg(feature = "std")]
pub mod testing;
pub mod traits;
pub mod transaction_validity;
pub mod random_number_generator;
/// 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 primitives::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}};
pub use app_crypto::{RuntimeAppPublic, BoundToRuntimeAppPublic};
/// Re-export `RuntimeDebug`, to avoid dependency clutter.
pub use primitives::RuntimeDebug;
/// Re-export top-level arithmetic stuff.
pub use arithmetic::{Perquintill, Perbill, Permill, Percent, Rational128, Fixed64};
/// Re-export 128 bit helpers.
pub use arithmetic::helpers_128bit;
/// Re-export big_uint stuff.
pub use arithmetic::biguint;
pub use random_number_generator::RandomNumberGenerator;
/// An abstraction over justification for a block's validity under a consensus algorithm.
///
/// Essentially a finality proof. The exact formulation will vary between consensus
/// algorithms. In the case where there are multiple valid proofs, inclusion within
/// the block itself would allow swapping justifications to change the block's hash
/// (and thus fork the chain). Sending a `Justification` alongside a block instead
/// bypasses this problem.
pub type Justification = Vec<u8>;
use traits::{Verify, Lazy};
/// A module identifier. These are per module and should be stored in a registry somewhere.
#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)]
pub struct ModuleId(pub [u8; 8]);
impl TypeId for ModuleId {
const TYPE_ID: [u8; 4] = *b"modl";
}
/// A String that is a `&'static str` on `no_std` and a `Cow<'static, str>` on `std`.
#[cfg(feature = "std")]
pub type RuntimeString = std::borrow::Cow<'static, str>;
/// A String that is a `&'static str` on `no_std` and a `Cow<'static, str>` on `std`.
#[cfg(not(feature = "std"))]
pub type RuntimeString = &'static str;
/// Create a const [`RuntimeString`].
#[cfg(feature = "std")]
#[macro_export]
macro_rules! create_runtime_str {
( $y:expr ) => {{ std::borrow::Cow::Borrowed($y) }}
}
/// Create a const [`RuntimeString`].
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! create_runtime_str {
( $y:expr ) => {{ $y }}
}
#[cfg(feature = "std")]
pub use serde::{Serialize, Deserialize, de::DeserializeOwned};
use crate::traits::IdentifyAccount;
/// Complex storage builder stuff.
#[cfg(feature = "std")]
pub trait BuildStorage: Sized {
/// Build the storage out of this builder.
fn build_storage(&self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> {
let mut storage = (Default::default(), Default::default());
self.assimilate_storage(&mut storage)?;
Ok(storage)
}
/// Assimilate the storage for this module into pre-existing overlays.
fn assimilate_storage(
&self,
storage: &mut (StorageOverlay, ChildrenStorageOverlay),
) -> Result<(), String>;
}
/// Something that can build the genesis storage of a module.
#[cfg(feature = "std")]
pub trait BuildModuleGenesisStorage<T, I>: Sized {
/// Create the module genesis storage into the given `storage` and `child_storage`.
fn build_module_genesis_storage(
&self,
storage: &mut (StorageOverlay, ChildrenStorageOverlay),
) -> Result<(), String>;
}
#[cfg(feature = "std")]
impl BuildStorage for (StorageOverlay, ChildrenStorageOverlay) {
fn assimilate_storage(
&self,
storage: &mut (StorageOverlay, ChildrenStorageOverlay),
)-> Result<(), String> {
storage.0.extend(self.0.iter().map(|(k, v)| (k.clone(), v.clone())));
for (k, other_map) in self.1.iter() {
let k = k.clone();
if let Some(map) = storage.1.get_mut(&k) {
map.extend(other_map.iter().map(|(k, v)| (k.clone(), v.clone())));
} else {
storage.1.insert(k, other_map.clone());
}
}
Ok(())
}
}
/// Consensus engine unique ID.
pub type ConsensusEngineId = [u8; 4];
/// Signature verify that can work with any known signature types..
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug)]
pub enum MultiSignature {
/// An Ed25519 signature.
Ed25519(ed25519::Signature),
/// An Sr25519 signature.
Sr25519(sr25519::Signature),
/// An ECDSA/SECP256k1 signature.
Ecdsa(ecdsa::Signature),
}
impl From<ed25519::Signature> for MultiSignature {
fn from(x: ed25519::Signature) -> Self {
MultiSignature::Ed25519(x)
}
}
impl From<sr25519::Signature> for MultiSignature {
fn from(x: sr25519::Signature) -> Self {
MultiSignature::Sr25519(x)
}
}
impl From<ecdsa::Signature> for MultiSignature {
fn from(x: ecdsa::Signature) -> Self {
MultiSignature::Ecdsa(x)
}
}
impl Default for MultiSignature {
fn default() -> Self {
MultiSignature::Ed25519(Default::default())
}
}
/// Public key for any known crypto algorithm.
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum MultiSigner {
/// An Ed25519 identity.
Ed25519(ed25519::Public),
/// An Sr25519 identity.
Sr25519(sr25519::Public),
/// An SECP256k1/ECDSA identity (actually, the Blake2 hash of the pub key).
Ecdsa(ecdsa::Public),
}
impl Default for MultiSigner {
fn default() -> Self {
MultiSigner::Ed25519(Default::default())
}
}
/// NOTE: This implementations is required by `SimpleAddressDeterminator`,
/// we convert the hash into some AccountId, it's fine to use any scheme.
impl<T: Into<H256>> crypto::UncheckedFrom<T> for MultiSigner {
fn unchecked_from(x: T) -> Self {
ed25519::Public::unchecked_from(x.into()).into()
}
}
impl AsRef<[u8]> for MultiSigner {
fn as_ref(&self) -> &[u8] {
match *self {
MultiSigner::Ed25519(ref who) => who.as_ref(),
MultiSigner::Sr25519(ref who) => who.as_ref(),
MultiSigner::Ecdsa(ref who) => who.as_ref(),
}
}
}
impl traits::IdentifyAccount for MultiSigner {
type AccountId = AccountId32;
fn into_account(self) -> AccountId32 {
match self {
MultiSigner::Ed25519(who) => <[u8; 32]>::from(who).into(),
MultiSigner::Sr25519(who) => <[u8; 32]>::from(who).into(),
MultiSigner::Ecdsa(who) => runtime_io::hashing::blake2_256(who.as_ref()).into(),
}
}
}
impl From<ed25519::Public> for MultiSigner {
fn from(x: ed25519::Public) -> Self {
MultiSigner::Ed25519(x)
}
}
impl TryFrom<MultiSigner> for ed25519::Public {
type Error = ();
fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
if let MultiSigner::Ed25519(x) = m { Ok(x) } else { Err(()) }
}
}
impl From<sr25519::Public> for MultiSigner {
fn from(x: sr25519::Public) -> Self {
MultiSigner::Sr25519(x)
}
}
impl TryFrom<MultiSigner> for sr25519::Public {
type Error = ();
fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
if let MultiSigner::Sr25519(x) = m { Ok(x) } else { Err(()) }
}
}
impl From<ecdsa::Public> for MultiSigner {
fn from(x: ecdsa::Public) -> Self {
MultiSigner::Ecdsa(x)
}
}
impl TryFrom<MultiSigner> for ecdsa::Public {
type Error = ();
fn try_from(m: MultiSigner) -> Result<Self, Self::Error> {
if let MultiSigner::Ecdsa(x) = m { Ok(x) } else { Err(()) }
}
}
#[cfg(feature = "std")]
impl std::fmt::Display for MultiSigner {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
MultiSigner::Ed25519(ref who) => write!(fmt, "ed25519: {}", who),
MultiSigner::Sr25519(ref who) => write!(fmt, "sr25519: {}", who),
MultiSigner::Ecdsa(ref who) => write!(fmt, "ecdsa: {}", who),
}
}
}
impl Verify for MultiSignature {
type Signer = MultiSigner;
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
use primitives::crypto::Public;
match (self, signer) {
(MultiSignature::Ed25519(ref sig), who) => sig.verify(msg, &ed25519::Public::from_slice(who.as_ref())),
(MultiSignature::Sr25519(ref sig), who) => sig.verify(msg, &sr25519::Public::from_slice(who.as_ref())),
(MultiSignature::Ecdsa(ref sig), who) => {
let m = runtime_io::hashing::blake2_256(msg.get());
match runtime_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) {
Ok(pubkey) =>
&runtime_io::hashing::blake2_256(pubkey.as_ref())
== <dyn AsRef<[u8; 32]>>::as_ref(who),
_ => false,
}
}
}
}
}
/// Signature verify that can work with any known signature types..
#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct AnySignature(H512);
impl Verify for AnySignature {
type Signer = sr25519::Public;
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sr25519::Public) -> bool {
use primitives::crypto::Public;
let msg = msg.get();
sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
.map(|s| s.verify(msg, signer))
.unwrap_or(false)
|| ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref())
.map(|s| s.verify(msg, &ed25519::Public::from_slice(signer.as_ref())))
.unwrap_or(false)
}
}
impl From<sr25519::Signature> for AnySignature {
fn from(s: sr25519::Signature) -> Self {
AnySignature(s.into())
}
}
impl From<ed25519::Signature> for AnySignature {
fn from(s: ed25519::Signature) -> Self {
AnySignature(s.into())
}
}
impl From<DispatchError> for DispatchOutcome {
fn from(err: DispatchError) -> Self {
Err(err)
}
}
#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Serialize))]
/// Reason why a dispatch call failed
pub struct DispatchError {
/// Module index, matching the metadata module index
pub module: Option<u8>,
/// Module specific error value
pub error: u8,
/// Optional error message.
#[codec(skip)]
pub message: Option<&'static str>,
}
impl DispatchError {
/// Create a new instance of `DispatchError`.
pub fn new(module: Option<u8>, error: u8, message: Option<&'static str>) -> Self {
Self {
module,
error,
message,
}
}
}
impl traits::Printable for DispatchError {
fn print(&self) {
"DispatchError".print();
if let Some(module) = self.module {
module.print();
}
self.error.print();
if let Some(msg) = self.message {
msg.print();
}
}
}
impl traits::ModuleDispatchError for &'static str {
fn as_u8(&self) -> u8 {
0
}
fn as_str(&self) -> &'static str {
self
}
}
impl From<&'static str> for DispatchError {
fn from(err: &'static str) -> DispatchError {
DispatchError::new(None, 0, Some(err))
}
}
/// This type specifies the outcome of dispatching a call to a module.
///
/// In case of failure an error specific to the module is returned.
///
/// Failure of the module call dispatching doesn't invalidate the extrinsic and it is still included
/// in the block, therefore all state changes performed by the dispatched call are still persisted.
///
/// For example, if the dispatching of an extrinsic involves inclusion fee payment then these
/// changes are going to be preserved even if the call dispatched failed.
pub type DispatchOutcome = Result<(), DispatchError>;
/// The result of applying of an extrinsic.
///
/// This type is typically used in the context of `BlockBuilder` to signal that the extrinsic
/// in question cannot be included.
///
/// A block containing extrinsics that have a negative inclusion outcome is invalid. A negative
/// result can only occur during the block production, where such extrinsics are detected and
/// removed from the block that is being created and the transaction pool.
///
/// To rehash: every extrinsic in a valid block must return a positive `ApplyExtrinsicResult`.
///
/// Examples of reasons preventing inclusion in a block:
/// - More block weight is required to process the extrinsic than is left in the block being built.
/// This doesn't neccessarily mean that the extrinsic is invalid, since it can still be
/// included in the next block if it has enough spare weight available.
/// - The sender doesn't have enough funds to pay the transaction inclusion fee. Including such
/// a transaction in the block doesn't make sense.
/// - The extrinsic supplied a bad signature. This transaction won't become valid ever.
pub type ApplyExtrinsicResult = Result<DispatchOutcome, transaction_validity::TransactionValidityError>;
/// Verify a signature on an encoded value in a lazy manner. This can be
/// an optimization if the signature scheme has an "unsigned" escape hash.
pub fn verify_encoded_lazy<V: Verify, T: codec::Encode>(
sig: &V,
item: &T,
signer: &<V::Signer as IdentifyAccount>::AccountId
) -> bool {
// The `Lazy<T>` trait expresses something like `X: FnMut<Output = for<'a> &'a T>`.
// unfortunately this is a lifetime relationship that can't
// be expressed without generic associated types, better unification of HRTBs in type position,
// and some kind of integration into the Fn* traits.
struct LazyEncode<F> {
inner: F,
encoded: Option<Vec<u8>>,
}
impl<F: Fn() -> Vec<u8>> traits::Lazy<[u8]> for LazyEncode<F> {
fn get(&mut self) -> &[u8] {
self.encoded.get_or_insert_with(&self.inner).as_slice()
}
}
sig.verify(
LazyEncode { inner: || item.encode(), encoded: None },
signer,
)
}
/// Helper macro for `impl_outer_config`
#[macro_export]
macro_rules! __impl_outer_config_types {
// Generic + Instance
(
$concrete:ident $config:ident $snake:ident { $instance:ident } < $ignore:ident >;
$( $rest:tt )*
) => {
#[cfg(any(feature = "std", test))]
pub type $config = $snake::GenesisConfig<$concrete, $snake::$instance>;
$crate::__impl_outer_config_types! { $concrete $( $rest )* }
};
// Generic
(
$concrete:ident $config:ident $snake:ident < $ignore:ident >;
$( $rest:tt )*
) => {
#[cfg(any(feature = "std", test))]
pub type $config = $snake::GenesisConfig<$concrete>;
$crate::__impl_outer_config_types! { $concrete $( $rest )* }
};
// No Generic and maybe Instance
(
$concrete:ident $config:ident $snake:ident $( { $instance:ident } )?;
$( $rest:tt )*
) => {
#[cfg(any(feature = "std", test))]
pub type $config = $snake::GenesisConfig;
$crate::__impl_outer_config_types! { $concrete $( $rest )* }
};
($concrete:ident) => ()
}
/// Implement the output "meta" module configuration struct,
/// which is basically:
/// pub struct GenesisConfig {
/// rust_module_one: Option<ModuleOneConfig>,
/// ...
/// }
#[macro_export]
macro_rules! impl_outer_config {
(
pub struct $main:ident for $concrete:ident {
$( $config:ident =>
$snake:ident $( $instance:ident )? $( <$generic:ident> )*, )*
}
) => {
$crate::__impl_outer_config_types! {
$concrete $( $config $snake $( { $instance } )? $( <$generic> )*; )*
}
$crate::paste::item! {
#[cfg(any(feature = "std", test))]
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct $main {
$(
pub [< $snake $(_ $instance )? >]: Option<$config>,
)*
}
#[cfg(any(feature = "std", test))]
impl $crate::BuildStorage for $main {
fn assimilate_storage(
&self,
storage: &mut ($crate::StorageOverlay, $crate::ChildrenStorageOverlay),
) -> std::result::Result<(), String> {
$(
if let Some(ref extra) = self.[< $snake $(_ $instance )? >] {
$crate::impl_outer_config! {
@CALL_FN
$concrete;
$snake;
$( $instance )?;
extra;
storage;
}
}
)*
Ok(())
}
}
}
};
(@CALL_FN
$runtime:ident;
$module:ident;
$instance:ident;
$extra:ident;
$storage:ident;
) => {
$crate::BuildModuleGenesisStorage::<$runtime, $module::$instance>::build_module_genesis_storage(
$extra,
$storage,
)?;
};
(@CALL_FN
$runtime:ident;
$module:ident;
;
$extra:ident;
$storage:ident;
) => {
$crate::BuildModuleGenesisStorage::<$runtime, $module::__InherentHiddenInstance>::build_module_genesis_storage(
$extra,
$storage,
)?;
}
}
/// Checks that `$x` is equal to `$y` with an error rate of `$error`.
///
/// # Example
///
/// ```rust
/// # fn main() {
/// sp_runtime::assert_eq_error_rate!(10, 10, 0);
/// sp_runtime::assert_eq_error_rate!(10, 11, 1);
/// sp_runtime::assert_eq_error_rate!(12, 10, 2);
/// # }
/// ```
///
/// ```rust,should_panic
/// # fn main() {
/// sp_runtime::assert_eq_error_rate!(12, 10, 1);
/// # }
/// ```
#[macro_export]
#[cfg(feature = "std")]
macro_rules! assert_eq_error_rate {
($x:expr, $y:expr, $error:expr $(,)?) => {
assert!(
($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)),
"{:?} != {:?} (with error rate {:?})",
$x,
$y,
$error,
);
};
}
/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized
/// correctly.
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
pub struct OpaqueExtrinsic(pub Vec<u8>);
impl rstd::fmt::Debug for OpaqueExtrinsic {
#[cfg(feature = "std")]
fn fmt(&self, fmt: &mut rstd::fmt::Formatter) -> rstd::fmt::Result {
write!(fmt, "{}", primitives::hexdisplay::HexDisplay::from(&self.0))
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _fmt: &mut rstd::fmt::Formatter) -> rstd::fmt::Result {
Ok(())
}
}
#[cfg(feature = "std")]
impl ::serde::Serialize for OpaqueExtrinsic {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer {
codec::Encode::using_encoded(&self.0, |bytes| ::primitives::bytes::serialize(bytes, seq))
}
}
#[cfg(feature = "std")]
impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
fn deserialize<D>(de: D) -> Result<Self, D::Error> where D: ::serde::Deserializer<'a> {
let r = ::primitives::bytes::deserialize(de)?;
Decode::decode(&mut &r[..])
.map_err(|e| ::serde::de::Error::custom(format!("Decode error: {}", e)))
}
}
impl traits::Extrinsic for OpaqueExtrinsic {
type Call = ();
type SignaturePayload = ();
}
/// Print something that implements `Printable` from the runtime.
pub fn print(print: impl traits::Printable) {
print.print();
}
#[cfg(test)]
mod tests {
use crate::DispatchError;
use codec::{Encode, Decode};
#[test]
fn opaque_extrinsic_serialization() {
let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]);
assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned());
}
#[test]
fn dispatch_error_encoding() {
let error = DispatchError {
module: Some(1),
error: 2,
message: Some("error message"),
};
let encoded = error.encode();
let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
assert_eq!(encoded, vec![1, 1, 2]);
assert_eq!(
decoded,
DispatchError {
module: Some(1),
error: 2,
message: None,
},
);
}
}
@@ -0,0 +1,606 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! A high-level helpers for making HTTP requests from Offchain Workers.
//!
//! `sp-io` crate exposes a low level methods to make and control HTTP requests
//! available only for Offchain Workers. Those might be hard to use
//! and usually that level of control is not really necessary.
//! This module aims to provide high-level wrappers for those APIs
//! to simplify making HTTP requests.
//!
//!
//! Example:
//! ```rust,no_run
//! use sp_runtime::offchain::http::Request;
//!
//! // initiate a GET request to localhost:1234
//! let request: Request = Request::get("http://localhost:1234");
//! let pending = request
//! .add_header("X-Auth", "hunter2")
//! .send()
//! .unwrap();
//!
//! // wait for the response indefinitely
//! let mut response = pending.wait().unwrap();
//!
//! // then check the headers
//! let mut headers = response.headers().into_iter();
//! assert_eq!(headers.current(), None);
//!
//! // and collect the body
//! let body = response.body();
//! assert_eq!(body.clone().collect::<Vec<_>>(), b"1234".to_vec());
//! assert_eq!(body.error(), &None);
//! ```
use rstd::str;
use rstd::prelude::Vec;
#[cfg(not(feature = "std"))]
use rstd::prelude::vec;
use primitives::RuntimeDebug;
use primitives::offchain::{
Timestamp,
HttpRequestId as RequestId,
HttpRequestStatus as RequestStatus,
HttpError,
};
/// Request method (HTTP verb)
#[derive(Clone, PartialEq, Eq, RuntimeDebug)]
pub enum Method {
/// GET request
Get,
/// POST request
Post,
/// PUT request
Put,
/// PATCH request
Patch,
/// DELETE request
Delete,
/// Custom verb
Other(&'static str),
}
impl AsRef<str> for Method {
fn as_ref(&self) -> &str {
match *self {
Method::Get => "GET",
Method::Post => "POST",
Method::Put => "PUT",
Method::Patch => "PATCH",
Method::Delete => "DELETE",
Method::Other(m) => m,
}
}
}
mod header {
use super::*;
/// A header type.
#[derive(Clone, PartialEq, Eq, RuntimeDebug)]
pub struct Header {
name: Vec<u8>,
value: Vec<u8>,
}
impl Header {
/// Creates new header given it's name and value.
pub fn new(name: &str, value: &str) -> Self {
Header {
name: name.as_bytes().to_vec(),
value: value.as_bytes().to_vec(),
}
}
/// Returns the name of this header.
pub fn name(&self) -> &str {
// Header keys are always produced from `&str` so this is safe.
// we don't store them as `Strings` to avoid bringing `alloc::String` to rstd
// or here.
unsafe { str::from_utf8_unchecked(&self.name) }
}
/// Returns the value of this header.
pub fn value(&self) -> &str {
// Header values are always produced from `&str` so this is safe.
// we don't store them as `Strings` to avoid bringing `alloc::String` to rstd
// or here.
unsafe { str::from_utf8_unchecked(&self.value) }
}
}
}
/// An HTTP request builder.
#[derive(Clone, PartialEq, Eq, RuntimeDebug)]
pub struct Request<'a, T = Vec<&'static [u8]>> {
/// Request method
pub method: Method,
/// Request URL
pub url: &'a str,
/// Body of the request
pub body: T,
/// Deadline to finish sending the request
pub deadline: Option<Timestamp>,
/// Request list of headers.
headers: Vec<header::Header>,
}
impl<T: Default> Default for Request<'static, T> {
fn default() -> Self {
Request {
method: Method::Get,
url: "http://localhost",
headers: Vec::new(),
body: Default::default(),
deadline: None,
}
}
}
impl<'a> Request<'a> {
/// Start a simple GET request
pub fn get(url: &'a str) -> Self {
Self::new(url)
}
}
impl<'a, T> Request<'a, T> {
/// Create new POST request with given body.
pub fn post(url: &'a str, body: T) -> Self {
let req: Request = Request::default();
Request {
url,
body,
method: Method::Post,
headers: req.headers,
deadline: req.deadline,
}
}
}
impl<'a, T: Default> Request<'a, T> {
/// Create new Request builder with given URL and body.
pub fn new(url: &'a str) -> Self {
Request::default().url(url)
}
/// Change the method of the request
pub fn method(mut self, method: Method) -> Self {
self.method = method;
self
}
/// Change the URL of the request.
pub fn url(mut self, url: &'a str) -> Self {
self.url = url;
self
}
/// Set the body of the request.
pub fn body(mut self, body: T) -> Self {
self.body = body;
self
}
/// Add a header.
pub fn add_header(mut self, name: &str, value: &str) -> Self {
self.headers.push(header::Header::new(name, value));
self
}
/// Set the deadline of the request.
pub fn deadline(mut self, deadline: Timestamp) -> Self {
self.deadline = Some(deadline);
self
}
}
impl<'a, I: AsRef<[u8]>, T: IntoIterator<Item=I>> Request<'a, T> {
/// Send the request and return a handle.
///
/// Err is returned in case the deadline is reached
/// or the request timeouts.
pub fn send(self) -> Result<PendingRequest, HttpError> {
let meta = &[];
// start an http request.
let id = runtime_io::offchain::http_request_start(
self.method.as_ref(),
self.url,
meta,
).map_err(|_| HttpError::IoError)?;
// add custom headers
for header in &self.headers {
runtime_io::offchain::http_request_add_header(
id,
header.name(),
header.value(),
).map_err(|_| HttpError::IoError)?
}
// write body
for chunk in self.body {
runtime_io::offchain::http_request_write_body(id, chunk.as_ref(), self.deadline)?;
}
// finalise the request
runtime_io::offchain::http_request_write_body(id, &[], self.deadline)?;
Ok(PendingRequest {
id,
})
}
}
/// A request error
#[derive(Clone, PartialEq, Eq, RuntimeDebug)]
pub enum Error {
/// Deadline has been reached.
DeadlineReached,
/// Request had timed out.
IoError,
/// Unknown error has been ecountered.
Unknown,
}
/// A struct representing an uncompleted http request.
#[derive(PartialEq, Eq, RuntimeDebug)]
pub struct PendingRequest {
/// Request ID
pub id: RequestId,
}
/// A result of waiting for a pending request.
pub type HttpResult = Result<Response, Error>;
impl PendingRequest {
/// Wait for the request to complete.
///
/// NOTE this waits for the request indefinitely.
pub fn wait(self) -> HttpResult {
match self.try_wait(None) {
Ok(res) => res,
Err(_) => panic!("Since `None` is passed we will never get a deadline error; qed"),
}
}
/// Attempts to wait for the request to finish,
/// but will return `Err` in case the deadline is reached.
pub fn try_wait(self, deadline: impl Into<Option<Timestamp>>) -> Result<HttpResult, PendingRequest> {
Self::try_wait_all(vec![self], deadline).pop().expect("One request passed, one status received; qed")
}
/// Wait for all provided requests.
pub fn wait_all(requests: Vec<PendingRequest>) -> Vec<HttpResult> {
Self::try_wait_all(requests, None)
.into_iter()
.map(|r| match r {
Ok(r) => r,
Err(_) => panic!("Since `None` is passed we will never get a deadline error; qed"),
})
.collect()
}
/// Attempt to wait for all provided requests, but up to given deadline.
///
/// Requests that are complete will resolve to an `Ok` others will return a `DeadlineReached` error.
pub fn try_wait_all(
requests: Vec<PendingRequest>,
deadline: impl Into<Option<Timestamp>>
) -> Vec<Result<HttpResult, PendingRequest>> {
let ids = requests.iter().map(|r| r.id).collect::<Vec<_>>();
let statuses = runtime_io::offchain::http_response_wait(&ids, deadline.into());
statuses
.into_iter()
.zip(requests.into_iter())
.map(|(status, req)| match status {
RequestStatus::DeadlineReached => Err(req),
RequestStatus::IoError => Ok(Err(Error::IoError)),
RequestStatus::Invalid => Ok(Err(Error::Unknown)),
RequestStatus::Finished(code) => Ok(Ok(Response::new(req.id, code))),
})
.collect()
}
}
/// A HTTP response.
#[derive(RuntimeDebug)]
pub struct Response {
/// Request id
pub id: RequestId,
/// Response status code
pub code: u16,
/// A collection of headers.
headers: Option<Headers>,
}
impl Response {
fn new(id: RequestId, code: u16) -> Self {
Self {
id,
code,
headers: None,
}
}
/// Retrieve the headers for this response.
pub fn headers(&mut self) -> &Headers {
if self.headers.is_none() {
self.headers = Some(
Headers { raw: runtime_io::offchain::http_response_headers(self.id) },
);
}
self.headers.as_ref().expect("Headers were just set; qed")
}
/// Retrieve the body of this response.
pub fn body(&self) -> ResponseBody {
ResponseBody::new(self.id)
}
}
/// A buffered byte iterator over response body.
///
/// Note that reading the body may return `None` in following cases:
/// 1. Either the deadline you've set is reached (check via `#error`;
/// In such case you can resume the reader by setting a new deadline)
/// 2. Or because of IOError. In such case the reader is not resumable and will keep
/// returning `None`.
/// 3. The body has been returned. The reader will keep returning `None`.
#[derive(Clone)]
pub struct ResponseBody {
id: RequestId,
error: Option<HttpError>,
buffer: [u8; 4096],
filled_up_to: Option<usize>,
position: usize,
deadline: Option<Timestamp>,
}
#[cfg(feature = "std")]
impl std::fmt::Debug for ResponseBody {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct("ResponseBody")
.field("id", &self.id)
.field("error", &self.error)
.field("buffer", &self.buffer.len())
.field("filled_up_to", &self.filled_up_to)
.field("position", &self.position)
.field("deadline", &self.deadline)
.finish()
}
}
impl ResponseBody {
fn new(id: RequestId) -> Self {
ResponseBody {
id,
error: None,
buffer: [0_u8; 4096],
filled_up_to: None,
position: 0,
deadline: None,
}
}
/// Set the deadline for reading the body.
pub fn deadline(&mut self, deadline: impl Into<Option<Timestamp>>) {
self.deadline = deadline.into();
self.error = None;
}
/// Return an error that caused the iterator to return `None`.
///
/// If the error is `DeadlineReached` you can resume the iterator by setting
/// a new deadline.
pub fn error(&self) -> &Option<HttpError> {
&self.error
}
}
impl Iterator for ResponseBody {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
if self.error.is_some() {
return None;
}
if self.filled_up_to.is_none() {
let result = runtime_io::offchain::http_response_read_body(
self.id,
&mut self.buffer,
self.deadline);
match result {
Err(e) => {
self.error = Some(e);
return None;
}
Ok(0) => {
return None;
}
Ok(size) => {
self.position = 0;
self.filled_up_to = Some(size as usize);
}
}
}
if Some(self.position) == self.filled_up_to {
self.filled_up_to = None;
return self.next();
}
let result = self.buffer[self.position];
self.position += 1;
Some(result)
}
}
/// A collection of Headers in the response.
#[derive(Clone, PartialEq, Eq, RuntimeDebug)]
pub struct Headers {
/// Raw headers
pub raw: Vec<(Vec<u8>, Vec<u8>)>,
}
impl Headers {
/// Retrieve a single header from the list of headers.
///
/// Note this method is linearly looking from all the headers
/// comparing them with the needle byte-by-byte.
/// If you want to consume multiple headers it's better to iterate
/// and collect them on your own.
pub fn find(&self, name: &str) -> Option<&str> {
let raw = name.as_bytes();
for &(ref key, ref val) in &self.raw {
if &**key == raw {
return str::from_utf8(&val).ok()
}
}
None
}
/// Convert this headers into an iterator.
pub fn into_iter(&self) -> HeadersIterator {
HeadersIterator { collection: &self.raw, index: None }
}
}
/// A custom iterator traversing all the headers.
#[derive(Clone, RuntimeDebug)]
pub struct HeadersIterator<'a> {
collection: &'a [(Vec<u8>, Vec<u8>)],
index: Option<usize>,
}
impl<'a> HeadersIterator<'a> {
/// Move the iterator to the next position.
///
/// Returns `true` is `current` has been set by this call.
pub fn next(&mut self) -> bool {
let index = self.index.map(|x| x + 1).unwrap_or(0);
self.index = Some(index);
index < self.collection.len()
}
/// Returns current element (if any).
///
/// Note that you have to call `next` prior to calling this
pub fn current(&self) -> Option<(&str, &str)> {
self.collection.get(self.index?)
.map(|val| (str::from_utf8(&val.0).unwrap_or(""), str::from_utf8(&val.1).unwrap_or("")))
}
}
#[cfg(test)]
mod tests {
use super::*;
use runtime_io::TestExternalities;
use primitives::offchain::{
OffchainExt,
testing,
};
#[test]
fn should_send_a_basic_request_and_get_response() {
let (offchain, state) = testing::TestOffchainExt::new();
let mut t = TestExternalities::default();
t.register_extension(OffchainExt::new(offchain));
t.execute_with(|| {
let request: Request = Request::get("http://localhost:1234");
let pending = request
.add_header("X-Auth", "hunter2")
.send()
.unwrap();
// make sure it's sent correctly
state.write().fulfill_pending_request(
0,
testing::PendingRequest {
method: "GET".into(),
uri: "http://localhost:1234".into(),
headers: vec![("X-Auth".into(), "hunter2".into())],
sent: true,
..Default::default()
},
b"1234".to_vec(),
None,
);
// wait
let mut response = pending.wait().unwrap();
// then check the response
let mut headers = response.headers().into_iter();
assert_eq!(headers.current(), None);
assert_eq!(headers.next(), false);
assert_eq!(headers.current(), None);
let body = response.body();
assert_eq!(body.clone().collect::<Vec<_>>(), b"1234".to_vec());
assert_eq!(body.error(), &None);
})
}
#[test]
fn should_send_a_post_request() {
let (offchain, state) = testing::TestOffchainExt::new();
let mut t = TestExternalities::default();
t.register_extension(OffchainExt::new(offchain));
t.execute_with(|| {
let pending = Request::default()
.method(Method::Post)
.url("http://localhost:1234")
.body(vec![b"1234"])
.send()
.unwrap();
// make sure it's sent correctly
state.write().fulfill_pending_request(
0,
testing::PendingRequest {
method: "POST".into(),
uri: "http://localhost:1234".into(),
body: b"1234".to_vec(),
sent: true,
..Default::default()
},
b"1234".to_vec(),
Some(("Test".to_owned(), "Header".to_owned())),
);
// wait
let mut response = pending.wait().unwrap();
// then check the response
let mut headers = response.headers().into_iter();
assert_eq!(headers.current(), None);
assert_eq!(headers.next(), true);
assert_eq!(headers.current(), Some(("Test", "Header")));
let body = response.body();
assert_eq!(body.clone().collect::<Vec<_>>(), b"1234".to_vec());
assert_eq!(body.error(), &None);
})
}
}
@@ -0,0 +1,19 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! A collection of higher lever helpers for offchain calls.
pub mod http;
@@ -0,0 +1,103 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! A simple pseudo random number generator that allows a stream of random numbers to be efficiently
//! created from a single initial seed hash.
use codec::{Encode, Decode};
use crate::traits::{Hash, TrailingZeroInput};
/// Pseudo-random number streamer. This retains the state of the random number stream. It's as
/// secure as the combination of the seed with which it is constructed and the hash function it uses
/// to cycle elements.
///
/// It can be saved and later reloaded using the Codec traits.
///
/// Example:
/// ```
/// use sp_runtime::traits::{Hash, BlakeTwo256};
/// use sp_runtime::RandomNumberGenerator;
/// let random_seed = BlakeTwo256::hash(b"Sixty-nine");
/// let mut rng = <RandomNumberGenerator<BlakeTwo256>>::new(random_seed);
/// assert_eq!(rng.pick_u32(100), 59);
/// assert_eq!(rng.pick_item(&[1, 2, 3]), Some(&1));
/// ```
///
/// This can use any cryptographic `Hash` function as the means of entropy-extension, and avoids
/// needless extensions of entropy.
///
/// If you're persisting it over blocks, be aware that the sequence will start to repeat. This won't
/// be a practical issue unless you're using tiny hash types (e.g. 64-bit) and pulling hundred of
/// megabytes of data from it.
#[derive(Encode, Decode)]
pub struct RandomNumberGenerator<Hashing: Hash> {
current: Hashing::Output,
offset: u32,
}
impl<Hashing: Hash> RandomNumberGenerator<Hashing> {
/// A new source of random data.
pub fn new(seed: Hashing::Output) -> Self {
Self {
current: seed,
offset: 0,
}
}
fn offset(&self) -> usize { self.offset as usize }
/// Returns a number at least zero, at most `max`.
pub fn pick_u32(&mut self, max: u32) -> u32 {
let needed = (4 - max.leading_zeros() / 8) as usize;
let top = ((1 << (needed as u64 * 8)) / ((max + 1) as u64) * ((max + 1) as u64) - 1) as u32;
loop {
if self.offset() + needed > self.current.as_ref().len() {
// rehash
self.current = Hashing::hash(self.current.as_ref());
self.offset = 0;
}
let data = &self.current.as_ref()[self.offset()..self.offset() + needed];
self.offset += needed as u32;
let raw = u32::decode(&mut TrailingZeroInput::new(data)).unwrap_or(0);
if raw <= top {
break if max < u32::max_value() {
raw % (max + 1)
} else {
raw
}
}
}
}
/// Returns a number at least zero, at most `max`.
///
/// This returns a `usize`, but internally it only uses `u32` so avoid consensus problems.
pub fn pick_usize(&mut self, max: usize) -> usize {
self.pick_u32(max as u32) as usize
}
/// Pick a random element from an array of `items`.
///
/// This is guaranteed to return `Some` except in the case that the given array `items` is
/// empty.
pub fn pick_item<'a, T>(&mut self, items: &'a [T]) -> Option<&'a T> {
if items.is_empty() {
None
} else {
Some(&items[self.pick_usize(items.len() - 1)])
}
}
}
+368
View File
@@ -0,0 +1,368 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Testing utilities.
use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer};
use std::{fmt::Debug, ops::Deref, fmt, cell::RefCell};
use crate::codec::{Codec, Encode, Decode};
use crate::traits::{
self, Checkable, Applyable, BlakeTwo256, OpaqueKeys,
SignedExtension, Dispatchable,
};
#[allow(deprecated)]
use crate::traits::ValidateUnsigned;
use crate::{generic, KeyTypeId, ApplyExtrinsicResult};
pub use primitives::{H256, sr25519};
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, PartialOrd, Ord)]
pub struct UintAuthorityId(pub u64);
impl From<u64> for UintAuthorityId {
fn from(id: u64) -> Self {
UintAuthorityId(id)
}
}
impl From<UintAuthorityId> for u64 {
fn from(id: UintAuthorityId) -> u64 {
id.0
}
}
impl UintAuthorityId {
/// Convert this authority id into a public key.
pub fn to_public_key<T: Public>(&self) -> T {
let bytes: [u8; 32] = U256::from(self.0).into();
T::from_slice(&bytes)
}
}
impl CryptoType for UintAuthorityId {
type Pair = Dummy;
}
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> {
ALL_KEYS.with(|l| l.borrow().clone())
}
fn generate_pair(_: Option<Vec<u8>>) -> Self {
use rand::RngCore;
UintAuthorityId(rand::thread_rng().next_u64())
}
fn sign<M: AsRef<[u8]>>(&self, msg: &M) -> Option<Self::Signature> {
let mut signature = [0u8; 8];
msg.as_ref().iter()
.chain(std::iter::repeat(&42u8))
.take(8)
.enumerate()
.for_each(|(i, v)| { signature[i] = *v; });
Some(u64::from_le_bytes(signature))
}
fn verify<M: AsRef<[u8]>>(&self, msg: &M, signature: &Self::Signature) -> bool {
let mut msg_signature = [0u8; 8];
msg.as_ref().iter()
.chain(std::iter::repeat(&42))
.take(8)
.enumerate()
.for_each(|(i, v)| { msg_signature[i] = *v; });
u64::from_le_bytes(msg_signature) == *signature
}
}
impl OpaqueKeys for UintAuthorityId {
type KeyTypeIdProviders = ();
fn key_ids() -> &'static [KeyTypeId] {
&[key_types::DUMMY]
}
fn get_raw(&self, _: KeyTypeId) -> &[u8] {
self.as_ref()
}
fn get<T: Decode>(&self, _: KeyTypeId) -> Option<T> {
self.using_encoded(|mut x| T::decode(&mut x)).ok()
}
}
impl crate::BoundToRuntimeAppPublic for UintAuthorityId {
type Public = Self;
}
/// Digest item
pub type DigestItem = generic::DigestItem<H256>;
/// Header Digest
pub type Digest = generic::Digest<H256>;
/// Block Header
#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, Default)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct Header {
/// Parent hash
pub parent_hash: H256,
/// Block Number
pub number: u64,
/// Post-execution state trie root
pub state_root: H256,
/// Merkle root of block's extrinsics
pub extrinsics_root: H256,
/// Digest items
pub digest: Digest,
}
impl traits::Header for Header {
type Number = u64;
type Hashing = BlakeTwo256;
type Hash = H256;
fn number(&self) -> &Self::Number { &self.number }
fn set_number(&mut self, num: Self::Number) { self.number = num }
fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root }
fn set_extrinsics_root(&mut self, root: Self::Hash) { self.extrinsics_root = root }
fn state_root(&self) -> &Self::Hash { &self.state_root }
fn set_state_root(&mut self, root: Self::Hash) { self.state_root = root }
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash }
fn digest(&self) -> &Digest { &self.digest }
fn digest_mut(&mut self) -> &mut Digest { &mut self.digest }
fn new(
number: Self::Number,
extrinsics_root: Self::Hash,
state_root: Self::Hash,
parent_hash: Self::Hash,
digest: Digest,
) -> Self {
Header {
number,
extrinsics_root,
state_root,
parent_hash,
digest,
}
}
}
impl Header {
/// A new header with the given number and default hash for all other fields.
pub fn new_from_number(number: <Self as traits::Header>::Number) -> Self {
Self {
number,
..Default::default()
}
}
}
impl<'a> Deserialize<'a> for Header {
fn deserialize<D: Deserializer<'a>>(de: D) -> Result<Self, D::Error> {
let r = <Vec<u8>>::deserialize(de)?;
Decode::decode(&mut &r[..])
.map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what())))
}
}
/// An opaque extrinsic wrapper type.
#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)]
pub struct ExtrinsicWrapper<Xt>(Xt);
impl<Xt> traits::Extrinsic for ExtrinsicWrapper<Xt> {
type Call = ();
type SignaturePayload = ();
fn is_signed(&self) -> Option<bool> {
None
}
}
impl<Xt: Encode> serde::Serialize for ExtrinsicWrapper<Xt> {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: ::serde::Serializer {
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
}
}
impl<Xt> From<Xt> for ExtrinsicWrapper<Xt> {
fn from(xt: Xt) -> Self {
ExtrinsicWrapper(xt)
}
}
impl<Xt> Deref for ExtrinsicWrapper<Xt> {
type Target = Xt;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// Testing block
#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)]
pub struct Block<Xt> {
/// Block header
pub header: Header,
/// List of extrinsics
pub extrinsics: Vec<Xt>,
}
impl<Xt: 'static + Codec + Sized + Send + Sync + Serialize + Clone + Eq + Debug + traits::Extrinsic> traits::Block
for Block<Xt>
{
type Extrinsic = Xt;
type Header = Header;
type Hash = <Header as traits::Header>::Hash;
fn header(&self) -> &Self::Header {
&self.header
}
fn extrinsics(&self) -> &[Self::Extrinsic] {
&self.extrinsics[..]
}
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>) {
(self.header, self.extrinsics)
}
fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self {
Block { header, extrinsics }
}
fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec<u8> {
(header, extrinsics).encode()
}
}
impl<'a, Xt> Deserialize<'a> for Block<Xt> where Block<Xt>: Decode {
fn deserialize<D: Deserializer<'a>>(de: D) -> Result<Self, D::Error> {
let r = <Vec<u8>>::deserialize(de)?;
Decode::decode(&mut &r[..])
.map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what())))
}
}
/// Test transaction, tuple of (sender, call, signed_extra)
/// with index only used if sender is some.
///
/// If sender is some then the transaction is signed otherwise it is unsigned.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
pub struct TestXt<Call, Extra>(pub Option<(u64, Extra)>, pub Call);
impl<Call, Extra> Serialize for TestXt<Call, Extra> where TestXt<Call, Extra>: Encode {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error> where S: Serializer {
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
}
}
impl<Call, Extra> Debug for TestXt<Call, Extra> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TestXt({:?}, ...)", self.0.as_ref().map(|x| &x.0))
}
}
impl<Call: Codec + Sync + Send, Context, Extra> Checkable<Context> for TestXt<Call, Extra> {
type Checked = Self;
fn check(self, _: &Context) -> Result<Self::Checked, TransactionValidityError> { Ok(self) }
}
impl<Call: Codec + Sync + Send, Extra> traits::Extrinsic for TestXt<Call, Extra> {
type Call = Call;
type SignaturePayload = (u64, Extra);
fn is_signed(&self) -> Option<bool> {
Some(self.0.is_some())
}
fn new(c: Call, sig: Option<Self::SignaturePayload>) -> Option<Self> {
Some(TestXt(sig, c))
}
}
impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where
Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Dispatchable<Origin=Origin>,
Extra: SignedExtension<AccountId=u64, Call=Call, DispatchInfo=Info>,
Origin: From<Option<u64>>,
Info: Clone,
{
type AccountId = u64;
type Call = Call;
type DispatchInfo = Info;
fn sender(&self) -> Option<&Self::AccountId> { self.0.as_ref().map(|x| &x.0) }
/// Checks to see if this is a valid *transaction*. It returns information on it if so.
#[allow(deprecated)] // Allow ValidateUnsigned
fn validate<U: ValidateUnsigned<Call=Self::Call>>(
&self,
_info: Self::DispatchInfo,
_len: usize,
) -> TransactionValidity {
Ok(Default::default())
}
/// Executes all necessary logic needed prior to dispatch and deconstructs into function call,
/// index and sender.
#[allow(deprecated)] // Allow ValidateUnsigned
fn apply<U: ValidateUnsigned<Call=Self::Call>>(
self,
info: Self::DispatchInfo,
len: usize,
) -> ApplyExtrinsicResult {
let maybe_who = if let Some((who, extra)) = self.0 {
Extra::pre_dispatch(extra, &who, &self.1, info, len)?;
Some(who)
} else {
Extra::pre_dispatch_unsigned(&self.1, info, len)?;
None
};
Ok(self.1.dispatch(maybe_who.into()).map_err(Into::into))
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,247 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Transaction validity interface.
use rstd::prelude::*;
use crate::codec::{Encode, Decode};
use crate::RuntimeDebug;
/// Priority for a transaction. Additive. Higher is better.
pub type TransactionPriority = u64;
/// Minimum number of blocks a transaction will remain valid for.
/// `TransactionLongevity::max_value()` means "forever".
pub type TransactionLongevity = u64;
/// Tag for a transaction. No two transactions with the same tag should be placed on-chain.
pub type TransactionTag = Vec<u8>;
/// An invalid transaction validity.
#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(serde::Serialize))]
pub enum InvalidTransaction {
/// The call of the transaction is not expected.
Call,
/// General error to do with the inability to pay some fees (e.g. account balance too low).
Payment,
/// General error to do with the transaction not yet being valid (e.g. nonce too high).
Future,
/// General error to do with the transaction being outdated (e.g. nonce too low).
Stale,
/// General error to do with the transaction's proofs (e.g. signature).
BadProof,
/// The transaction birth block is ancient.
AncientBirthBlock,
/// The transaction would exhaust the resources of current block.
///
/// The transaction might be valid, but there are not enough resources left in the current block.
ExhaustsResources,
/// Any other custom invalid validity that is not covered by this enum.
Custom(u8),
}
impl InvalidTransaction {
/// Returns if the reason for the invalidity was block resource exhaustion.
pub fn exhausted_resources(&self) -> bool {
match self {
Self::ExhaustsResources => true,
_ => false,
}
}
}
impl From<InvalidTransaction> for &'static str {
fn from(invalid: InvalidTransaction) -> &'static str {
match invalid {
InvalidTransaction::Call => "Transaction call is not expected",
InvalidTransaction::Future => "Transaction will be valid in the future",
InvalidTransaction::Stale => "Transaction is outdated",
InvalidTransaction::BadProof => "Transaction has a bad signature",
InvalidTransaction::AncientBirthBlock => "Transaction has an ancient birth block",
InvalidTransaction::ExhaustsResources =>
"Transaction would exhausts the block limits",
InvalidTransaction::Payment =>
"Inability to pay some fees (e.g. account balance too low)",
InvalidTransaction::Custom(_) => "InvalidTransaction custom error",
}
}
}
/// An unknown transaction validity.
#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(serde::Serialize))]
pub enum UnknownTransaction {
/// Could not lookup some information that is required to validate the transaction.
CannotLookup,
/// No validator found for the given unsigned transaction.
NoUnsignedValidator,
/// Any other custom unknown validity that is not covered by this enum.
Custom(u8),
}
impl From<UnknownTransaction> for &'static str {
fn from(unknown: UnknownTransaction) -> &'static str {
match unknown {
UnknownTransaction::CannotLookup =>
"Could not lookup information required to validate the transaction",
UnknownTransaction::NoUnsignedValidator =>
"Could not find an unsigned validator for the unsigned transaction",
UnknownTransaction::Custom(_) => "UnknownTransaction custom error",
}
}
}
/// Errors that can occur while checking the validity of a transaction.
#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(serde::Serialize))]
pub enum TransactionValidityError {
/// The transaction is invalid.
Invalid(InvalidTransaction),
/// Transaction validity can't be determined.
Unknown(UnknownTransaction),
}
impl TransactionValidityError {
/// Returns `true` if the reason for the error was block resource exhaustion.
pub fn exhausted_resources(&self) -> bool {
match self {
Self::Invalid(e) => e.exhausted_resources(),
Self::Unknown(_) => false,
}
}
}
impl From<TransactionValidityError> for &'static str {
fn from(err: TransactionValidityError) -> &'static str {
match err {
TransactionValidityError::Invalid(invalid) => invalid.into(),
TransactionValidityError::Unknown(unknown) => unknown.into(),
}
}
}
impl From<InvalidTransaction> for TransactionValidityError {
fn from(err: InvalidTransaction) -> Self {
TransactionValidityError::Invalid(err)
}
}
impl From<UnknownTransaction> for TransactionValidityError {
fn from(err: UnknownTransaction) -> Self {
TransactionValidityError::Unknown(err)
}
}
/// Information on a transaction's validity and, if valid, on how it relates to other transactions.
pub type TransactionValidity = Result<ValidTransaction, TransactionValidityError>;
impl Into<TransactionValidity> for InvalidTransaction {
fn into(self) -> TransactionValidity {
Err(self.into())
}
}
impl Into<TransactionValidity> for UnknownTransaction {
fn into(self) -> TransactionValidity {
Err(self.into())
}
}
/// Information concerning a valid transaction.
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
pub struct ValidTransaction {
/// Priority of the transaction.
///
/// Priority determines the ordering of two transactions that have all
/// their dependencies (required tags) satisfied.
pub priority: TransactionPriority,
/// Transaction dependencies
///
/// A non-empty list signifies that some other transactions which provide
/// given tags are required to be included before that one.
pub requires: Vec<TransactionTag>,
/// Provided tags
///
/// A list of tags this transaction provides. Successfully importing the transaction
/// will enable other transactions that depend on (require) those tags to be included as well.
/// Provided and required tags allow Substrate to build a dependency graph of transactions
/// and import them in the right (linear) order.
pub provides: Vec<TransactionTag>,
/// Transaction longevity
///
/// Longevity describes minimum number of blocks the validity is correct.
/// After this period transaction should be removed from the pool or revalidated.
pub longevity: TransactionLongevity,
/// A flag indicating if the transaction should be propagated to other peers.
///
/// By setting `false` here the transaction will still be considered for
/// including in blocks that are authored on the current node, but will
/// never be sent to other peers.
pub propagate: bool,
}
impl Default for ValidTransaction {
fn default() -> Self {
ValidTransaction {
priority: 0,
requires: vec![],
provides: vec![],
longevity: TransactionLongevity::max_value(),
propagate: true,
}
}
}
impl ValidTransaction {
/// Combine two instances into one, as a best effort. This will take the superset of each of the
/// `provides` and `requires` tags, it will sum the priorities, take the minimum longevity and
/// the logic *And* of the propagate flags.
pub fn combine_with(mut self, mut other: ValidTransaction) -> Self {
ValidTransaction {
priority: self.priority.saturating_add(other.priority),
requires: { self.requires.append(&mut other.requires); self.requires },
provides: { self.provides.append(&mut other.provides); self.provides },
longevity: self.longevity.min(other.longevity),
propagate: self.propagate && other.propagate,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_encode_and_decode() {
let v: TransactionValidity = Ok(ValidTransaction {
priority: 5,
requires: vec![vec![1, 2, 3, 4]],
provides: vec![vec![4, 5, 6]],
longevity: 42,
propagate: false,
});
let encoded = v.encode();
assert_eq!(
encoded,
vec![0, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, 0]
);
// decode back
assert_eq!(TransactionValidity::decode(&mut &*encoded), Ok(v));
}
}