Never panic during execution proof check (#3504)

* do not panic during execution proof check

* Update core/state-machine/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Update core/state-machine/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Update core/state-machine/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* BackendTrustLevel enum

* up runtime version

* Update core/state-machine/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Update core/state-machine/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* fixed some grumbles

* Update core/state-machine/src/testing.rs

Co-Authored-By: Gavin Wood <gavin@parity.io>

* Update core/state-machine/src/lib.rs

Co-Authored-By: Gavin Wood <gavin@parity.io>

* mov where

* spaces -> tabs (to restart build)
This commit is contained in:
Svyatoslav Nikolsky
2019-09-11 10:27:32 +03:00
committed by GitHub
parent 9607afd629
commit 010395e620
18 changed files with 254 additions and 78 deletions
+70 -19
View File
@@ -19,7 +19,7 @@
//! This module defines and implements the wasm part of Substrate Host Interface and provides
//! an interface for calling into the wasm runtime.
use std::{convert::TryFrom, str};
use std::{convert::TryFrom, str, panic};
use tiny_keccak;
use secp256k1;
@@ -31,8 +31,8 @@ use crate::error::{Error, Result};
use codec::{Encode, Decode};
use primitives::{
blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, Pair, crypto::KeyTypeId,
offchain, hexdisplay::HexDisplay, sandbox as sandbox_primitives, H256, Blake2Hasher,
traits::Externalities, child_storage_key::ChildStorageKey,
offchain, hexdisplay::HexDisplay, sandbox as sandbox_primitives, Blake2Hasher,
traits::Externalities,
};
use trie::{TrieConfiguration, trie_types::Layout};
use crate::sandbox;
@@ -447,7 +447,9 @@ impl_wasm_host_interface! {
.map_err(|_| "Invalid attempt to determine key in ext_set_storage")?;
let value = context.read_memory(value_data, value_len)
.map_err(|_| "Invalid attempt to determine value in ext_set_storage")?;
runtime_io::set_storage(&key, &value);
with_external_storage(move ||
Ok(runtime_io::set_storage(&key, &value))
)?;
Ok(())
}
@@ -466,7 +468,9 @@ impl_wasm_host_interface! {
let value = context.read_memory(value_data, value_len)
.map_err(|_| "Invalid attempt to determine value in ext_set_child_storage")?;
runtime_io::set_child_storage(&storage_key, &key, &value);
with_external_storage(move ||
Ok(runtime_io::set_child_storage(&storage_key, &key, &value))
)?;
Ok(())
}
@@ -481,21 +485,27 @@ impl_wasm_host_interface! {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to determine key in ext_clear_child_storage")?;
runtime_io::clear_child_storage(&storage_key, &key);
with_external_storage(move ||
Ok(runtime_io::clear_child_storage(&storage_key, &key))
)?;
Ok(())
}
ext_clear_storage(key_data: Pointer<u8>, key_len: WordSize) {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to determine key in ext_clear_storage")?;
runtime_io::clear_storage(&key);
with_external_storage(move ||
Ok(runtime_io::clear_storage(&key))
)?;
Ok(())
}
ext_exists_storage(key_data: Pointer<u8>, key_len: WordSize) -> u32 {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to determine key in ext_exists_storage")?;
Ok(if runtime_io::exists_storage(&key) { 1 } else { 0 })
with_external_storage(move ||
Ok(if runtime_io::exists_storage(&key) { 1 } else { 0 })
)
}
ext_exists_child_storage(
@@ -509,13 +519,17 @@ impl_wasm_host_interface! {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to determine key in ext_exists_child_storage")?;
Ok(if runtime_io::exists_child_storage(&storage_key, &key) { 1 } else { 0 })
with_external_storage(move ||
Ok(if runtime_io::exists_child_storage(&storage_key, &key) { 1 } else { 0 })
)
}
ext_clear_prefix(prefix_data: Pointer<u8>, prefix_len: WordSize) {
let prefix = context.read_memory(prefix_data, prefix_len)
.map_err(|_| "Invalid attempt to determine prefix in ext_clear_prefix")?;
runtime_io::clear_prefix(&prefix);
with_external_storage(move ||
Ok(runtime_io::clear_prefix(&prefix))
)?;
Ok(())
}
@@ -529,7 +543,9 @@ impl_wasm_host_interface! {
.map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_prefix")?;
let prefix = context.read_memory(prefix_data, prefix_len)
.map_err(|_| "Invalid attempt to determine prefix in ext_clear_child_prefix")?;
runtime_io::clear_child_prefix(&storage_key, &prefix);
with_external_storage(move ||
Ok(runtime_io::clear_child_prefix(&storage_key, &prefix))
)?;
Ok(())
}
@@ -537,7 +553,9 @@ impl_wasm_host_interface! {
ext_kill_child_storage(storage_key_data: Pointer<u8>, storage_key_len: WordSize) {
let storage_key = context.read_memory(storage_key_data, storage_key_len)
.map_err(|_| "Invalid attempt to determine storage_key in ext_kill_child_storage")?;
runtime_io::kill_child_storage(&storage_key);
with_external_storage(move ||
Ok(runtime_io::kill_child_storage(&storage_key))
)?;
Ok(())
}
@@ -549,7 +567,9 @@ impl_wasm_host_interface! {
) -> Pointer<u8> {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to determine key in ext_get_allocated_storage")?;
let maybe_value = runtime_io::storage(&key);
let maybe_value = with_external_storage(move ||
Ok(runtime_io::storage(&key))
)?;
if let Some(value) = maybe_value {
let offset = context.allocate_memory(value.len() as u32)?;
@@ -577,7 +597,9 @@ impl_wasm_host_interface! {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to determine key in ext_get_allocated_child_storage")?;
let maybe_value = runtime_io::child_storage(&storage_key, &key);
let maybe_value = with_external_storage(move ||
Ok(runtime_io::child_storage(&storage_key, &key))
)?;
if let Some(value) = maybe_value {
let offset = context.allocate_memory(value.len() as u32)?;
@@ -602,7 +624,9 @@ impl_wasm_host_interface! {
) -> WordSize {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to get key in ext_get_storage_into")?;
let maybe_value = runtime_io::storage(&key);
let maybe_value = with_external_storage(move ||
Ok(runtime_io::storage(&key))
)?;
if let Some(value) = maybe_value {
let value = &value[value_offset as usize..];
@@ -629,7 +653,9 @@ impl_wasm_host_interface! {
let key = context.read_memory(key_data, key_len)
.map_err(|_| "Invalid attempt to get key in ext_get_child_storage_into")?;
let maybe_value = runtime_io::child_storage(&storage_key, &key);
let maybe_value = with_external_storage(move ||
Ok(runtime_io::child_storage(&storage_key, &key))
)?;
if let Some(value) = maybe_value {
let value = &value[value_offset as usize..];
@@ -643,7 +669,9 @@ impl_wasm_host_interface! {
}
ext_storage_root(result: Pointer<u8>) {
let r = runtime_io::storage_root();
let r = with_external_storage(move ||
Ok(runtime_io::storage_root())
)?;
context.write_memory(result, r.as_ref())
.map_err(|_| "Invalid attempt to set memory in ext_storage_root")?;
Ok(())
@@ -656,7 +684,9 @@ impl_wasm_host_interface! {
) -> Pointer<u8> {
let storage_key = context.read_memory(storage_key_data, storage_key_len)
.map_err(|_| "Invalid attempt to determine storage_key in ext_child_storage_root")?;
let value = runtime_io::child_storage_root(&storage_key);
let value = with_external_storage(move ||
Ok(runtime_io::child_storage_root(&storage_key))
)?;
let offset = context.allocate_memory(value.len() as u32)?;
context.write_memory(offset, &value)
@@ -674,7 +704,9 @@ impl_wasm_host_interface! {
let mut parent_hash = [0u8; 32];
context.read_memory_into(parent_hash_data, &mut parent_hash[..])
.map_err(|_| "Invalid attempt to get parent_hash in ext_storage_changes_root")?;
let r = runtime_io::storage_changes_root(parent_hash);
let r = with_external_storage(move ||
Ok(runtime_io::storage_changes_root(parent_hash))
)?;
if let Some(r) = r {
context.write_memory(result, &r[..])
@@ -1331,6 +1363,25 @@ impl_wasm_host_interface! {
}
}
/// Execute closure that access external storage.
///
/// All panics that happen within closure are captured and transformed into
/// runtime error. This requires special panic handler mode to be enabled
/// during the call (see `panic_handler::AbortGuard::never_abort`).
/// If this mode isn't enabled, then all panics within externalities are
/// leading to process abort.
fn with_external_storage<T, F>(f: F) -> std::result::Result<T, String>
where
F: panic::UnwindSafe + FnOnce() -> Result<T>
{
// it is safe beause basic methods of StorageExternalities are guaranteed to touch only
// its internal state + we should discard it on error
panic::catch_unwind(move || f())
.map_err(|_| Error::Runtime)
.and_then(|result| result)
.map_err(|err| format!("{}", err))
}
/// Wasm rust executor for contracts.
///
/// Executes the provided code in a sandboxed wasm runtime.