Move Externalities into its own crate (#3775)

* Move `Externalities` into `substrate-externalities`

- `Externalities` now support generic extensions
- Split of `primtives-storage` for storage primitive types

* Move the externalities scoping into `substrate-externalities`

* Fix compilation

* Review feedback

* Adds macro for declaring extensions

* Fix benchmarks

* Introduce `ExtensionStore` trait

* Last review comments

* Implement it for `ExtensionStore`
This commit is contained in:
Bastian Köcher
2019-10-09 15:50:30 +02:00
committed by GitHub
parent 984c6ac839
commit 8a39be474e
95 changed files with 1600 additions and 1420 deletions
+34 -27
View File
@@ -16,15 +16,14 @@
//! Basic implementation for Externalities.
use std::collections::HashMap;
use std::iter::FromIterator;
use std::{collections::HashMap, any::{TypeId, Any}, iter::FromIterator};
use crate::backend::{Backend, InMemory};
use hash_db::Hasher;
use trie::{TrieConfiguration, default_child_trie_root};
use trie::trie_types::Layout;
use primitives::{
storage::well_known_keys::is_child_storage_key, child_storage_key::ChildStorageKey, offchain,
traits::Externalities,
storage::{well_known_keys::is_child_storage_key, ChildStorageKey},
traits::Externalities, Blake2Hasher, hash::H256,
};
use log::warn;
@@ -88,21 +87,37 @@ impl From<HashMap<Vec<u8>, Vec<u8>>> for BasicExternalities {
}
}
impl<H: Hasher> Externalities<H> for BasicExternalities where H::Out: Ord {
impl Externalities for BasicExternalities {
fn storage(&self, key: &[u8]) -> Option<Vec<u8>> {
self.top.get(key).cloned()
}
fn storage_hash(&self, key: &[u8]) -> Option<H256> {
self.storage(key).map(|v| Blake2Hasher::hash(&v))
}
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
Externalities::<H>::storage(self, key)
self.storage(key)
}
fn original_storage_hash(&self, key: &[u8]) -> Option<H256> {
self.storage_hash(key)
}
fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
self.children.get(storage_key.as_ref()).and_then(|child| child.get(key)).cloned()
}
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v))
}
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
self.child_storage_hash(storage_key, key)
}
fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
Externalities::<H>::child_storage(self, storage_key, key)
Externalities::child_storage(self, storage_key, key)
}
fn place_storage(&mut self, key: Vec<u8>, maybe_value: Option<Vec<u8>>) {
@@ -155,16 +170,15 @@ impl<H: Hasher> Externalities<H> for BasicExternalities where H::Out: Ord {
fn chain_id(&self) -> u64 { 42 }
fn storage_root(&mut self) -> H::Out {
fn storage_root(&mut self) -> H256 {
let mut top = self.top.clone();
let keys: Vec<_> = self.children.keys().map(|k| k.to_vec()).collect();
// Single child trie implementation currently allows using the same child
// empty root for all child trie. Using null storage key until multiple
// type of child trie support.
let empty_hash = default_child_trie_root::<Layout<H>>(&[]);
let empty_hash = default_child_trie_root::<Layout<Blake2Hasher>>(&[]);
for storage_key in keys {
let child_root = Externalities::<H>::child_storage_root(
self,
let child_root = self.child_storage_root(
ChildStorageKey::from_slice(storage_key.as_slice())
.expect("Map only feed by valid keys; qed"),
);
@@ -175,30 +189,27 @@ impl<H: Hasher> Externalities<H> for BasicExternalities where H::Out: Ord {
}
}
Layout::<H>::trie_root(self.top.clone())
Layout::<Blake2Hasher>::trie_root(self.top.clone())
}
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8> {
if let Some(child) = self.children.get(storage_key.as_ref()) {
let delta = child.clone().into_iter().map(|(k, v)| (k, Some(v)));
InMemory::<H>::default().child_storage_root(storage_key.as_ref(), delta).0
InMemory::<Blake2Hasher>::default().child_storage_root(storage_key.as_ref(), delta).0
} else {
default_child_trie_root::<Layout<H>>(storage_key.as_ref())
default_child_trie_root::<Layout<Blake2Hasher>>(storage_key.as_ref())
}
}
fn storage_changes_root(&mut self, _parent: H::Out) -> Result<Option<H::Out>, ()> {
fn storage_changes_root(&mut self, _parent: H256) -> Result<Option<H256>, ()> {
Ok(None)
}
}
fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities> {
warn!("Call to non-existent offchain externalities set.");
None
}
fn keystore(&self) -> Option<primitives::traits::BareCryptoStorePtr> {
warn!("Call to non-existent keystore.");
impl externalities::ExtensionStore for BasicExternalities {
fn extension_by_type_id(&mut self, _: TypeId) -> Option<&mut dyn Any> {
warn!("Extensions are not supported by `BasicExternalities`.");
None
}
}
@@ -206,14 +217,13 @@ impl<H: Hasher> Externalities<H> for BasicExternalities where H::Out: Ord {
#[cfg(test)]
mod tests {
use super::*;
use primitives::{Blake2Hasher, H256, map};
use primitives::{H256, map};
use primitives::storage::well_known_keys::CODE;
use hex_literal::hex;
#[test]
fn commit_should_work() {
let mut ext = BasicExternalities::default();
let ext = &mut ext as &mut dyn Externalities<Blake2Hasher>;
ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec());
ext.set_storage(b"dog".to_vec(), b"puppy".to_vec());
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
@@ -225,7 +235,6 @@ mod tests {
#[test]
fn set_and_retrieve_code() {
let mut ext = BasicExternalities::default();
let ext = &mut ext as &mut dyn Externalities<Blake2Hasher>;
let code = vec![1, 2, 3];
ext.set_storage(CODE.to_vec(), code.clone());
@@ -246,8 +255,6 @@ mod tests {
]
);
let ext = &mut ext as &mut dyn Externalities<Blake2Hasher>;
let child = || ChildStorageKey::from_vec(child_storage.clone()).unwrap();
assert_eq!(ext.child_storage(child(), b"doe"), Some(b"reindeer".to_vec()));