use crate::{
codec::{Codec, Decode, Encode, MaxEncodedLen},
generic::Digest,
scale_info::{MetaType, StaticTypeInfo, TypeInfo},
transaction_validity::{
TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
ValidTransaction,
},
DispatchResult,
};
use impl_trait_for_tuples::impl_for_tuples;
#[cfg(feature = "std")]
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use sp_application_crypto::AppKey;
pub use sp_arithmetic::traits::{
checked_pow, ensure_pow, AtLeast32Bit, AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedDiv,
CheckedMul, CheckedShl, CheckedShr, CheckedSub, Ensure, EnsureAdd, EnsureAddAssign, EnsureDiv,
EnsureDivAssign, EnsureFixedPointNumber, EnsureFrom, EnsureInto, EnsureMul, EnsureMulAssign,
EnsureOp, EnsureOpAssign, EnsureSub, EnsureSubAssign, IntegerSquareRoot, One,
SaturatedConversion, Saturating, UniqueSaturatedFrom, UniqueSaturatedInto, Zero,
};
use sp_core::{self, storage::StateVersion, Hasher, RuntimeDebug, TypeId};
#[doc(hidden)]
pub use sp_core::{
parameter_types, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128,
ConstU16, ConstU32, ConstU64, ConstU8, Get, GetDefault, TryCollect, TypedGet,
};
#[doc(hidden)]
pub use sp_std::marker::PhantomData;
use sp_std::{self, fmt::Debug, prelude::*};
#[cfg(feature = "std")]
use std::fmt::Display;
#[cfg(feature = "std")]
use std::str::FromStr;
pub trait Lazy<T: ?Sized> {
fn get(&mut self) -> &T;
}
impl<'a> Lazy<[u8]> for &'a [u8] {
fn get(&mut self) -> &[u8] {
self
}
}
pub trait IdentifyAccount {
type AccountId;
fn into_account(self) -> Self::AccountId;
}
impl IdentifyAccount for sp_core::ed25519::Public {
type AccountId = Self;
fn into_account(self) -> Self {
self
}
}
impl IdentifyAccount for sp_core::sr25519::Public {
type AccountId = Self;
fn into_account(self) -> Self {
self
}
}
impl IdentifyAccount for sp_core::ecdsa::Public {
type AccountId = Self;
fn into_account(self) -> Self {
self
}
}
pub trait Verify {
type Signer: IdentifyAccount;
fn verify<L: Lazy<[u8]>>(
&self,
msg: L,
signer: &<Self::Signer as IdentifyAccount>::AccountId,
) -> bool;
}
impl Verify for sp_core::ed25519::Signature {
type Signer = sp_core::ed25519::Public;
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ed25519::Public) -> bool {
sp_io::crypto::ed25519_verify(self, msg.get(), signer)
}
}
impl Verify for sp_core::sr25519::Signature {
type Signer = sp_core::sr25519::Public;
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::sr25519::Public) -> bool {
sp_io::crypto::sr25519_verify(self, msg.get(), signer)
}
}
impl Verify for sp_core::ecdsa::Signature {
type Signer = sp_core::ecdsa::Public;
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &sp_core::ecdsa::Public) -> bool {
match sp_io::crypto::secp256k1_ecdsa_recover_compressed(
self.as_ref(),
&sp_io::hashing::blake2_256(msg.get()),
) {
Ok(pubkey) => signer.as_ref() == &pubkey[..],
_ => false,
}
}
}
pub trait AppVerify {
type AccountId;
fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &Self::AccountId) -> bool;
}
impl<
S: Verify<Signer = <<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic>
+ From<T>,
T: sp_application_crypto::Wraps<Inner = S>
+ sp_application_crypto::AppKey
+ sp_application_crypto::AppSignature
+ AsRef<S>
+ AsMut<S>
+ From<S>,
> AppVerify for T
where
<S as Verify>::Signer: IdentifyAccount<AccountId = <S as Verify>::Signer>,
<<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic: IdentifyAccount<
AccountId = <<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic,
>,
{
type AccountId = <T as AppKey>::Public;
fn verify<L: Lazy<[u8]>>(&self, msg: L, signer: &<T as AppKey>::Public) -> bool {
use sp_application_crypto::IsWrappedBy;
let inner: &S = self.as_ref();
let inner_pubkey =
<<T as AppKey>::Public as sp_application_crypto::AppPublic>::Generic::from_ref(signer);
Verify::verify(inner, msg, inner_pubkey)
}
}
#[derive(Encode, Decode, RuntimeDebug)]
pub struct BadOrigin;
impl From<BadOrigin> for &'static str {
fn from(_: BadOrigin) -> &'static str {
"Bad origin"
}
}
#[derive(Encode, Decode, RuntimeDebug)]
pub struct LookupError;
impl From<LookupError> for &'static str {
fn from(_: LookupError) -> &'static str {
"Can not lookup"
}
}
impl From<LookupError> for TransactionValidityError {
fn from(_: LookupError) -> Self {
UnknownTransaction::CannotLookup.into()
}
}
pub trait Lookup {
type Source;
type Target;
fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError>;
}
pub trait StaticLookup {
type Source: Codec + Clone + PartialEq + Debug + TypeInfo;
type Target;
fn lookup(s: Self::Source) -> Result<Self::Target, LookupError>;
fn unlookup(t: Self::Target) -> Self::Source;
}
#[derive(Default)]
pub struct IdentityLookup<T>(PhantomData<T>);
impl<T: Codec + Clone + PartialEq + Debug + TypeInfo> StaticLookup for IdentityLookup<T> {
type Source = T;
type Target = T;
fn lookup(x: T) -> Result<T, LookupError> {
Ok(x)
}
fn unlookup(x: T) -> T {
x
}
}
impl<T> Lookup for IdentityLookup<T> {
type Source = T;
type Target = T;
fn lookup(&self, x: T) -> Result<T, LookupError> {
Ok(x)
}
}
pub struct AccountIdLookup<AccountId, AccountIndex>(PhantomData<(AccountId, AccountIndex)>);
impl<AccountId, AccountIndex> StaticLookup for AccountIdLookup<AccountId, AccountIndex>
where
AccountId: Codec + Clone + PartialEq + Debug,
AccountIndex: Codec + Clone + PartialEq + Debug,
crate::MultiAddress<AccountId, AccountIndex>: Codec + StaticTypeInfo,
{
type Source = crate::MultiAddress<AccountId, AccountIndex>;
type Target = AccountId;
fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
match x {
crate::MultiAddress::Id(i) => Ok(i),
_ => Err(LookupError),
}
}
fn unlookup(x: Self::Target) -> Self::Source {
crate::MultiAddress::Id(x)
}
}
impl<A, B> StaticLookup for (A, B)
where
A: StaticLookup,
B: StaticLookup<Source = A::Source, Target = A::Target>,
{
type Source = A::Source;
type Target = A::Target;
fn lookup(x: Self::Source) -> Result<Self::Target, LookupError> {
A::lookup(x.clone()).or_else(|_| B::lookup(x))
}
fn unlookup(x: Self::Target) -> Self::Source {
A::unlookup(x)
}
}
pub trait Morph<A> {
type Outcome;
fn morph(a: A) -> Self::Outcome;
}
impl<T> Morph<T> for Identity {
type Outcome = T;
fn morph(a: T) -> T {
a
}
}
pub trait TryMorph<A> {
type Outcome;
fn try_morph(a: A) -> Result<Self::Outcome, ()>;
}
impl<T> TryMorph<T> for Identity {
type Outcome = T;
fn try_morph(a: T) -> Result<T, ()> {
Ok(a)
}
}
#[macro_export]
macro_rules! morph_types {
(
@DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ()
) => {
$( #[doc = $doc] )* $vq struct $name;
};
(
@DECL $( #[doc = $doc:expr] )* $vq:vis $name:ident ( $( $bound_id:ident ),+ )
) => {
$( #[doc = $doc] )*
$vq struct $name < $($bound_id,)* > ( $crate::traits::PhantomData< ( $($bound_id,)* ) > ) ;
};
(
@IMPL $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
) => {
impl<$($bounds)*> $crate::traits::Morph<$var_type> for $name $( $where )? {
type Outcome = $outcome;
fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
}
};
(
@IMPL_TRY $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
) => {
impl<$($bounds)*> $crate::traits::TryMorph<$var_type> for $name $( $where )? {
type Outcome = $outcome;
fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
}
};
(
@IMPL $name:ty : () ( $( $where:tt )* )
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
) => {
impl $crate::traits::Morph<$var_type> for $name $( $where )? {
type Outcome = $outcome;
fn morph($var: $var_type) -> Self::Outcome { $( $ex )* }
}
};
(
@IMPL_TRY $name:ty : () ( $( $where:tt )* )
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
) => {
impl $crate::traits::TryMorph<$var_type> for $name $( $where )? {
type Outcome = $outcome;
fn try_morph($var: $var_type) -> Result<Self::Outcome, ()> { $( $ex )* }
}
};
(
@IMPL_BOTH $name:ty : ( $( $bounds:tt )* ) ( $( $where:tt )* )
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
) => {
morph_types! {
@IMPL $name : ($($bounds)*) ($($where)*)
= |$var: $var_type| -> $outcome { $( $ex )* }
}
morph_types! {
@IMPL_TRY $name : ($($bounds)*) ($($where)*)
= |$var: $var_type| -> $outcome { Ok({$( $ex )*}) }
}
};
(
$( #[doc = $doc:expr] )* $vq:vis type $name:ident
$( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
$(: $type:tt)?
= |_| -> $outcome:ty { $( $ex:expr )* };
$( $rest:tt )*
) => {
morph_types! {
$( #[doc = $doc] )* $vq type $name
$( < $( $bound_id $( : $bound_head $( | $bound_tail )* )? ),+ > )?
EXTRA_GENERIC(X)
$(: $type)?
= |_x: X| -> $outcome { $( $ex )* };
$( $rest )*
}
};
(
$( #[doc = $doc:expr] )* $vq:vis type $name:ident
$( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
$( EXTRA_GENERIC ($extra:ident) )?
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
$( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
$( $rest:tt )*
) => {
morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
morph_types! {
@IMPL_BOTH $name $( < $( $bound_id ),* > )? :
( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
= |$var: $var_type| -> $outcome { $( $ex )* }
}
morph_types!{ $($rest)* }
};
(
$( #[doc = $doc:expr] )* $vq:vis type $name:ident
$( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
$( EXTRA_GENERIC ($extra:ident) )?
: Morph
= |$var:ident: $var_type:ty| -> $outcome:ty { $( $ex:expr )* }
$( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
$( $rest:tt )*
) => {
morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
morph_types! {
@IMPL $name $( < $( $bound_id ),* > )? :
( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
= |$var: $var_type| -> $outcome { $( $ex )* }
}
morph_types!{ $($rest)* }
};
(
$( #[doc = $doc:expr] )* $vq:vis type $name:ident
$( < $( $bound_id:ident $( : $bound_head:path $( | $bound_tail:path )* )? ),+ > )?
$( EXTRA_GENERIC ($extra:ident) )?
: TryMorph
= |$var:ident: $var_type:ty| -> Result<$outcome:ty, ()> { $( $ex:expr )* }
$( where $( $where_path:ty : $where_bound_head:path $( | $where_bound_tail:path )* ),* )?;
$( $rest:tt )*
) => {
morph_types! { @DECL $( #[doc = $doc] )* $vq $name ( $( $( $bound_id ),+ )? ) }
morph_types! {
@IMPL_TRY $name $( < $( $bound_id ),* > )? :
( $( $( $bound_id $( : $bound_head $( + $bound_tail )* )? , )+ )? $( $extra )? )
( $( where $( $where_path : $where_bound_head $( + $where_bound_tail )* ),* )? )
= |$var: $var_type| -> $outcome { $( $ex )* }
}
morph_types!{ $($rest)* }
};
() => {}
}
morph_types! {
pub type Replace<V: TypedGet> = |_| -> V::Type { V::get() };
pub type ReduceBy<N: TypedGet> = |r: N::Type| -> N::Type {
r.checked_sub(&N::get()).unwrap_or(Zero::zero())
} where N::Type: CheckedSub | Zero;
}
pub trait Convert<A, B> {
fn convert(a: A) -> B;
}
impl<A, B: Default> Convert<A, B> for () {
fn convert(_: A) -> B {
Default::default()
}
}
pub struct Identity;
impl<T> Convert<T, T> for Identity {
fn convert(a: T) -> T {
a
}
}
impl<T> ConvertBack<T, T> for Identity {
fn convert_back(a: T) -> T {
a
}
}
pub struct ConvertInto;
impl<A, B: From<A>> Convert<A, B> for ConvertInto {
fn convert(a: A) -> B {
a.into()
}
}
pub trait ConvertBack<A, B>: Convert<A, B> {
fn convert_back(b: B) -> A;
}
pub trait CheckedConversion {
fn checked_from<T>(t: T) -> Option<Self>
where
Self: TryFrom<T>,
{
<Self as TryFrom<T>>::try_from(t).ok()
}
fn checked_into<T>(self) -> Option<T>
where
Self: TryInto<T>,
{
<Self as TryInto<T>>::try_into(self).ok()
}
}
impl<T: Sized> CheckedConversion for T {}
pub trait Scale<Other> {
type Output;
fn mul(self, other: Other) -> Self::Output;
fn div(self, other: Other) -> Self::Output;
fn rem(self, other: Other) -> Self::Output;
}
macro_rules! impl_scale {
($self:ty, $other:ty) => {
impl Scale<$other> for $self {
type Output = Self;
fn mul(self, other: $other) -> Self::Output {
self * (other as Self)
}
fn div(self, other: $other) -> Self::Output {
self / (other as Self)
}
fn rem(self, other: $other) -> Self::Output {
self % (other as Self)
}
}
};
}
impl_scale!(u128, u128);
impl_scale!(u128, u64);
impl_scale!(u128, u32);
impl_scale!(u128, u16);
impl_scale!(u128, u8);
impl_scale!(u64, u64);
impl_scale!(u64, u32);
impl_scale!(u64, u16);
impl_scale!(u64, u8);
impl_scale!(u32, u32);
impl_scale!(u32, u16);
impl_scale!(u32, u8);
impl_scale!(u16, u16);
impl_scale!(u16, u8);
impl_scale!(u8, u8);
pub trait Clear {
fn is_clear(&self) -> bool;
fn clear() -> Self;
}
impl<T: Default + Eq + PartialEq> Clear for T {
fn is_clear(&self) -> bool {
*self == Self::clear()
}
fn clear() -> Self {
Default::default()
}
}
pub trait SimpleBitOps:
Sized
+ Clear
+ sp_std::ops::BitOr<Self, Output = Self>
+ sp_std::ops::BitXor<Self, Output = Self>
+ sp_std::ops::BitAnd<Self, Output = Self>
{
}
impl<
T: Sized
+ Clear
+ sp_std::ops::BitOr<Self, Output = Self>
+ sp_std::ops::BitXor<Self, Output = Self>
+ sp_std::ops::BitAnd<Self, Output = Self>,
> SimpleBitOps for T
{
}
pub trait Hash:
'static
+ MaybeSerializeDeserialize
+ Debug
+ Clone
+ Eq
+ PartialEq
+ Hasher<Out = <Self as Hash>::Output>
{
type Output: Member
+ MaybeSerializeDeserialize
+ Debug
+ sp_std::hash::Hash
+ AsRef<[u8]>
+ AsMut<[u8]>
+ Copy
+ Default
+ Encode
+ Decode
+ MaxEncodedLen
+ TypeInfo;
fn hash(s: &[u8]) -> Self::Output {
<Self as Hasher>::hash(s)
}
fn hash_of<S: Encode>(s: &S) -> Self::Output {
Encode::using_encoded(s, <Self as Hasher>::hash)
}
fn ordered_trie_root(input: Vec<Vec<u8>>, state_version: StateVersion) -> Self::Output;
fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, state_version: StateVersion) -> Self::Output;
}
#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct BlakeTwo256;
impl Hasher for BlakeTwo256 {
type Out = sp_core::H256;
type StdHasher = hash256_std_hasher::Hash256StdHasher;
const LENGTH: usize = 32;
fn hash(s: &[u8]) -> Self::Out {
sp_io::hashing::blake2_256(s).into()
}
}
impl Hash for BlakeTwo256 {
type Output = sp_core::H256;
fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
sp_io::trie::blake2_256_root(input, version)
}
fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
sp_io::trie::blake2_256_ordered_root(input, version)
}
}
#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Keccak256;
impl Hasher for Keccak256 {
type Out = sp_core::H256;
type StdHasher = hash256_std_hasher::Hash256StdHasher;
const LENGTH: usize = 32;
fn hash(s: &[u8]) -> Self::Out {
sp_io::hashing::keccak_256(s).into()
}
}
impl Hash for Keccak256 {
type Output = sp_core::H256;
fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>, version: StateVersion) -> Self::Output {
sp_io::trie::keccak_256_root(input, version)
}
fn ordered_trie_root(input: Vec<Vec<u8>>, version: StateVersion) -> Self::Output {
sp_io::trie::keccak_256_ordered_root(input, version)
}
}
pub trait CheckEqual {
fn check_equal(&self, other: &Self);
}
impl CheckEqual for sp_core::H256 {
#[cfg(feature = "std")]
fn check_equal(&self, other: &Self) {
use sp_core::hexdisplay::HexDisplay;
if self != other {
println!(
"Hash: given={}, expected={}",
HexDisplay::from(self.as_fixed_bytes()),
HexDisplay::from(other.as_fixed_bytes()),
);
}
}
#[cfg(not(feature = "std"))]
fn check_equal(&self, other: &Self) {
if self != other {
"Hash not equal".print();
self.as_bytes().print();
other.as_bytes().print();
}
}
}
impl CheckEqual for super::generic::DigestItem {
#[cfg(feature = "std")]
fn check_equal(&self, other: &Self) {
if self != other {
println!("DigestItem: given={:?}, expected={:?}", self, other);
}
}
#[cfg(not(feature = "std"))]
fn check_equal(&self, other: &Self) {
if self != other {
"DigestItem not equal".print();
(&Encode::encode(self)[..]).print();
(&Encode::encode(other)[..]).print();
}
}
}
sp_core::impl_maybe_marker!(
trait MaybeDisplay: Display;
trait MaybeFromStr: FromStr;
trait MaybeHash: sp_std::hash::Hash;
trait MaybeSerialize: Serialize;
trait MaybeSerializeDeserialize: DeserializeOwned, Serialize;
);
pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {}
impl<T: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static> Member for T {}
pub trait IsMember<MemberId> {
fn is_member(member_id: &MemberId) -> bool;
}
pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerialize + Debug + 'static {
type Number: Member
+ MaybeSerializeDeserialize
+ Debug
+ sp_std::hash::Hash
+ Copy
+ MaybeDisplay
+ AtLeast32BitUnsigned
+ Codec
+ sp_std::str::FromStr;
type Hash: Member
+ MaybeSerializeDeserialize
+ Debug
+ sp_std::hash::Hash
+ Ord
+ Copy
+ MaybeDisplay
+ Default
+ SimpleBitOps
+ Codec
+ AsRef<[u8]>
+ AsMut<[u8]>
+ TypeInfo;
type Hashing: Hash<Output = Self::Hash>;
fn new(
number: Self::Number,
extrinsics_root: Self::Hash,
state_root: Self::Hash,
parent_hash: Self::Hash,
digest: Digest,
) -> Self;
fn number(&self) -> &Self::Number;
fn set_number(&mut self, number: Self::Number);
fn extrinsics_root(&self) -> &Self::Hash;
fn set_extrinsics_root(&mut self, root: Self::Hash);
fn state_root(&self) -> &Self::Hash;
fn set_state_root(&mut self, root: Self::Hash);
fn parent_hash(&self) -> &Self::Hash;
fn set_parent_hash(&mut self, hash: Self::Hash);
fn digest(&self) -> &Digest;
fn digest_mut(&mut self) -> &mut Digest;
fn hash(&self) -> Self::Hash {
<Self::Hashing as Hash>::hash_of(self)
}
}
pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerialize + Debug + 'static {
type Extrinsic: Member + Codec + Extrinsic + MaybeSerialize;
type Header: Header<Hash = Self::Hash>;
type Hash: Member
+ MaybeSerializeDeserialize
+ Debug
+ sp_std::hash::Hash
+ Ord
+ Copy
+ MaybeDisplay
+ Default
+ SimpleBitOps
+ Codec
+ AsRef<[u8]>
+ AsMut<[u8]>
+ TypeInfo;
fn header(&self) -> &Self::Header;
fn extrinsics(&self) -> &[Self::Extrinsic];
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>);
fn new(header: Self::Header, extrinsics: Vec<Self::Extrinsic>) -> Self;
fn hash(&self) -> Self::Hash {
<<Self::Header as Header>::Hashing as Hash>::hash_of(self.header())
}
fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec<u8>;
}
pub trait Extrinsic: Sized {
type Call;
type SignaturePayload;
fn is_signed(&self) -> Option<bool> {
None
}
fn new(_call: Self::Call, _signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
None
}
}
pub trait ExtrinsicMetadata {
const VERSION: u8;
type SignedExtensions: SignedExtension;
}
pub type HashFor<B> = <<B as Block>::Header as Header>::Hashing;
pub type NumberFor<B> = <<B as Block>::Header as Header>::Number;
pub trait Checkable<Context>: Sized {
type Checked;
fn check(self, c: &Context) -> Result<Self::Checked, TransactionValidityError>;
#[cfg(feature = "try-runtime")]
fn unchecked_into_checked_i_know_what_i_am_doing(
self,
c: &Context,
) -> Result<Self::Checked, TransactionValidityError>;
}
pub trait BlindCheckable: Sized {
type Checked;
fn check(self) -> Result<Self::Checked, TransactionValidityError>;
}
impl<T: BlindCheckable, Context> Checkable<Context> for T {
type Checked = <Self as BlindCheckable>::Checked;
fn check(self, _c: &Context) -> Result<Self::Checked, TransactionValidityError> {
BlindCheckable::check(self)
}
#[cfg(feature = "try-runtime")]
fn unchecked_into_checked_i_know_what_i_am_doing(
self,
_: &Context,
) -> Result<Self::Checked, TransactionValidityError> {
unreachable!();
}
}
pub trait Dispatchable {
type RuntimeOrigin;
type Config;
type Info;
type PostInfo: Eq + PartialEq + Clone + Copy + Encode + Decode + Printable;
fn dispatch(self, origin: Self::RuntimeOrigin)
-> crate::DispatchResultWithInfo<Self::PostInfo>;
}
pub type DispatchInfoOf<T> = <T as Dispatchable>::Info;
pub type PostDispatchInfoOf<T> = <T as Dispatchable>::PostInfo;
impl Dispatchable for () {
type RuntimeOrigin = ();
type Config = ();
type Info = ();
type PostInfo = ();
fn dispatch(
self,
_origin: Self::RuntimeOrigin,
) -> crate::DispatchResultWithInfo<Self::PostInfo> {
panic!("This implementation should not be used for actual dispatch.");
}
}
pub trait SignedExtension:
Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
{
const IDENTIFIER: &'static str;
type AccountId;
type Call: Dispatchable;
type AdditionalSigned: Encode + TypeInfo;
type Pre;
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError>;
fn validate(
&self,
_who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> TransactionValidity {
Ok(ValidTransaction::default())
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError>;
fn validate_unsigned(
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> TransactionValidity {
Ok(ValidTransaction::default())
}
fn pre_dispatch_unsigned(
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<(), TransactionValidityError> {
Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into)
}
fn post_dispatch(
_pre: Option<Self::Pre>,
_info: &DispatchInfoOf<Self::Call>,
_post_info: &PostDispatchInfoOf<Self::Call>,
_len: usize,
_result: &DispatchResult,
) -> Result<(), TransactionValidityError> {
Ok(())
}
fn metadata() -> Vec<SignedExtensionMetadata> {
sp_std::vec![SignedExtensionMetadata {
identifier: Self::IDENTIFIER,
ty: scale_info::meta_type::<Self>(),
additional_signed: scale_info::meta_type::<Self::AdditionalSigned>()
}]
}
}
pub struct SignedExtensionMetadata {
pub identifier: &'static str,
pub ty: MetaType,
pub additional_signed: MetaType,
}
#[impl_for_tuples(1, 12)]
impl<AccountId, Call: Dispatchable> SignedExtension for Tuple {
for_tuples!( where #( Tuple: SignedExtension<AccountId=AccountId, Call=Call,> )* );
type AccountId = AccountId;
type Call = Call;
const IDENTIFIER: &'static str = "You should call `identifier()`!";
for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); );
for_tuples!( type Pre = ( #( Tuple::Pre ),* ); );
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) ))
}
fn validate(
&self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> TransactionValidity {
let valid = ValidTransaction::default();
for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info, len)?); )* );
Ok(valid)
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) ))
}
fn validate_unsigned(
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> TransactionValidity {
let valid = ValidTransaction::default();
for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* );
Ok(valid)
}
fn pre_dispatch_unsigned(
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<(), TransactionValidityError> {
for_tuples!( #( Tuple::pre_dispatch_unsigned(call, info, len)?; )* );
Ok(())
}
fn post_dispatch(
pre: Option<Self::Pre>,
info: &DispatchInfoOf<Self::Call>,
post_info: &PostDispatchInfoOf<Self::Call>,
len: usize,
result: &DispatchResult,
) -> Result<(), TransactionValidityError> {
match pre {
Some(x) => {
for_tuples!( #( Tuple::post_dispatch(Some(x.Tuple), info, post_info, len, result)?; )* );
},
None => {
for_tuples!( #( Tuple::post_dispatch(None, info, post_info, len, result)?; )* );
},
}
Ok(())
}
fn metadata() -> Vec<SignedExtensionMetadata> {
let mut ids = Vec::new();
for_tuples!( #( ids.extend(Tuple::metadata()); )* );
ids
}
}
#[cfg(feature = "std")]
impl SignedExtension for () {
type AccountId = u64;
type AdditionalSigned = ();
type Call = ();
type Pre = ();
const IDENTIFIER: &'static str = "UnitSignedExtension";
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
Ok(())
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
self.validate(who, call, info, len).map(|_| ())
}
}
pub trait Applyable: Sized + Send + Sync {
type Call: Dispatchable;
fn validate<V: ValidateUnsigned<Call = Self::Call>>(
&self,
source: TransactionSource,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> TransactionValidity;
fn apply<V: ValidateUnsigned<Call = Self::Call>>(
self,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>>;
}
pub trait GetRuntimeBlockType {
type RuntimeBlock: self::Block;
}
pub trait GetNodeBlockType {
type NodeBlock: self::Block;
}
pub trait ValidateUnsigned {
type Call;
fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> {
Self::validate_unsigned(TransactionSource::InBlock, call)
.map(|_| ())
.map_err(Into::into)
}
fn validate_unsigned(source: TransactionSource, call: &Self::Call) -> TransactionValidity;
}
pub trait OpaqueKeys: Clone {
type KeyTypeIdProviders;
fn key_ids() -> &'static [crate::KeyTypeId];
fn get_raw(&self, i: super::KeyTypeId) -> &[u8];
fn get<T: Decode>(&self, i: super::KeyTypeId) -> Option<T> {
T::decode(&mut self.get_raw(i)).ok()
}
fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool {
true
}
}
pub struct AppendZerosInput<'a, T>(&'a mut T);
impl<'a, T> AppendZerosInput<'a, T> {
pub fn new(input: &'a mut T) -> Self {
Self(input)
}
}
impl<'a, T: codec::Input> codec::Input for AppendZerosInput<'a, T> {
fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
Ok(None)
}
fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
let remaining = self.0.remaining_len()?;
let completed = if let Some(n) = remaining {
let readable = into.len().min(n);
self.0.read(&mut into[..readable])?;
readable
} else {
let mut i = 0;
while i < into.len() {
if let Ok(b) = self.0.read_byte() {
into[i] = b;
i += 1;
} else {
break
}
}
i
};
for i in &mut into[completed..] {
*i = 0;
}
Ok(())
}
}
pub struct TrailingZeroInput<'a>(&'a [u8]);
impl<'a> TrailingZeroInput<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self(data)
}
pub fn zeroes() -> Self {
Self::new(&[][..])
}
}
impl<'a> codec::Input for TrailingZeroInput<'a> {
fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
Ok(None)
}
fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
let len_from_inner = into.len().min(self.0.len());
into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]);
for i in &mut into[len_from_inner..] {
*i = 0;
}
self.0 = &self.0[len_from_inner..];
Ok(())
}
}
pub trait AccountIdConversion<AccountId>: Sized {
fn into_account_truncating(&self) -> AccountId {
self.into_sub_account_truncating(&())
}
fn try_into_account(&self) -> Option<AccountId> {
self.try_into_sub_account(&())
}
fn try_from_account(a: &AccountId) -> Option<Self> {
Self::try_from_sub_account::<()>(a).map(|x| x.0)
}
fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> AccountId;
fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<AccountId>;
fn try_from_sub_account<S: Decode>(x: &AccountId) -> Option<(Self, S)>;
}
impl<T: Encode + Decode, Id: Encode + Decode + TypeId> AccountIdConversion<T> for Id {
fn into_sub_account_truncating<S: Encode>(&self, sub: S) -> T {
(Id::TYPE_ID, self, sub)
.using_encoded(|b| T::decode(&mut TrailingZeroInput(b)))
.expect("All byte sequences are valid `AccountIds`; qed")
}
fn try_into_sub_account<S: Encode>(&self, sub: S) -> Option<T> {
let encoded_seed = (Id::TYPE_ID, self, sub).encode();
let account = T::decode(&mut TrailingZeroInput(&encoded_seed))
.expect("All byte sequences are valid `AccountIds`; qed");
if encoded_seed.len() <= account.encoded_size() {
Some(account)
} else {
None
}
}
fn try_from_sub_account<S: Decode>(x: &T) -> Option<(Self, S)> {
x.using_encoded(|d| {
if d[0..4] != Id::TYPE_ID {
return None
}
let mut cursor = &d[4..];
let result = Decode::decode(&mut cursor).ok()?;
if cursor.iter().all(|x| *x == 0) {
Some(result)
} else {
None
}
})
}
}
#[macro_export]
macro_rules! count {
($f:ident ($($x:tt)*) ) => ();
($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); };
($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); };
($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); };
($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => {
$f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3);
};
($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => {
$f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_opaque_keys_inner {
(
$( #[ $attr:meta ] )*
pub struct $name:ident {
$(
$( #[ $inner_attr:meta ] )*
pub $field:ident: $type:ty,
)*
}
) => {
$( #[ $attr ] )*
#[derive(
Clone, PartialEq, Eq,
$crate::codec::Encode,
$crate::codec::Decode,
$crate::scale_info::TypeInfo,
$crate::RuntimeDebug,
)]
pub struct $name {
$(
$( #[ $inner_attr ] )*
pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public,
)*
}
impl $name {
pub fn generate(seed: Option<$crate::sp_std::vec::Vec<u8>>) -> $crate::sp_std::vec::Vec<u8> {
let keys = Self{
$(
$field: <
<
$type as $crate::BoundToRuntimeAppPublic
>::Public as $crate::RuntimeAppPublic
>::generate_pair(seed.clone()),
)*
};
$crate::codec::Encode::encode(&keys)
}
pub fn into_raw_public_keys(
self,
) -> $crate::sp_std::vec::Vec<($crate::sp_std::vec::Vec<u8>, $crate::KeyTypeId)> {
let mut keys = Vec::new();
$(
keys.push((
$crate::RuntimeAppPublic::to_raw_vec(&self.$field),
<
<
$type as $crate::BoundToRuntimeAppPublic
>::Public as $crate::RuntimeAppPublic
>::ID,
));
)*
keys
}
pub fn decode_into_raw_public_keys(
encoded: &[u8],
) -> Option<$crate::sp_std::vec::Vec<($crate::sp_std::vec::Vec<u8>, $crate::KeyTypeId)>> {
<Self as $crate::codec::Decode>::decode(&mut &encoded[..])
.ok()
.map(|s| s.into_raw_public_keys())
}
}
impl $crate::traits::OpaqueKeys for $name {
type KeyTypeIdProviders = ( $( $type, )* );
fn key_ids() -> &'static [$crate::KeyTypeId] {
&[
$(
<
<
$type as $crate::BoundToRuntimeAppPublic
>::Public as $crate::RuntimeAppPublic
>::ID
),*
]
}
fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] {
match i {
$(
i if i == <
<
$type as $crate::BoundToRuntimeAppPublic
>::Public as $crate::RuntimeAppPublic
>::ID =>
self.$field.as_ref(),
)*
_ => &[],
}
}
}
};
}
#[macro_export]
#[cfg(feature = "std")]
macro_rules! impl_opaque_keys {
{
$( #[ $attr:meta ] )*
pub struct $name:ident {
$(
$( #[ $inner_attr:meta ] )*
pub $field:ident: $type:ty,
)*
}
} => {
$crate::paste::paste! {
use $crate::serde as [< __opaque_keys_serde_import__ $name >];
$crate::impl_opaque_keys_inner! {
$( #[ $attr ] )*
#[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
#[serde(crate = "__opaque_keys_serde_import__" $name)]
pub struct $name {
$(
$( #[ $inner_attr ] )*
pub $field: $type,
)*
}
}
}
}
}
#[macro_export]
#[cfg(not(feature = "std"))]
#[doc(hidden)]
macro_rules! impl_opaque_keys {
{
$( #[ $attr:meta ] )*
pub struct $name:ident {
$(
$( #[ $inner_attr:meta ] )*
pub $field:ident: $type:ty,
)*
}
} => {
$crate::impl_opaque_keys_inner! {
$( #[ $attr ] )*
pub struct $name {
$(
$( #[ $inner_attr ] )*
pub $field: $type,
)*
}
}
}
}
pub trait Printable {
fn print(&self);
}
impl<T: Printable> Printable for &T {
fn print(&self) {
(*self).print()
}
}
impl Printable for u8 {
fn print(&self) {
(*self as u64).print()
}
}
impl Printable for u32 {
fn print(&self) {
(*self as u64).print()
}
}
impl Printable for usize {
fn print(&self) {
(*self as u64).print()
}
}
impl Printable for u64 {
fn print(&self) {
sp_io::misc::print_num(*self);
}
}
impl Printable for &[u8] {
fn print(&self) {
sp_io::misc::print_hex(self);
}
}
impl<const N: usize> Printable for [u8; N] {
fn print(&self) {
sp_io::misc::print_hex(&self[..]);
}
}
impl Printable for &str {
fn print(&self) {
sp_io::misc::print_utf8(self.as_bytes());
}
}
impl Printable for bool {
fn print(&self) {
if *self {
"true".print()
} else {
"false".print()
}
}
}
impl Printable for sp_weights::Weight {
fn print(&self) {
self.ref_time().print()
}
}
impl Printable for () {
fn print(&self) {
"()".print()
}
}
#[impl_for_tuples(1, 12)]
impl Printable for Tuple {
fn print(&self) {
for_tuples!( #( Tuple.print(); )* )
}
}
#[cfg(feature = "std")]
pub trait BlockIdTo<Block: self::Block> {
type Error: std::error::Error;
fn to_hash(
&self,
block_id: &crate::generic::BlockId<Block>,
) -> Result<Option<Block::Hash>, Self::Error>;
fn to_number(
&self,
block_id: &crate::generic::BlockId<Block>,
) -> Result<Option<NumberFor<Block>>, Self::Error>;
}
pub trait BlockNumberProvider {
type BlockNumber: Codec + Clone + Ord + Eq + AtLeast32BitUnsigned;
fn current_block_number() -> Self::BlockNumber;
#[cfg(feature = "runtime-benchmarks")]
fn set_block_number(_block: Self::BlockNumber) {}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::codec::{Decode, Encode, Input};
use sp_core::{
crypto::{Pair, UncheckedFrom},
ecdsa,
};
mod t {
use sp_application_crypto::{app_crypto, sr25519};
use sp_core::crypto::KeyTypeId;
app_crypto!(sr25519, KeyTypeId(*b"test"));
}
#[test]
fn app_verify_works() {
use super::AppVerify;
use t::*;
let s = Signature::try_from(vec![0; 64]).unwrap();
let _ = s.verify(&[0u8; 100][..], &Public::unchecked_from([0; 32]));
}
#[derive(Encode, Decode, Default, PartialEq, Debug)]
struct U128Value(u128);
impl super::TypeId for U128Value {
const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0x0d, 0xf0];
}
#[derive(Encode, Decode, Default, PartialEq, Debug)]
struct U32Value(u32);
impl super::TypeId for U32Value {
const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca];
}
#[derive(Encode, Decode, Default, PartialEq, Debug)]
struct U16Value(u16);
impl super::TypeId for U16Value {
const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0];
}
type AccountId = u64;
#[test]
fn into_account_truncating_should_work() {
let r: AccountId = U32Value::into_account_truncating(&U32Value(0xdeadbeef));
assert_eq!(r, 0x_deadbeef_cafef00d);
}
#[test]
fn try_into_account_should_work() {
let r: AccountId = U32Value::try_into_account(&U32Value(0xdeadbeef)).unwrap();
assert_eq!(r, 0x_deadbeef_cafef00d);
let maybe: Option<AccountId> = U128Value::try_into_account(&U128Value(u128::MAX));
assert!(maybe.is_none());
}
#[test]
fn try_from_account_should_work() {
let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64);
assert_eq!(r.unwrap(), U32Value(0xdeadbeef));
}
#[test]
fn into_account_truncating_with_fill_should_work() {
let r: AccountId = U16Value::into_account_truncating(&U16Value(0xc0da));
assert_eq!(r, 0x_0000_c0da_f00dcafe);
}
#[test]
fn try_into_sub_account_should_work() {
let r: AccountId = U16Value::try_into_account(&U16Value(0xc0da)).unwrap();
assert_eq!(r, 0x_0000_c0da_f00dcafe);
let maybe: Option<AccountId> = U16Value::try_into_sub_account(
&U16Value(0xc0da),
"a really large amount of additional encoded information which will certainly overflow the account id type ;)"
);
assert!(maybe.is_none())
}
#[test]
fn try_from_account_with_fill_should_work() {
let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64);
assert_eq!(r.unwrap(), U16Value(0xc0da));
}
#[test]
fn bad_try_from_account_should_fail() {
let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64);
assert!(r.is_none());
let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
assert!(r.is_none());
}
#[test]
fn trailing_zero_should_work() {
let mut t = super::TrailingZeroInput(&[1, 2, 3]);
assert_eq!(t.remaining_len(), Ok(None));
let mut buffer = [0u8; 2];
assert_eq!(t.read(&mut buffer), Ok(()));
assert_eq!(t.remaining_len(), Ok(None));
assert_eq!(buffer, [1, 2]);
assert_eq!(t.read(&mut buffer), Ok(()));
assert_eq!(t.remaining_len(), Ok(None));
assert_eq!(buffer, [3, 0]);
assert_eq!(t.read(&mut buffer), Ok(()));
assert_eq!(t.remaining_len(), Ok(None));
assert_eq!(buffer, [0, 0]);
}
#[test]
fn ecdsa_verify_works() {
let msg = &b"test-message"[..];
let (pair, _) = ecdsa::Pair::generate();
let signature = pair.sign(&msg);
assert!(ecdsa::Pair::verify(&signature, msg, &pair.public()));
assert!(signature.verify(msg, &pair.public()));
assert!(signature.verify(msg, &pair.public()));
}
}