Skip to content

Commit

Permalink
Merge pull request #2 from moonbeam-foundation/crystalin-runtime-wasm
Browse files Browse the repository at this point in the history
Fix allow_missing_func_imports
  • Loading branch information
crystalin authored and ahmadkaouk committed Dec 11, 2023
1 parent b8edfca commit e15a1f9
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

14 changes: 8 additions & 6 deletions substrate/client/chain-spec/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@

//! Tool for creating the genesis block.

use std::{collections::hash_map::DefaultHasher, marker::PhantomData, sync::Arc};
use std::{marker::PhantomData, sync::Arc};

use sc_client_api::{backend::Backend, BlockImportOperation};
use sc_executor::RuntimeVersionOf;
use sp_core::storage::{well_known_keys, StateVersion, Storage};
use sp_core::{
storage::{well_known_keys, StateVersion, Storage},
Blake2Hasher,
};

use sp_runtime::{
traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero},
BuildStorage,
Expand All @@ -44,10 +48,8 @@ where
code_fetcher: &code_fetcher,
heap_pages: None,
hash: {
use std::hash::{Hash, Hasher};
let mut state = DefaultHasher::new();
wasm.hash(&mut state);
state.finish().to_le_bytes().to_vec()
use sp_core::Hasher;
Blake2Hasher::hash(&wasm.to_vec()).as_ref().to_vec()
},
};
let runtime_version = RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code)
Expand Down
12 changes: 6 additions & 6 deletions substrate/client/cli/src/commands/precompile_wasm_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ use crate::{

use clap::Parser;
use sc_client_api::{Backend, HeaderBackend};
use sp_core::traits::RuntimeCode;
use sc_executor::{
HeapAllocStrategy, DEFAULT_HEAP_ALLOC_PAGES, precompile_and_serialize_versioned_wasm_runtime,
};
use sp_runtime::traits::Block as BlockT;
use sc_service::ChainSpec;
use sp_core::traits::RuntimeCode;
use sp_runtime::traits::Block as BlockT;
use sp_state_machine::backend::BackendRuntimeCode;
use std::{fmt::Debug, path::PathBuf, sync::Arc};

Expand Down Expand Up @@ -78,7 +78,7 @@ pub struct PrecompileWasmCmd {

impl PrecompileWasmCmd {
/// Run the precompile-wasm command
pub async fn run<B, BA>(&self, backend: Arc<BA>, spec: Box<dyn ChainSpec>,) -> error::Result<()>
pub async fn run<B, BA>(&self, backend: Arc<BA>, spec: Box<dyn ChainSpec>) -> error::Result<()>
where
B: BlockT,
BA: Backend<B>,
Expand All @@ -92,7 +92,6 @@ impl PrecompileWasmCmd {
let state = backend.state_at(backend.blockchain().info().finalized_hash)?;

precompile_and_serialize_versioned_wasm_runtime(
true,
HeapAllocStrategy::Static { extra_pages: heap_pages },
&BackendRuntimeCode::new(&state).runtime_code()?,
execution_method_from_cli(
Expand All @@ -106,12 +105,13 @@ impl PrecompileWasmCmd {
let storage = spec.as_storage_builder().build_storage()?;
if let Some(wasm_bytecode) = storage.top.get(sp_storage::well_known_keys::CODE) {
let runtime_code = RuntimeCode {
code_fetcher: &sp_core::traits::WrappedRuntimeCode(wasm_bytecode.as_slice().into()),
code_fetcher: &sp_core::traits::WrappedRuntimeCode(
wasm_bytecode.as_slice().into(),
),
hash: sp_core::blake2_256(&wasm_bytecode).to_vec(),
heap_pages: Some(heap_pages as u64),
};
precompile_and_serialize_versioned_wasm_runtime(
true,
HeapAllocStrategy::Static { extra_pages: heap_pages },
&runtime_code,
execution_method_from_cli(
Expand Down
1 change: 1 addition & 0 deletions substrate/client/executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
parking_lot = "0.12.1"
schnellru = "0.2.1"
tracing = "0.1.29"
log = "0.4.17"

codec = { package = "parity-scale-codec", version = "3.6.1" }
sc-executor-common = { path = "common" }
Expand Down
54 changes: 40 additions & 14 deletions substrate/client/executor/src/wasm_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,27 +324,44 @@ where
return WasmError::Instantiation(format!("Io error when loading wasmtime precompiled folder ({}): {}", wasmtime_precompiled_dir.display(), e));
};
let mut maybe_compiled_artifact = None;

let artifact_version =
compute_artifact_version(allow_missing_func_imports, code_hash, &semantics);
log::debug!(
target: "wasmtime-runtime",
"Searching for wasm hash: {}",
artifact_version.clone()
);

for entry in std::fs::read_dir(wasmtime_precompiled_dir).map_err(handle_err)? {
let entry = entry.map_err(handle_err)?;
if let Some(file_name) = entry.file_name().to_str() {
let artifact_version = compute_artifact_version(allow_missing_func_imports, code_hash, &semantics);

// We check that the artifact was generated for this specific artifact version
// and with the same wasm interface version and configuration.
if file_name.contains(&artifact_version) {
// We change the version check strategy to make sure that the file content
// was serialized with the exact same config as well
maybe_compiled_artifact = Some((entry.path(), sc_executor_wasmtime::ModuleVersionStrategy::Custom(artifact_version)));
// We check that the artifact was generated for this specific artifact
// version and with the same wasm interface version and configuration.
if file_name.contains(&artifact_version.clone()) {
log::info!(
target: "wasmtime-runtime",
"Found precompiled wasm: {}",
file_name
);
// We change the version check strategy to make sure that the file
// content was serialized with the exact same config as well
maybe_compiled_artifact = Some((
entry.path(),
sc_executor_wasmtime::ModuleVersionStrategy::Custom(
artifact_version.clone(),
),
));
}
} else {
return Err(WasmError::Instantiation("wasmtime precompiled folder contain a file with invalid utf8 name".to_owned()));
}
}

if let Some((compiled_artifact_path, module_version_strategy)) = maybe_compiled_artifact {
// # Safety
//
// The file name of the artifact was checked before,
// The file name of the artifact was checked before,
// so if the user has not renamed nor modified the file,
// it's certain that the file has been generated by
// `prepare_runtime_artifact` and with the same wasmtime
Expand Down Expand Up @@ -388,7 +405,6 @@ where

/// Create and serialize a precompiled artifact of a wasm runtime with the given `code`.
pub fn precompile_and_serialize_versioned_wasm_runtime<'c>(
allow_missing_func_imports: bool,
heap_alloc_strategy: HeapAllocStrategy,
runtime_code: &'c RuntimeCode<'c>,
wasm_method: WasmExecutionMethod,
Expand All @@ -407,12 +423,17 @@ pub fn precompile_and_serialize_versioned_wasm_runtime<'c>(
wasm_reference_types: false,
wasm_simd: false,
}
}
},
};

let code_hash = &runtime_code.hash;

let artifact_version = compute_artifact_version(allow_missing_func_imports, code_hash, &semantics);
let artifact_version = compute_artifact_version(false, code_hash, &semantics);
log::debug!(
target: "wasmtime-runtime",
"Generated precompiled wasm hash: {}",
artifact_version.clone()
);

let code = runtime_code.fetch_runtime_code().ok_or(WasmError::CodeNotFound)?;

Expand All @@ -427,7 +448,7 @@ pub fn precompile_and_serialize_versioned_wasm_runtime<'c>(
)?;

// Write in a file
let mut file = std::fs::File::create(wasmtime_precompiled_path.join(format!("precompiled_wasm_0x{}", &artifact_version)))
let mut file = std::fs::File::create(wasmtime_precompiled_path.join(format!("precompiled_wasm_{}", &artifact_version)))
.map_err(|e| WasmError::Other(format!("Fail to create file 'precompiled_wasm_0x{}', I/O Error: {}", &artifact_version, e)))?;
file.write_all(&serialized_precompiled_wasm)
.map_err(|e| WasmError::Other(format!("Fail to write precompiled artifact, I/O Error: {}", e)))?;
Expand All @@ -442,6 +463,11 @@ fn compute_artifact_version(
code_hash: &[u8],
semantics: &sc_executor_wasmtime::Semantics,
) -> String {
log::trace!(
target: "wasmtime-runtime",
"Computing wasm runtime hash [allow_missing_func_imports: {}, code_hash: {}, semantics: {:?}]",
allow_missing_func_imports, sp_core::bytes::to_hex(&code_hash, false), semantics
);
let mut buffer = Vec::new();
buffer.extend_from_slice(code_hash);
buffer.extend_from_slice(sp_wasm_interface::VERSION.as_bytes());
Expand Down
4 changes: 2 additions & 2 deletions substrate/client/executor/wasmtime/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ fn common_config(semantics: &Semantics) -> std::result::Result<wasmtime::Config,
/// See [here][stack_height] for more details of the instrumentation
///
/// [stack_height]: https://github.com/paritytech/wasm-instrument/blob/master/src/stack_limiter/mod.rs
#[derive(Clone, codec::Encode)]
#[derive(Debug, Clone, codec::Encode)]
pub struct DeterministicStackLimit {
/// A number of logical "values" that can be pushed on the wasm stack. A trap will be triggered
/// if exceeded.
Expand Down Expand Up @@ -419,7 +419,7 @@ enum InternalInstantiationStrategy {
Builtin,
}

#[derive(Clone, codec::Encode)]
#[derive(Debug, Clone, codec::Encode)]
pub struct Semantics {
/// The instantiation strategy to use.
pub instantiation_strategy: InstantiationStrategy,
Expand Down

0 comments on commit e15a1f9

Please sign in to comment.