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
@@ -111,7 +111,7 @@ fn prepare_extrinsics_input<'a, B, H, Number>(
block: block.clone(),
storage_key: storage_key.clone(),
};
let iter = prepare_extrinsics_input_inner(backend, block, changes, Some(storage_key))?;
children_result.insert(child_index, iter);
}
@@ -120,7 +120,7 @@ fn prepare_extrinsics_input<'a, B, H, Number>(
Ok((top, children_result))
}
fn prepare_extrinsics_input_inner<'a, B, H, Number>(
backend: &'a B,
block: &Number,
@@ -100,7 +100,7 @@ impl<H: Hasher, Number: BlockNumber> InMemoryStorage<H, Number> {
for (storage_key, child_input) in children_inputs {
for (block, pairs) in child_input {
let root = insert_into_memory_db::<H, _>(&mut mdb, pairs.into_iter().map(Into::into));
if let Some(root) = root {
let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) {
ix
+3 -3
View File
@@ -174,13 +174,12 @@ where
}
impl<'a, B, T, H, N, O> Externalities<H> for Ext<'a, H, N, B, T, O>
where
H: Hasher,
where H: Hasher,
B: 'a + Backend<H>,
T: 'a + ChangesTrieStorage<H, N>,
O: 'a + offchain::Externalities,
H::Out: Ord + 'static,
N: crate::changes_trie::BlockNumber,
O: 'a + offchain::Externalities,
{
fn storage(&self, key: &[u8]) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::force_abort();
@@ -371,6 +370,7 @@ where
fn keystore(&self) -> Option<BareCryptoStorePtr> {
self.keystore.clone()
}
}
#[cfg(test)]
+34 -7
View File
@@ -89,13 +89,26 @@ pub enum ExecutionStrategy {
NativeElseWasm,
}
/// Storage backend trust level.
#[derive(Debug, Clone)]
pub enum BackendTrustLevel {
/// Panics from trusted backends are considered justified, and never caught.
Trusted,
/// Panics from untrusted backend are caught and interpreted as runtime error.
/// Untrusted backend may be missing some parts of the trie, so panics are not considered
/// fatal.
Untrusted,
}
/// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure.
#[derive(Clone)]
pub enum ExecutionManager<F> {
/// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm.
NativeWhenPossible,
/// Use the given wasm module.
AlwaysWasm,
/// Use the given wasm module. The backend on which code is executed code could be
/// trusted to provide all storage or not (i.e. the light client cannot be trusted to provide
/// for all storage queries since the storage entries it has come from an external node).
AlwaysWasm(BackendTrustLevel),
/// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepency.
Both(F),
/// First native, then if that fails or is not possible, wasm.
@@ -106,7 +119,7 @@ impl<'a, F> From<&'a ExecutionManager<F>> for ExecutionStrategy {
fn from(s: &'a ExecutionManager<F>) -> Self {
match *s {
ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible,
ExecutionManager::AlwaysWasm => ExecutionStrategy::AlwaysWasm,
ExecutionManager::AlwaysWasm(_) => ExecutionStrategy::AlwaysWasm,
ExecutionManager::NativeElseWasm => ExecutionStrategy::NativeElseWasm,
ExecutionManager::Both(_) => ExecutionStrategy::Both,
}
@@ -119,7 +132,7 @@ impl ExecutionStrategy {
self,
) -> ExecutionManager<DefaultHandler<R, E>> {
match self {
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm,
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted),
ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
ExecutionStrategy::NativeElseWasm => ExecutionManager::NativeElseWasm,
ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| {
@@ -139,6 +152,16 @@ pub fn native_else_wasm<E, R: Decode>() -> ExecutionManager<DefaultHandler<R, E>
ExecutionManager::NativeElseWasm
}
/// Evaluate to ExecutionManager::AlwaysWasm with trusted backend, without having to figure out the type.
fn always_wasm<E, R: Decode>() -> ExecutionManager<DefaultHandler<R, E>> {
ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted)
}
/// Evaluate ExecutionManager::AlwaysWasm with untrusted backend, without having to figure out the type.
fn always_untrusted_wasm<E, R: Decode>() -> ExecutionManager<DefaultHandler<R, E>> {
ExecutionManager::AlwaysWasm(BackendTrustLevel::Untrusted)
}
/// The substrate state machine.
pub struct StateMachine<'a, B, H, N, T, O, Exec> {
backend: B,
@@ -375,7 +398,11 @@ impl<'a, B, H, N, T, O, Exec> StateMachine<'a, B, H, N, T, O, Exec> where
orig_prospective,
)
},
ExecutionManager::AlwaysWasm => {
ExecutionManager::AlwaysWasm(trust_level) => {
let _abort_guard = match trust_level {
BackendTrustLevel::Trusted => None,
BackendTrustLevel::Untrusted => Some(panic_handler::AbortGuard::never_abort()),
};
let res = self.execute_aux(compute_tx, false, native_call);
(res.0, res.2, res.3)
},
@@ -444,7 +471,7 @@ where
);
let (result, _, _) = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
native_else_wasm(),
always_wasm(),
false,
None,
)?;
@@ -490,7 +517,7 @@ where
);
sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
native_else_wasm(),
always_untrusted_wasm(),
false,
None,
).map(|(result, _, _)| result.into_encoded())
+4 -5
View File
@@ -142,11 +142,10 @@ impl<H: Hasher, N: ChangesTrieBlockNumber> From<StorageTuple> for TestExternalit
}
}
impl<H, N> Externalities<H> for TestExternalities<H, N>
where
H: Hasher,
N: ChangesTrieBlockNumber,
H::Out: Ord + 'static
impl<H, N> Externalities<H> for TestExternalities<H, N> where
H: Hasher,
N: ChangesTrieBlockNumber,
H::Out: Ord + 'static,
{
fn storage(&self, key: &[u8]) -> Option<Vec<u8>> {
self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(||