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
4 changes: 4 additions & 0 deletions Cargo.lock

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

16 changes: 13 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::{Blake2Hasher, 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};

Expand Down Expand Up @@ -89,9 +89,12 @@ fn construct_block<E: Externalities>(
digest: Default::default(),
};

let runtime_code = RuntimeCode::from_externalities(ext).expect("`ext` provides `:code`");

// execute the block to get the real header.
executor.call::<_, NeverNativeValue, fn() -> _>(
ext,
&runtime_code,
"Core_initialize_block",
&header.encode(),
true,
Expand All @@ -101,6 +104,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 @@ -110,6 +114,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 @@ -165,17 +170,22 @@ fn bench_execute_block(c: &mut Criterion) {
// 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());
let runtime_code = RuntimeCode::from_externalities(&test_ext.ext())
.expect("`test_ext` provides `:code`");
executor.runtime_version(&mut test_ext.ext(), &runtime_code).unwrap();
}

let blocks = test_blocks(&genesis_config, &executor);

b.iter_batched_ref(
|| new_test_ext(&genesis_config),
|test_ext| {
let runtime_code = RuntimeCode::from_externalities(&test_ext.ext())
.expect("`test_ext` provides `:code`");
for block in blocks.iter() {
executor.call::<_, NeverNativeValue, fn() -> _>(
&mut test_ext.ext(),
&runtime_code,
"Core_execute_block",
&block.0,
use_native,
Expand Down
6 changes: 4 additions & 2 deletions bin/node/executor/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ use codec::{Encode, Decode};
use frame_support::Hashable;
use sp_state_machine::TestExternalities as CoreTestExternalities;
use sp_core::{
Blake2Hasher, NeverNativeValue, NativeOrEncoded,
traits::CodeExecutor,
Blake2Hasher, NeverNativeValue, NativeOrEncoded, traits::{CodeExecutor, RuntimeCode},
};
use sp_runtime::{ApplyExtrinsicResult, traits::Header as HeaderT};
use sc_executor::{NativeExecutor, WasmExecutionMethod};
Expand Down Expand Up @@ -74,8 +73,11 @@ pub fn executor_call<
native_call: Option<NC>,
) -> (Result<NativeOrEncoded<R>>, bool) {
let mut t = t.ext();
let runtime_code = RuntimeCode::from_externalities(&t)
.expect("Code should be part of the externalities");
executor().call::<_, R, NC>(
&mut t,
&runtime_code,
method,
data,
use_native,
Expand Down
3 changes: 2 additions & 1 deletion client/basic-authorship/src/basic_authorship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ impl<A, B, Block, C> ProposerInner<B, Block, C, A>
debug!("[{:?}] Pushed to the block.", pending_tx_hash);
}
Err(sp_blockchain::Error::ApplyExtrinsicFailed(sp_blockchain::ApplyExtrinsicFailed::Validity(e)))
if e.exhausted_resources() => {
if e.exhausted_resources() =>
{
if is_first {
debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending_tx_hash);
unqueue_invalid.push(pending_tx_hash);
Expand Down
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" }
54 changes: 50 additions & 4 deletions client/block-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,20 @@ where

/// Push onto the block's list of extrinsics.
///
/// This will treat incoming extrinsic `xt` as trusted and skip signature check (for signed transactions).
pub fn push_trusted(&mut self, xt: <Block as BlockT>::Extrinsic) -> Result<(), ApiErrorFor<A, Block>> {
/// This will treat incoming extrinsic `xt` as trusted and skip signature check
/// (for signed transactions).
pub fn push_trusted(
&mut self,
xt: <Block as BlockT>::Extrinsic,
) -> Result<(), ApiErrorFor<A, Block>> {
self.push_internal(xt, true)
}

fn push_internal(&mut self, xt: <Block as BlockT>::Extrinsic, skip_signature: bool) -> Result<(), ApiErrorFor<A, Block>> {
fn push_internal(
&mut self,
xt: <Block as BlockT>::Extrinsic,
skip_signature: bool,
) -> Result<(), ApiErrorFor<A, Block>> {
let block_id = &self.block_id;
let extrinsics = &mut self.extrinsics;

Expand All @@ -175,7 +183,7 @@ where
ExecutionContext::BlockConstruction,
xt.clone(),
)?
} else {
} else {
api.apply_extrinsic_with_context(
block_id,
ExecutionContext::BlockConstruction,
Expand Down Expand Up @@ -241,3 +249,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"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably just leave .unwrap_err() - comparing strings seems a bit fragile?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I wanted to match on the error, however it is a string already. The full error message is much longer, but this part is the important one (as long as no one changes the display impl for the error, it should be fine).

);
}
}
8 changes: 6 additions & 2 deletions client/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,12 @@ pub trait RuntimeInfo {
/// Native runtime information.
fn native_version(&self) -> &NativeVersion;

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

#[cfg(test)]
Expand Down
16 changes: 10 additions & 6 deletions client/executor/src/native_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
};
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, cell::RefCell, panic::{UnwindSafe, AssertUnwindSafe}, sync::Arc};
use sp_wasm_interface::{HostFunctions, Function};
Expand Down Expand Up @@ -130,6 +130,7 @@ impl<D: NativeExecutionDispatch> NativeExecutor<D> {
fn with_runtime<E, R>(
&self,
ext: &mut E,
runtime_code: &RuntimeCode,
f: impl for<'a> FnOnce(
AssertUnwindSafe<&'a mut (dyn WasmRuntime + 'static)>,
&'a RuntimeVersion,
Expand All @@ -138,8 +139,9 @@ impl<D: NativeExecutionDispatch> NativeExecutor<D> {
) -> Result<R> where E: Externalities {
RUNTIMES_CACHE.with(|cache| {
let mut cache = cache.borrow_mut();
let (runtime, version, code_hash) = cache.fetch_runtime(
let (runtime, version) = cache.fetch_runtime(
ext,
runtime_code,
self.fallback_method,
self.default_heap_pages,
&*self.host_functions,
Expand All @@ -151,7 +153,7 @@ impl<D: NativeExecutionDispatch> NativeExecutor<D> {
match f(runtime, version, ext) {
Ok(res) => res,
Err(e) => {
cache.invalidate_runtime(self.fallback_method, code_hash);
cache.invalidate_runtime(self.fallback_method, runtime_code.hash.clone());
Err(e)
}
}
Expand Down Expand Up @@ -179,8 +181,9 @@ impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
fn runtime_version<E: Externalities>(
&self,
ext: &mut E,
runtime_code: &RuntimeCode,
) -> Result<RuntimeVersion> {
self.with_runtime(ext, |_runtime, version, _ext| Ok(Ok(version.clone())))
self.with_runtime(ext, runtime_code, |_runtime, version, _ext| Ok(Ok(version.clone())))
}
}

Expand All @@ -195,13 +198,14 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
>(
&self,
ext: &mut E,
runtime_code: &RuntimeCode,
method: &str,
data: &[u8],
use_native: bool,
native_call: Option<NC>,
) -> (Result<NativeOrEncoded<R>>, bool){
) -> (Result<NativeOrEncoded<R>>, bool) {
let mut used_native = false;
let result = self.with_runtime(ext, |mut runtime, onchain_version, mut ext| {
let result = self.with_runtime(ext, runtime_code, |mut runtime, onchain_version, mut ext| {
match (
use_native,
onchain_version.can_call_with(&self.native_version.runtime_version),
Expand Down
41 changes: 21 additions & 20 deletions client/executor/src/wasm_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use crate::error::{Error, WasmError};
use log::{trace, warn};
use codec::Decode;
use sp_core::{storage::well_known_keys, traits::Externalities};
use sp_core::traits::{Externalities, RuntimeCode};
use sp_version::RuntimeVersion;
use std::{collections::hash_map::{Entry, HashMap}, panic::AssertUnwindSafe};
use sc_executor_common::wasm_runtime::WasmRuntime;
Expand Down Expand Up @@ -86,17 +86,18 @@ impl RuntimesCache {
///
/// # Parameters
///
/// `ext` - Externalities to use for the runtime. This is used for setting
/// up an initial runtime instance.
/// `ext` - Externalities to use for the getting the runtime's version call.
///
/// `runtime_code` - The runtime wasm code used setup the runtime.
///
/// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution.
///
/// `host_functions` - The host functions that should be registered for the Wasm runtime.
///
/// # Return value
///
/// If no error occurred a tuple `(&mut WasmRuntime, H256)` is
/// returned. `H256` is the hash of the runtime code.
/// If no error occurred a tuple `(&mut WasmRuntime, RuntimeVerion)` is
/// returned.
///
/// In case of failure one of two errors can be returned:
///
Expand All @@ -107,20 +108,14 @@ impl RuntimesCache {
pub fn fetch_runtime<E: Externalities>(
&mut self,
ext: &mut E,
runtime_code: &RuntimeCode,
wasm_method: WasmExecutionMethod,
default_heap_pages: u64,
host_functions: &[&'static dyn Function],
) -> Result<(&mut (dyn WasmRuntime + 'static), &RuntimeVersion, Vec<u8>), Error> {
let code_hash = ext
.original_storage_hash(well_known_keys::CODE)
.ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?;

let heap_pages = ext
.storage(well_known_keys::HEAP_PAGES)
.and_then(|pages| u64::decode(&mut &pages[..]).ok())
.unwrap_or(default_heap_pages);
) -> Result<(&mut (dyn WasmRuntime + 'static), &RuntimeVersion), Error> {
let heap_pages = runtime_code.heap_pages.unwrap_or(default_heap_pages);

let result = match self.instances.entry((wasm_method, code_hash.clone())) {
let result = match self.instances.entry((wasm_method, runtime_code.hash.clone())) {
Entry::Occupied(o) => {
let result = o.into_mut();
if let Ok(ref mut cached_runtime) = result {
Expand All @@ -142,6 +137,7 @@ impl RuntimesCache {
*result = create_versioned_wasm_runtime(
ext,
wasm_method,
runtime_code,
heap_pages,
host_functions.into(),
);
Expand All @@ -157,6 +153,7 @@ impl RuntimesCache {
let result = create_versioned_wasm_runtime(
ext,
wasm_method,
runtime_code,
heap_pages,
host_functions.into(),
);
Expand All @@ -168,7 +165,7 @@ impl RuntimesCache {
};

result.as_mut()
.map(|entry| (entry.runtime.as_mut(), &entry.version, code_hash))
.map(|entry| (entry.runtime.as_mut(), &entry.version))
.map_err(|ref e| Error::InvalidCode(format!("{:?}", e)))
}

Expand Down Expand Up @@ -209,13 +206,17 @@ pub fn create_wasm_runtime_with_code(
fn create_versioned_wasm_runtime<E: Externalities>(
ext: &mut E,
wasm_method: WasmExecutionMethod,
runtime_code: &RuntimeCode,
heap_pages: u64,
host_functions: Vec<&'static dyn Function>,
) -> Result<VersionedRuntime, WasmError> {
let code = ext
.original_storage(well_known_keys::CODE)
.ok_or(WasmError::CodeNotFound)?;
let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code, host_functions, false)?;
let mut runtime = create_wasm_runtime_with_code(
wasm_method,
heap_pages,
&runtime_code.code,
host_functions,
false,
)?;

// Call to determine runtime version.
let version_result = {
Expand Down
Loading