mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 07:37:57 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -23,8 +23,8 @@
|
||||
// borthersome.
|
||||
#![cfg(feature = "wasmtime")]
|
||||
|
||||
use crate::WasmExecutionMethod;
|
||||
use super::mk_test_runtime;
|
||||
use crate::WasmExecutionMethod;
|
||||
use codec::Encode as _;
|
||||
|
||||
mod smaps;
|
||||
@@ -54,17 +54,11 @@ fn memory_consumption_compiled() {
|
||||
}
|
||||
|
||||
instance
|
||||
.call_export(
|
||||
"test_dirty_plenty_memory",
|
||||
&(heap_base as u32, 1u32).encode(),
|
||||
)
|
||||
.call_export("test_dirty_plenty_memory", &(heap_base as u32, 1u32).encode())
|
||||
.unwrap();
|
||||
let probe_1 = probe_rss(&*instance);
|
||||
instance
|
||||
.call_export(
|
||||
"test_dirty_plenty_memory",
|
||||
&(heap_base as u32, 1024u32).encode(),
|
||||
)
|
||||
.call_export("test_dirty_plenty_memory", &(heap_base as u32, 1024u32).encode())
|
||||
.unwrap();
|
||||
let probe_2 = probe_rss(&*instance);
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
//! A tool for extracting information about the memory consumption of the current process from
|
||||
//! the procfs.
|
||||
|
||||
use std::ops::Range;
|
||||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, ops::Range};
|
||||
|
||||
/// An interface to the /proc/self/smaps
|
||||
///
|
||||
@@ -69,7 +68,8 @@ impl Smaps {
|
||||
}
|
||||
|
||||
fn get_map(&self, addr: usize) -> &BTreeMap<String, usize> {
|
||||
&self.0
|
||||
&self
|
||||
.0
|
||||
.iter()
|
||||
.find(|(range, _)| addr >= range.start && addr < range.end)
|
||||
.unwrap()
|
||||
|
||||
@@ -20,20 +20,22 @@
|
||||
mod linux;
|
||||
mod sandbox;
|
||||
|
||||
use std::sync::Arc;
|
||||
use codec::{Encode, Decode};
|
||||
use codec::{Decode, Encode};
|
||||
use hex_literal::hex;
|
||||
use sp_core::{
|
||||
blake2_128, blake2_256, ed25519, sr25519, map, Pair,
|
||||
offchain::{OffchainWorkerExt, OffchainDbExt, testing},
|
||||
traits::Externalities,
|
||||
};
|
||||
use sc_executor_common::{runtime_blob::RuntimeBlob, wasm_runtime::WasmModule};
|
||||
use sc_runtime_test::wasm_binary_unwrap;
|
||||
use sp_state_machine::TestExternalities as CoreTestExternalities;
|
||||
use sp_trie::{TrieConfiguration, trie_types::Layout};
|
||||
use sp_wasm_interface::HostFunctions as _;
|
||||
use sp_core::{
|
||||
blake2_128, blake2_256, ed25519, map,
|
||||
offchain::{testing, OffchainDbExt, OffchainWorkerExt},
|
||||
sr25519,
|
||||
traits::Externalities,
|
||||
Pair,
|
||||
};
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use sc_executor_common::{wasm_runtime::WasmModule, runtime_blob::RuntimeBlob};
|
||||
use sp_state_machine::TestExternalities as CoreTestExternalities;
|
||||
use sp_trie::{trie_types::Layout, TrieConfiguration};
|
||||
use sp_wasm_interface::HostFunctions as _;
|
||||
use std::sync::Arc;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
|
||||
use crate::WasmExecutionMethod;
|
||||
@@ -96,12 +98,7 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let output = call_in_wasm(
|
||||
"test_empty_return",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
let output = call_in_wasm("test_empty_return", &[], wasm_method, &mut ext).unwrap();
|
||||
assert_eq!(output, vec![0u8; 0]);
|
||||
}
|
||||
|
||||
@@ -164,28 +161,13 @@ fn panicking_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let output = call_in_wasm(
|
||||
"test_panic",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
);
|
||||
let output = call_in_wasm("test_panic", &[], wasm_method, &mut ext);
|
||||
assert!(output.is_err());
|
||||
|
||||
let output = call_in_wasm(
|
||||
"test_conditional_panic",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
);
|
||||
let output = call_in_wasm("test_conditional_panic", &[0], wasm_method, &mut ext);
|
||||
assert_eq!(Decode::decode(&mut &output.unwrap()[..]), Ok(Vec::<u8>::new()));
|
||||
|
||||
let output = call_in_wasm(
|
||||
"test_conditional_panic",
|
||||
&vec![2].encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
);
|
||||
let output = call_in_wasm("test_conditional_panic", &vec![2].encode(), wasm_method, &mut ext);
|
||||
assert!(output.is_err());
|
||||
}
|
||||
|
||||
@@ -197,12 +179,9 @@ fn storage_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = ext.ext();
|
||||
ext.set_storage(b"foo".to_vec(), b"bar".to_vec());
|
||||
|
||||
let output = call_in_wasm(
|
||||
"test_data_in",
|
||||
&b"Hello world".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
let output =
|
||||
call_in_wasm("test_data_in", &b"Hello world".to_vec().encode(), wasm_method, &mut ext)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output, b"all ok!".to_vec().encode());
|
||||
}
|
||||
@@ -230,12 +209,9 @@ fn clear_prefix_should_work(wasm_method: WasmExecutionMethod) {
|
||||
ext.set_storage(b"bbb".to_vec(), b"5".to_vec());
|
||||
|
||||
// This will clear all entries which prefix is "ab".
|
||||
let output = call_in_wasm(
|
||||
"test_clear_prefix",
|
||||
&b"ab".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
let output =
|
||||
call_in_wasm("test_clear_prefix", &b"ab".to_vec().encode(), wasm_method, &mut ext)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output, b"all ok!".to_vec().encode());
|
||||
}
|
||||
@@ -256,21 +232,12 @@ fn blake2_256_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_blake2_256",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_blake2_256", &[0], wasm_method, &mut ext,).unwrap(),
|
||||
blake2_256(&b""[..]).to_vec().encode(),
|
||||
);
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_blake2_256",
|
||||
&b"Hello world!".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_blake2_256", &b"Hello world!".to_vec().encode(), wasm_method, &mut ext,)
|
||||
.unwrap(),
|
||||
blake2_256(&b"Hello world!"[..]).to_vec().encode(),
|
||||
);
|
||||
}
|
||||
@@ -280,21 +247,12 @@ fn blake2_128_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_blake2_128",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_blake2_128", &[0], wasm_method, &mut ext,).unwrap(),
|
||||
blake2_128(&b""[..]).to_vec().encode(),
|
||||
);
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_blake2_128",
|
||||
&b"Hello world!".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_blake2_128", &b"Hello world!".to_vec().encode(), wasm_method, &mut ext,)
|
||||
.unwrap(),
|
||||
blake2_128(&b"Hello world!"[..]).to_vec().encode(),
|
||||
);
|
||||
}
|
||||
@@ -304,25 +262,14 @@ fn sha2_256_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sha2_256",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
)
|
||||
.unwrap(),
|
||||
call_in_wasm("test_sha2_256", &[0], wasm_method, &mut ext,).unwrap(),
|
||||
hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
.to_vec()
|
||||
.encode(),
|
||||
);
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sha2_256",
|
||||
&b"Hello world!".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
)
|
||||
.unwrap(),
|
||||
call_in_wasm("test_sha2_256", &b"Hello world!".to_vec().encode(), wasm_method, &mut ext,)
|
||||
.unwrap(),
|
||||
hex!("c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a")
|
||||
.to_vec()
|
||||
.encode(),
|
||||
@@ -334,26 +281,17 @@ fn twox_256_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_twox_256",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
hex!(
|
||||
"99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a"
|
||||
).to_vec().encode(),
|
||||
call_in_wasm("test_twox_256", &[0], wasm_method, &mut ext,).unwrap(),
|
||||
hex!("99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a")
|
||||
.to_vec()
|
||||
.encode(),
|
||||
);
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_twox_256",
|
||||
&b"Hello world!".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
hex!(
|
||||
"b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74"
|
||||
).to_vec().encode(),
|
||||
call_in_wasm("test_twox_256", &b"Hello world!".to_vec().encode(), wasm_method, &mut ext,)
|
||||
.unwrap(),
|
||||
hex!("b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74")
|
||||
.to_vec()
|
||||
.encode(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -362,21 +300,12 @@ fn twox_128_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_twox_128",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_twox_128", &[0], wasm_method, &mut ext,).unwrap(),
|
||||
hex!("99e9d85137db46ef4bbea33613baafd5").to_vec().encode(),
|
||||
);
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_twox_128",
|
||||
&b"Hello world!".to_vec().encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_twox_128", &b"Hello world!".to_vec().encode(), wasm_method, &mut ext,)
|
||||
.unwrap(),
|
||||
hex!("b27dfd7f223f177f2a13647b533599af").to_vec().encode(),
|
||||
);
|
||||
}
|
||||
@@ -392,12 +321,7 @@ fn ed25519_verify_should_work(wasm_method: WasmExecutionMethod) {
|
||||
calldata.extend_from_slice(sig.as_ref());
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_ed25519_verify",
|
||||
&calldata.encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_ed25519_verify", &calldata.encode(), wasm_method, &mut ext,).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
|
||||
@@ -407,12 +331,7 @@ fn ed25519_verify_should_work(wasm_method: WasmExecutionMethod) {
|
||||
calldata.extend_from_slice(other_sig.as_ref());
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_ed25519_verify",
|
||||
&calldata.encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_ed25519_verify", &calldata.encode(), wasm_method, &mut ext,).unwrap(),
|
||||
false.encode(),
|
||||
);
|
||||
}
|
||||
@@ -428,12 +347,7 @@ fn sr25519_verify_should_work(wasm_method: WasmExecutionMethod) {
|
||||
calldata.extend_from_slice(sig.as_ref());
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sr25519_verify",
|
||||
&calldata.encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sr25519_verify", &calldata.encode(), wasm_method, &mut ext,).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
|
||||
@@ -443,12 +357,7 @@ fn sr25519_verify_should_work(wasm_method: WasmExecutionMethod) {
|
||||
calldata.extend_from_slice(other_sig.as_ref());
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sr25519_verify",
|
||||
&calldata.encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sr25519_verify", &calldata.encode(), wasm_method, &mut ext,).unwrap(),
|
||||
false.encode(),
|
||||
);
|
||||
}
|
||||
@@ -458,12 +367,7 @@ fn ordered_trie_root_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let trie_input = vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()];
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_ordered_trie_root",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext.ext(),
|
||||
).unwrap(),
|
||||
call_in_wasm("test_ordered_trie_root", &[0], wasm_method, &mut ext.ext(),).unwrap(),
|
||||
Layout::<BlakeTwo256>::ordered_trie_root(trie_input.iter()).as_bytes().encode(),
|
||||
);
|
||||
}
|
||||
@@ -473,17 +377,14 @@ fn offchain_index(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let (offchain, _state) = testing::TestOffchainExt::new();
|
||||
ext.register_extension(OffchainWorkerExt::new(offchain));
|
||||
call_in_wasm(
|
||||
"test_offchain_index_set",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext.ext(),
|
||||
).unwrap();
|
||||
call_in_wasm("test_offchain_index_set", &[0], wasm_method, &mut ext.ext()).unwrap();
|
||||
|
||||
use sp_core::offchain::OffchainOverlayedChange;
|
||||
let data = ext.overlayed_changes().clone().offchain_drain_committed().find(|(k, _v)| {
|
||||
k == &(sp_core::offchain::STORAGE_PREFIX.to_vec(), b"k".to_vec())
|
||||
});
|
||||
let data = ext
|
||||
.overlayed_changes()
|
||||
.clone()
|
||||
.offchain_drain_committed()
|
||||
.find(|(k, _v)| k == &(sp_core::offchain::STORAGE_PREFIX.to_vec(), b"k".to_vec()));
|
||||
assert_eq!(data.map(|data| data.1), Some(OffchainOverlayedChange::SetValue(b"v".to_vec())));
|
||||
}
|
||||
|
||||
@@ -494,12 +395,7 @@ fn offchain_local_storage_should_work(wasm_method: WasmExecutionMethod) {
|
||||
ext.register_extension(OffchainDbExt::new(offchain.clone()));
|
||||
ext.register_extension(OffchainWorkerExt::new(offchain));
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_offchain_local_storage",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext.ext(),
|
||||
).unwrap(),
|
||||
call_in_wasm("test_offchain_local_storage", &[0], wasm_method, &mut ext.ext(),).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
assert_eq!(state.read().persistent_storage.get(b"test"), Some(vec![]));
|
||||
@@ -511,24 +407,18 @@ fn offchain_http_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let (offchain, state) = testing::TestOffchainExt::new();
|
||||
ext.register_extension(OffchainWorkerExt::new(offchain));
|
||||
state.write().expect_request(testing::PendingRequest {
|
||||
method: "POST".into(),
|
||||
uri: "http://localhost:12345".into(),
|
||||
body: vec![1, 2, 3, 4],
|
||||
headers: vec![("X-Auth".to_owned(), "test".to_owned())],
|
||||
sent: true,
|
||||
response: Some(vec![1, 2, 3]),
|
||||
response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())],
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
method: "POST".into(),
|
||||
uri: "http://localhost:12345".into(),
|
||||
body: vec![1, 2, 3, 4],
|
||||
headers: vec![("X-Auth".to_owned(), "test".to_owned())],
|
||||
sent: true,
|
||||
response: Some(vec![1, 2, 3]),
|
||||
response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())],
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_offchain_http",
|
||||
&[0],
|
||||
wasm_method,
|
||||
&mut ext.ext(),
|
||||
).unwrap(),
|
||||
call_in_wasm("test_offchain_http", &[0], wasm_method, &mut ext.ext(),).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
}
|
||||
@@ -539,7 +429,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
let executor = crate::WasmExecutor::new(
|
||||
wasm_method,
|
||||
Some(17), // `17` is the initial number of pages compiled into the binary.
|
||||
Some(17), // `17` is the initial number of pages compiled into the binary.
|
||||
HostFunctions::host_functions(),
|
||||
8,
|
||||
None,
|
||||
@@ -593,17 +483,13 @@ fn returns_mutable_static_bss(wasm_method: WasmExecutionMethod) {
|
||||
let runtime = mk_test_runtime(wasm_method, 1024);
|
||||
|
||||
let instance = runtime.new_instance().unwrap();
|
||||
let res = instance
|
||||
.call_export("returns_mutable_static_bss", &[0])
|
||||
.unwrap();
|
||||
let res = instance.call_export("returns_mutable_static_bss", &[0]).unwrap();
|
||||
assert_eq!(1, u64::decode(&mut &res[..]).unwrap());
|
||||
|
||||
// We expect that every invocation will need to return the initial
|
||||
// value plus one. If the value increases more than that then it is
|
||||
// a sign that the wasm runtime preserves the memory content.
|
||||
let res = instance
|
||||
.call_export("returns_mutable_static_bss", &[0])
|
||||
.unwrap();
|
||||
let res = instance.call_export("returns_mutable_static_bss", &[0]).unwrap();
|
||||
assert_eq!(1, u64::decode(&mut &res[..]).unwrap());
|
||||
}
|
||||
|
||||
@@ -638,7 +524,8 @@ fn heap_is_reset_between_calls(wasm_method: WasmExecutionMethod) {
|
||||
let runtime = mk_test_runtime(wasm_method, 1024);
|
||||
let instance = runtime.new_instance().unwrap();
|
||||
|
||||
let heap_base = instance.get_global_const("__heap_base")
|
||||
let heap_base = instance
|
||||
.get_global_const("__heap_base")
|
||||
.expect("`__heap_base` is valid")
|
||||
.expect("`__heap_base` exists")
|
||||
.as_i32()
|
||||
@@ -689,8 +576,8 @@ fn parallel_execution(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
test_wasm_execution!(wasm_tracing_should_work);
|
||||
fn wasm_tracing_should_work(wasm_method: WasmExecutionMethod) {
|
||||
use std::sync::Mutex;
|
||||
use sc_tracing::{SpanDatum, TraceEvent};
|
||||
use std::sync::Mutex;
|
||||
|
||||
struct TestTraceHandler(Arc<Mutex<Vec<SpanDatum>>>);
|
||||
|
||||
@@ -706,36 +593,23 @@ fn wasm_tracing_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let handler = TestTraceHandler(traces.clone());
|
||||
|
||||
// Create subscriber with wasm_tracing disabled
|
||||
let test_subscriber = tracing_subscriber::fmt().finish().with(
|
||||
sc_tracing::ProfilingLayer::new_with_handler(
|
||||
Box::new(handler), "default"
|
||||
)
|
||||
);
|
||||
let test_subscriber = tracing_subscriber::fmt()
|
||||
.finish()
|
||||
.with(sc_tracing::ProfilingLayer::new_with_handler(Box::new(handler), "default"));
|
||||
|
||||
let _guard = tracing::subscriber::set_default(test_subscriber);
|
||||
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let span_id = call_in_wasm(
|
||||
"test_enter_span",
|
||||
Default::default(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
let span_id =
|
||||
call_in_wasm("test_enter_span", Default::default(), wasm_method, &mut ext).unwrap();
|
||||
|
||||
let span_id = u64::decode(&mut &span_id[..]).unwrap();
|
||||
|
||||
assert!(
|
||||
span_id > 0
|
||||
);
|
||||
assert!(span_id > 0);
|
||||
|
||||
call_in_wasm(
|
||||
"test_exit_span",
|
||||
&span_id.encode(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
call_in_wasm("test_exit_span", &span_id.encode(), wasm_method, &mut ext).unwrap();
|
||||
|
||||
// Check there is only the single trace
|
||||
let len = traces.lock().unwrap().len();
|
||||
@@ -747,12 +621,7 @@ fn wasm_tracing_should_work(wasm_method: WasmExecutionMethod) {
|
||||
assert_eq!(span_datum.name, "");
|
||||
assert_eq!(values.bool_values.get("wasm").unwrap(), &true);
|
||||
|
||||
call_in_wasm(
|
||||
"test_nested_spans",
|
||||
Default::default(),
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
call_in_wasm("test_nested_spans", Default::default(), wasm_method, &mut ext).unwrap();
|
||||
let len = traces.lock().unwrap().len();
|
||||
assert_eq!(len, 2);
|
||||
}
|
||||
@@ -762,12 +631,7 @@ fn spawning_runtime_instance_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
call_in_wasm(
|
||||
"test_spawn",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
call_in_wasm("test_spawn", &[], wasm_method, &mut ext).unwrap();
|
||||
}
|
||||
|
||||
test_wasm_execution!(spawning_runtime_instance_nested_should_work);
|
||||
@@ -775,12 +639,7 @@ fn spawning_runtime_instance_nested_should_work(wasm_method: WasmExecutionMethod
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
call_in_wasm(
|
||||
"test_nested_spawn",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap();
|
||||
call_in_wasm("test_nested_spawn", &[], wasm_method, &mut ext).unwrap();
|
||||
}
|
||||
|
||||
test_wasm_execution!(panic_in_spawned_instance_panics_on_joining_its_result);
|
||||
@@ -788,12 +647,8 @@ fn panic_in_spawned_instance_panics_on_joining_its_result(wasm_method: WasmExecu
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let error_result = call_in_wasm(
|
||||
"test_panic_in_spawned",
|
||||
&[],
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap_err();
|
||||
let error_result =
|
||||
call_in_wasm("test_panic_in_spawned", &[], wasm_method, &mut ext).unwrap_err();
|
||||
|
||||
assert!(format!("{}", error_result).contains("Spawned task"));
|
||||
}
|
||||
|
||||
@@ -16,9 +16,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{TestExternalities, call_in_wasm};
|
||||
use crate::WasmExecutionMethod;
|
||||
use crate::test_wasm_execution;
|
||||
use super::{call_in_wasm, TestExternalities};
|
||||
use crate::{test_wasm_execution, WasmExecutionMethod};
|
||||
|
||||
use codec::Encode;
|
||||
|
||||
@@ -27,7 +26,8 @@ fn sandbox_should_work(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(import "env" "assert" (func $assert (param i32)))
|
||||
(import "env" "inc_counter" (func $inc_counter (param i32) (result i32)))
|
||||
@@ -46,17 +46,12 @@ fn sandbox_should_work(wasm_method: WasmExecutionMethod) {
|
||||
call $assert
|
||||
)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
assert_eq!(call_in_wasm("test_sandbox", &code, wasm_method, &mut ext,).unwrap(), true.encode(),);
|
||||
}
|
||||
|
||||
test_wasm_execution!(sandbox_trap);
|
||||
@@ -64,7 +59,8 @@ fn sandbox_trap(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(import "env" "assert" (func $assert (param i32)))
|
||||
(func (export "call")
|
||||
@@ -72,17 +68,11 @@ fn sandbox_trap(wasm_method: WasmExecutionMethod) {
|
||||
call $assert
|
||||
)
|
||||
)
|
||||
"#).unwrap();
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
vec![0],
|
||||
);
|
||||
assert_eq!(call_in_wasm("test_sandbox", &code, wasm_method, &mut ext,).unwrap(), vec![0],);
|
||||
}
|
||||
|
||||
test_wasm_execution!(start_called);
|
||||
@@ -90,7 +80,8 @@ fn start_called(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(import "env" "assert" (func $assert (param i32)))
|
||||
(import "env" "inc_counter" (func $inc_counter (param i32) (result i32)))
|
||||
@@ -115,17 +106,12 @@ fn start_called(wasm_method: WasmExecutionMethod) {
|
||||
call $assert
|
||||
)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
assert_eq!(call_in_wasm("test_sandbox", &code, wasm_method, &mut ext,).unwrap(), true.encode(),);
|
||||
}
|
||||
|
||||
test_wasm_execution!(invoke_args);
|
||||
@@ -133,7 +119,8 @@ fn invoke_args(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(import "env" "assert" (func $assert (param i32)))
|
||||
|
||||
@@ -154,15 +141,13 @@ fn invoke_args(wasm_method: WasmExecutionMethod) {
|
||||
)
|
||||
)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_args",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_args", &code, wasm_method, &mut ext,).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
}
|
||||
@@ -172,7 +157,8 @@ fn return_val(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(func (export "call") (param $x i32) (result i32)
|
||||
(i32.add
|
||||
@@ -181,15 +167,13 @@ fn return_val(wasm_method: WasmExecutionMethod) {
|
||||
)
|
||||
)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_return_val",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_return_val", &code, wasm_method, &mut ext,).unwrap(),
|
||||
true.encode(),
|
||||
);
|
||||
}
|
||||
@@ -199,22 +183,21 @@ fn unlinkable_module(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(import "env" "non-existent" (func))
|
||||
|
||||
(func (export "call")
|
||||
)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_instantiate",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(),
|
||||
1u8.encode(),
|
||||
);
|
||||
}
|
||||
@@ -228,12 +211,7 @@ fn corrupted_module(wasm_method: WasmExecutionMethod) {
|
||||
let code = vec![0u8, 0, 0, 0, 1, 0, 0, 0].encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_instantiate",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(),
|
||||
1u8.encode(),
|
||||
);
|
||||
}
|
||||
@@ -243,7 +221,8 @@ fn start_fn_ok(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(func (export "call")
|
||||
)
|
||||
@@ -253,15 +232,13 @@ fn start_fn_ok(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
(start $start)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_instantiate",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(),
|
||||
0u8.encode(),
|
||||
);
|
||||
}
|
||||
@@ -271,7 +248,8 @@ fn start_fn_traps(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(func (export "call")
|
||||
)
|
||||
@@ -282,15 +260,13 @@ fn start_fn_traps(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
(start $start)
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_instantiate",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_instantiate", &code, wasm_method, &mut ext,).unwrap(),
|
||||
2u8.encode(),
|
||||
);
|
||||
}
|
||||
@@ -300,19 +276,18 @@ fn get_global_val_works(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wat::parse_str(r#"
|
||||
let code = wat::parse_str(
|
||||
r#"
|
||||
(module
|
||||
(global (export "test_global") i64 (i64.const 500))
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_get_global_val",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
call_in_wasm("test_sandbox_get_global_val", &code, wasm_method, &mut ext,).unwrap(),
|
||||
500i64.encode(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,26 +29,25 @@
|
||||
//! wasm engine used, instance cache.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![recursion_limit="128"]
|
||||
#![recursion_limit = "128"]
|
||||
|
||||
#[macro_use]
|
||||
mod native_executor;
|
||||
mod wasm_runtime;
|
||||
#[cfg(test)]
|
||||
mod integration_tests;
|
||||
mod wasm_runtime;
|
||||
|
||||
pub use wasmi;
|
||||
pub use native_executor::{
|
||||
with_externalities_safe, NativeExecutor, WasmExecutor, NativeExecutionDispatch,
|
||||
};
|
||||
pub use sp_version::{RuntimeVersion, NativeVersion};
|
||||
pub use codec::Codec;
|
||||
pub use native_executor::{
|
||||
with_externalities_safe, NativeExecutionDispatch, NativeExecutor, WasmExecutor,
|
||||
};
|
||||
#[doc(hidden)]
|
||||
pub use sp_core::traits::{Externalities};
|
||||
pub use sp_core::traits::Externalities;
|
||||
pub use sp_version::{NativeVersion, RuntimeVersion};
|
||||
#[doc(hidden)]
|
||||
pub use sp_wasm_interface;
|
||||
pub use wasm_runtime::WasmExecutionMethod;
|
||||
pub use wasm_runtime::read_embedded_version;
|
||||
pub use wasm_runtime::{read_embedded_version, WasmExecutionMethod};
|
||||
pub use wasmi;
|
||||
|
||||
pub use sc_executor_common::{error, sandbox};
|
||||
|
||||
@@ -68,10 +67,10 @@ pub trait RuntimeInfo {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sc_executor_common::runtime_blob::RuntimeBlob;
|
||||
use sc_runtime_test::wasm_binary_unwrap;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_wasm_interface::HostFunctions;
|
||||
use sc_executor_common::runtime_blob::RuntimeBlob;
|
||||
|
||||
#[test]
|
||||
fn call_in_interpreted_wasm_works() {
|
||||
|
||||
@@ -17,32 +17,36 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
RuntimeInfo, error::{Error, Result},
|
||||
error::{Error, Result},
|
||||
wasm_runtime::{RuntimeCache, WasmExecutionMethod},
|
||||
RuntimeInfo,
|
||||
};
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
panic::{UnwindSafe, AssertUnwindSafe},
|
||||
result,
|
||||
sync::{Arc, atomic::{AtomicU64, Ordering}, mpsc},
|
||||
panic::{AssertUnwindSafe, UnwindSafe},
|
||||
path::PathBuf,
|
||||
result,
|
||||
sync::{
|
||||
atomic::{AtomicU64, Ordering},
|
||||
mpsc, Arc,
|
||||
},
|
||||
};
|
||||
|
||||
use sp_version::{NativeVersion, RuntimeVersion};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_core::{
|
||||
NativeOrEncoded,
|
||||
traits::{CodeExecutor, Externalities, RuntimeCode, RuntimeSpawnExt, RuntimeSpawn},
|
||||
};
|
||||
use log::trace;
|
||||
use sp_wasm_interface::{HostFunctions, Function};
|
||||
use sc_executor_common::{
|
||||
wasm_runtime::{WasmInstance, WasmModule, InvokeMethod},
|
||||
runtime_blob::RuntimeBlob,
|
||||
wasm_runtime::{InvokeMethod, WasmInstance, WasmModule},
|
||||
};
|
||||
use sp_core::{
|
||||
traits::{CodeExecutor, Externalities, RuntimeCode, RuntimeSpawn, RuntimeSpawnExt},
|
||||
NativeOrEncoded,
|
||||
};
|
||||
use sp_externalities::ExternalitiesExt as _;
|
||||
use sp_tasks::new_async_externalities;
|
||||
use sp_version::{NativeVersion, RuntimeVersion};
|
||||
use sp_wasm_interface::{Function, HostFunctions};
|
||||
|
||||
/// Default num of pages for the heap
|
||||
const DEFAULT_HEAP_PAGES: u64 = 2048;
|
||||
@@ -51,25 +55,23 @@ const DEFAULT_HEAP_PAGES: u64 = 2048;
|
||||
///
|
||||
/// If the inner closure panics, it will be caught and return an error.
|
||||
pub fn with_externalities_safe<F, U>(ext: &mut dyn Externalities, f: F) -> Result<U>
|
||||
where F: UnwindSafe + FnOnce() -> U
|
||||
where
|
||||
F: UnwindSafe + FnOnce() -> U,
|
||||
{
|
||||
sp_externalities::set_and_run_with_externalities(
|
||||
ext,
|
||||
move || {
|
||||
// Substrate uses custom panic hook that terminates process on panic. Disable
|
||||
// termination for the native call.
|
||||
let _guard = sp_panic_handler::AbortGuard::force_unwind();
|
||||
std::panic::catch_unwind(f).map_err(|e| {
|
||||
if let Some(err) = e.downcast_ref::<String>() {
|
||||
Error::RuntimePanicked(err.clone())
|
||||
} else if let Some(err) = e.downcast_ref::<&'static str>() {
|
||||
Error::RuntimePanicked(err.to_string())
|
||||
} else {
|
||||
Error::RuntimePanicked("Unknown panic".into())
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
sp_externalities::set_and_run_with_externalities(ext, move || {
|
||||
// Substrate uses custom panic hook that terminates process on panic. Disable
|
||||
// termination for the native call.
|
||||
let _guard = sp_panic_handler::AbortGuard::force_unwind();
|
||||
std::panic::catch_unwind(f).map_err(|e| {
|
||||
if let Some(err) = e.downcast_ref::<String>() {
|
||||
Error::RuntimePanicked(err.clone())
|
||||
} else if let Some(err) = e.downcast_ref::<&'static str>() {
|
||||
Error::RuntimePanicked(err.to_string())
|
||||
} else {
|
||||
Error::RuntimePanicked("Unknown panic".into())
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Delegate for dispatching a CodeExecutor call.
|
||||
@@ -163,7 +165,8 @@ impl WasmExecutor {
|
||||
allow_missing_host_functions: bool,
|
||||
f: F,
|
||||
) -> Result<R>
|
||||
where F: FnOnce(
|
||||
where
|
||||
F: FnOnce(
|
||||
AssertUnwindSafe<&Arc<dyn WasmModule>>,
|
||||
AssertUnwindSafe<&dyn WasmInstance>,
|
||||
Option<&RuntimeVersion>,
|
||||
@@ -182,7 +185,7 @@ impl WasmExecutor {
|
||||
let instance = AssertUnwindSafe(instance);
|
||||
let ext = AssertUnwindSafe(ext);
|
||||
f(module, instance, version, ext)
|
||||
}
|
||||
},
|
||||
)? {
|
||||
Ok(r) => r,
|
||||
Err(e) => Err(e),
|
||||
@@ -245,7 +248,7 @@ impl sp_core::traits::ReadRuntimeVersion for WasmExecutor {
|
||||
.map_err(|e| format!("Failed to read the static section: {:?}", e))
|
||||
.map(|v| v.map(|v| v.encode()))?
|
||||
{
|
||||
return Ok(version);
|
||||
return Ok(version)
|
||||
}
|
||||
|
||||
// If the blob didn't have embedded runtime version section, we fallback to the legacy
|
||||
@@ -296,13 +299,13 @@ impl<D: NativeExecutionDispatch> NativeExecutor<D> {
|
||||
.into_iter()
|
||||
// filter out any host function overrides provided.
|
||||
.filter(|host_fn| {
|
||||
extended.iter()
|
||||
extended
|
||||
.iter()
|
||||
.find(|ext_host_fn| host_fn.name() == ext_host_fn.name())
|
||||
.is_none()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
||||
// Add the custom host functions provided by the user.
|
||||
host_functions.extend(extended);
|
||||
let wasm_executor = WasmExecutor::new(
|
||||
@@ -331,13 +334,10 @@ impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
|
||||
ext: &mut dyn Externalities,
|
||||
runtime_code: &RuntimeCode,
|
||||
) -> Result<RuntimeVersion> {
|
||||
self.wasm.with_instance(
|
||||
runtime_code,
|
||||
ext,
|
||||
false,
|
||||
|_module, _instance, version, _ext|
|
||||
Ok(version.cloned().ok_or_else(|| Error::ApiError("Unknown version".into()))),
|
||||
)
|
||||
self.wasm
|
||||
.with_instance(runtime_code, ext, false, |_module, _instance, version, _ext| {
|
||||
Ok(version.cloned().ok_or_else(|| Error::ApiError("Unknown version".into())))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,70 +358,67 @@ impl RuntimeSpawn for RuntimeInstanceSpawn {
|
||||
|
||||
let module = self.module.clone();
|
||||
let scheduler = self.scheduler.clone();
|
||||
self.scheduler.spawn("executor-extra-runtime-instance", Box::pin(async move {
|
||||
let module = AssertUnwindSafe(module);
|
||||
self.scheduler.spawn(
|
||||
"executor-extra-runtime-instance",
|
||||
Box::pin(async move {
|
||||
let module = AssertUnwindSafe(module);
|
||||
|
||||
let async_ext = match new_async_externalities(scheduler.clone()) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
target: "executor",
|
||||
"Failed to setup externalities for async context: {}",
|
||||
e,
|
||||
);
|
||||
let async_ext = match new_async_externalities(scheduler.clone()) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
target: "executor",
|
||||
"Failed to setup externalities for async context: {}",
|
||||
e,
|
||||
);
|
||||
|
||||
// This will drop sender and receiver end will panic
|
||||
return;
|
||||
}
|
||||
};
|
||||
// This will drop sender and receiver end will panic
|
||||
return
|
||||
},
|
||||
};
|
||||
|
||||
let mut async_ext = match async_ext.with_runtime_spawn(
|
||||
Box::new(RuntimeInstanceSpawn::new(module.clone(), scheduler))
|
||||
) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
target: "executor",
|
||||
"Failed to setup runtime extension for async externalities: {}",
|
||||
e,
|
||||
);
|
||||
let mut async_ext = match async_ext.with_runtime_spawn(Box::new(
|
||||
RuntimeInstanceSpawn::new(module.clone(), scheduler),
|
||||
)) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
target: "executor",
|
||||
"Failed to setup runtime extension for async externalities: {}",
|
||||
e,
|
||||
);
|
||||
|
||||
// This will drop sender and receiver end will panic
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let result = with_externalities_safe(
|
||||
&mut async_ext,
|
||||
move || {
|
||||
// This will drop sender and receiver end will panic
|
||||
return
|
||||
},
|
||||
};
|
||||
|
||||
let result = with_externalities_safe(&mut async_ext, move || {
|
||||
// FIXME: Should be refactored to shared "instance factory".
|
||||
// Instantiating wasm here every time is suboptimal at the moment, shared
|
||||
// pool of instances should be used.
|
||||
//
|
||||
// https://github.com/paritytech/substrate/issues/7354
|
||||
let instance = module.new_instance()
|
||||
.expect("Failed to create new instance from module");
|
||||
let instance =
|
||||
module.new_instance().expect("Failed to create new instance from module");
|
||||
|
||||
instance.call(
|
||||
InvokeMethod::TableWithWrapper { dispatcher_ref, func },
|
||||
&data[..],
|
||||
).expect("Failed to invoke instance.")
|
||||
instance
|
||||
.call(InvokeMethod::TableWithWrapper { dispatcher_ref, func }, &data[..])
|
||||
.expect("Failed to invoke instance.")
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(output) => {
|
||||
let _ = sender.send(output);
|
||||
},
|
||||
Err(error) => {
|
||||
// If execution is panicked, the `join` in the original runtime code will panic as well,
|
||||
// since the sender is dropped without sending anything.
|
||||
log::error!("Call error in spawned task: {:?}", error);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
match result {
|
||||
Ok(output) => {
|
||||
let _ = sender.send(output);
|
||||
},
|
||||
Err(error) => {
|
||||
// If execution is panicked, the `join` in the original runtime code will panic as well,
|
||||
// since the sender is dropped without sending anything.
|
||||
log::error!("Call error in spawned task: {:?}", error);
|
||||
},
|
||||
}
|
||||
}));
|
||||
|
||||
}),
|
||||
);
|
||||
|
||||
new_handle
|
||||
}
|
||||
@@ -438,12 +435,7 @@ impl RuntimeInstanceSpawn {
|
||||
module: Arc<dyn WasmModule>,
|
||||
scheduler: Box<dyn sp_core::traits::SpawnNamed>,
|
||||
) -> Self {
|
||||
Self {
|
||||
module,
|
||||
scheduler,
|
||||
counter: 0.into(),
|
||||
tasks: HashMap::new().into(),
|
||||
}
|
||||
Self { module, scheduler, counter: 0.into(), tasks: HashMap::new().into() }
|
||||
}
|
||||
|
||||
fn with_externalities_and_module(
|
||||
@@ -495,17 +487,13 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
|
||||
ext,
|
||||
false,
|
||||
|module, instance, onchain_version, mut ext| {
|
||||
let onchain_version = onchain_version.ok_or_else(
|
||||
|| Error::ApiError("Unknown version".into())
|
||||
)?;
|
||||
let onchain_version =
|
||||
onchain_version.ok_or_else(|| Error::ApiError("Unknown version".into()))?;
|
||||
|
||||
let can_call_with = onchain_version.can_call_with(&self.native_version.runtime_version);
|
||||
let can_call_with =
|
||||
onchain_version.can_call_with(&self.native_version.runtime_version);
|
||||
|
||||
match (
|
||||
use_native,
|
||||
can_call_with,
|
||||
native_call,
|
||||
) {
|
||||
match (use_native, can_call_with, native_call) {
|
||||
(_, false, _) | (false, _, _) => {
|
||||
if !can_call_with {
|
||||
trace!(
|
||||
@@ -516,13 +504,10 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
|
||||
);
|
||||
}
|
||||
|
||||
with_externalities_safe(
|
||||
&mut **ext,
|
||||
move || {
|
||||
preregister_builtin_ext(module.clone());
|
||||
instance.call_export(method, data).map(NativeOrEncoded::Encoded)
|
||||
}
|
||||
)
|
||||
with_externalities_safe(&mut **ext, move || {
|
||||
preregister_builtin_ext(module.clone());
|
||||
instance.call_export(method, data).map(NativeOrEncoded::Encoded)
|
||||
})
|
||||
},
|
||||
(true, true, Some(call)) => {
|
||||
trace!(
|
||||
@@ -535,13 +520,10 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
|
||||
|
||||
used_native = true;
|
||||
let res = with_externalities_safe(&mut **ext, move || (call)())
|
||||
.and_then(|r| r
|
||||
.map(NativeOrEncoded::Native)
|
||||
.map_err(Error::ApiError)
|
||||
);
|
||||
.and_then(|r| r.map(NativeOrEncoded::Native).map_err(Error::ApiError));
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
trace!(
|
||||
target: "executor",
|
||||
@@ -552,9 +534,9 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
|
||||
|
||||
used_native = true;
|
||||
Ok(D::dispatch(&mut **ext, method, data).map(NativeOrEncoded::Encoded))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
(result, used_native)
|
||||
}
|
||||
@@ -617,7 +599,6 @@ impl<D: NativeExecutionDispatch> sp_core::traits::ReadRuntimeVersion for NativeE
|
||||
///
|
||||
/// When you have multiple interfaces, you can give the host functions as a tuple e.g.:
|
||||
/// `(my_interface::HostFunctions, my_interface2::HostFunctions)`
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! native_executor_instance {
|
||||
( $pub:vis $name:ident, $dispatcher:path, $version:path $(,)?) => {
|
||||
@@ -675,16 +656,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn native_executor_registers_custom_interface() {
|
||||
let executor = NativeExecutor::<MyExecutor>::new(
|
||||
WasmExecutionMethod::Interpreted,
|
||||
None,
|
||||
8,
|
||||
);
|
||||
let executor = NativeExecutor::<MyExecutor>::new(WasmExecutionMethod::Interpreted, None, 8);
|
||||
my_interface::HostFunctions::host_functions().iter().for_each(|function| {
|
||||
assert_eq!(
|
||||
executor.wasm.host_functions.iter().filter(|f| f == &function).count(),
|
||||
2,
|
||||
);
|
||||
assert_eq!(executor.wasm.host_functions.iter().filter(|f| f == &function).count(), 2,);
|
||||
});
|
||||
|
||||
my_interface::say_hello_world("hey");
|
||||
|
||||
@@ -21,17 +21,19 @@
|
||||
//! The primary means of accessing the runtimes is through a cache which saves the reusable
|
||||
//! components of the runtime that are expensive to initialize.
|
||||
|
||||
use std::sync::Arc;
|
||||
use crate::error::{Error, WasmError};
|
||||
use parking_lot::Mutex;
|
||||
use codec::Decode;
|
||||
use sp_core::traits::{Externalities, RuntimeCode, FetchRuntimeCode};
|
||||
use sp_version::RuntimeVersion;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
use std::path::{Path, PathBuf};
|
||||
use parking_lot::Mutex;
|
||||
use sc_executor_common::{
|
||||
wasm_runtime::{WasmModule, WasmInstance},
|
||||
runtime_blob::RuntimeBlob,
|
||||
wasm_runtime::{WasmInstance, WasmModule},
|
||||
};
|
||||
use sp_core::traits::{Externalities, FetchRuntimeCode, RuntimeCode};
|
||||
use sp_version::RuntimeVersion;
|
||||
use std::{
|
||||
panic::AssertUnwindSafe,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use sp_wasm_interface::Function;
|
||||
@@ -70,27 +72,26 @@ struct VersionedRuntime {
|
||||
|
||||
impl VersionedRuntime {
|
||||
/// Run the given closure `f` with an instance of this runtime.
|
||||
fn with_instance<'c, R, F>(
|
||||
&self,
|
||||
ext: &mut dyn Externalities,
|
||||
f: F,
|
||||
) -> Result<R, Error>
|
||||
where F: FnOnce(
|
||||
fn with_instance<'c, R, F>(&self, ext: &mut dyn Externalities, f: F) -> Result<R, Error>
|
||||
where
|
||||
F: FnOnce(
|
||||
&Arc<dyn WasmModule>,
|
||||
&dyn WasmInstance,
|
||||
Option<&RuntimeVersion>,
|
||||
&mut dyn Externalities)
|
||||
-> Result<R, Error>,
|
||||
&mut dyn Externalities,
|
||||
) -> Result<R, Error>,
|
||||
{
|
||||
// Find a free instance
|
||||
let instance = self.instances
|
||||
let instance = self
|
||||
.instances
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(index, i)| i.try_lock().map(|i| (index, i)));
|
||||
|
||||
match instance {
|
||||
Some((index, mut locked)) => {
|
||||
let (instance, new_inst) = locked.take()
|
||||
let (instance, new_inst) = locked
|
||||
.take()
|
||||
.map(|r| Ok((r, false)))
|
||||
.unwrap_or_else(|| self.module.new_instance().map(|i| (i, true)))?;
|
||||
|
||||
@@ -131,7 +132,7 @@ impl VersionedRuntime {
|
||||
let instance = self.module.new_instance()?;
|
||||
|
||||
f(&self.module, &*instance, self.version.as_ref(), ext)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,11 +169,7 @@ impl RuntimeCache {
|
||||
/// `cache_path` allows to specify an optional directory where the executor can store files
|
||||
/// for caching.
|
||||
pub fn new(max_runtime_instances: usize, cache_path: Option<PathBuf>) -> RuntimeCache {
|
||||
RuntimeCache {
|
||||
runtimes: Default::default(),
|
||||
max_runtime_instances,
|
||||
cache_path,
|
||||
}
|
||||
RuntimeCache { runtimes: Default::default(), max_runtime_instances, cache_path }
|
||||
}
|
||||
|
||||
/// Prepares a WASM module instance and executes given function for it.
|
||||
@@ -213,29 +210,31 @@ impl RuntimeCache {
|
||||
allow_missing_func_imports: bool,
|
||||
f: F,
|
||||
) -> Result<Result<R, Error>, Error>
|
||||
where F: FnOnce(
|
||||
where
|
||||
F: FnOnce(
|
||||
&Arc<dyn WasmModule>,
|
||||
&dyn WasmInstance,
|
||||
Option<&RuntimeVersion>,
|
||||
&mut dyn Externalities)
|
||||
-> Result<R, Error>,
|
||||
&mut dyn Externalities,
|
||||
) -> Result<R, Error>,
|
||||
{
|
||||
let code_hash = &runtime_code.hash;
|
||||
let heap_pages = runtime_code.heap_pages.unwrap_or(default_heap_pages);
|
||||
|
||||
let mut runtimes = self.runtimes.lock(); // this must be released prior to calling f
|
||||
let pos = runtimes.iter().position(|r| r.as_ref().map_or(
|
||||
false,
|
||||
|r| r.wasm_method == wasm_method &&
|
||||
r.code_hash == *code_hash &&
|
||||
r.heap_pages == heap_pages
|
||||
));
|
||||
let pos = runtimes.iter().position(|r| {
|
||||
r.as_ref().map_or(false, |r| {
|
||||
r.wasm_method == wasm_method &&
|
||||
r.code_hash == *code_hash &&
|
||||
r.heap_pages == heap_pages
|
||||
})
|
||||
});
|
||||
|
||||
let runtime = match pos {
|
||||
Some(n) => runtimes[n]
|
||||
.clone()
|
||||
.expect("`position` only returns `Some` for entries that are `Some`"),
|
||||
None => {
|
||||
None => {
|
||||
let code = runtime_code.fetch_runtime_code().ok_or(WasmError::CodeNotFound)?;
|
||||
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
@@ -262,30 +261,29 @@ impl RuntimeCache {
|
||||
result.version,
|
||||
time.elapsed().as_millis(),
|
||||
);
|
||||
}
|
||||
},
|
||||
Err(ref err) => {
|
||||
log::warn!(target: "wasm-runtime", "Cannot create a runtime: {:?}", err);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Arc::new(result?)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Rearrange runtimes by last recently used.
|
||||
match pos {
|
||||
Some(0) => {},
|
||||
Some(n) => {
|
||||
for i in (1 .. n + 1).rev() {
|
||||
Some(n) =>
|
||||
for i in (1..n + 1).rev() {
|
||||
runtimes.swap(i, i - 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
runtimes[MAX_RUNTIMES-1] = Some(runtime.clone());
|
||||
for i in (1 .. MAX_RUNTIMES).rev() {
|
||||
runtimes[MAX_RUNTIMES - 1] = Some(runtime.clone());
|
||||
for i in (1..MAX_RUNTIMES).rev() {
|
||||
runtimes.swap(i, i - 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
drop(runtimes);
|
||||
|
||||
@@ -317,49 +315,48 @@ pub fn create_wasm_runtime_with_code(
|
||||
allow_missing_func_imports,
|
||||
)
|
||||
.map(|runtime| -> Arc<dyn WasmModule> { Arc::new(runtime) })
|
||||
}
|
||||
#[cfg(feature = "wasmtime")]
|
||||
WasmExecutionMethod::Compiled => {
|
||||
sc_executor_wasmtime::create_runtime(
|
||||
blob,
|
||||
sc_executor_wasmtime::Config {
|
||||
heap_pages: heap_pages as u32,
|
||||
allow_missing_func_imports,
|
||||
cache_path: cache_path.map(ToOwned::to_owned),
|
||||
semantics: sc_executor_wasmtime::Semantics {
|
||||
fast_instance_reuse: true,
|
||||
deterministic_stack_limit: None,
|
||||
canonicalize_nans: false,
|
||||
},
|
||||
},
|
||||
host_functions,
|
||||
).map(|runtime| -> Arc<dyn WasmModule> { Arc::new(runtime) })
|
||||
},
|
||||
#[cfg(feature = "wasmtime")]
|
||||
WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_runtime(
|
||||
blob,
|
||||
sc_executor_wasmtime::Config {
|
||||
heap_pages: heap_pages as u32,
|
||||
allow_missing_func_imports,
|
||||
cache_path: cache_path.map(ToOwned::to_owned),
|
||||
semantics: sc_executor_wasmtime::Semantics {
|
||||
fast_instance_reuse: true,
|
||||
deterministic_stack_limit: None,
|
||||
canonicalize_nans: false,
|
||||
},
|
||||
},
|
||||
host_functions,
|
||||
)
|
||||
.map(|runtime| -> Arc<dyn WasmModule> { Arc::new(runtime) }),
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_version(mut version: &[u8]) -> Result<RuntimeVersion, WasmError> {
|
||||
let v: RuntimeVersion = sp_api::OldRuntimeVersion::decode(&mut &version[..])
|
||||
.map_err(|_|
|
||||
WasmError::Instantiation(
|
||||
"failed to decode \"Core_version\" result using old runtime version".into(),
|
||||
)
|
||||
)?.into();
|
||||
.map_err(|_| {
|
||||
WasmError::Instantiation(
|
||||
"failed to decode \"Core_version\" result using old runtime version".into(),
|
||||
)
|
||||
})?
|
||||
.into();
|
||||
|
||||
let core_api_id = sp_core::hashing::blake2_64(b"Core");
|
||||
if v.has_api_with(&core_api_id, |v| v >= 3) {
|
||||
sp_api::RuntimeVersion::decode(&mut version)
|
||||
.map_err(|_|
|
||||
WasmError::Instantiation("failed to decode \"Core_version\" result".into())
|
||||
)
|
||||
sp_api::RuntimeVersion::decode(&mut version).map_err(|_| {
|
||||
WasmError::Instantiation("failed to decode \"Core_version\" result".into())
|
||||
})
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_runtime_apis(apis: &[u8]) -> Result<Vec<([u8; 8], u32)>, WasmError> {
|
||||
use std::convert::TryFrom;
|
||||
use sp_api::RUNTIME_API_INFO_SIZE;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
apis.chunks(RUNTIME_API_INFO_SIZE)
|
||||
.map(|chunk| {
|
||||
@@ -367,9 +364,7 @@ fn decode_runtime_apis(apis: &[u8]) -> Result<Vec<([u8; 8], u32)>, WasmError> {
|
||||
// completely divide by `RUNTIME_API_INFO_SIZE`.
|
||||
<[u8; RUNTIME_API_INFO_SIZE]>::try_from(chunk)
|
||||
.map(sp_api::deserialize_runtime_api_info)
|
||||
.map_err(|_| {
|
||||
WasmError::Other("a clipped runtime api info declaration".to_owned())
|
||||
})
|
||||
.map_err(|_| WasmError::Other("a clipped runtime api info declaration".to_owned()))
|
||||
})
|
||||
.collect::<Result<Vec<_>, WasmError>>()
|
||||
}
|
||||
@@ -379,9 +374,7 @@ fn decode_runtime_apis(apis: &[u8]) -> Result<Vec<([u8; 8], u32)>, WasmError> {
|
||||
///
|
||||
/// If there are no such sections, it returns `None`. If there is an error during decoding those
|
||||
/// sections, `Err` will be returned.
|
||||
pub fn read_embedded_version(
|
||||
blob: &RuntimeBlob,
|
||||
) -> Result<Option<RuntimeVersion>, WasmError> {
|
||||
pub fn read_embedded_version(blob: &RuntimeBlob) -> Result<Option<RuntimeVersion>, WasmError> {
|
||||
if let Some(mut version_section) = blob.custom_section_contents("runtime_version") {
|
||||
// We do not use `decode_version` here because the runtime_version section is not supposed
|
||||
// to ever contain a legacy version. Apart from that `decode_version` relies on presence
|
||||
@@ -389,9 +382,7 @@ pub fn read_embedded_version(
|
||||
// the structure found in the `runtime_version` always contain an empty `apis` field. Therefore
|
||||
// the version read will be mistakenly treated as an legacy one.
|
||||
let mut decoded_version = sp_api::RuntimeVersion::decode(&mut version_section)
|
||||
.map_err(|_|
|
||||
WasmError::Instantiation("failed to decode version section".into())
|
||||
)?;
|
||||
.map_err(|_| WasmError::Instantiation("failed to decode version section".into()))?;
|
||||
|
||||
// Don't stop on this and check if there is a special section that encodes all runtime APIs.
|
||||
if let Some(apis_section) = blob.custom_section_contents("runtime_apis") {
|
||||
@@ -443,10 +434,10 @@ fn create_versioned_wasm_runtime(
|
||||
// The following unwind safety assertion is OK because if the method call panics, the
|
||||
// runtime will be dropped.
|
||||
let runtime = AssertUnwindSafe(runtime.as_ref());
|
||||
crate::native_executor::with_externalities_safe(
|
||||
&mut **ext,
|
||||
move || runtime.new_instance()?.call("Core_version".into(), &[])
|
||||
).map_err(|_| WasmError::Instantiation("panic in call to get runtime version".into()))?
|
||||
crate::native_executor::with_externalities_safe(&mut **ext, move || {
|
||||
runtime.new_instance()?.call("Core_version".into(), &[])
|
||||
})
|
||||
.map_err(|_| WasmError::Instantiation("panic in call to get runtime version".into()))?
|
||||
};
|
||||
|
||||
if let Ok(version_buf) = version_result {
|
||||
@@ -457,23 +448,16 @@ fn create_versioned_wasm_runtime(
|
||||
let mut instances = Vec::with_capacity(max_instances);
|
||||
instances.resize_with(max_instances, || Mutex::new(None));
|
||||
|
||||
Ok(VersionedRuntime {
|
||||
code_hash,
|
||||
module: runtime,
|
||||
version,
|
||||
heap_pages,
|
||||
wasm_method,
|
||||
instances,
|
||||
})
|
||||
Ok(VersionedRuntime { code_hash, module: runtime, version, heap_pages, wasm_method, instances })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_wasm_interface::HostFunctions;
|
||||
use sp_api::{Core, RuntimeApiInfo};
|
||||
use substrate_test_runtime::Block;
|
||||
use codec::Encode;
|
||||
use sp_api::{Core, RuntimeApiInfo};
|
||||
use sp_wasm_interface::HostFunctions;
|
||||
use substrate_test_runtime::Block;
|
||||
|
||||
#[test]
|
||||
fn host_functions_are_equal() {
|
||||
@@ -533,7 +517,8 @@ mod tests {
|
||||
let wasm = sp_maybe_compressed_blob::decompress(
|
||||
substrate_test_runtime::wasm_binary_unwrap(),
|
||||
sp_maybe_compressed_blob::CODE_BLOB_BOMB_LIMIT,
|
||||
).expect("Decompressing works");
|
||||
)
|
||||
.expect("Decompressing works");
|
||||
|
||||
let runtime_version = RuntimeVersion {
|
||||
spec_name: "test_replace".into(),
|
||||
@@ -545,10 +530,8 @@ mod tests {
|
||||
transaction_version: 100,
|
||||
};
|
||||
|
||||
let embedded = sp_version::embed::embed_runtime_version(
|
||||
&wasm,
|
||||
runtime_version.clone(),
|
||||
).expect("Embedding works");
|
||||
let embedded = sp_version::embed::embed_runtime_version(&wasm, runtime_version.clone())
|
||||
.expect("Embedding works");
|
||||
|
||||
let blob = RuntimeBlob::new(&embedded).expect("Embedded blob is valid");
|
||||
let read_version = read_embedded_version(&blob)
|
||||
|
||||
Reference in New Issue
Block a user