Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bin/node/executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pallet-transaction-payment = { version = "2.0.0-alpha.2", path = "../../../frame
pallet-treasury = { version = "2.0.0-alpha.2", path = "../../../frame/treasury" }
sp-application-crypto = { version = "2.0.0-alpha.2", path = "../../../primitives/application-crypto" }
sp-runtime = { version = "2.0.0-alpha.2", path = "../../../primitives/runtime" }
sp-externalities = { version = "0.8.0-alpha.3", path = "../../../primitives/externalities" }
substrate-test-client = { version = "2.0.0-dev", path = "../../../test-utils/client" }
wabt = "0.9.2"

Expand Down
21 changes: 18 additions & 3 deletions bin/node/executor/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use node_runtime::constants::currency::*;
use node_testing::keyring::*;
use sp_core::{NativeOrEncoded, NeverNativeValue};
use sp_core::storage::well_known_keys;
use sp_core::traits::CodeExecutor;
use frame_support::Hashable;
use sp_core::traits::{CodeExecutor, RuntimeCode};
use frame_support::Hashable;
use sp_state_machine::TestExternalities as CoreTestExternalities;
use sc_executor::{NativeExecutor, RuntimeInfo, WasmExecutionMethod, Externalities};
use sp_runtime::traits::BlakeTwo256;
Expand Down Expand Up @@ -90,9 +90,16 @@ fn construct_block<E: Externalities>(
digest: Default::default(),
};

let runtime_code = RuntimeCode {
code_fetcher: &sp_core::traits::WrappedRuntimeCode(COMPACT_CODE.into()),
hash: vec![1, 2, 3],
heap_pages: None,
};

// execute the block to get the real header.
executor.call::<NeverNativeValue, fn() -> _>(
ext,
&runtime_code,
"Core_initialize_block",
&header.encode(),
true,
Expand All @@ -102,6 +109,7 @@ fn construct_block<E: Externalities>(
for i in extrinsics.iter() {
executor.call::<NeverNativeValue, fn() -> _>(
ext,
&runtime_code,
"BlockBuilder_apply_extrinsic",
&i.encode(),
true,
Expand All @@ -111,6 +119,7 @@ fn construct_block<E: Externalities>(

let header = match executor.call::<NeverNativeValue, fn() -> _>(
ext,
&runtime_code,
"BlockBuilder_finalize_block",
&[0u8;0],
true,
Expand Down Expand Up @@ -162,11 +171,16 @@ fn bench_execute_block(c: &mut Criterion) {
ExecutionMethod::Wasm(wasm_method) => (false, *wasm_method),
};
let executor = NativeExecutor::new(wasm_method, None);
let runtime_code = RuntimeCode {
code_fetcher: &sp_core::traits::WrappedRuntimeCode(COMPACT_CODE.into()),
hash: vec![1, 2, 3],
heap_pages: None,
};

// Get the runtime version to initialize the runtimes cache.
{
let mut test_ext = new_test_ext(&genesis_config);
executor.runtime_version(&mut test_ext.ext()).unwrap();
executor.runtime_version(&mut test_ext.ext(), &runtime_code).unwrap();
}

let blocks = test_blocks(&genesis_config, &executor);
Expand All @@ -177,6 +191,7 @@ fn bench_execute_block(c: &mut Criterion) {
for block in blocks.iter() {
executor.call::<NeverNativeValue, fn() -> _>(
&mut test_ext.ext(),
&runtime_code,
"Core_execute_block",
&block.0,
use_native,
Expand Down
13 changes: 12 additions & 1 deletion bin/node/executor/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use codec::{Encode, Decode};
use frame_support::Hashable;
use sp_state_machine::TestExternalities as CoreTestExternalities;
use sp_core::{NeverNativeValue, NativeOrEncoded, traits::CodeExecutor};
use sp_core::{NeverNativeValue, NativeOrEncoded, traits::{CodeExecutor, RuntimeCode}};
use sp_runtime::{ApplyExtrinsicResult, traits::{Header as HeaderT, BlakeTwo256}};
use sc_executor::{NativeExecutor, WasmExecutionMethod};
use sc_executor::error::Result;
Expand All @@ -29,6 +29,7 @@ use node_runtime::{
};
use node_primitives::{Hash, BlockNumber};
use node_testing::keyring::*;
use sp_externalities::Externalities;

/// The wasm runtime code.
///
Expand Down Expand Up @@ -71,8 +72,18 @@ pub fn executor_call<
native_call: Option<NC>,
) -> (Result<NativeOrEncoded<R>>, 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::<R, NC>(
&mut t,
&runtime_code,
method,
data,
use_native,
Expand Down
1 change: 0 additions & 1 deletion client/basic-authorship/src/basic_authorship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,4 +471,3 @@ mod tests {
client.import(BlockOrigin::Own, block).unwrap();
}
}

4 changes: 4 additions & 0 deletions client/block-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ sp-core = { version = "2.0.0-alpha.2", path = "../../primitives/core" }
sp-block-builder = { version = "2.0.0-alpha.2", path = "../../primitives/block-builder" }
sc-client-api = { version = "2.0.0-alpha.2", path = "../api" }
codec = { package = "parity-scale-codec", version = "1.2.0", features = ["derive"] }

[dev-dependencies]
substrate-test-runtime-client = { path = "../../test-utils/runtime/client" }
sp-trie = { version = "2.0.0-alpha.2", path = "../../primitives/trie" }
38 changes: 38 additions & 0 deletions client/block-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,41 @@ where
})
}
}

#[cfg(test)]
mod tests {
use super::*;
use sp_blockchain::HeaderBackend;
use sp_core::Blake2Hasher;
use sp_state_machine::Backend;
use substrate_test_runtime_client::{DefaultTestClientBuilderExt, TestClientBuilderExt};

#[test]
fn block_building_storage_proof_does_not_include_runtime_by_default() {
let builder = substrate_test_runtime_client::TestClientBuilder::new();
let backend = builder.backend();
let client = builder.build();

let block = BlockBuilder::new(
&client,
client.info().best_hash,
client.info().best_number,
RecordProof::Yes,
Default::default(),
&*backend,
).unwrap().build().unwrap();

let proof = block.proof.expect("Proof is build on request");

let backend = sp_state_machine::create_proof_check_backend::<Blake2Hasher>(
block.storage_changes.transaction_storage_root,
proof,
).unwrap();

assert!(
backend.storage(&sp_core::storage::well_known_keys::CODE)
.unwrap_err()
.contains("Database missing expected key"),
);
}
}
2 changes: 2 additions & 0 deletions client/executor/src/integration_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fn call_in_wasm<E: Externalities>(
);
executor.call_in_wasm(
&WASM_BINARY[..],
None,
function,
call_data,
ext,
Expand Down Expand Up @@ -513,6 +514,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) {
);
executor.call_in_wasm(
&WASM_BINARY[..],
None,
"test_exhaust_heap",
&[0],
&mut ext.ext(),
Expand Down
9 changes: 7 additions & 2 deletions client/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ pub trait RuntimeInfo {
/// Native runtime information.
fn native_version(&self) -> &NativeVersion;

/// Extract RuntimeVersion of given :code block
fn runtime_version(&self, ext: &mut dyn Externalities) -> error::Result<RuntimeVersion>;
/// Extract [`RuntimeVersion`](sp_version::RuntimeVersion) of the given `runtime_code`.
fn runtime_version(
&self,
ext: &mut dyn Externalities,
runtime_code: &sp_core::traits::RuntimeCode,
) -> error::Result<RuntimeVersion>;
}

#[cfg(test)]
Expand All @@ -77,6 +81,7 @@ mod tests {
);
let res = executor.call_in_wasm(
&WASM_BINARY[..],
None,
"test_empty_return",
&[],
&mut ext,
Expand Down
60 changes: 48 additions & 12 deletions client/executor/src/native_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

use crate::{
RuntimeInfo, error::{Error, Result},
wasm_runtime::{RuntimeCache, WasmExecutionMethod, CodeSource},
wasm_runtime::{RuntimeCache, WasmExecutionMethod},
};
use sp_version::{NativeVersion, RuntimeVersion};
use codec::{Decode, Encode};
use sp_core::{NativeOrEncoded, traits::{CodeExecutor, Externalities}};
use sp_core::{NativeOrEncoded, traits::{CodeExecutor, Externalities, RuntimeCode}};
use log::trace;
use std::{result, panic::{UnwindSafe, AssertUnwindSafe}, sync::Arc};
use sp_wasm_interface::{HostFunctions, Function};
Expand Down Expand Up @@ -111,7 +111,7 @@ impl WasmExecutor {
}
}

/// Execute the given closure `f` with the latest runtime (based on the `CODE` key in `ext`).
/// Execute the given closure `f` with the latest runtime (based on `runtime_code`).
///
/// The closure `f` is expected to return `Err(_)` when there happened a `panic!` in native code
/// while executing the runtime in Wasm. If a `panic!` occurred, the runtime is invalidated to
Expand All @@ -124,9 +124,9 @@ impl WasmExecutor {
/// runtime is invalidated on any `panic!` to prevent a poisoned state. `ext` is already
/// implicitly handled as unwind safe, as we store it in a global variable while executing the
/// native runtime.
fn with_instance<'c, R, F>(
fn with_instance<R, F>(
&self,
code: CodeSource<'c>,
runtime_code: &RuntimeCode,
ext: &mut dyn Externalities,
f: F,
) -> Result<R>
Expand All @@ -137,7 +137,7 @@ impl WasmExecutor {
) -> Result<Result<R>>,
{
match self.cache.with_instance(
code,
runtime_code,
ext,
self.method,
self.default_heap_pages,
Expand All @@ -158,17 +158,48 @@ impl WasmExecutor {
impl sp_core::traits::CallInWasm for WasmExecutor {
fn call_in_wasm(
&self,
wasm_blob: &[u8],
wasm_code: &[u8],
code_hash: Option<Vec<u8>>,
method: &str,
call_data: &[u8],
ext: &mut dyn Externalities,
) -> std::result::Result<Vec<u8>, String> {
self.with_instance(CodeSource::Custom(wasm_blob), ext, |instance, _, mut ext| {
if let Some(hash) = code_hash {
let code = RuntimeCode {
code_fetcher: &sp_core::traits::WrappedRuntimeCode(wasm_code.into()),
hash,
heap_pages: None,
};

self.with_instance(&code, ext, |instance, _, mut ext| {
with_externalities_safe(
&mut **ext,
move || instance.call(method, call_data),
)
}).map_err(|e| e.to_string())
} else {
let module = crate::wasm_runtime::create_wasm_runtime_with_code(
self.method,
self.default_heap_pages,
&wasm_code,
self.host_functions.to_vec(),
self.allow_missing_func_imports,
)
.map_err(|e| format!("Failed to create module: {:?}", e))?;

let instance = module.new_instance()
.map_err(|e| format!("Failed to create instance: {:?}", e))?;

let instance = AssertUnwindSafe(instance);
let mut ext = AssertUnwindSafe(ext);

with_externalities_safe(
&mut **ext,
move || instance.call(method, call_data),
)
}).map_err(|e| e.to_string())
.and_then(|r| r)
.map_err(|e| e.to_string())
}
}
}

Expand Down Expand Up @@ -220,8 +251,11 @@ impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
fn runtime_version(
&self,
ext: &mut dyn Externalities,
runtime_code: &RuntimeCode,
) -> Result<RuntimeVersion> {
self.wasm.with_instance(CodeSource::Externalities, ext,
self.wasm.with_instance(
runtime_code,
ext,
|_instance, version, _ext|
Ok(version.cloned().ok_or_else(|| Error::ApiError("Unknown version".into())))
)
Expand All @@ -237,14 +271,15 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
>(
&self,
ext: &mut dyn Externalities,
runtime_code: &RuntimeCode,
method: &str,
data: &[u8],
use_native: bool,
native_call: Option<NC>,
) -> (Result<NativeOrEncoded<R>>, bool) {
let mut used_native = false;
let result = self.wasm.with_instance(
CodeSource::Externalities,
runtime_code,
ext,
|instance, onchain_version, mut ext| {
let onchain_version = onchain_version.ok_or_else(
Expand Down Expand Up @@ -324,11 +359,12 @@ impl<D: NativeExecutionDispatch> sp_core::traits::CallInWasm for NativeExecutor<
fn call_in_wasm(
&self,
wasm_blob: &[u8],
code_hash: Option<Vec<u8>>,
method: &str,
call_data: &[u8],
ext: &mut dyn Externalities,
) -> std::result::Result<Vec<u8>, String> {
sp_core::traits::CallInWasm::call_in_wasm(&self.wasm, wasm_blob, method, call_data, ext)
self.wasm.call_in_wasm(wasm_blob, code_hash, method, call_data, ext)
}
}

Expand Down
Loading