// This file is part of Substrate. // Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! The Substrate runtime. This can be compiled with `#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] pub mod genesismap; pub mod system; use codec::{Decode, Encode, Error, Input, MaxEncodedLen}; use scale_info::TypeInfo; use sp_std::{marker::PhantomData, prelude::*}; use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic}; use sp_core::{offchain::KeyTypeId, OpaqueMetadata, RuntimeDebug}; use sp_trie::{ trie_types::{TrieDBBuilder, TrieDBMutBuilderV1}, PrefixedMemoryDB, StorageProof, }; use trie_db::{Trie, TrieMut}; use cfg_if::cfg_if; use frame_support::{ dispatch::RawOrigin, parameter_types, traits::{CallerTrait, ConstU32, ConstU64, CrateVersion, KeyOwnerProofSystem}, weights::{RuntimeDbWeight, Weight}, }; use frame_system::limits::{BlockLength, BlockWeights}; use sp_api::{decl_runtime_apis, impl_runtime_apis}; pub use sp_core::hash::H256; use sp_inherents::{CheckInherentsResult, InherentData}; #[cfg(feature = "std")] use sp_runtime::traits::NumberFor; use sp_runtime::{ create_runtime_str, impl_opaque_keys, traits::{ BlakeTwo256, BlindCheckable, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType, GetRuntimeBlockType, IdentityLookup, Verify, }, transaction_validity::{ InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, }, ApplyExtrinsicResult, Perbill, }; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; use sp_version::RuntimeVersion; // Ensure Babe and Aura use the same crypto to simplify things a bit. pub use sp_consensus_babe::{AllowedSlots, AuthorityId, Slot}; pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; // Include the WASM binary #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); #[cfg(feature = "std")] pub mod wasm_binary_logging_disabled { include!(concat!(env!("OUT_DIR"), "/wasm_binary_logging_disabled.rs")); } /// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect( "Development wasm binary is not available. Testing is only supported with the flag \ disabled.", ) } /// Wasm binary unwrapped. If built with `SKIP_WASM_BUILD`, the function panics. #[cfg(feature = "std")] pub fn wasm_binary_logging_disabled_unwrap() -> &'static [u8] { wasm_binary_logging_disabled::WASM_BINARY.expect( "Development wasm binary is not available. Testing is only supported with the flag \ disabled.", ) } /// Test runtime version. #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("test"), impl_name: create_runtime_str!("parity-test"), authoring_version: 1, spec_version: 2, impl_version: 2, apis: RUNTIME_API_VERSIONS, transaction_version: 1, state_version: 1, }; fn version() -> RuntimeVersion { VERSION } /// Native version. #[cfg(any(feature = "std", test))] pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } /// Calls in transactions. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct Transfer { pub from: AccountId, pub to: AccountId, pub amount: u64, pub nonce: u64, } impl Transfer { /// Convert into a signed extrinsic. #[cfg(feature = "std")] pub fn into_signed_tx(self) -> Extrinsic { let signature = sp_keyring::AccountKeyring::from_public(&self.from) .expect("Creates keyring from public key.") .sign(&self.encode()); Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: false } } /// Convert into a signed extrinsic, which will only end up included in the block /// if it's the first transaction. Otherwise it will cause `ResourceExhaustion` error /// which should be considered as block being full. #[cfg(feature = "std")] pub fn into_resources_exhausting_tx(self) -> Extrinsic { let signature = sp_keyring::AccountKeyring::from_public(&self.from) .expect("Creates keyring from public key.") .sign(&self.encode()); Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: true } } } /// Extrinsic for test-runtime. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum Extrinsic { AuthoritiesChange(Vec), Transfer { transfer: Transfer, signature: AccountSignature, exhaust_resources_when_not_first: bool, }, IncludeData(Vec), StorageChange(Vec, Option>), OffchainIndexSet(Vec, Vec), OffchainIndexClear(Vec), Store(Vec), EnqueueTxs(u64), } #[cfg(feature = "std")] impl serde::Serialize for Extrinsic { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer, { self.using_encoded(|bytes| seq.serialize_bytes(bytes)) } } // rustc can't deduce this trait bound https://github.com/rust-lang/rust/issues/48214 #[cfg(feature = "std")] impl<'a> serde::Deserialize<'a> for Extrinsic { fn deserialize(de: D) -> Result where D: serde::Deserializer<'a>, { let r = sp_core::bytes::deserialize(de)?; Decode::decode(&mut &r[..]) .map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e))) } } impl BlindCheckable for Extrinsic { type Checked = Self; fn check(self) -> Result { match self { Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first } => if sp_runtime::verify_encoded_lazy(&signature, &transfer, &transfer.from) { Ok(Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first, }) } else { Err(InvalidTransaction::BadProof.into()) }, Extrinsic::IncludeData(v) => Ok(Extrinsic::IncludeData(v)), Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), Extrinsic::OffchainIndexSet(key, value) => Ok(Extrinsic::OffchainIndexSet(key, value)), Extrinsic::OffchainIndexClear(key) => Ok(Extrinsic::OffchainIndexClear(key)), Extrinsic::Store(data) => Ok(Extrinsic::Store(data)), Extrinsic::EnqueueTxs(data) => Ok(Extrinsic::EnqueueTxs(data)), } } } impl ExtrinsicT for Extrinsic { type Call = Extrinsic; type SignaturePayload = (); fn is_signed(&self) -> Option { if let Extrinsic::IncludeData(_) = *self { Some(false) } else { Some(true) } } fn new(call: Self::Call, _signature_payload: Option) -> Option { Some(call) } } impl sp_runtime::traits::Dispatchable for Extrinsic { type RuntimeOrigin = RuntimeOrigin; type Config = (); type Info = (); type PostInfo = (); fn dispatch( self, _origin: Self::RuntimeOrigin, ) -> sp_runtime::DispatchResultWithInfo { panic!("This implementation should not be used for actual dispatch."); } } impl Extrinsic { /// Convert `&self` into `&Transfer`. /// /// Panics if this is no `Transfer` extrinsic. pub fn transfer(&self) -> &Transfer { self.try_transfer().expect("cannot convert to transfer ref") } /// Try to convert `&self` into `&Transfer`. /// /// Returns `None` if this is no `Transfer` extrinsic. pub fn try_transfer(&self) -> Option<&Transfer> { match self { Extrinsic::Transfer { ref transfer, .. } => Some(transfer), _ => None, } } } /// The signature type used by accounts/transactions. pub type AccountSignature = sr25519::Signature; /// An identifier for an account on this system. pub type AccountId = ::Signer; /// A simple hash type for all our hashing. pub type Hash = H256; /// The hashing algorithm used. pub type Hashing = BlakeTwo256; /// The block number type used in this runtime. pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. pub type DigestItem = sp_runtime::generic::DigestItem; /// The digest of a block. pub type Digest = sp_runtime::generic::Digest; /// A test block. pub type Block = sp_runtime::generic::Block; /// A test block's header. pub type Header = sp_runtime::generic::HeaderVer; /// Run whatever tests we have. pub fn run_tests(mut input: &[u8]) -> Vec { use sp_runtime::print; print("run_tests..."); let block = Block::decode(&mut input).unwrap(); print("deserialized block."); let stxs = block.extrinsics.iter().map(Encode::encode); print("reserialized transactions."); [stxs.count() as u8].encode() } /// A type that can not be decoded. #[derive(PartialEq)] pub struct DecodeFails { _phantom: PhantomData, } impl Encode for DecodeFails { fn encode(&self) -> Vec { Vec::new() } } impl codec::EncodeLike for DecodeFails {} impl Default for DecodeFails { /// Create a default instance. fn default() -> DecodeFails { DecodeFails { _phantom: Default::default() } } } impl Decode for DecodeFails { fn decode(_: &mut I) -> Result { Err("DecodeFails always fails".into()) } } cfg_if! { if #[cfg(feature = "std")] { decl_runtime_apis! { #[api_version(2)] pub trait TestAPI { /// Return the balance of the given account id. fn balance_of(id: AccountId) -> u64; /// A benchmark function that adds one to the given value and returns the result. fn benchmark_add_one(val: &u64) -> u64; /// A benchmark function that adds one to each value in the given vector and returns the /// result. fn benchmark_vector_add_one(vec: &Vec) -> Vec; /// A function that always fails to convert a parameter between runtime and node. fn fail_convert_parameter(param: DecodeFails); /// A function that always fails to convert its return value between runtime and node. fn fail_convert_return_value() -> DecodeFails; /// A function for that the signature changed in version `2`. #[changed_in(2)] fn function_signature_changed() -> Vec; /// The new signature. fn function_signature_changed() -> u64; fn fail_on_native() -> u64; fn fail_on_wasm() -> u64; /// trie no_std testing fn use_trie() -> u64; fn benchmark_indirect_call() -> u64; fn benchmark_direct_call() -> u64; fn vec_with_capacity(size: u32) -> Vec; /// Returns the initialized block number. fn get_block_number() -> u64; /// Takes and returns the initialized block number. fn take_block_number() -> Option; /// Test that `ed25519` crypto works in the runtime. /// /// Returns the signature generated for the message `ed25519` and the public key. fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic); /// Test that `sr25519` crypto works in the runtime. /// /// Returns the signature generated for the message `sr25519`. fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); /// Test that `ecdsa` crypto works in the runtime. /// /// Returns the signature generated for the message `ecdsa`. fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic); /// Run various tests against storage. fn test_storage(); /// Check a witness. fn test_witness(proof: StorageProof, root: crate::Hash); /// Test that ensures that we can call a function that takes multiple /// arguments. fn test_multiple_arguments(data: Vec, other: Vec, num: u32); /// Traces log "Hey I'm runtime." fn do_trace_log(); /// Verify the given signature, public & message bundle. fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec) -> bool; } } } else { decl_runtime_apis! { pub trait TestAPI { /// Return the balance of the given account id. fn balance_of(id: AccountId) -> u64; /// A benchmark function that adds one to the given value and returns the result. fn benchmark_add_one(val: &u64) -> u64; /// A benchmark function that adds one to each value in the given vector and returns the /// result. fn benchmark_vector_add_one(vec: &Vec) -> Vec; /// A function that always fails to convert a parameter between runtime and node. fn fail_convert_parameter(param: DecodeFails); /// A function that always fails to convert its return value between runtime and node. fn fail_convert_return_value() -> DecodeFails; /// In wasm we just emulate the old behavior. fn function_signature_changed() -> Vec; fn fail_on_native() -> u64; fn fail_on_wasm() -> u64; /// trie no_std testing fn use_trie() -> u64; fn benchmark_indirect_call() -> u64; fn benchmark_direct_call() -> u64; fn vec_with_capacity(size: u32) -> Vec; /// Returns the initialized block number. fn get_block_number() -> u64; /// Takes and returns the initialized block number. fn take_block_number() -> Option; /// Test that `ed25519` crypto works in the runtime. /// /// Returns the signature generated for the message `ed25519` and the public key. fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic); /// Test that `sr25519` crypto works in the runtime. /// /// Returns the signature generated for the message `sr25519`. fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); /// Test that `ecdsa` crypto works in the runtime. /// /// Returns the signature generated for the message `ecdsa`. fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic); /// Run various tests against storage. fn test_storage(); /// Check a witness. fn test_witness(proof: StorageProof, root: crate::Hash); /// Test that ensures that we can call a function that takes multiple /// arguments. fn test_multiple_arguments(data: Vec, other: Vec, num: u32); /// Traces log "Hey I'm runtime." fn do_trace_log(); /// Verify the given signature, public & message bundle. fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec) -> bool; } } } } #[derive(Clone, Eq, PartialEq, TypeInfo)] pub struct Runtime; impl GetNodeBlockType for Runtime { type NodeBlock = Block; } impl GetRuntimeBlockType for Runtime { type RuntimeBlock = Block; } #[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct RuntimeOrigin; impl From::AccountId>> for RuntimeOrigin { fn from(_: RawOrigin<::AccountId>) -> Self { unimplemented!("Not required in tests!") } } impl CallerTrait<::AccountId> for RuntimeOrigin { fn into_system(self) -> Option::AccountId>> { unimplemented!("Not required in tests!") } fn as_system_ref(&self) -> Option<&RawOrigin<::AccountId>> { unimplemented!("Not required in tests!") } } impl From for Result, RuntimeOrigin> { fn from(_origin: RuntimeOrigin) -> Result, RuntimeOrigin> { unimplemented!("Not required in tests!") } } impl frame_support::traits::OriginTrait for RuntimeOrigin { type Call = ::RuntimeCall; type PalletsOrigin = RuntimeOrigin; type AccountId = ::AccountId; fn add_filter(&mut self, _filter: impl Fn(&Self::Call) -> bool + 'static) { unimplemented!("Not required in tests!") } fn reset_filter(&mut self) { unimplemented!("Not required in tests!") } fn set_caller_from(&mut self, _other: impl Into) { unimplemented!("Not required in tests!") } fn filter_call(&self, _call: &Self::Call) -> bool { unimplemented!("Not required in tests!") } fn caller(&self) -> &Self::PalletsOrigin { unimplemented!("Not required in tests!") } fn into_caller(self) -> Self::PalletsOrigin { unimplemented!("Not required in tests!") } fn try_with_caller( self, _f: impl FnOnce(Self::PalletsOrigin) -> Result, ) -> Result { unimplemented!("Not required in tests!") } fn none() -> Self { unimplemented!("Not required in tests!") } fn root() -> Self { unimplemented!("Not required in tests!") } fn signed(_by: Self::AccountId) -> Self { unimplemented!("Not required in tests!") } fn as_signed(self) -> Option { unimplemented!("Not required in tests!") } fn as_system_ref(&self) -> Option<&RawOrigin> { unimplemented!("Not required in tests!") } } #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct RuntimeEvent; impl From> for RuntimeEvent { fn from(_evt: frame_system::Event) -> Self { unimplemented!("Not required in tests!") } } impl frame_support::traits::PalletInfo for Runtime { fn index() -> Option { let type_id = sp_std::any::TypeId::of::

(); if type_id == sp_std::any::TypeId::of::>() { return Some(0) } if type_id == sp_std::any::TypeId::of::>() { return Some(1) } if type_id == sp_std::any::TypeId::of::>() { return Some(2) } None } fn name() -> Option<&'static str> { let type_id = sp_std::any::TypeId::of::

(); if type_id == sp_std::any::TypeId::of::>() { return Some("System") } if type_id == sp_std::any::TypeId::of::>() { return Some("Timestamp") } if type_id == sp_std::any::TypeId::of::>() { return Some("Babe") } None } fn module_name() -> Option<&'static str> { let type_id = sp_std::any::TypeId::of::

(); if type_id == sp_std::any::TypeId::of::>() { return Some("system") } if type_id == sp_std::any::TypeId::of::>() { return Some("pallet_timestamp") } if type_id == sp_std::any::TypeId::of::>() { return Some("pallet_babe") } None } fn crate_version() -> Option { use frame_support::traits::PalletInfoAccess as _; let type_id = sp_std::any::TypeId::of::

(); if type_id == sp_std::any::TypeId::of::>() { return Some(system::Pallet::::crate_version()) } if type_id == sp_std::any::TypeId::of::>() { return Some(pallet_timestamp::Pallet::::crate_version()) } if type_id == sp_std::any::TypeId::of::>() { return Some(pallet_babe::Pallet::::crate_version()) } None } } parameter_types! { pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 100, write: 1000, }; pub RuntimeBlockLength: BlockLength = BlockLength::max(4 * 1024 * 1024); pub RuntimeBlockWeights: BlockWeights = BlockWeights::with_sensible_defaults(Weight::from_ref_time(4 * 1024 * 1024), Perbill::from_percent(75)); } impl From> for Extrinsic { fn from(_: frame_system::Call) -> Self { unimplemented!("Not required in tests!") } } impl frame_system::pallet::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = Extrinsic; type Index = u64; type BlockNumber = u64; type Hash = H256; type Hashing = Hashing; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<2400>; type DbWeight = (); type Version = (); type PalletInfo = Self; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; } impl system::Config for Runtime {} impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = ConstU64<5>; type WeightInfo = (); } parameter_types! { pub const EpochDuration: u64 = 6; } impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ConstU64<10_000>; // there is no actual runtime in this test-runtime, so testing crates // are manually adding the digests. normally in this situation you'd use // pallet_babe::SameAuthoritiesForever. type EpochChangeTrigger = pallet_babe::ExternalTrigger; type DisabledValidators = (); type KeyOwnerProofSystem = (); type KeyOwnerProof = >::Proof; type KeyOwnerIdentification = >::IdentificationTuple; type HandleEquivocation = (); type WeightInfo = (); type MaxAuthorities = ConstU32<10>; } /// Adds one to the given input and returns the final result. #[inline(never)] fn benchmark_add_one(i: u64) -> u64 { i + 1 } /// The `benchmark_add_one` function as function pointer. #[cfg(not(feature = "std"))] static BENCHMARK_ADD_ONE: sp_runtime_interface::wasm::ExchangeableFunction u64> = sp_runtime_interface::wasm::ExchangeableFunction::new(benchmark_add_one); fn code_using_trie() -> u64 { let pairs = [ (b"0103000000000000000464".to_vec(), b"0400000000".to_vec()), (b"0103000000000000000469".to_vec(), b"0401000000".to_vec()), ] .to_vec(); let mut mdb = PrefixedMemoryDB::default(); let mut root = sp_std::default::Default::default(); { let mut t = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); for (key, value) in &pairs { if t.insert(key, value).is_err() { return 101 } } } let trie = TrieDBBuilder::::new(&mdb, &root).build(); let res = if let Ok(iter) = trie.iter() { iter.flatten().count() as u64 } else { 102 }; res } impl_opaque_keys! { pub struct SessionKeys { pub ed25519: ed25519::AppPublic, pub sr25519: sr25519::AppPublic, pub ecdsa: ecdsa::AppPublic, } } cfg_if! { if #[cfg(feature = "std")] { impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { version() } fn execute_block(block: Block) { system::execute_block(block); } fn initialize_block(header: &::Header) { system::initialize_block(header) } } impl ver_api::VerApi for Runtime { fn get_signer( _tx: ::Extrinsic, ) -> Option<(sp_runtime::AccountId32, u32)> { None } fn is_storage_migration_scheduled() -> bool{ false } fn store_seed(_seed: sp_core::H256){ } fn can_enqueue_txs() -> bool { true } fn create_enqueue_txs_inherent(txs: Vec<::Extrinsic>) -> ::Extrinsic{ //just return some garbage Extrinsic::EnqueueTxs(txs.len() as u64) } fn pop_txs(_count: u64) -> sp_application_crypto::Vec> { Default::default() } fn get_previous_block_txs() -> Vec>{Default::default()} fn start_prevalidation() {} } impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { unimplemented!() } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( _source: TransactionSource, utx: ::Extrinsic, _: ::Hash, ) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { return Ok(ValidTransaction { priority: data.len() as u64, requires: vec![], provides: vec![data], longevity: 1, propagate: false, }); } system::validate_transaction(utx) } } impl sp_block_builder::BlockBuilder for Runtime { fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { system::execute_transaction(extrinsic) } fn finalize_block() -> ::Header { system::finalize_block() } fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { vec![] } fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { CheckInherentsResult::new() } } impl self::TestAPI for Runtime { fn balance_of(id: AccountId) -> u64 { system::balance_of(id) } fn benchmark_add_one(val: &u64) -> u64 { val + 1 } fn benchmark_vector_add_one(vec: &Vec) -> Vec { let mut vec = vec.clone(); vec.iter_mut().for_each(|v| *v += 1); vec } fn fail_convert_parameter(_: DecodeFails) {} fn fail_convert_return_value() -> DecodeFails { DecodeFails::default() } fn function_signature_changed() -> u64 { 1 } fn fail_on_native() -> u64 { panic!("Failing because we are on native") } fn fail_on_wasm() -> u64 { 1 } fn use_trie() -> u64 { code_using_trie() } fn benchmark_indirect_call() -> u64 { let function = benchmark_add_one; (0..1000).fold(0, |p, i| p + function(i)) } fn benchmark_direct_call() -> u64 { (0..1000).fold(0, |p, i| p + benchmark_add_one(i)) } fn vec_with_capacity(_size: u32) -> Vec { unimplemented!("is not expected to be invoked from non-wasm builds"); } fn get_block_number() -> u64 { system::get_block_number().expect("Block number is initialized") } fn take_block_number() -> Option { system::take_block_number() } fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { test_ed25519_crypto() } fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { test_sr25519_crypto() } fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) { test_ecdsa_crypto() } fn test_storage() { test_read_storage(); test_read_child_storage(); } fn test_witness(proof: StorageProof, root: crate::Hash) { test_witness(proof, root); } fn test_multiple_arguments(data: Vec, other: Vec, num: u32) { assert_eq!(&data[..], &other[..]); assert_eq!(data.len(), num as usize); } fn do_trace_log() { log::trace!("Hey I'm runtime"); } fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec) -> bool { sp_io::crypto::ed25519_verify(&sig, &message, &public) } } impl sp_consensus_aura::AuraApi for Runtime { fn slot_duration() -> sp_consensus_aura::SlotDuration { sp_consensus_aura::SlotDuration::from_millis(1000) } fn authorities() -> Vec { system::authorities().into_iter().map(|a| { let authority: sr25519::Public = a.into(); AuraId::from(authority) }).collect() } } impl sp_consensus_babe::BabeApi for Runtime { fn configuration() -> sp_consensus_babe::BabeConfiguration { sp_consensus_babe::BabeConfiguration { slot_duration: 1000, epoch_length: EpochDuration::get(), c: (3, 10), authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, } } fn current_epoch_start() -> Slot { >::current_epoch_start() } fn current_epoch() -> sp_consensus_babe::Epoch { >::current_epoch() } fn next_epoch() -> sp_consensus_babe::Epoch { >::next_epoch() } fn submit_report_equivocation_unsigned_extrinsic( _equivocation_proof: sp_consensus_babe::EquivocationProof< ::Header, >, _key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( _slot: sp_consensus_babe::Slot, _authority_id: sp_consensus_babe::AuthorityId, ) -> Option { None } } impl sp_offchain::OffchainWorkerApi for Runtime { fn offchain_worker(header: &::Header) { let ex = Extrinsic::IncludeData(header.number.encode()); sp_io::offchain::submit_transaction(ex.encode()).unwrap(); } } impl sp_session::SessionKeys for Runtime { fn generate_session_keys(_: Option>) -> Vec { SessionKeys::generate(None) } fn decode_session_keys( encoded: Vec, ) -> Option, sp_core::crypto::KeyTypeId)>> { SessionKeys::decode_into_raw_public_keys(&encoded) } } impl sp_finality_grandpa::GrandpaApi for Runtime { fn grandpa_authorities() -> sp_finality_grandpa::AuthorityList { Vec::new() } fn current_set_id() -> sp_finality_grandpa::SetId { 0 } fn submit_report_equivocation_unsigned_extrinsic( _equivocation_proof: sp_finality_grandpa::EquivocationProof< ::Hash, NumberFor, >, _key_owner_proof: sp_finality_grandpa::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( _set_id: sp_finality_grandpa::SetId, _authority_id: sp_finality_grandpa::AuthorityId, ) -> Option { None } } impl sp_beefy::BeefyApi for Runtime { fn validator_set() -> Option> { None } } impl beefy_merkle_tree::BeefyMmrApi for Runtime { fn authority_set_proof() -> sp_beefy::mmr::BeefyAuthoritySet { Default::default() } fn next_authority_set_proof() -> sp_beefy::mmr::BeefyNextAuthoritySet { Default::default() } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(_account: AccountId) -> Index { 0 } } } } else { impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { version() } fn execute_block(block: Block) { system::execute_block(block); } fn initialize_block(header: &::Header) { system::initialize_block(header) } } impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { unimplemented!() } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( _source: TransactionSource, utx: ::Extrinsic, _: ::Hash, ) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { return Ok(ValidTransaction{ priority: data.len() as u64, requires: vec![], provides: vec![data], longevity: 1, propagate: false, }); } system::validate_transaction(utx) } } impl sp_block_builder::BlockBuilder for Runtime { fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { system::execute_transaction(extrinsic) } fn finalize_block() -> ::Header { system::finalize_block() } fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { vec![] } fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { CheckInherentsResult::new() } } impl self::TestAPI for Runtime { fn balance_of(id: AccountId) -> u64 { system::balance_of(id) } fn benchmark_add_one(val: &u64) -> u64 { val + 1 } fn benchmark_vector_add_one(vec: &Vec) -> Vec { let mut vec = vec.clone(); vec.iter_mut().for_each(|v| *v += 1); vec } fn fail_convert_parameter(_: DecodeFails) {} fn fail_convert_return_value() -> DecodeFails { DecodeFails::default() } fn function_signature_changed() -> Vec { let mut vec = Vec::new(); vec.push(1); vec.push(2); vec } fn fail_on_native() -> u64 { 1 } fn fail_on_wasm() -> u64 { panic!("Failing because we are on wasm") } fn use_trie() -> u64 { code_using_trie() } fn benchmark_indirect_call() -> u64 { (0..10000).fold(0, |p, i| p + BENCHMARK_ADD_ONE.get()(i)) } fn benchmark_direct_call() -> u64 { (0..10000).fold(0, |p, i| p + benchmark_add_one(i)) } fn vec_with_capacity(size: u32) -> Vec { Vec::with_capacity(size as usize) } fn get_block_number() -> u64 { system::get_block_number().expect("Block number is initialized") } fn take_block_number() -> Option { system::take_block_number() } fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { test_ed25519_crypto() } fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { test_sr25519_crypto() } fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) { test_ecdsa_crypto() } fn test_storage() { test_read_storage(); test_read_child_storage(); } fn test_witness(proof: StorageProof, root: crate::Hash) { test_witness(proof, root); } fn test_multiple_arguments(data: Vec, other: Vec, num: u32) { assert_eq!(&data[..], &other[..]); assert_eq!(data.len(), num as usize); } fn do_trace_log() { log::trace!("Hey I'm runtime: {}", log::STATIC_MAX_LEVEL); } fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec) -> bool { sp_io::crypto::ed25519_verify(&sig, &message, &public) } } impl sp_consensus_aura::AuraApi for Runtime { fn slot_duration() -> sp_consensus_aura::SlotDuration { sp_consensus_aura::SlotDuration::from_millis(1000) } fn authorities() -> Vec { system::authorities().into_iter().map(|a| { let authority: sr25519::Public = a.into(); AuraId::from(authority) }).collect() } } impl sp_consensus_babe::BabeApi for Runtime { fn configuration() -> sp_consensus_babe::BabeConfiguration { sp_consensus_babe::BabeConfiguration { slot_duration: 1000, epoch_length: EpochDuration::get(), c: (3, 10), authorities: system::authorities() .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots, } } fn current_epoch_start() -> Slot { >::current_epoch_start() } fn current_epoch() -> sp_consensus_babe::Epoch { >::current_epoch() } fn next_epoch() -> sp_consensus_babe::Epoch { >::next_epoch() } fn submit_report_equivocation_unsigned_extrinsic( _equivocation_proof: sp_consensus_babe::EquivocationProof< ::Header, >, _key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( _slot: sp_consensus_babe::Slot, _authority_id: sp_consensus_babe::AuthorityId, ) -> Option { None } } impl sp_offchain::OffchainWorkerApi for Runtime { fn offchain_worker(header: &::Header) { let ex = Extrinsic::IncludeData(header.number.encode()); sp_io::offchain::submit_transaction(ex.encode()).unwrap() } } impl sp_session::SessionKeys for Runtime { fn generate_session_keys(_: Option>) -> Vec { SessionKeys::generate(None) } fn decode_session_keys( encoded: Vec, ) -> Option, sp_core::crypto::KeyTypeId)>> { SessionKeys::decode_into_raw_public_keys(&encoded) } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { fn account_nonce(_account: AccountId) -> Index { 0 } } } } } fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { let public0 = ed25519::AppPublic::generate_pair(None); let public1 = ed25519::AppPublic::generate_pair(None); let public2 = ed25519::AppPublic::generate_pair(None); let all = ed25519::AppPublic::all(); assert!(all.contains(&public0)); assert!(all.contains(&public1)); assert!(all.contains(&public2)); let signature = public0.sign(&"ed25519").expect("Generates a valid `ed25519` signature."); assert!(public0.verify(&"ed25519", &signature)); (signature, public0) } fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { let public0 = sr25519::AppPublic::generate_pair(None); let public1 = sr25519::AppPublic::generate_pair(None); let public2 = sr25519::AppPublic::generate_pair(None); let all = sr25519::AppPublic::all(); assert!(all.contains(&public0)); assert!(all.contains(&public1)); assert!(all.contains(&public2)); let signature = public0.sign(&"sr25519").expect("Generates a valid `sr25519` signature."); assert!(public0.verify(&"sr25519", &signature)); (signature, public0) } fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) { let public0 = ecdsa::AppPublic::generate_pair(None); let public1 = ecdsa::AppPublic::generate_pair(None); let public2 = ecdsa::AppPublic::generate_pair(None); let all = ecdsa::AppPublic::all(); assert!(all.contains(&public0)); assert!(all.contains(&public1)); assert!(all.contains(&public2)); let signature = public0.sign(&"ecdsa").expect("Generates a valid `ecdsa` signature."); assert!(public0.verify(&"ecdsa", &signature)); (signature, public0) } fn test_read_storage() { const KEY: &[u8] = b":read_storage"; sp_io::storage::set(KEY, b"test"); let mut v = [0u8; 4]; let r = sp_io::storage::read(KEY, &mut v, 0); assert_eq!(r, Some(4)); assert_eq!(&v, b"test"); let mut v = [0u8; 4]; let r = sp_io::storage::read(KEY, &mut v, 4); assert_eq!(r, Some(0)); assert_eq!(&v, &[0, 0, 0, 0]); } fn test_read_child_storage() { const STORAGE_KEY: &[u8] = b"unique_id_1"; const KEY: &[u8] = b":read_child_storage"; sp_io::default_child_storage::set(STORAGE_KEY, KEY, b"test"); let mut v = [0u8; 4]; let r = sp_io::default_child_storage::read(STORAGE_KEY, KEY, &mut v, 0); assert_eq!(r, Some(4)); assert_eq!(&v, b"test"); let mut v = [0u8; 4]; let r = sp_io::default_child_storage::read(STORAGE_KEY, KEY, &mut v, 8); assert_eq!(r, Some(0)); assert_eq!(&v, &[0, 0, 0, 0]); } fn test_witness(proof: StorageProof, root: crate::Hash) { use sp_externalities::Externalities; let db: sp_trie::MemoryDB = proof.into_memory_db(); let backend = sp_state_machine::TrieBackendBuilder::<_, crate::Hashing>::new(db, root).build(); let mut overlay = sp_state_machine::OverlayedChanges::default(); let mut cache = sp_state_machine::StorageTransactionCache::<_, _>::default(); let mut ext = sp_state_machine::Ext::new( &mut overlay, &mut cache, &backend, #[cfg(feature = "std")] None, ); assert!(ext.storage(b"value3").is_some()); assert!(ext.storage_root(Default::default()).as_slice() == &root[..]); ext.place_storage(vec![0], Some(vec![1])); assert!(ext.storage_root(Default::default()).as_slice() != &root[..]); } #[cfg(test)] mod tests { use codec::Encode; use sc_block_builder::BlockBuilderProvider; use sp_api::ProvideRuntimeApi; use sp_consensus::BlockOrigin; use sp_core::storage::well_known_keys::HEAP_PAGES; use sp_runtime::generic::BlockId; use sp_state_machine::ExecutionStrategy; use substrate_test_runtime_client::{ prelude::*, runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder, }; #[test] fn heap_pages_is_respected() { // This tests that the on-chain HEAP_PAGES parameter is respected. // Create a client devoting only 8 pages of wasm memory. This gives us ~512k of heap memory. let mut client = TestClientBuilder::new() .set_execution_strategy(ExecutionStrategy::AlwaysWasm) .set_heap_pages(8) .build(); let block_id = BlockId::Hash(client.chain_info().best_hash); // Try to allocate 1024k of memory on heap. This is going to fail since it is twice larger // than the heap. let ret = client.runtime_api().vec_with_capacity(&block_id, 1048576); assert!(ret.is_err()); // Create a block that sets the `:heap_pages` to 32 pages of memory which corresponds to // ~2048k of heap memory. let (new_block_id, block) = { let mut builder = client.new_block(Default::default()).unwrap(); builder.push_storage_change(HEAP_PAGES.to_vec(), Some(32u64.encode())).unwrap(); let block = builder.build().unwrap().block; let hash = block.header.hash(); (BlockId::Hash(hash), block) }; futures::executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); let (new_block_id, block) = { let builder = client.new_block_at(&new_block_id, Default::default(), false).unwrap(); let block = builder.build().unwrap().block; let hash = block.header.hash(); (BlockId::Hash(hash), block) }; futures::executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); // Allocation of 1024k while having ~2048k should succeed. let ret = client.runtime_api().vec_with_capacity(&new_block_id, 1048576); assert!(ret.is_ok()); } #[test] fn test_storage() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); let block_id = BlockId::Hash(client.chain_info().best_hash); runtime_api.test_storage(&block_id).unwrap(); } fn witness_backend() -> (sp_trie::MemoryDB, crate::Hash) { use sp_trie::TrieMut; let mut root = crate::Hash::default(); let mut mdb = sp_trie::MemoryDB::::default(); { let mut trie = sp_trie::trie_types::TrieDBMutBuilderV1::new(&mut mdb, &mut root).build(); trie.insert(b"value3", &[142]).expect("insert failed"); trie.insert(b"value4", &[124]).expect("insert failed"); }; (mdb, root) } #[test] fn witness_backend_works() { let (db, root) = witness_backend(); let backend = sp_state_machine::TrieBackendBuilder::<_, crate::Hashing>::new(db, root).build(); let proof = sp_state_machine::prove_read(backend, vec![b"value3"]).unwrap(); let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); let block_id = BlockId::Hash(client.chain_info().best_hash); runtime_api.test_witness(&block_id, proof, root).unwrap(); } }