state_machine no_std witness externalities (#6934)

* checkpoint before removing CT from change trie

* before trie backend without tx

* undo

* Started no transaction, but would need using a different root
calculation method, out of the scope of this pr, will roll back.

* Remove NoTransaction.

* partially address review.
dummy stats implementation for no_std.

* Remove ChangeTrieOverlay.

* modified function

* Remove witness_ext

* need noops changes root

* update from cumulus branch

* line break

* remove warning

* line break

* From review: renamings and stats active in no std (except time).

* include cache, exclude change trie cache with individual temporary bad looking
no_std check

* little test

* fuse imports and filter_map prepare_extrinsics_input_inner fold.

* put back ExtInner into Ext, awkward double proto for new function.

* Apply suggestions from code review

* Update primitives/state-machine/Cargo.toml

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
cheme
2020-09-11 12:11:25 +02:00
committed by GitHub
parent 45d26e7419
commit 232a30fdb4
18 changed files with 1209 additions and 794 deletions
+114 -36
View File
@@ -18,23 +18,28 @@
//! Concrete externalities implementation.
use crate::{
StorageKey, StorageValue, OverlayedChanges, StorageTransactionCache,
StorageKey, StorageValue, OverlayedChanges,
backend::Backend,
changes_trie::State as ChangesTrieState,
};
use hash_db::Hasher;
use sp_core::{
offchain::storage::OffchainOverlayedChanges,
storage::{well_known_keys::is_child_storage_key, ChildInfo, TrackedStorageKey},
traits::Externalities, hexdisplay::HexDisplay,
hexdisplay::HexDisplay,
};
use sp_trie::{trie_types::Layout, empty_child_trie_root};
use sp_externalities::{Extensions, Extension};
use sp_externalities::{Externalities, Extensions, Extension,
ExtensionStore};
use codec::{Decode, Encode, EncodeAppend};
use std::{error, fmt, any::{Any, TypeId}};
use log::{warn, trace};
use sp_std::{fmt, any::{Any, TypeId}, vec::Vec, vec, boxed::Box};
use crate::{warn, trace, log_error};
#[cfg(feature = "std")]
use sp_core::offchain::storage::OffchainOverlayedChanges;
#[cfg(feature = "std")]
use crate::changes_trie::State as ChangesTrieState;
use crate::StorageTransactionCache;
#[cfg(feature = "std")]
use std::error;
const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime";
const BENCHMARKING_FN: &str = "\
@@ -42,7 +47,19 @@ const BENCHMARKING_FN: &str = "\
For that reason client started transactions before calling into runtime are not allowed.
Without client transactions the loop condition garantuees the success of the tx close.";
#[cfg(feature = "std")]
fn guard() -> sp_panic_handler::AbortGuard {
sp_panic_handler::AbortGuard::force_abort()
}
#[cfg(not(feature = "std"))]
fn guard() -> () {
()
}
/// Errors that can occur when interacting with the externalities.
#[cfg(feature = "std")]
#[derive(Debug, Copy, Clone)]
pub enum Error<B, E> {
/// Failure to load state data from the backend.
@@ -53,6 +70,7 @@ pub enum Error<B, E> {
Executor(E),
}
#[cfg(feature = "std")]
impl<B: fmt::Display, E: fmt::Display> fmt::Display for Error<B, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@@ -62,6 +80,7 @@ impl<B: fmt::Display, E: fmt::Display> fmt::Display for Error<B, E> {
}
}
#[cfg(feature = "std")]
impl<B: error::Error, E: error::Error> error::Error for Error<B, E> {
fn description(&self) -> &str {
match *self {
@@ -81,30 +100,49 @@ pub struct Ext<'a, H, N, B>
/// The overlayed changes to write to.
overlay: &'a mut OverlayedChanges,
/// The overlayed changes destined for the Offchain DB.
#[cfg(feature = "std")]
offchain_overlay: &'a mut OffchainOverlayedChanges,
/// The storage backend to read from.
backend: &'a B,
/// The cache for the storage transactions.
storage_transaction_cache: &'a mut StorageTransactionCache<B::Transaction, H, N>,
/// Changes trie state to read from.
#[cfg(feature = "std")]
changes_trie_state: Option<ChangesTrieState<'a, H, N>>,
/// Pseudo-unique id used for tracing.
pub id: u16,
/// Dummy usage of N arg.
_phantom: std::marker::PhantomData<N>,
_phantom: sp_std::marker::PhantomData<N>,
/// Extensions registered with this instance.
#[cfg(feature = "std")]
extensions: Option<&'a mut Extensions>,
}
impl<'a, H, N, B> Ext<'a, H, N, B>
where
H: Hasher,
H::Out: Ord + 'static + codec::Codec,
B: 'a + Backend<H>,
N: crate::changes_trie::BlockNumber,
where
H: Hasher,
B: Backend<H>,
N: crate::changes_trie::BlockNumber,
{
/// Create a new `Ext`.
#[cfg(not(feature = "std"))]
pub fn new(
overlay: &'a mut OverlayedChanges,
storage_transaction_cache: &'a mut StorageTransactionCache<B::Transaction, H, N>,
backend: &'a B,
) -> Self {
Ext {
overlay,
backend,
id: 0,
storage_transaction_cache,
_phantom: Default::default(),
}
}
/// Create a new `Ext` from overlayed changes and read-only backend
#[cfg(feature = "std")]
pub fn new(
overlay: &'a mut OverlayedChanges,
offchain_overlay: &'a mut OffchainOverlayedChanges,
@@ -133,6 +171,7 @@ where
}
/// Read only accessor for the scheduled overlay changes.
#[cfg(feature = "std")]
pub fn get_offchain_storage_changes(&self) -> &OffchainOverlayedChanges {
&*self.offchain_overlay
}
@@ -159,14 +198,14 @@ where
}
}
impl<'a, H, B, N> Externalities for Ext<'a, H, N, B>
impl<'a, H, N, B> Externalities for Ext<'a, H, N, B>
where
H: Hasher,
H::Out: Ord + 'static + codec::Codec,
B: 'a + Backend<H>,
B: Backend<H>,
N: crate::changes_trie::BlockNumber,
{
#[cfg(feature = "std")]
fn set_offchain_storage(&mut self, key: &[u8], value: Option<&[u8]>) {
use ::sp_core::offchain::STORAGE_PREFIX;
match value {
@@ -175,8 +214,11 @@ where
}
}
#[cfg(not(feature = "std"))]
fn set_offchain_storage(&mut self, _key: &[u8], _value: Option<&[u8]>) {}
fn storage(&self, key: &[u8]) -> Option<StorageValue> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let result = self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(||
self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL));
trace!(target: "state", "{:04x}: Get {}={:?}",
@@ -188,7 +230,7 @@ where
}
fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let result = self.overlay
.storage(key)
.map(|x| x.map(|x| H::hash(x)))
@@ -207,7 +249,7 @@ where
child_info: &ChildInfo,
key: &[u8],
) -> Option<StorageValue> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let result = self.overlay
.child_storage(child_info, key)
.map(|x| x.map(|x| x.to_vec()))
@@ -231,7 +273,7 @@ where
child_info: &ChildInfo,
key: &[u8],
) -> Option<Vec<u8>> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let result = self.overlay
.child_storage(child_info, key)
.map(|x| x.map(|x| H::hash(x)))
@@ -251,7 +293,7 @@ where
}
fn exists_storage(&self, key: &[u8]) -> bool {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let result = match self.overlay.storage(key) {
Some(x) => x.is_some(),
_ => self.backend.exists_storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL),
@@ -271,7 +313,7 @@ where
child_info: &ChildInfo,
key: &[u8],
) -> bool {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let result = match self.overlay.child_storage(child_info, key) {
Some(x) => x.is_some(),
@@ -337,7 +379,7 @@ where
HexDisplay::from(&key),
value.as_ref().map(HexDisplay::from)
);
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
if is_child_storage_key(&key) {
warn!(target: "trie", "Refuse to directly set child storage key");
return;
@@ -359,7 +401,7 @@ where
HexDisplay::from(&key),
value.as_ref().map(HexDisplay::from)
);
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
self.mark_dirty();
self.overlay.set_child_storage(child_info, key, value);
@@ -373,7 +415,7 @@ where
self.id,
HexDisplay::from(&child_info.storage_key()),
);
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
self.mark_dirty();
self.overlay.clear_child_storage(child_info);
@@ -387,7 +429,7 @@ where
self.id,
HexDisplay::from(&prefix),
);
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
if is_child_storage_key(prefix) {
warn!(target: "trie", "Refuse to directly clear prefix that is part of child storage key");
return;
@@ -410,7 +452,7 @@ where
HexDisplay::from(&child_info.storage_key()),
HexDisplay::from(&prefix),
);
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
self.mark_dirty();
self.overlay.clear_child_prefix(child_info, prefix);
@@ -430,7 +472,7 @@ where
HexDisplay::from(&value),
);
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
self.mark_dirty();
let backend = &mut self.backend;
@@ -446,7 +488,7 @@ where
}
fn storage_root(&mut self) -> Vec<u8> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
if let Some(ref root) = self.storage_transaction_cache.transaction_storage_root {
trace!(target: "state", "{:04x}: Root(cached) {}",
self.id,
@@ -464,7 +506,7 @@ where
&mut self,
child_info: &ChildInfo,
) -> Vec<u8> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let storage_key = child_info.storage_key();
let prefixed_storage_key = child_info.prefixed_storage_key();
if self.storage_transaction_cache.transaction_storage_root.is_some() {
@@ -525,8 +567,14 @@ where
}
}
#[cfg(not(feature = "std"))]
fn storage_changes_root(&mut self, _parent_hash: &[u8]) -> Result<Option<Vec<u8>>, ()> {
Ok(None)
}
#[cfg(feature = "std")]
fn storage_changes_root(&mut self, parent_hash: &[u8]) -> Result<Option<Vec<u8>>, ()> {
let _guard = sp_panic_handler::AbortGuard::force_abort();
let _guard = guard();
let root = self.overlay.changes_trie_root(
self.backend,
self.changes_trie_state.as_ref(),
@@ -569,6 +617,7 @@ where
}
self.overlay.drain_storage_changes(
&self.backend,
#[cfg(feature = "std")]
None,
Default::default(),
self.storage_transaction_cache,
@@ -586,6 +635,7 @@ where
}
let changes = self.overlay.drain_storage_changes(
&self.backend,
#[cfg(feature = "std")]
None,
Default::default(),
self.storage_transaction_cache,
@@ -619,7 +669,6 @@ where
}
}
/// Implement `Encode` by forwarding the stored raw vec.
struct EncodeOpaqueValue(Vec<u8>);
@@ -644,12 +693,12 @@ impl<'a> StorageAppend<'a> {
pub fn append(&mut self, value: Vec<u8>) {
let value = vec![EncodeOpaqueValue(value)];
let item = std::mem::take(self.0);
let item = sp_std::mem::take(self.0);
*self.0 = match Vec::<EncodeOpaqueValue>::append_or_new(item, &value) {
Ok(item) => item,
Err(_) => {
log::error!(
log_error!(
target: "runtime",
"Failed to append value, resetting storage item to `[value]`.",
);
@@ -659,7 +708,36 @@ impl<'a> StorageAppend<'a> {
}
}
impl<'a, H, B, N> sp_externalities::ExtensionStore for Ext<'a, H, N, B>
#[cfg(not(feature = "std"))]
impl<'a, H, N, B> ExtensionStore for Ext<'a, H, N, B>
where
H: Hasher,
H::Out: Ord + 'static + codec::Codec,
B: Backend<H>,
N: crate::changes_trie::BlockNumber,
{
fn extension_by_type_id(&mut self, _type_id: TypeId) -> Option<&mut dyn Any> {
None
}
fn register_extension_with_type_id(
&mut self,
_type_id: TypeId,
_extension: Box<dyn Extension>,
) -> Result<(), sp_externalities::Error> {
Err(sp_externalities::Error::ExtensionsAreNotSupported)
}
fn deregister_extension_by_type_id(
&mut self,
_type_id: TypeId,
) -> Result<(), sp_externalities::Error> {
Err(sp_externalities::Error::ExtensionsAreNotSupported)
}
}
#[cfg(feature = "std")]
impl<'a, H, N, B> ExtensionStore for Ext<'a, H, N, B>
where
H: Hasher,
B: 'a + Backend<H>,