-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Use parity-common to make substrate generic over hasher and trie encoding codec #297
Changes from 9 commits
45e0ee8
eb26a69
acf8284
90707dc
4ccc851
21b7892
6b2fa02
f331b0c
f0f2413
87740d7
a34f614
c7503ad
711da4f
a70f4a0
b4f210a
3b5f60b
1aeb495
f7c30f4
80c96a1
e3277ac
d38216b
5f19c7b
848ce8f
1358bb9
9b8f417
ca01909
9e42668
0f77d2b
402c35c
85b5fe1
56649b6
5e5e61e
fc14711
05d8200
65c4f64
56f9ef6
eac3f25
f3422c5
aa40b78
54a2b66
277aadd
02a302a
dae069b
7a93cf7
6329abb
dc7fc67
d7c0935
a553f31
9bfe799
e4cefb3
6277110
adc13a2
252bbd8
c94018c
c49609d
0fb6dc1
6ebfc7f
056bffd
ccb61a9
f565cf9
d11d578
c7334b2
b6bde9a
08f25d3
9b139b2
0c82f95
50b4b12
111f9fd
1276733
334e008
2faff87
751fe9e
81d7278
dd551a6
dcd9541
2370a16
0d4a4fe
6367815
cf7e338
af1b17e
ca89697
da711ef
3b206c2
8064c6d
0066026
bfcf5df
35b29ba
04b7065
8152a78
cafe669
11ea517
4d14020
19d07db
60df8c1
6833f7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| /target/ | ||
| **/target/ | ||
| **/*.rs.bk | ||
| *.swp | ||
| .wasm-binaries | ||
|
|
||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,12 +6,12 @@ authors = ["Parity Technologies <[email protected]>"] | |
| [dependencies] | ||
| parking_lot = "0.4" | ||
| log = "0.3" | ||
| kvdb = { git = "https://github.com/paritytech/parity.git" } | ||
| kvdb-rocksdb = { git = "https://github.com/paritytech/parity.git" } | ||
| kvdb = { git = "https://github.com/paritytech/parity-common" } | ||
| kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common" } | ||
| ethereum-types = "0.3" | ||
| hashdb = { git = "https://github.com/paritytech/parity.git" } | ||
| patricia-trie = { git = "https://github.com/paritytech/parity.git" } | ||
| memorydb = { git = "https://github.com/paritytech/parity.git" } | ||
| hashdb = { git = "https://github.com/paritytech/parity-common" } | ||
| patricia-trie = { git = "https://github.com/paritytech/parity-common" } | ||
| memorydb = { git = "https://github.com/paritytech/parity-common" } | ||
| substrate-primitives = { path = "../../../substrate/primitives" } | ||
| substrate-runtime-primitives = { path = "../../../substrate/runtime/primitives" } | ||
| substrate-client = { path = "../../../substrate/client" } | ||
|
|
@@ -22,4 +22,4 @@ substrate-executor = { path = "../../../substrate/executor" } | |
| substrate-state-db = { path = "../../../substrate/state-db" } | ||
|
|
||
| [dev-dependencies] | ||
| kvdb-memorydb = { git = "https://github.com/paritytech/parity.git" } | ||
| kvdb-memorydb = { git = "https://github.com/paritytech/parity-common" } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ version = "0.1.0" | |
| authors = ["Parity Technologies <[email protected]>"] | ||
|
|
||
| [dependencies] | ||
| ethcore-crypto = { git = "https://github.com/paritytech/parity.git", default_features = false } | ||
| parity-crypto = { git = "https://github.com/paritytech/parity-common.git", default_features = false } | ||
| ed25519 = { path = "../ed25519" } | ||
| error-chain = "0.12" | ||
| hex = "0.3" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,15 +17,21 @@ | |
| //! State machine backends. These manage the code and storage of contracts. | ||
|
|
||
| use std::{error, fmt}; | ||
| use std::cmp::Ord; | ||
| use std::collections::HashMap; | ||
| use std::marker::PhantomData; | ||
| use std::sync::Arc; | ||
|
|
||
| use hashdb::Hasher; | ||
| use rlp::Encodable; | ||
| use trie_backend::{TryIntoTrieBackend, TrieBackend}; | ||
| use patricia_trie::{TrieDBMut, TrieMut, NodeCodec}; | ||
|
|
||
| /// A state backend is used to read state data and can have changes committed | ||
| /// to it. | ||
| /// | ||
| /// The clone operation (if implemented) should be cheap. | ||
| pub trait Backend: TryIntoTrieBackend { | ||
| pub trait Backend<H: Hasher, C: NodeCodec<H>>: TryIntoTrieBackend<H, C> { | ||
| /// An error type when fetching data is not possible. | ||
| type Error: super::Error; | ||
|
|
||
|
|
@@ -41,8 +47,10 @@ pub trait Backend: TryIntoTrieBackend { | |
|
|
||
| /// Calculate the storage root, with given delta over what is already stored in | ||
| /// the backend, and produce a "transaction" that can be used to commit. | ||
| fn storage_root<I>(&self, delta: I) -> ([u8; 32], Self::Transaction) | ||
| where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>; | ||
| fn storage_root<I>(&self, delta: I) -> (H::Out, Self::Transaction) | ||
| where | ||
| I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>, | ||
| H::Out: Ord + Encodable; | ||
|
|
||
| /// Get all key/value pairs into a Vec. | ||
| fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)>; | ||
|
|
@@ -66,21 +74,25 @@ impl error::Error for Void { | |
| /// In-memory backend. Fully recomputes tries on each commit but useful for | ||
| /// tests. | ||
| #[derive(Clone, PartialEq, Eq)] | ||
| pub struct InMemory { | ||
| pub struct InMemory<H, C> { | ||
| inner: Arc<HashMap<Vec<u8>, Vec<u8>>>, | ||
| _hasher: PhantomData<H>, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Curious: why did you opt for an underscore here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No real good reason. I keep going back and forth on how to name my phantoms, so I end up being inconsistent. Sometimes I like I'd like to have a rule to follow here. What do you use?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clippy states that underscore-prefixed names are expected to be in there for compile-passing-purposes only and aren't actually used. Which is the case here, and combined with a proper descriptive name, I think this is totally the appropriate way to do it, @dvdplm :) .
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "compile-passing-purposes" – rofl |
||
| _codec: PhantomData<C>, | ||
| } | ||
|
|
||
| impl Default for InMemory { | ||
| impl<H, C> Default for InMemory<H, C> { | ||
| fn default() -> Self { | ||
| InMemory { | ||
| inner: Arc::new(Default::default()), | ||
| _hasher: PhantomData, | ||
| _codec: PhantomData, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl InMemory { | ||
| impl<H: Hasher, C: NodeCodec<H>> InMemory<H, C> { | ||
| /// Copy the state, with applied updates | ||
| pub fn update(&self, changes: <Self as Backend>::Transaction) -> Self { | ||
| pub fn update(&self, changes: <Self as Backend<H, C>>::Transaction) -> Self { | ||
| let mut inner: HashMap<_, _> = (&*self.inner).clone(); | ||
| for (key, val) in changes { | ||
| match val { | ||
|
|
@@ -93,15 +105,15 @@ impl InMemory { | |
| } | ||
| } | ||
|
|
||
| impl From<HashMap<Vec<u8>, Vec<u8>>> for InMemory { | ||
| impl<H, C> From<HashMap<Vec<u8>, Vec<u8>>> for InMemory<H, C> { | ||
| fn from(inner: HashMap<Vec<u8>, Vec<u8>>) -> Self { | ||
| InMemory { | ||
| inner: Arc::new(inner), | ||
| inner: Arc::new(inner), _hasher: PhantomData, _codec: PhantomData | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Backend for InMemory { | ||
| impl<H: Hasher, C: NodeCodec<H>> Backend<H, C> for InMemory<H, C> { | ||
| type Error = Void; | ||
| type Transaction = Vec<(Vec<u8>, Option<Vec<u8>>)>; | ||
|
|
||
|
|
@@ -113,17 +125,19 @@ impl Backend for InMemory { | |
| self.inner.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f); | ||
| } | ||
|
|
||
| fn storage_root<I>(&self, delta: I) -> ([u8; 32], Self::Transaction) | ||
| where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)> | ||
| fn storage_root<I>(&self, delta: I) -> (H::Out, Self::Transaction) | ||
| where | ||
| I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>, | ||
| <H as Hasher>::Out: Ord + Encodable, | ||
| { | ||
| let existing_pairs = self.inner.iter().map(|(k, v)| (k.clone(), Some(v.clone()))); | ||
|
|
||
| let transaction: Vec<_> = delta.into_iter().collect(); | ||
| let root = ::triehash::trie_root(existing_pairs.chain(transaction.iter().cloned()) | ||
| let root = ::triehash::trie_root::<H, _, _, _>(existing_pairs.chain(transaction.iter().cloned()) | ||
| .collect::<HashMap<_, _>>() | ||
| .into_iter() | ||
| .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) | ||
| ).0; | ||
| ); | ||
|
|
||
| (root, transaction) | ||
| } | ||
|
|
@@ -133,16 +147,13 @@ impl Backend for InMemory { | |
| } | ||
| } | ||
|
|
||
| impl TryIntoTrieBackend for InMemory { | ||
| fn try_into_trie_backend(self) -> Option<TrieBackend> { | ||
| use ethereum_types::H256 as TrieH256; | ||
| impl<H: Hasher, C: NodeCodec<H>> TryIntoTrieBackend<H, C> for InMemory<H, C> { | ||
| fn try_into_trie_backend(self) -> Option<TrieBackend<H, C>> { | ||
| use memorydb::MemoryDB; | ||
| use patricia_trie::{TrieDBMut, TrieMut}; | ||
|
|
||
| let mut root = TrieH256::default(); | ||
| let mut mdb = MemoryDB::default(); | ||
| let mut root = <H as Hasher>::Out::default(); | ||
| let mut mdb = MemoryDB::new(); | ||
| { | ||
| let mut trie = TrieDBMut::new(&mut mdb, &mut root); | ||
| let mut trie = TrieDBMut::<H, C>::new(&mut mdb, &mut root); | ||
| for (key, value) in self.inner.iter() { | ||
| if let Err(e) = trie.insert(&key, &value) { | ||
| warn!(target: "trie", "Failed to write to trie: {}", e); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,9 +16,12 @@ | |
|
|
||
| //! Conrete externalities implementation. | ||
|
|
||
| use std::{error, fmt}; | ||
| use std::{error, fmt, cmp::Ord}; | ||
| use backend::Backend; | ||
| use {Externalities, OverlayedChanges}; | ||
| use hashdb::Hasher; | ||
| use rlp::Encodable; | ||
| use patricia_trie::NodeCodec; | ||
|
|
||
| /// Errors that can occur when interacting with the externalities. | ||
| #[derive(Debug, Copy, Clone)] | ||
|
|
@@ -50,16 +53,22 @@ impl<B: error::Error, E: error::Error> error::Error for Error<B, E> { | |
| } | ||
|
|
||
| /// Wraps a read-only backend, call executor, and current overlayed changes. | ||
| pub struct Ext<'a, B: 'a + Backend> { | ||
| pub struct Ext<'a, H: Hasher, C: NodeCodec<H>, B: 'a + Backend<H, C>> { //TODO: can I get rid of the trait bounds here? | ||
| // The overlayed changes to write to. | ||
| overlay: &'a mut OverlayedChanges, | ||
| // The storage backend to read from. | ||
| backend: &'a B, | ||
| // The transaction necessary to commit to the backend. | ||
| transaction: Option<(B::Transaction, [u8; 32])>, | ||
| transaction: Option<(B::Transaction, H::Out)>, | ||
| } | ||
|
|
||
| impl<'a, B: 'a + Backend> Ext<'a, B> { | ||
| impl<'a, H, C, B> Ext<'a, H, C, B> | ||
| where | ||
| H: Hasher, | ||
| C: NodeCodec<H>, | ||
| B: 'a + Backend<H, C>, | ||
| H::Out: Ord + Encodable | ||
| { | ||
| /// Create a new `Ext` from overlayed changes and read-only backend | ||
| pub fn new(overlay: &'a mut OverlayedChanges, backend: &'a B) -> Self { | ||
| Ext { | ||
|
|
@@ -84,7 +93,7 @@ impl<'a, B: 'a + Backend> Ext<'a, B> { | |
| } | ||
|
|
||
| #[cfg(test)] | ||
| impl<'a, B: 'a + Backend> Ext<'a, B> { | ||
| impl<'a, H: Hasher, C: NodeCodec<H>, B: 'a + Backend<H, C>> Ext<'a, H, C, B> { | ||
| pub fn storage_pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> { | ||
| use std::collections::HashMap; | ||
|
|
||
|
|
@@ -99,8 +108,12 @@ impl<'a, B: 'a + Backend> Ext<'a, B> { | |
| } | ||
| } | ||
|
|
||
| impl<'a, B: 'a> Externalities for Ext<'a, B> | ||
| where B: Backend | ||
| impl<'a, B: 'a, H, C> Externalities<H> for Ext<'a, H, C, B> | ||
| where | ||
| H: Hasher, | ||
| C: NodeCodec<H>, | ||
| B: 'a + Backend<H, C>, | ||
| H::Out: Ord + Encodable | ||
| { | ||
| fn storage(&self, key: &[u8]) -> Option<Vec<u8>> { | ||
| self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| | ||
|
|
@@ -123,7 +136,7 @@ impl<'a, B: 'a> Externalities for Ext<'a, B> | |
| 42 | ||
| } | ||
|
|
||
| fn storage_root(&mut self) -> [u8; 32] { | ||
| fn storage_root(&mut self) -> H::Out where H::Out: Ord + Encodable { | ||
|
||
| if let Some((_, ref root)) = self.transaction { | ||
| return root.clone(); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You missed renaming an import, see travis test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks!