mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-10 21:51:04 +00:00
WIP on chain heap (#639)
* move heap size on chain * fix the interface change * decode heap size * fix code comments * fix comment * update Cargo.lock * rename to heappages * add one heap pages variable in runtime
This commit is contained in:
Generated
+1
@@ -3002,6 +3002,7 @@ dependencies = [
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"triehash 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
]
|
||||
|
||||
@@ -155,7 +155,7 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
|
||||
init_logger(log_pattern);
|
||||
|
||||
// Create client
|
||||
let executor = NativeExecutor::with_heap_pages(8);
|
||||
let executor = NativeExecutor::new();
|
||||
|
||||
let god_key = hex!["3d866ec8a9190c8343c2fc593d21d8a6d0c5c4763aaab2349de3a6111d64d124"];
|
||||
let genesis_config = GenesisConfig {
|
||||
|
||||
@@ -98,7 +98,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn executor() -> ::substrate_executor::NativeExecutor<Executor> {
|
||||
::substrate_executor::NativeExecutor::with_heap_pages(8)
|
||||
::substrate_executor::NativeExecutor::new()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -114,9 +114,9 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call(&mut t, 8, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
assert!(r.is_ok());
|
||||
let v = executor().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap();
|
||||
let v = executor().call(&mut t, 8, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap();
|
||||
let r = ApplyResult::decode(&mut &v[..]).unwrap();
|
||||
assert_eq!(r, Err(ApplyError::CantPay));
|
||||
}
|
||||
@@ -134,9 +134,9 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call(&mut t, 8, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
assert!(r.is_ok());
|
||||
let v = executor().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap();
|
||||
let v = executor().call(&mut t, 8, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0.unwrap();
|
||||
let r = ApplyResult::decode(&mut &v[..]).unwrap();
|
||||
assert_eq!(r, Err(ApplyError::CantPay));
|
||||
}
|
||||
@@ -154,9 +154,9 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call(&mut t, 8, COMPACT_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
assert!(r.is_ok());
|
||||
let r = executor().call(&mut t, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0;
|
||||
let r = executor().call(&mut t, 8, COMPACT_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0;
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
@@ -178,9 +178,9 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Concrete>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
];
|
||||
|
||||
let r = executor().call(&mut t, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
let r = executor().call(&mut t, 8, BLOATY_CODE, "initialise_block", &vec![].and(&from_block_number(1u64)), true).0;
|
||||
assert!(r.is_ok());
|
||||
let r = executor().call(&mut t, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0;
|
||||
let r = executor().call(&mut t, 8, BLOATY_CODE, "apply_extrinsic", &vec![].and(&xt()), true).0;
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
@@ -312,7 +312,7 @@ mod tests {
|
||||
fn full_native_block_import_works() {
|
||||
let mut t = new_test_ext();
|
||||
|
||||
executor().call(&mut t, COMPACT_CODE, "execute_block", &block1().0, true).0.unwrap();
|
||||
executor().call(&mut t, 8, COMPACT_CODE, "execute_block", &block1().0, true).0.unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 41);
|
||||
@@ -329,7 +329,7 @@ mod tests {
|
||||
]);
|
||||
});
|
||||
|
||||
executor().call(&mut t, COMPACT_CODE, "execute_block", &block2().0, true).0.unwrap();
|
||||
executor().call(&mut t, 8, COMPACT_CODE, "execute_block", &block2().0, true).0.unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 30);
|
||||
@@ -359,14 +359,14 @@ mod tests {
|
||||
fn full_wasm_block_import_works() {
|
||||
let mut t = new_test_ext();
|
||||
|
||||
WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap();
|
||||
WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "execute_block", &block1().0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 41);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69);
|
||||
});
|
||||
|
||||
WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap();
|
||||
WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "execute_block", &block2().0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 30);
|
||||
@@ -378,7 +378,7 @@ mod tests {
|
||||
fn wasm_big_block_import_fails() {
|
||||
let mut t = new_test_ext();
|
||||
|
||||
let r = WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0);
|
||||
let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "execute_block", &block1big().0);
|
||||
assert!(!r.is_ok());
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ mod tests {
|
||||
fn native_big_block_import_succeeds() {
|
||||
let mut t = new_test_ext();
|
||||
|
||||
let r = Executor::with_heap_pages(8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0, true).0;
|
||||
let r = Executor::new().call(&mut t, 8, COMPACT_CODE, "execute_block", &block1big().0, true).0;
|
||||
assert!(r.is_ok());
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ mod tests {
|
||||
fn native_big_block_import_fails_on_fallback() {
|
||||
let mut t = new_test_ext();
|
||||
|
||||
let r = Executor::with_heap_pages(8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0, false).0;
|
||||
let r = Executor::new().call(&mut t, 8, COMPACT_CODE, "execute_block", &block1big().0, false).0;
|
||||
assert!(!r.is_ok());
|
||||
}
|
||||
|
||||
@@ -412,9 +412,9 @@ mod tests {
|
||||
];
|
||||
|
||||
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm");
|
||||
let r = WasmExecutor::new(8).call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64)));
|
||||
let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64)));
|
||||
assert!(r.is_ok());
|
||||
let r = WasmExecutor::new(8).call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = ApplyResult::decode(&mut &r[..]).unwrap();
|
||||
assert_eq!(r, Err(ApplyError::CantPay));
|
||||
}
|
||||
@@ -433,9 +433,9 @@ mod tests {
|
||||
];
|
||||
|
||||
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm");
|
||||
let r = WasmExecutor::new(8).call(&mut t, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64)));
|
||||
let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "initialise_block", &vec![].and(&from_block_number(1u64)));
|
||||
assert!(r.is_ok());
|
||||
let r = WasmExecutor::new(8).call(&mut t, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "apply_extrinsic", &vec![].and(&xt())).unwrap();
|
||||
let r = ApplyResult::decode(&mut &r[..]).unwrap();
|
||||
assert_eq!(r, Ok(ApplyOutcome::Success));
|
||||
|
||||
|
||||
Generated
+1
@@ -903,6 +903,7 @@ dependencies = [
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"triehash 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
]
|
||||
|
||||
@@ -125,10 +125,6 @@ args:
|
||||
long: execution
|
||||
value_name: STRATEGY
|
||||
help: The means of execution used when calling into the runtime. Can be either wasm, native or both.
|
||||
- max-heap-pages:
|
||||
long: max-heap-pages
|
||||
value_name: COUNT
|
||||
help: The maximum number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing.
|
||||
subcommands:
|
||||
- build-spec:
|
||||
about: Build a spec.json file, outputing to stdout
|
||||
|
||||
@@ -266,10 +266,6 @@ where
|
||||
service::Roles::FULL
|
||||
};
|
||||
|
||||
if let Some(v) = matches.value_of("max-heap-pages") {
|
||||
config.max_heap_pages = v.parse().map_err(|_| "Invalid --max-heap-pages argument")?;
|
||||
}
|
||||
|
||||
if let Some(s) = matches.value_of("execution") {
|
||||
config.execution_strategy = match s {
|
||||
"both" => service::ExecutionStrategy::Both,
|
||||
@@ -398,10 +394,6 @@ fn import_blocks<F, E>(matches: &clap::ArgMatches, spec: ChainSpec<FactoryGenesi
|
||||
let mut config = service::Configuration::default_with_spec(spec);
|
||||
config.database_path = db_path(&base_path, config.chain_spec.id()).to_string_lossy().into();
|
||||
|
||||
if let Some(v) = matches.value_of("max-heap-pages") {
|
||||
config.max_heap_pages = v.parse().map_err(|_| "Invalid --max-heap-pages argument")?;
|
||||
}
|
||||
|
||||
if let Some(s) = matches.value_of("execution") {
|
||||
config.execution_strategy = match s {
|
||||
"both" => service::ExecutionStrategy::Both,
|
||||
|
||||
@@ -26,6 +26,7 @@ use patricia_trie::NodeCodec;
|
||||
use primitives::{KeccakHasher, RlpCodec};
|
||||
use hashdb::Hasher;
|
||||
use rlp::Encodable;
|
||||
use codec::Decode;
|
||||
|
||||
use backend;
|
||||
use error;
|
||||
@@ -145,8 +146,9 @@ where
|
||||
let mut externalities = Ext::new(&mut overlay, &state);
|
||||
let code = externalities.storage(b":code").ok_or(error::ErrorKind::VersionInvalid)?
|
||||
.to_vec();
|
||||
let heap_pages = externalities.storage(b":heappages").and_then(|v| u64::decode(&mut &v[..])).unwrap_or(8) as usize;
|
||||
|
||||
self.executor.runtime_version(&mut externalities, &code)
|
||||
self.executor.runtime_version(&mut externalities, heap_pages, &code)
|
||||
.ok_or(error::ErrorKind::VersionInvalid.into())
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ mod tests {
|
||||
native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::VERSION, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
|
||||
|
||||
fn executor() -> ::executor::NativeExecutor<Executor> {
|
||||
NativeExecutionDispatch::with_heap_pages(8)
|
||||
NativeExecutionDispatch::new()
|
||||
}
|
||||
|
||||
fn construct_block(backend: &InMemory<KeccakHasher, RlpCodec>, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transfer>) -> (Vec<u8>, Hash) {
|
||||
@@ -194,7 +194,7 @@ mod tests {
|
||||
let _ = execute(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&Executor::with_heap_pages(8),
|
||||
&Executor::new(),
|
||||
"execute_block",
|
||||
&b1data,
|
||||
ExecutionStrategy::NativeWhenPossible,
|
||||
|
||||
@@ -270,7 +270,7 @@ pub mod tests {
|
||||
let remote_read_proof = remote_client.read_proof(&remote_block_id, b":auth:len").unwrap();
|
||||
|
||||
// check remote read proof locally
|
||||
let local_executor = test_client::LocalExecutor::with_heap_pages(8);
|
||||
let local_executor = test_client::LocalExecutor::new();
|
||||
let local_checker = new_fetch_checker::<_, KeccakHasher, RlpCodec>(local_executor);
|
||||
let request = RemoteReadRequest {
|
||||
block: remote_block_hash,
|
||||
|
||||
@@ -156,7 +156,7 @@ mod tests {
|
||||
let remote_execution_proof = remote_client.execution_proof(&remote_block_id, "authorities", &[]).unwrap().1;
|
||||
|
||||
// check remote execution proof locally
|
||||
let local_executor = test_client::LocalExecutor::with_heap_pages(8);
|
||||
let local_executor = test_client::LocalExecutor::new();
|
||||
check_execution_proof::<_, _, _, RlpCodec>(&local_executor, &RemoteCallRequest {
|
||||
block: test_client::runtime::Hash::default(),
|
||||
header: test_client::runtime::Header {
|
||||
|
||||
@@ -87,6 +87,7 @@ pub trait RuntimeInfo {
|
||||
fn runtime_version<E: Externalities<KeccakHasher>> (
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8]
|
||||
) -> Option<RuntimeVersion>;
|
||||
}
|
||||
|
||||
@@ -55,12 +55,13 @@ fn fetch_cached_runtime_version<'a, E: Externalities<KeccakHasher>>(
|
||||
wasm_executor: &WasmExecutor,
|
||||
cache: &'a mut MutexGuard<CacheType>,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8]
|
||||
) -> Result<(&'a WasmModule, &'a Option<RuntimeVersion>)> {
|
||||
let maybe_runtime_preproc = cache.entry(gen_cache_key(code))
|
||||
.or_insert_with(|| match WasmModule::from_buffer(code) {
|
||||
Ok(module) => {
|
||||
let version = wasm_executor.call_in_wasm_module(ext, &module, "version", &[])
|
||||
let version = wasm_executor.call_in_wasm_module(ext, heap_pages, &module, "version", &[])
|
||||
.ok()
|
||||
.and_then(|v| RuntimeVersion::decode(&mut v.as_slice()));
|
||||
RuntimePreproc::ValidCode(module, version)
|
||||
@@ -108,9 +109,9 @@ pub trait NativeExecutionDispatch: Send + Sync {
|
||||
/// Get native runtime version.
|
||||
const VERSION: RuntimeVersion;
|
||||
|
||||
/// Construct corresponding `NativeExecutor` with given `heap_pages`.
|
||||
fn with_heap_pages(max_heap_pages: usize) -> NativeExecutor<Self> where Self: Sized {
|
||||
NativeExecutor::with_heap_pages(max_heap_pages)
|
||||
/// Construct corresponding `NativeExecutor`
|
||||
fn new() -> NativeExecutor<Self> where Self: Sized {
|
||||
NativeExecutor::new()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,11 +126,11 @@ pub struct NativeExecutor<D: NativeExecutionDispatch> {
|
||||
}
|
||||
|
||||
impl<D: NativeExecutionDispatch> NativeExecutor<D> {
|
||||
/// Create new instance with specific number of pages for wasm fallback's heap.
|
||||
pub fn with_heap_pages(max_heap_pages: usize) -> Self {
|
||||
/// Create new instance.
|
||||
pub fn new() -> Self {
|
||||
NativeExecutor {
|
||||
_dummy: Default::default(),
|
||||
fallback: WasmExecutor::new(max_heap_pages),
|
||||
fallback: WasmExecutor::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,9 +150,10 @@ impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
|
||||
fn runtime_version<E: Externalities<KeccakHasher>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8],
|
||||
) -> Option<RuntimeVersion> {
|
||||
fetch_cached_runtime_version(&self.fallback, &mut RUNTIMES_CACHE.lock(), ext, code).ok()?.1.clone()
|
||||
fetch_cached_runtime_version(&self.fallback, &mut RUNTIMES_CACHE.lock(), ext, heap_pages, code).ok()?.1.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,23 +163,24 @@ impl<D: NativeExecutionDispatch> CodeExecutor<KeccakHasher> for NativeExecutor<D
|
||||
fn call<E: Externalities<KeccakHasher>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8],
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
use_native: bool,
|
||||
) -> (Result<Vec<u8>>, bool) {
|
||||
let mut c = RUNTIMES_CACHE.lock();
|
||||
let (module, onchain_version) = match fetch_cached_runtime_version(&self.fallback, &mut c, ext, code) {
|
||||
let (module, onchain_version) = match fetch_cached_runtime_version(&self.fallback, &mut c, ext, heap_pages, code) {
|
||||
Ok((module, onchain_version)) => (module, onchain_version),
|
||||
Err(_) => return (Err(ErrorKind::InvalidCode(code.into()).into()), false),
|
||||
};
|
||||
match (use_native, onchain_version.as_ref().map_or(false, |v| v.can_call_with(&D::VERSION))) {
|
||||
(_, false) => {
|
||||
trace!(target: "executor", "Request for native execution failed (native: {}, chain: {})", D::VERSION, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
|
||||
(self.fallback.call_in_wasm_module(ext, module, method, data), false)
|
||||
(self.fallback.call_in_wasm_module(ext, heap_pages, module, method, data), false)
|
||||
}
|
||||
(false, _) => {
|
||||
(self.fallback.call_in_wasm_module(ext, module, method, data), false)
|
||||
(self.fallback.call_in_wasm_module(ext, heap_pages, module, method, data), false)
|
||||
}
|
||||
_ => {
|
||||
trace!(target: "executor", "Request for native execution succeeded (native: {}, chain: {})", D::VERSION, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
|
||||
@@ -213,8 +216,8 @@ macro_rules! native_executor_instance {
|
||||
.ok_or_else(|| $crate::error::ErrorKind::MethodNotFound(method.to_owned()).into())
|
||||
}
|
||||
|
||||
fn with_heap_pages(max_heap_pages: usize) -> $crate::NativeExecutor<$name> {
|
||||
$crate::NativeExecutor::with_heap_pages(max_heap_pages)
|
||||
fn new() -> $crate::NativeExecutor<$name> {
|
||||
$crate::NativeExecutor::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,7 +554,7 @@ mod tests {
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_sandbox", &code).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
@@ -575,7 +575,7 @@ mod tests {
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_sandbox", &code).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(),
|
||||
vec![0],
|
||||
);
|
||||
}
|
||||
@@ -613,7 +613,7 @@ mod tests {
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_sandbox", &code).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
@@ -647,7 +647,7 @@ mod tests {
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_sandbox_args", &code).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_args", &code).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
@@ -669,7 +669,7 @@ mod tests {
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_sandbox_return_val", &code).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_return_val", &code).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -496,47 +496,36 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
/// Wasm rust executor for contracts.
|
||||
///
|
||||
/// Executes the provided code in a sandboxed wasm runtime.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WasmExecutor {
|
||||
/// The max number of pages to allocate for the heap.
|
||||
pub max_heap_pages: usize,
|
||||
}
|
||||
|
||||
impl Clone for WasmExecutor {
|
||||
fn clone(&self) -> Self {
|
||||
WasmExecutor {
|
||||
max_heap_pages: self.max_heap_pages,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmExecutor {
|
||||
|
||||
/// Create a new instance.
|
||||
pub fn new(max_heap_pages: usize) -> Self {
|
||||
WasmExecutor {
|
||||
max_heap_pages,
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
WasmExecutor{}
|
||||
}
|
||||
|
||||
|
||||
/// Call a given method in the given code.
|
||||
/// This should be used for tests only.
|
||||
pub fn call<E: Externalities<KeccakHasher>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8],
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>> {
|
||||
let module = ::wasmi::Module::from_buffer(code).expect("all modules compiled with rustc are valid wasm code; qed");
|
||||
self.call_in_wasm_module(ext, &module, method, data)
|
||||
self.call_in_wasm_module(ext, heap_pages, &module, method, data)
|
||||
}
|
||||
|
||||
/// Call a given method in the given wasm-module runtime.
|
||||
pub fn call_in_wasm_module<E: Externalities<KeccakHasher>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
module: &Module,
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
@@ -564,7 +553,7 @@ impl WasmExecutor {
|
||||
.export_by_name("__indirect_function_table")
|
||||
.and_then(|e| e.as_table().cloned());
|
||||
|
||||
let mut fec = FunctionExecutor::new(memory.clone(), self.max_heap_pages, table, ext)?;
|
||||
let mut fec = FunctionExecutor::new(memory.clone(), heap_pages, table, ext)?;
|
||||
|
||||
// finish instantiation by running 'start' function (if any).
|
||||
let instance = intermediate_instance.run_start(&mut fec)?;
|
||||
@@ -585,7 +574,7 @@ impl WasmExecutor {
|
||||
let returned = match result {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
trace!(target: "wasm-executor", "Failed to execute code with {} pages", self.max_heap_pages);
|
||||
trace!(target: "wasm-executor", "Failed to execute code with {} pages", heap_pages);
|
||||
return Err(e.into())
|
||||
},
|
||||
};
|
||||
@@ -620,7 +609,7 @@ mod tests {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
let output = WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_empty_return", &[]).unwrap();
|
||||
let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_empty_return", &[]).unwrap();
|
||||
assert_eq!(output, vec![0u8; 0]);
|
||||
}
|
||||
|
||||
@@ -629,10 +618,10 @@ mod tests {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
let output = WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_panic", &[]);
|
||||
let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_panic", &[]);
|
||||
assert!(output.is_err());
|
||||
|
||||
let output = WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_conditional_panic", &[2]);
|
||||
let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_conditional_panic", &[2]);
|
||||
assert!(output.is_err());
|
||||
}
|
||||
|
||||
@@ -642,7 +631,7 @@ mod tests {
|
||||
ext.set_storage(b"foo".to_vec(), b"bar".to_vec());
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
let output = WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_data_in", b"Hello world").unwrap();
|
||||
let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_data_in", b"Hello world").unwrap();
|
||||
|
||||
assert_eq!(output, b"all ok!".to_vec());
|
||||
|
||||
@@ -665,7 +654,7 @@ mod tests {
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
// This will clear all entries which prefix is "ab".
|
||||
let output = WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_clear_prefix", b"ab").unwrap();
|
||||
let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_clear_prefix", b"ab").unwrap();
|
||||
|
||||
assert_eq!(output, b"all ok!".to_vec());
|
||||
|
||||
@@ -682,11 +671,11 @@ mod tests {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_blake2_256", &[]).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_blake2_256", &[]).unwrap(),
|
||||
blake2_256(&b""[..]).encode()
|
||||
);
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_blake2_256", b"Hello world!").unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_blake2_256", b"Hello world!").unwrap(),
|
||||
blake2_256(&b"Hello world!"[..]).encode()
|
||||
);
|
||||
}
|
||||
@@ -696,11 +685,11 @@ mod tests {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_twox_256", &[]).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_256", &[]).unwrap(),
|
||||
hex!("99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a")
|
||||
);
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_twox_256", b"Hello world!").unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_256", b"Hello world!").unwrap(),
|
||||
hex!("b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74")
|
||||
);
|
||||
}
|
||||
@@ -710,11 +699,11 @@ mod tests {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_twox_128", &[]).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_128", &[]).unwrap(),
|
||||
hex!("99e9d85137db46ef4bbea33613baafd5")
|
||||
);
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_twox_128", b"Hello world!").unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_128", b"Hello world!").unwrap(),
|
||||
hex!("b27dfd7f223f177f2a13647b533599af")
|
||||
);
|
||||
}
|
||||
@@ -730,7 +719,7 @@ mod tests {
|
||||
calldata.extend_from_slice(sig.as_ref());
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_ed25519_verify", &calldata).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_ed25519_verify", &calldata).unwrap(),
|
||||
vec![1]
|
||||
);
|
||||
|
||||
@@ -740,7 +729,7 @@ mod tests {
|
||||
calldata.extend_from_slice(other_sig.as_ref());
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_ed25519_verify", &calldata).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_ed25519_verify", &calldata).unwrap(),
|
||||
vec![0]
|
||||
);
|
||||
}
|
||||
@@ -750,7 +739,7 @@ mod tests {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
assert_eq!(
|
||||
WasmExecutor::new(8).call(&mut ext, &test_code[..], "test_enumerated_trie_root", &[]).unwrap(),
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_enumerated_trie_root", &[]).unwrap(),
|
||||
ordered_trie_root(vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]).0.encode()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,8 +59,6 @@ pub struct Configuration<C, G: Serialize + DeserializeOwned + BuildStorage> {
|
||||
pub name: String,
|
||||
/// Execution strategy.
|
||||
pub execution_strategy: ExecutionStrategy,
|
||||
/// Maximum number of heap pages to allocate for Wasm execution.
|
||||
pub max_heap_pages: usize,
|
||||
/// RPC over HTTP binding address. `None` if disabled.
|
||||
pub rpc_http: Option<SocketAddr>,
|
||||
/// RPC over Websockets binding address. `None` if disabled.
|
||||
@@ -88,7 +86,6 @@ impl<C: Default, G: Serialize + DeserializeOwned + BuildStorage> Configuration<C
|
||||
telemetry: Default::default(),
|
||||
pruning: PruningMode::default(),
|
||||
execution_strategy: ExecutionStrategy::Both,
|
||||
max_heap_pages: 1024,
|
||||
rpc_http: None,
|
||||
rpc_ws: None,
|
||||
telemetry_url: None,
|
||||
|
||||
@@ -100,7 +100,7 @@ pub struct Service<Components: components::Components> {
|
||||
pub fn new_client<Factory: components::ServiceFactory>(config: FactoryFullConfiguration<Factory>)
|
||||
-> Result<Arc<ComponentClient<components::FullComponents<Factory>>>, error::Error>
|
||||
{
|
||||
let executor = NativeExecutor::with_heap_pages(config.max_heap_pages);
|
||||
let executor = NativeExecutor::new();
|
||||
let (client, _) = components::FullComponents::<Factory>::build_client(
|
||||
&config,
|
||||
executor,
|
||||
@@ -122,7 +122,7 @@ impl<Components> Service<Components>
|
||||
let (signal, exit) = ::exit_future::signal();
|
||||
|
||||
// Create client
|
||||
let executor = NativeExecutor::with_heap_pages(config.max_heap_pages);
|
||||
let executor = NativeExecutor::new();
|
||||
|
||||
let mut keystore = Keystore::open(config.keystore_path.as_str().into())?;
|
||||
for seed in &config.keys {
|
||||
|
||||
@@ -12,6 +12,7 @@ parking_lot = "0.4"
|
||||
heapsize = "0.4"
|
||||
|
||||
substrate-primitives = { path = "../primitives", version = "0.1.0" }
|
||||
substrate-codec = { path = "../codec", default_features = false }
|
||||
|
||||
hashdb = { git = "https://github.com/paritytech/parity-common" }
|
||||
memorydb = { git = "https://github.com/paritytech/parity-common" }
|
||||
|
||||
@@ -34,6 +34,7 @@ extern crate rlp;
|
||||
extern crate heapsize;
|
||||
#[cfg(test)]
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_codec as codec;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
@@ -41,6 +42,7 @@ use hashdb::Hasher;
|
||||
use patricia_trie::NodeCodec;
|
||||
use rlp::Encodable;
|
||||
use heapsize::HeapSizeOf;
|
||||
use codec::Decode;
|
||||
|
||||
pub mod backend;
|
||||
mod ext;
|
||||
@@ -206,6 +208,7 @@ pub trait CodeExecutor<H: Hasher>: Sized + Send + Sync {
|
||||
fn call<E: Externalities<H>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8],
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
@@ -325,6 +328,9 @@ where
|
||||
.ok_or_else(|| Box::new(ExecutionError::CodeEntryDoesNotExist) as Box<Error>)?
|
||||
.to_vec();
|
||||
|
||||
let heap_pages = ext::Ext::new(overlay, backend).storage(b":heappages")
|
||||
.and_then(|v| u64::decode(&mut &v[..])).unwrap_or(8) as usize;
|
||||
|
||||
let result = {
|
||||
let mut orig_prospective = overlay.prospective.clone();
|
||||
|
||||
@@ -334,6 +340,7 @@ where
|
||||
(
|
||||
exec.call(
|
||||
&mut externalities,
|
||||
heap_pages,
|
||||
&code,
|
||||
method,
|
||||
call_data,
|
||||
@@ -358,6 +365,7 @@ where
|
||||
(
|
||||
exec.call(
|
||||
&mut externalities,
|
||||
heap_pages,
|
||||
&code,
|
||||
method,
|
||||
call_data,
|
||||
@@ -488,6 +496,7 @@ mod tests {
|
||||
fn call<E: Externalities<H>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
_heap_pages: usize,
|
||||
_code: &[u8],
|
||||
_method: &str,
|
||||
_data: &[u8],
|
||||
|
||||
@@ -39,7 +39,7 @@ pub trait TestClient {
|
||||
|
||||
impl TestClient for Client<Backend, Executor, runtime::Block> {
|
||||
fn new_for_tests() -> Self {
|
||||
client::new_in_mem(NativeExecutor::with_heap_pages(8), genesis_storage()).unwrap()
|
||||
client::new_in_mem(NativeExecutor::new(), genesis_storage()).unwrap()
|
||||
}
|
||||
|
||||
fn justify_and_import(&self, origin: client::BlockOrigin, block: runtime::Block) -> client::error::Result<()> {
|
||||
|
||||
@@ -43,6 +43,7 @@ impl GenesisConfig {
|
||||
.map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec()))
|
||||
.chain(vec![
|
||||
(b":code"[..].into(), wasm_runtime),
|
||||
(b":heappages"[..].into(), vec![].and(&(16 as u64))),
|
||||
(b":auth:len"[..].into(), vec![].and(&(self.authorities.len() as u32))),
|
||||
].into_iter())
|
||||
.chain(self.authorities.iter()
|
||||
|
||||
@@ -661,6 +661,7 @@ dependencies = [
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"substrate-codec 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"triehash 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user