mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 13:27:57 +00:00
Rename folder: primitives/sr-primitives -> primitives/runtime (#4280)
* primitives/sr-primitives -> primitives/runtime * update
This commit is contained in:
committed by
Bastian Köcher
parent
94b6921d03
commit
04fcc71809
@@ -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,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user