// Copyright 2018-2020 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 . use codec::{Encode, Decode}; use frame_system::offchain::AppCrypto; use frame_support::Hashable; use sp_state_machine::TestExternalities as CoreTestExternalities; use sp_core::{ NeverNativeValue, NativeOrEncoded, crypto::KeyTypeId, sr25519::Signature, traits::{CodeExecutor, RuntimeCode}, }; use sp_runtime::{ ApplyExtrinsicResult, MultiSigner, MultiSignature, traits::{Header as HeaderT, BlakeTwo256}, }; use sc_executor::{NativeExecutor, WasmExecutionMethod}; use sc_executor::error::Result; use node_executor::Executor; use node_runtime::{ Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Runtime, BuildStorage, constants::currency::*, }; use node_primitives::{Hash, BlockNumber}; use node_testing::keyring::*; use sp_externalities::Externalities; pub const TEST_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"test"); pub mod sr25519 { mod app_sr25519 { use sp_application_crypto::{app_crypto, sr25519}; use super::super::TEST_KEY_TYPE_ID; app_crypto!(sr25519, TEST_KEY_TYPE_ID); } pub type AuthorityId = app_sr25519::Public; } pub struct TestAuthorityId; impl AppCrypto for TestAuthorityId { type RuntimeAppPublic = sr25519::AuthorityId; type GenericSignature = Signature; type GenericPublic = sp_core::sr25519::Public; } /// The wasm runtime code. /// /// `compact` since it is after post-processing with wasm-gc which performs tree-shaking thus /// making the binary slimmer. There is a convention to use compact version of the runtime /// as canonical. This is why `native_executor_instance` also uses the compact version of the /// runtime. pub const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; pub const GENESIS_HASH: [u8; 32] = [69u8; 32]; pub const VERSION: u32 = node_runtime::VERSION.spec_version; pub type TestExternalities = CoreTestExternalities; pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) } pub fn default_transfer_call() -> pallet_balances::Call { pallet_balances::Call::transfer::(bob().into(), 69 * DOLLARS) } pub fn from_block_number(n: u32) -> Header { Header::new(n, Default::default(), Default::default(), [69; 32].into(), Default::default()) } pub fn executor() -> NativeExecutor { NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8) } pub fn executor_call< R:Decode + Encode + PartialEq, NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe >( t: &mut TestExternalities, method: &str, data: &[u8], use_native: bool, native_call: Option, ) -> (Result>, bool) { let mut t = t.ext(); let code = t.storage(sp_core::storage::well_known_keys::CODE).unwrap(); let heap_pages = t.storage(sp_core::storage::well_known_keys::HEAP_PAGES); let runtime_code = RuntimeCode { code_fetcher: &sp_core::traits::WrappedRuntimeCode(code.as_slice().into()), hash: sp_core::blake2_256(&code).to_vec(), heap_pages: heap_pages.and_then(|hp| Decode::decode(&mut &hp[..]).ok()), }; executor().call::( &mut t, &runtime_code, method, data, use_native, native_call, ) } pub fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { let mut ext = TestExternalities::new_with_code( code, node_testing::genesis::config(support_changes_trie, Some(code)).build_storage().unwrap(), ); ext.changes_trie_storage().insert(0, GENESIS_HASH.into(), Default::default()); ext } /// Construct a fake block. /// /// `extrinsics` must be a list of valid extrinsics, i.e. none of the extrinsics for example /// can report `ExhaustResources`. Otherwise, this function panics. pub fn construct_block( env: &mut TestExternalities, number: BlockNumber, parent_hash: Hash, extrinsics: Vec, ) -> (Vec, Hash) { use sp_trie::{TrieConfiguration, trie_types::Layout}; // sign extrinsics. let extrinsics = extrinsics.into_iter().map(sign).collect::>(); // calculate the header fields that we can. let extrinsics_root = Layout::::ordered_trie_root(extrinsics.iter().map(Encode::encode)) .to_fixed_bytes() .into(); let header = Header { parent_hash, number, extrinsics_root, state_root: Default::default(), digest: Default::default(), }; // execute the block to get the real header. executor_call:: _>( env, "Core_initialize_block", &header.encode(), true, None, ).0.unwrap(); for extrinsic in extrinsics.iter() { // Try to apply the `extrinsic`. It should be valid, in the sense that it passes // all pre-inclusion checks. let r = executor_call:: _>( env, "BlockBuilder_apply_extrinsic", &extrinsic.encode(), true, None, ).0.expect("application of an extrinsic failed").into_encoded(); match ApplyExtrinsicResult::decode(&mut &r[..]).expect("apply result deserialization failed") { Ok(_) => {}, Err(e) => panic!("Applying extrinsic failed: {:?}", e), } } let header = match executor_call:: _>( env, "BlockBuilder_finalize_block", &[0u8;0], true, None, ).0.unwrap() { NativeOrEncoded::Native(_) => unreachable!(), NativeOrEncoded::Encoded(h) => Header::decode(&mut &h[..]).unwrap(), }; let hash = header.blake2_256(); (Block { header, extrinsics }.encode(), hash.into()) }