2016-01-15 14:40:51 +01:00
use common ::* ;
2015-11-29 15:50:33 +01:00
use hashdb ::* ;
2015-11-30 02:57:02 +01:00
use nibbleslice ::* ;
use rlp ::* ;
2015-12-19 13:35:26 +01:00
use super ::node ::* ;
use super ::journal ::* ;
use super ::trietraits ::* ;
2015-12-17 12:43:50 +01:00
2015-12-19 13:53:05 +01:00
/// A `Trie` implementation using a generic `HashDB` backing database.
///
/// Use it as a `Trie` trait object. You can use `db()` to get the backing database object, `keys`
/// to get the keys belonging to the trie in the backing database, and `db_items_remaining()` to get
/// which items in the backing database do not belong to this trie. If this is the only trie in the
/// backing database, then `db_items_remaining()` should be empty.
///
/// # Example
/// ```
/// extern crate ethcore_util as util;
/// use util::trie::*;
/// use util::hashdb::*;
/// use util::memorydb::*;
/// use util::hash::*;
/// use util::rlp::*;
///
/// fn main() {
/// let mut memdb = MemoryDB::new();
/// let mut root = H256::new();
/// let mut t = TrieDBMut::new(&mut memdb, &mut root);
/// assert!(t.is_empty());
/// assert_eq!(*t.root(), SHA3_NULL_RLP);
/// t.insert(b"foo", b"bar");
/// assert!(t.contains(b"foo"));
/// assert_eq!(t.get(b"foo").unwrap(), b"bar");
/// assert!(t.db_items_remaining().is_empty());
/// t.remove(b"foo");
/// assert!(!t.contains(b"foo"));
/// assert!(t.db_items_remaining().is_empty());
/// }
/// ```
2016-01-06 13:53:23 +01:00
pub struct TrieDBMut < ' db > {
db : & ' db mut HashDB ,
root : & ' db mut H256 ,
pub hash_count : usize ,
}
/// Option-like type allowing either a Node object passthrough or Bytes in the case of data alteration.
enum MaybeChanged < ' a > {
Same ( Node < ' a > ) ,
Changed ( Bytes ) ,
}
2015-12-17 12:43:50 +01:00
impl < ' db > TrieDBMut < ' db > {
2015-12-11 03:00:39 +01:00
/// Create a new trie with the backing database `db` and empty `root`
/// Initialise to the state entailed by the genesis block.
/// This guarantees the trie is built correctly.
2015-12-13 19:36:49 +01:00
pub fn new ( db : & ' db mut HashDB , root : & ' db mut H256 ) -> Self {
2015-12-17 12:43:50 +01:00
let mut r = TrieDBMut {
2015-12-10 15:48:25 +01:00
db : db ,
2015-12-11 03:00:39 +01:00
root : root ,
2015-12-10 15:48:25 +01:00
hash_count : 0
} ;
2015-11-29 15:50:33 +01:00
2015-12-11 03:00:39 +01:00
// set root rlp
2016-01-15 04:02:24 +01:00
* r . root = SHA3_NULL_RLP . clone ( ) ;
2015-12-10 15:48:25 +01:00
r
}
2015-11-29 15:50:33 +01:00
2016-01-17 22:18:47 +01:00
/// Create a new trie with the backing database `db` and `root`.
/// Panics, if `root` does not exist.
// TODO: return Result<Self, TrieError>
2016-01-08 22:30:45 +01:00
pub fn from_existing ( db : & ' db mut HashDB , root : & ' db mut H256 ) -> Self {
2016-01-15 14:40:51 +01:00
if ! db . exists ( root ) {
flush ( format! ( " Trie root not found {} " , root ) ) ;
panic! ( " Trie root not found! " ) ;
}
2015-12-17 12:43:50 +01:00
TrieDBMut {
2015-12-11 03:00:39 +01:00
db : db ,
root : root ,
hash_count : 0
}
}
2015-12-07 15:00:54 +01:00
/// Get the backing database.
2015-12-13 19:36:49 +01:00
pub fn db ( & ' db self ) -> & ' db HashDB {
2015-12-10 15:48:25 +01:00
self . db
}
2015-11-29 15:50:33 +01:00
2015-12-07 15:00:54 +01:00
/// Determine all the keys in the backing database that belong to the trie.
pub fn keys ( & self ) -> Vec < H256 > {
let mut ret : Vec < H256 > = Vec ::new ( ) ;
ret . push ( self . root . clone ( ) ) ;
self . accumulate_keys ( self . root_node ( ) , & mut ret ) ;
ret
}
/// Convert a vector of hashes to a hashmap of hash to occurances.
pub fn to_map ( hashes : Vec < H256 > ) -> HashMap < H256 , u32 > {
let mut r : HashMap < H256 , u32 > = HashMap ::new ( ) ;
for h in hashes . into_iter ( ) {
let c = * r . get ( & h ) . unwrap_or ( & 0 ) ;
r . insert ( h , c + 1 ) ;
}
r
}
/// Determine occurances of items in the backing database which are not related to this
/// trie.
pub fn db_items_remaining ( & self ) -> HashMap < H256 , i32 > {
2015-12-13 19:36:49 +01:00
let mut ret = self . db . keys ( ) ;
2015-12-07 15:00:54 +01:00
for ( k , v ) in Self ::to_map ( self . keys ( ) ) . into_iter ( ) {
let keycount = * ret . get ( & k ) . unwrap_or ( & 0 ) ;
2016-01-15 04:02:24 +01:00
match keycount < = v as i32 {
2015-12-07 15:00:54 +01:00
true = > ret . remove ( & k ) ,
_ = > ret . insert ( k , keycount - v as i32 ) ,
} ;
}
ret
}
/// Set the trie to a new root node's RLP, inserting the new RLP into the backing database
/// and removing the old.
2015-11-30 02:57:02 +01:00
fn set_root_rlp ( & mut self , root_data : & [ u8 ] ) {
2015-11-30 14:53:22 +01:00
self . db . kill ( & self . root ) ;
2015-12-11 03:00:39 +01:00
* self . root = self . db . insert ( root_data ) ;
2015-12-04 18:05:59 +01:00
self . hash_count + = 1 ;
2015-12-01 18:25:18 +01:00
trace! ( " set_root_rlp {:?} {:?} " , root_data . pretty ( ) , self . root ) ;
2015-11-30 02:57:02 +01:00
}
2015-12-07 15:00:54 +01:00
/// Apply the items in `journal` into the backing database.
fn apply ( & mut self , journal : Journal ) {
2015-12-19 13:35:26 +01:00
self . hash_count + = journal . apply ( self . db ) . inserts ;
2015-12-01 01:12:06 +01:00
}
2015-12-01 01:44:18 +01:00
2015-12-07 15:00:54 +01:00
/// Recursion helper for `keys`.
2015-12-03 14:56:39 +01:00
fn accumulate_keys ( & self , node : Node , acc : & mut Vec < H256 > ) {
let mut handle_payload = | payload | {
let p = Rlp ::new ( payload ) ;
if p . is_data ( ) & & p . size ( ) = = 32 {
2015-12-08 00:45:04 +01:00
acc . push ( p . as_val ( ) ) ;
2015-12-03 14:56:39 +01:00
}
self . accumulate_keys ( self . get_node ( payload ) , acc ) ;
} ;
match node {
Node ::Extension ( _ , payload ) = > handle_payload ( payload ) ,
Node ::Branch ( payloads , _ ) = > for payload in payloads . iter ( ) { handle_payload ( payload ) } ,
_ = > { } ,
}
}
2015-12-07 15:00:54 +01:00
/// Get the root node's RLP.
fn root_node ( & self ) -> Node {
Node ::decoded ( self . db . lookup ( & self . root ) . expect ( " Trie root not found! " ) )
2015-12-03 14:56:39 +01:00
}
2015-12-07 15:00:54 +01:00
/// Get the root node as a `Node`.
fn get_node < ' a > ( & ' a self , node : & ' a [ u8 ] ) -> Node {
Node ::decoded ( self . get_raw_or_lookup ( node ) )
2015-12-03 14:56:39 +01:00
}
2015-12-07 15:00:54 +01:00
/// Indentation helper for `formal_all`.
2015-12-01 19:19:16 +01:00
fn fmt_indent ( & self , f : & mut fmt ::Formatter , size : usize ) -> fmt ::Result {
2015-12-01 19:24:14 +01:00
for _ in 0 .. size {
2015-12-01 20:34:49 +01:00
try ! ( write! ( f , " " ) ) ;
2015-12-01 19:19:16 +01:00
}
Ok ( ( ) )
}
2015-12-07 15:00:54 +01:00
/// Recursion helper for implementation of formatting trait.
2015-12-02 15:03:20 +01:00
fn fmt_all ( & self , node : Node , f : & mut fmt ::Formatter , deepness : usize ) -> fmt ::Result {
2015-12-01 18:25:47 +01:00
match node {
2015-12-02 22:59:00 +01:00
Node ::Leaf ( slice , value ) = > try ! ( writeln! ( f , " '{:?}: {:?}. " , slice , value . pretty ( ) ) ) ,
2015-12-01 23:14:38 +01:00
Node ::Extension ( ref slice , ref item ) = > {
2015-12-02 22:59:00 +01:00
try ! ( write! ( f , " '{:?} " , slice ) ) ;
2015-12-02 15:03:20 +01:00
try ! ( self . fmt_all ( self . get_node ( item ) , f , deepness ) ) ;
2015-12-01 18:25:47 +01:00
} ,
2015-12-02 00:14:14 +01:00
Node ::Branch ( ref nodes , ref value ) = > {
2015-12-02 00:19:58 +01:00
try ! ( writeln! ( f , " " ) ) ;
2015-12-02 00:14:14 +01:00
match value {
& Some ( v ) = > {
2015-12-01 23:14:38 +01:00
try ! ( self . fmt_indent ( f , deepness + 1 ) ) ;
2015-12-02 00:14:14 +01:00
try ! ( writeln! ( f , " =: {:?} " , v . pretty ( ) ) )
} ,
& None = > { }
}
for i in 0 .. 16 {
2015-12-02 15:03:20 +01:00
match self . get_node ( nodes [ i ] ) {
Node ::Empty = > { } ,
n = > {
2015-12-02 00:14:14 +01:00
try ! ( self . fmt_indent ( f , deepness + 1 ) ) ;
2015-12-02 22:59:00 +01:00
try ! ( write! ( f , " '{:x} " , i ) ) ;
2015-12-02 15:03:20 +01:00
try ! ( self . fmt_all ( n , f , deepness + 1 ) ) ;
}
2015-12-01 19:19:16 +01:00
}
2015-12-01 18:25:47 +01:00
}
} ,
// empty
2015-12-02 15:03:20 +01:00
Node ::Empty = > {
2015-12-02 00:19:58 +01:00
try ! ( writeln! ( f , " <empty> " ) ) ;
2015-12-01 18:25:47 +01:00
}
2015-12-01 19:19:16 +01:00
} ;
Ok ( ( ) )
2015-12-01 18:25:47 +01:00
}
2015-12-07 15:00:54 +01:00
/// Return optional data for a key given as a `NibbleSlice`. Returns `None` if no data exists.
2015-12-17 12:43:50 +01:00
fn do_lookup < ' a , ' key > ( & ' a self , key : & NibbleSlice < ' key > ) -> Option < & ' a [ u8 ] > where ' a : ' key {
2015-12-01 16:39:44 +01:00
let root_rlp = self . db . lookup ( & self . root ) . expect ( " Trie root not found! " ) ;
self . get_from_node ( & root_rlp , key )
}
2015-12-07 15:00:54 +01:00
/// Recursible function to retrieve the value given a `node` and a partial `key`. `None` if no
/// value exists for the key.
///
/// Note: Not a public API; use Trie trait functions.
2015-12-01 23:32:23 +01:00
fn get_from_node < ' a , ' key > ( & ' a self , node : & ' a [ u8 ] , key : & NibbleSlice < ' key > ) -> Option < & ' a [ u8 ] > where ' a : ' key {
2015-12-01 16:39:44 +01:00
match Node ::decoded ( node ) {
Node ::Leaf ( ref slice , ref value ) if key = = slice = > Some ( value ) ,
2015-12-01 23:14:38 +01:00
Node ::Extension ( ref slice , ref item ) if key . starts_with ( slice ) = > {
self . get_from_node ( self . get_raw_or_lookup ( item ) , & key . mid ( slice . len ( ) ) )
2015-12-01 16:39:44 +01:00
} ,
2015-12-02 00:14:14 +01:00
Node ::Branch ( ref nodes , value ) = > match key . is_empty ( ) {
true = > value ,
2015-12-02 15:03:20 +01:00
false = > self . get_from_node ( self . get_raw_or_lookup ( nodes [ key . at ( 0 ) as usize ] ) , & key . mid ( 1 ) )
2015-12-01 16:39:44 +01:00
} ,
_ = > None
}
}
2015-12-07 15:00:54 +01:00
/// Given some node-describing data `node`, return the actual node RLP.
/// This could be a simple identity operation in the case that the node is sufficiently small, but
/// may require a database lookup.
2015-12-02 23:35:34 +01:00
fn get_raw_or_lookup < ' a > ( & ' a self , node : & ' a [ u8 ] ) -> & ' a [ u8 ] {
2015-12-01 23:14:38 +01:00
// check if its sha3 + len
2015-12-02 00:14:14 +01:00
let r = Rlp ::new ( node ) ;
match r . is_data ( ) & & r . size ( ) = = 32 {
2015-12-08 00:45:04 +01:00
true = > self . db . lookup ( & r . as_val ::< H256 > ( ) ) . expect ( " Not found! " ) ,
2015-12-01 23:14:38 +01:00
false = > node
}
}
2015-12-07 15:00:54 +01:00
/// Insert a `key` and `value` pair into the trie.
///
/// Note: Not a public API; use Trie trait functions.
fn insert_ns ( & mut self , key : & NibbleSlice , value : & [ u8 ] ) {
2015-12-01 18:25:18 +01:00
trace! ( " ADD: {:?} {:?} " , key , value . pretty ( ) ) ;
2015-11-30 02:57:02 +01:00
// determine what the new root is, insert new nodes and remove old as necessary.
2015-12-07 15:00:54 +01:00
let mut todo : Journal = Journal ::new ( ) ;
2015-12-01 03:35:55 +01:00
let root_rlp = self . augmented ( self . db . lookup ( & self . root ) . expect ( " Trie root not found! " ) , key , value , & mut todo ) ;
2015-12-01 01:32:10 +01:00
self . apply ( todo ) ;
self . set_root_rlp ( & root_rlp ) ;
2015-12-01 18:25:18 +01:00
trace! ( " / " ) ;
2015-12-01 01:32:10 +01:00
}
2015-12-07 15:00:54 +01:00
/// Remove a `key` and `value` pair from the trie.
///
/// Note: Not a public API; use Trie trait functions.
fn remove_ns ( & mut self , key : & NibbleSlice ) {
2015-12-02 15:03:20 +01:00
trace! ( " DELETE: {:?} " , key ) ;
// determine what the new root is, insert new nodes and remove old as necessary.
2015-12-07 15:00:54 +01:00
let mut todo : Journal = Journal ::new ( ) ;
2015-12-02 22:59:00 +01:00
match self . cleared_from_slice ( self . db . lookup ( & self . root ) . expect ( " Trie root not found! " ) , key , & mut todo ) {
Some ( root_rlp ) = > {
self . apply ( todo ) ;
self . set_root_rlp ( & root_rlp ) ;
} ,
None = > {
trace! ( " no change needed " ) ;
}
}
2015-12-02 15:03:20 +01:00
trace! ( " / " ) ;
}
2015-12-07 15:00:54 +01:00
/// Compose a leaf node in RLP given the `partial` key and `value`.
2015-12-01 01:44:18 +01:00
fn compose_leaf ( partial : & NibbleSlice , value : & [ u8 ] ) -> Bytes {
2015-12-01 18:25:18 +01:00
trace! ( " compose_leaf {:?} {:?} ({:?}) " , partial , value . pretty ( ) , partial . encoded ( true ) . pretty ( ) ) ;
2015-12-01 01:32:10 +01:00
let mut s = RlpStream ::new_list ( 2 ) ;
2015-12-01 01:44:18 +01:00
s . append ( & partial . encoded ( true ) ) ;
s . append ( & value ) ;
2015-12-01 01:32:10 +01:00
let r = s . out ( ) ;
2015-12-01 18:25:18 +01:00
trace! ( " compose_leaf: -> {:?} " , r . pretty ( ) ) ;
2015-12-01 01:32:10 +01:00
r
}
2015-12-07 15:00:54 +01:00
/// Compose a raw extension/leaf node in RLP given the `partial` key, `raw_payload` and whether it `is_leaf`.
2015-12-01 01:52:20 +01:00
fn compose_raw ( partial : & NibbleSlice , raw_payload : & [ u8 ] , is_leaf : bool ) -> Bytes {
2015-12-02 15:03:20 +01:00
trace! ( " compose_raw {:?} {:?} {:?} ({:?}) " , partial , raw_payload . pretty ( ) , is_leaf , partial . encoded ( is_leaf ) ) ;
2015-12-01 01:32:10 +01:00
let mut s = RlpStream ::new_list ( 2 ) ;
2015-12-01 01:44:18 +01:00
s . append ( & partial . encoded ( is_leaf ) ) ;
s . append_raw ( raw_payload , 1 ) ;
2015-12-01 01:32:10 +01:00
let r = s . out ( ) ;
2015-12-02 15:03:20 +01:00
trace! ( " compose_raw: -> {:?} " , r . pretty ( ) ) ;
2015-12-01 01:32:10 +01:00
r
}
2015-12-07 15:00:54 +01:00
/// Compose a branch node in RLP with a particular `value` sitting in the value position (17th place).
2015-12-01 20:24:47 +01:00
fn compose_stub_branch ( value : & [ u8 ] ) -> Bytes {
let mut s = RlpStream ::new_list ( 17 ) ;
for _ in 0 .. 16 { s . append_empty_data ( ) ; }
s . append ( & value ) ;
s . out ( )
}
2015-12-07 15:00:54 +01:00
/// Compose an extension node's RLP with the `partial` key and `raw_payload`.
2015-12-01 01:32:10 +01:00
fn compose_extension ( partial : & NibbleSlice , raw_payload : & [ u8 ] ) -> Bytes {
Self ::compose_raw ( partial , raw_payload , false )
}
2015-12-01 01:12:06 +01:00
2015-12-07 15:00:54 +01:00
/// Return the bytes encoding the node represented by `rlp`. `journal` will record necessary
/// removal instructions from the backing database.
fn take_node < ' a , ' rlp_view > ( & ' a self , rlp : & ' rlp_view Rlp < ' a > , journal : & mut Journal ) -> & ' a [ u8 ] where ' a : ' rlp_view {
2015-12-01 02:23:53 +01:00
if rlp . is_list ( ) {
2016-01-08 15:52:43 +01:00
trace! ( " take_node {:?} (inline) " , rlp . as_raw ( ) . pretty ( ) ) ;
rlp . as_raw ( )
2015-11-30 02:57:02 +01:00
}
2015-12-01 02:23:53 +01:00
else if rlp . is_data ( ) & & rlp . size ( ) = = 32 {
2015-12-08 00:45:04 +01:00
let h = rlp . as_val ( ) ;
2015-12-04 18:05:59 +01:00
let r = self . db . lookup ( & h ) . unwrap_or_else ( | | {
2016-01-08 15:52:43 +01:00
println! ( " Node not found! rlp= {:?} , node_hash= {:?} " , rlp . as_raw ( ) . pretty ( ) , h ) ;
2015-12-07 15:00:54 +01:00
println! ( " Journal: {:?} " , journal ) ;
2015-12-04 18:05:59 +01:00
panic! ( ) ;
} ) ;
2016-01-08 15:52:43 +01:00
trace! ( " take_node {:?} (indirect for {:?}) " , rlp . as_raw ( ) . pretty ( ) , r ) ;
2015-12-07 15:00:54 +01:00
journal . delete_node_sha3 ( h ) ;
2015-12-01 01:12:06 +01:00
r
2015-11-30 02:57:02 +01:00
}
2015-12-01 01:52:20 +01:00
else {
2016-01-08 15:52:43 +01:00
trace! ( " take_node {:?} (???) " , rlp . as_raw ( ) . pretty ( ) ) ;
2015-12-01 01:52:20 +01:00
panic! ( " Empty or invalid node given? " ) ;
}
2015-11-30 02:57:02 +01:00
}
2015-12-01 01:12:06 +01:00
/// Determine the RLP of the node, assuming we're inserting `partial` into the
/// node currently of data `old`. This will *not* delete any hash of `old` from the database;
/// it will just return the new RLP that includes the new node.
2015-11-30 02:57:02 +01:00
///
2015-12-07 15:00:54 +01:00
/// `journal` will record the database updates so as to make the returned RLP valid through inserting
2015-11-30 02:57:02 +01:00
/// and deleting nodes as necessary.
2015-12-01 01:12:06 +01:00
///
2015-12-02 15:03:20 +01:00
/// **This operation will not insert the new node nor destroy the original.**
2015-12-07 15:00:54 +01:00
fn augmented ( & self , old : & [ u8 ] , partial : & NibbleSlice , value : & [ u8 ] , journal : & mut Journal ) -> Bytes {
2015-12-01 19:09:48 +01:00
trace! ( " augmented (old: {:?}, partial: {:?}, value: {:?}) " , old . pretty ( ) , partial , value . pretty ( ) ) ;
2015-12-01 01:12:06 +01:00
// already have an extension. either fast_forward, cleve or transmute_to_branch.
let old_rlp = Rlp ::new ( old ) ;
match old_rlp . prototype ( ) {
2015-11-30 13:25:37 +01:00
Prototype ::List ( 17 ) = > {
2015-12-01 12:10:36 +01:00
trace! ( " branch: ROUTE,AUGMENT " ) ;
2015-12-01 03:35:55 +01:00
// already have a branch. route and augment.
2015-12-07 15:00:54 +01:00
let mut s = RlpStream ::new_list ( 17 ) ;
let index = if partial . is_empty ( ) { 16 } else { partial . at ( 0 ) as usize } ;
for i in 0 .. 17 {
match index = = i {
// not us - leave alone.
2016-01-08 15:52:43 +01:00
false = > { s . append_raw ( old_rlp . at ( i ) . as_raw ( ) , 1 ) ; } ,
2015-12-07 15:00:54 +01:00
// branch-leaf entry - just replace.
true if i = = 16 = > { s . append ( & value ) ; } ,
// original had empty slot - place a leaf there.
true if old_rlp . at ( i ) . is_empty ( ) = > journal . new_node ( Self ::compose_leaf ( & partial . mid ( 1 ) , value ) , & mut s ) ,
// original has something there already; augment.
true = > {
let new = self . augmented ( self . take_node ( & old_rlp . at ( i ) , journal ) , & partial . mid ( 1 ) , value , journal ) ;
journal . new_node ( new , & mut s ) ;
}
}
}
s . out ( )
2015-11-30 02:57:02 +01:00
} ,
2015-11-30 13:25:37 +01:00
Prototype ::List ( 2 ) = > {
2015-12-01 03:35:55 +01:00
let existing_key_rlp = old_rlp . at ( 0 ) ;
let ( existing_key , is_leaf ) = NibbleSlice ::from_encoded ( existing_key_rlp . data ( ) ) ;
2015-12-01 19:09:48 +01:00
match ( is_leaf , partial . common_prefix ( & existing_key ) ) {
( true , cp ) if cp = = existing_key . len ( ) & & partial . len ( ) = = existing_key . len ( ) = > {
2015-12-01 03:35:55 +01:00
// equivalent-leaf: replace
trace! ( " equivalent-leaf: REPLACE " ) ;
2015-12-01 02:23:53 +01:00
Self ::compose_leaf ( partial , value )
2015-12-01 01:12:06 +01:00
} ,
2015-12-01 19:09:48 +01:00
( _ , 0 ) = > {
2015-12-01 01:12:06 +01:00
// one of us isn't empty: transmute to branch here
2015-12-01 03:35:55 +01:00
trace! ( " no-common-prefix, not-both-empty (exist={:?}; new={:?}): TRANSMUTE,AUGMENT " , existing_key . len ( ) , partial . len ( ) ) ;
2015-12-07 15:00:54 +01:00
assert! ( is_leaf | | ! existing_key . is_empty ( ) ) ; // extension nodes are not allowed to have empty partial keys.
let mut s = RlpStream ::new_list ( 17 ) ;
let index = if existing_key . is_empty ( ) { 16 } else { existing_key . at ( 0 ) } ;
for i in 0 .. 17 {
match is_leaf {
// not us - empty.
_ if index ! = i = > { s . append_empty_data ( ) ; } ,
// branch-value: just replace.
2016-01-08 15:52:43 +01:00
true if i = = 16 = > { s . append_raw ( old_rlp . at ( 1 ) . as_raw ( ) , 1 ) ; } ,
2015-12-07 15:00:54 +01:00
// direct extension: just replace.
2016-01-08 15:52:43 +01:00
false if existing_key . len ( ) = = 1 = > { s . append_raw ( old_rlp . at ( 1 ) . as_raw ( ) , 1 ) ; } ,
2015-12-07 15:00:54 +01:00
// original has empty slot.
true = > journal . new_node ( Self ::compose_leaf ( & existing_key . mid ( 1 ) , old_rlp . at ( 1 ) . data ( ) ) , & mut s ) ,
// additional work required after branching.
2016-01-08 15:52:43 +01:00
false = > journal . new_node ( Self ::compose_extension ( & existing_key . mid ( 1 ) , old_rlp . at ( 1 ) . as_raw ( ) ) , & mut s ) ,
2015-12-07 15:00:54 +01:00
}
} ;
self . augmented ( & s . out ( ) , partial , value , journal )
2015-11-30 16:06:29 +01:00
} ,
2015-12-01 19:09:48 +01:00
( _ , cp ) if cp = = existing_key . len ( ) = > {
2015-12-01 03:35:55 +01:00
trace! ( " complete-prefix (cp={:?}): AUGMENT-AT-END " , cp ) ;
2015-12-01 01:12:06 +01:00
// fully-shared prefix for this extension:
2015-12-01 20:24:47 +01:00
// transform to an extension + augmented version of onward node.
2015-12-04 20:04:26 +01:00
let downstream_node : Bytes = match is_leaf {
2015-12-01 20:24:47 +01:00
// no onward node because we're a leaf - create fake stub and use that.
2015-12-07 15:00:54 +01:00
true = > self . augmented ( & Self ::compose_stub_branch ( old_rlp . at ( 1 ) . data ( ) ) , & partial . mid ( cp ) , value , journal ) ,
false = > self . augmented ( self . take_node ( & old_rlp . at ( 1 ) , journal ) , & partial . mid ( cp ) , value , journal ) ,
2015-12-01 20:24:47 +01:00
} ;
2015-12-07 15:00:54 +01:00
trace! ( " create_extension partial: {:?}, downstream_node: {:?} " , existing_key , downstream_node . pretty ( ) ) ;
let mut s = RlpStream ::new_list ( 2 ) ;
s . append ( & existing_key . encoded ( false ) ) ;
journal . new_node ( downstream_node , & mut s ) ;
s . out ( )
2015-11-30 16:06:29 +01:00
} ,
2015-12-01 19:09:48 +01:00
( _ , cp ) = > {
2015-12-01 01:12:06 +01:00
// partially-shared prefix for this extension:
// split into two extensions, high and low, pass the
2015-12-01 03:35:55 +01:00
// low through augment with the value before inserting the result
2015-12-01 01:12:06 +01:00
// into high to create the new.
2015-12-01 03:35:55 +01:00
// TODO: optimise by doing this without creating augmented_low.
trace! ( " partially-shared-prefix (exist={:?}; new={:?}; cp={:?}): AUGMENT-AT-END " , existing_key . len ( ) , partial . len ( ) , cp ) ;
2015-12-01 01:12:06 +01:00
// low (farther from root)
2016-01-08 15:52:43 +01:00
let low = Self ::compose_raw ( & existing_key . mid ( cp ) , old_rlp . at ( 1 ) . as_raw ( ) , is_leaf ) ;
2015-12-07 15:00:54 +01:00
let augmented_low = self . augmented ( & low , & partial . mid ( cp ) , value , journal ) ;
2015-12-01 01:12:06 +01:00
// high (closer to root)
let mut s = RlpStream ::new_list ( 2 ) ;
2015-12-01 03:35:55 +01:00
s . append ( & existing_key . encoded_leftmost ( cp , false ) ) ;
2015-12-07 15:00:54 +01:00
journal . new_node ( augmented_low , & mut s ) ;
2015-12-01 01:12:06 +01:00
s . out ( )
2015-11-30 16:06:29 +01:00
} ,
2015-12-01 02:23:53 +01:00
}
2015-11-30 02:57:02 +01:00
} ,
2015-12-01 19:45:30 +01:00
Prototype ::Data ( 0 ) = > {
2015-12-01 12:10:36 +01:00
trace! ( " empty: COMPOSE " ) ;
2015-12-01 01:44:18 +01:00
Self ::compose_leaf ( partial , value )
2015-11-30 14:53:22 +01:00
} ,
2015-12-01 23:15:23 +01:00
_ = > panic! ( " Invalid RLP for node: {:?} " , old . pretty ( ) ) ,
2015-11-30 13:25:37 +01:00
}
2015-11-30 02:57:02 +01:00
}
2015-12-02 23:00:36 +01:00
2015-12-07 15:00:54 +01:00
/// Given a `MaybeChanged` result `n`, return the node's RLP regardless of whether it changed.
2015-12-02 22:59:00 +01:00
fn encoded ( n : MaybeChanged ) -> Bytes {
match n {
MaybeChanged ::Same ( n ) = > n . encoded ( ) ,
MaybeChanged ::Changed ( b ) = > b ,
}
}
2015-12-02 15:03:20 +01:00
2015-12-07 15:00:54 +01:00
/// Fix the node payload's sizes in `n`, replacing any over-size payloads with the hashed reference
/// and placing the payload DB insertions in the `journal`.
fn fixed_indirection < ' a > ( n : Node < ' a > , journal : & mut Journal ) -> MaybeChanged < ' a > {
2015-12-02 22:59:00 +01:00
match n {
2015-12-03 00:50:14 +01:00
Node ::Extension ( partial , payload ) if payload . len ( ) > = 32 & & Rlp ::new ( payload ) . is_list ( ) = > {
2015-12-02 22:59:00 +01:00
// make indirect
2015-12-07 15:00:54 +01:00
MaybeChanged ::Changed ( Node ::Extension ( partial , & Node ::decoded ( payload ) . encoded_and_added ( journal ) ) . encoded ( ) )
2015-12-02 22:59:00 +01:00
} ,
2015-12-03 00:50:14 +01:00
Node ::Branch ( payloads , value ) = > {
2015-12-02 22:59:00 +01:00
// check each child isn't too big
// TODO OPTIMISE - should really check at the point of (re-)constructing the branch.
for i in 0 .. 16 {
2015-12-03 00:50:14 +01:00
if payloads [ i ] . len ( ) > = 32 & & Rlp ::new ( payloads [ i ] ) . is_list ( ) {
2015-12-07 15:00:54 +01:00
let n = Node ::decoded ( payloads [ i ] ) . encoded_and_added ( journal ) ;
2015-12-03 00:50:14 +01:00
let mut new_nodes = payloads ;
2015-12-02 22:59:00 +01:00
new_nodes [ i ] = & n ;
2015-12-03 00:50:14 +01:00
return MaybeChanged ::Changed ( Node ::Branch ( new_nodes , value ) . encoded ( ) )
2015-12-02 22:59:00 +01:00
}
}
MaybeChanged ::Same ( n )
}
_ = > MaybeChanged ::Same ( n ) ,
}
}
/// Given a node `n` which may be in an _invalid state_, fix it such that it is then in a valid
/// state.
///
/// _invalid state_ means:
/// - Branch node where there is only a single entry;
/// - Extension node followed by anything other than a Branch node.
/// - Extension node with a child which has too many bytes to be inline.
///
2015-12-07 15:00:54 +01:00
/// `journal` will record the database updates so as to make the returned RLP valid through inserting
/// and deleting nodes as necessary.
///
2015-12-02 22:59:00 +01:00
/// **This operation will not insert the new node nor destroy the original.**
2015-12-07 15:00:54 +01:00
fn fixed < ' a , ' b > ( & ' a self , n : Node < ' b > , journal : & mut Journal ) -> MaybeChanged < ' b > where ' a : ' b {
2015-12-03 00:32:58 +01:00
trace! ( " fixed node={:?} " , n ) ;
2015-12-02 22:59:00 +01:00
match n {
Node ::Branch ( nodes , node_value ) = > {
// if only a single value, transmute to leaf/extension and feed through fixed.
2015-12-03 00:32:58 +01:00
#[ derive(Debug) ]
enum UsedIndex {
None ,
2015-12-03 00:50:14 +01:00
One ( u8 ) ,
2015-12-03 00:32:58 +01:00
Many ,
} ;
let mut used_index = UsedIndex ::None ;
2015-12-02 22:59:00 +01:00
for i in 0 .. 16 {
2015-12-03 00:32:58 +01:00
match ( nodes [ i ] = = NULL_RLP , & used_index ) {
2015-12-03 00:50:14 +01:00
( false , & UsedIndex ::None ) = > used_index = UsedIndex ::One ( i as u8 ) ,
2015-12-03 00:32:58 +01:00
( false , & UsedIndex ::One ( _ ) ) = > used_index = UsedIndex ::Many ,
( _ , _ ) = > { } ,
2015-12-02 22:59:00 +01:00
}
}
2015-12-03 00:32:58 +01:00
trace! ( " branch: used_index={:?}, node_value={:?} " , used_index , node_value ) ;
match ( used_index , node_value ) {
( UsedIndex ::None , None ) = > panic! ( " Branch with no subvalues. Something went wrong. " ) ,
( UsedIndex ::One ( a ) , None ) = > { // one onward node
2015-12-02 22:59:00 +01:00
// transmute to extension.
// TODO: OPTIMISE: - don't call fixed again but put the right node in straight away here.
// call fixed again since the transmute may cause invalidity.
2015-12-03 00:50:14 +01:00
let new_partial : [ u8 ; 1 ] = [ a ; 1 ] ;
2015-12-07 15:00:54 +01:00
MaybeChanged ::Changed ( Self ::encoded ( self . fixed ( Node ::Extension ( NibbleSlice ::new_offset ( & new_partial [ .. ] , 1 ) , nodes [ a as usize ] ) , journal ) ) )
2015-12-02 22:59:00 +01:00
} ,
2015-12-03 00:32:58 +01:00
( UsedIndex ::None , Some ( value ) ) = > { // one leaf value
2015-12-02 22:59:00 +01:00
// transmute to leaf.
// call fixed again since the transmute may cause invalidity.
2015-12-07 15:00:54 +01:00
MaybeChanged ::Changed ( Self ::encoded ( self . fixed ( Node ::Leaf ( NibbleSlice ::new ( & b " " [ .. ] ) , value ) , journal ) ) )
2015-12-02 22:59:00 +01:00
}
_ = > { // onwards node(s) and/or leaf
// no transmute needed, but should still fix the indirection.
2015-12-03 00:50:14 +01:00
trace! ( " no-transmute: FIXINDIRECTION " ) ;
2015-12-07 15:00:54 +01:00
Self ::fixed_indirection ( Node ::Branch ( nodes , node_value ) , journal )
2015-12-02 22:59:00 +01:00
} ,
}
} ,
Node ::Extension ( partial , payload ) = > {
match Node ::decoded ( self . get_raw_or_lookup ( payload ) ) {
Node ::Extension ( sub_partial , sub_payload ) = > {
// combine with node below
2015-12-07 15:00:54 +01:00
journal . delete_node ( payload ) ;
MaybeChanged ::Changed ( Self ::encoded ( Self ::fixed_indirection ( Node ::Extension ( NibbleSlice ::new_composed ( & partial , & sub_partial ) , sub_payload ) , journal ) ) )
2015-12-02 22:59:00 +01:00
} ,
Node ::Leaf ( sub_partial , sub_value ) = > {
// combine with node below
2015-12-07 15:00:54 +01:00
journal . delete_node ( payload ) ;
MaybeChanged ::Changed ( Self ::encoded ( Self ::fixed_indirection ( Node ::Leaf ( NibbleSlice ::new_composed ( & partial , & sub_partial ) , sub_value ) , journal ) ) )
2015-12-02 22:59:00 +01:00
} ,
// no change, might still have an oversize node inline - fix indirection
2015-12-07 15:00:54 +01:00
_ = > Self ::fixed_indirection ( n , journal ) ,
2015-12-02 22:59:00 +01:00
}
} ,
// leaf or empty. no change.
n = > { MaybeChanged ::Same ( n ) }
}
}
2015-12-02 15:03:20 +01:00
/// Determine the RLP of the node, assuming we're removing `partial` from the
/// node currently of data `old`. This will *not* delete any hash of `old` from the database;
/// it will just return the new RLP that represents the new node.
2015-12-02 22:59:00 +01:00
/// `None` may be returned should no change be needed.
2015-12-02 15:03:20 +01:00
///
2015-12-07 15:00:54 +01:00
/// `journal` will record the database updates so as to make the returned RLP valid through inserting
2015-12-02 15:03:20 +01:00
/// and deleting nodes as necessary.
///
/// **This operation will not insert the new node nor destroy the original.**
2015-12-07 15:00:54 +01:00
fn cleared_from_slice ( & self , old : & [ u8 ] , partial : & NibbleSlice , journal : & mut Journal ) -> Option < Bytes > {
self . cleared ( Node ::decoded ( old ) , partial , journal )
2015-12-02 22:59:00 +01:00
}
2015-12-02 15:03:20 +01:00
2015-12-07 15:00:54 +01:00
/// Compose the RLP of the node equivalent to `n` except with the `partial` key removed from its (sub-)trie.
///
/// `journal` will record the database updates so as to make the returned RLP valid through inserting
/// and deleting nodes as necessary.
///
/// **This operation will not insert the new node nor destroy the original.**
fn cleared ( & self , n : Node , partial : & NibbleSlice , journal : & mut Journal ) -> Option < Bytes > {
2015-12-03 00:32:58 +01:00
trace! ( " cleared old={:?}, partial={:?}) " , n , partial ) ;
2015-12-02 22:59:00 +01:00
match ( n , partial . is_empty ( ) ) {
( Node ::Empty , _ ) = > None ,
2015-12-02 23:00:36 +01:00
( Node ::Branch ( _ , None ) , true ) = > { None } ,
2015-12-07 15:00:54 +01:00
( Node ::Branch ( payloads , _ ) , true ) = > Some ( Self ::encoded ( self . fixed ( Node ::Branch ( payloads , None ) , journal ) ) ) , // matched as leaf-branch - give back fixed branch with it.
2015-12-03 00:32:58 +01:00
( Node ::Branch ( payloads , value ) , false ) = > {
2015-12-02 22:59:00 +01:00
// Branch with partial left - route, clear, fix.
let i : usize = partial . at ( 0 ) as usize ;
2015-12-03 00:32:58 +01:00
trace! ( " branch-with-partial node[{:?}]={:?} " , i , payloads [ i ] . pretty ( ) ) ;
2015-12-07 15:00:54 +01:00
self . cleared ( self . get_node ( payloads [ i ] ) , & partial . mid ( 1 ) , journal ) . map ( | new_payload | {
2015-12-03 00:32:58 +01:00
trace! ( " branch-new-payload={:?}; delete-old={:?} " , new_payload . pretty ( ) , payloads [ i ] . pretty ( ) ) ;
2015-12-02 22:59:00 +01:00
// downsteam node needed to be changed.
2015-12-07 15:00:54 +01:00
journal . delete_node ( payloads [ i ] ) ;
2015-12-02 22:59:00 +01:00
// return fixed up new node.
2015-12-03 00:32:58 +01:00
let mut new_payloads = payloads ;
new_payloads [ i ] = & new_payload ;
2015-12-07 15:00:54 +01:00
Self ::encoded ( self . fixed ( Node ::Branch ( new_payloads , value ) , journal ) )
2015-12-02 22:59:00 +01:00
} )
} ,
2015-12-02 23:00:36 +01:00
( Node ::Leaf ( node_partial , _ ) , _ ) = > {
2015-12-03 00:32:58 +01:00
trace! ( " leaf partial={:?} " , node_partial ) ;
2015-12-02 22:59:00 +01:00
match node_partial . common_prefix ( partial ) {
2015-12-03 00:32:58 +01:00
cp if cp = = partial . len ( ) = > { // leaf to be deleted - delete it :)
trace! ( " matched-prefix (cp={:?}): REPLACE-EMPTY " , cp ) ;
Some ( Node ::Empty . encoded ( ) )
} ,
2015-12-02 23:00:36 +01:00
_ = > None , // anything else and the key doesn't exit - no change.
2015-12-02 22:59:00 +01:00
}
} ,
( Node ::Extension ( node_partial , node_payload ) , _ ) = > {
2015-12-03 00:32:58 +01:00
trace! ( " extension partial={:?}, payload={:?} " , node_partial , node_payload . pretty ( ) ) ;
2015-12-02 22:59:00 +01:00
match node_partial . common_prefix ( partial ) {
2015-12-03 00:32:58 +01:00
cp if cp = = node_partial . len ( ) = > {
trace! ( " matching-prefix (cp={:?}): SKIP,CLEAR,FIXUP " , cp ) ;
2015-12-02 22:59:00 +01:00
// key at end of extension - skip, clear, fix
2015-12-07 15:00:54 +01:00
self . cleared ( self . get_node ( node_payload ) , & partial . mid ( node_partial . len ( ) ) , journal ) . map ( | new_payload | {
2015-12-03 00:32:58 +01:00
trace! ( " extension-new-payload={:?}; delete-old={:?} " , new_payload . pretty ( ) , node_payload . pretty ( ) ) ;
2015-12-02 22:59:00 +01:00
// downsteam node needed to be changed.
2015-12-07 15:00:54 +01:00
journal . delete_node ( node_payload ) ;
2015-12-02 22:59:00 +01:00
// return fixed up new node.
2015-12-07 15:00:54 +01:00
Self ::encoded ( self . fixed ( Node ::Extension ( node_partial , & new_payload ) , journal ) )
2015-12-02 22:59:00 +01:00
} )
} ,
2015-12-03 00:32:58 +01:00
_ = > None , // key in the middle of an extension - doesn't exist.
2015-12-02 22:59:00 +01:00
}
} ,
}
2015-12-02 15:03:20 +01:00
}
2015-11-29 15:50:33 +01:00
}
2015-12-17 12:43:50 +01:00
impl < ' db > Trie for TrieDBMut < ' db > {
2015-11-29 15:50:33 +01:00
fn root ( & self ) -> & H256 { & self . root }
2015-11-29 18:45:41 +01:00
2015-12-02 00:21:03 +01:00
fn contains ( & self , key : & [ u8 ] ) -> bool {
2015-12-17 12:43:50 +01:00
self . get ( key ) . is_some ( )
2015-11-29 18:45:41 +01:00
}
2015-12-17 12:43:50 +01:00
fn get < ' a , ' key > ( & ' a self , key : & ' key [ u8 ] ) -> Option < & ' a [ u8 ] > where ' a : ' key {
self . do_lookup ( & NibbleSlice ::new ( key ) )
2015-11-29 18:45:41 +01:00
}
2015-12-17 12:43:50 +01:00
}
2015-11-29 18:45:41 +01:00
2015-12-17 12:43:50 +01:00
impl < ' db > TrieMut for TrieDBMut < ' db > {
2015-11-30 02:57:02 +01:00
fn insert ( & mut self , key : & [ u8 ] , value : & [ u8 ] ) {
2015-12-07 15:00:54 +01:00
match value . is_empty ( ) {
false = > self . insert_ns ( & NibbleSlice ::new ( key ) , value ) ,
true = > self . remove_ns ( & NibbleSlice ::new ( key ) ) ,
}
2015-11-29 18:45:41 +01:00
}
2015-12-02 15:03:20 +01:00
fn remove ( & mut self , key : & [ u8 ] ) {
2015-12-07 15:00:54 +01:00
self . remove_ns ( & NibbleSlice ::new ( key ) ) ;
}
}
2015-12-17 12:43:50 +01:00
impl < ' db > fmt ::Debug for TrieDBMut < ' db > {
2015-12-07 15:00:54 +01:00
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
try ! ( writeln! ( f , " c={:?} [ " , self . hash_count ) ) ;
let root_rlp = self . db . lookup ( & self . root ) . expect ( " Trie root not found! " ) ;
try ! ( self . fmt_all ( Node ::decoded ( root_rlp ) , f , 0 ) ) ;
writeln! ( f , " ] " )
2015-11-29 18:45:41 +01:00
}
2015-11-29 15:50:33 +01:00
}
2015-12-01 03:35:55 +01:00
#[ cfg(test) ]
mod tests {
2015-12-03 00:29:31 +01:00
extern crate json_tests ;
2015-12-03 05:44:35 +01:00
use self ::json_tests ::{ trie , execute_tests_from_directory } ;
2015-11-30 14:53:22 +01:00
use triehash ::* ;
2015-12-03 00:29:31 +01:00
use hash ::* ;
2015-12-10 15:48:25 +01:00
use hashdb ::* ;
use memorydb ::* ;
2015-12-01 03:35:55 +01:00
use super ::* ;
2015-12-01 16:39:44 +01:00
use nibbleslice ::* ;
2015-12-19 13:35:26 +01:00
use rlp ::* ;
2015-12-01 01:44:18 +01:00
use env_logger ;
2015-12-02 02:37:26 +01:00
use rand ::random ;
2015-12-03 18:42:51 +01:00
use std ::collections ::HashSet ;
2016-01-08 11:52:46 +01:00
use bytes ::{ ToPretty , Bytes , Populatable } ;
2015-12-19 13:35:26 +01:00
use super ::super ::node ::* ;
use super ::super ::trietraits ::* ;
2015-12-03 18:42:51 +01:00
2015-12-07 15:00:54 +01:00
fn random_key ( alphabet : & [ u8 ] , min_count : usize , journal_count : usize ) -> Vec < u8 > {
2015-12-03 18:42:51 +01:00
let mut ret : Vec < u8 > = Vec ::new ( ) ;
2015-12-07 15:00:54 +01:00
let r = min_count + if journal_count > 0 { random ::< usize > ( ) % journal_count } else { 0 } ;
2015-12-03 18:42:51 +01:00
for _ in 0 .. r {
2015-12-04 18:05:59 +01:00
ret . push ( alphabet [ random ::< usize > ( ) % alphabet . len ( ) ] ) ;
2015-12-03 18:42:51 +01:00
}
ret
}
2015-12-04 18:05:59 +01:00
fn random_value_indexed ( j : usize ) -> Bytes {
2015-12-03 18:42:51 +01:00
match random ::< usize > ( ) % 2 {
2015-12-19 13:35:26 +01:00
0 = > encode ( & j ) ,
2015-12-03 18:42:51 +01:00
_ = > {
let mut h = H256 ::new ( ) ;
2016-01-07 23:59:50 +01:00
h . as_slice_mut ( ) [ 31 ] = j as u8 ;
2015-12-19 13:35:26 +01:00
encode ( & h )
2015-12-03 18:42:51 +01:00
} ,
}
}
2015-12-17 12:43:50 +01:00
fn populate_trie < ' db > ( db : & ' db mut HashDB , root : & ' db mut H256 , v : & Vec < ( Vec < u8 > , Vec < u8 > ) > ) -> TrieDBMut < ' db > {
let mut t = TrieDBMut ::new ( db , root ) ;
2015-12-03 18:42:51 +01:00
for i in 0 .. v . len ( ) {
let key : & [ u8 ] = & v [ i ] . 0 ;
let val : & [ u8 ] = & v [ i ] . 1 ;
t . insert ( & key , & val ) ;
}
t
}
2015-12-17 12:43:50 +01:00
fn unpopulate_trie < ' a , ' db > ( t : & mut TrieDBMut < ' db > , v : & Vec < ( Vec < u8 > , Vec < u8 > ) > ) {
2015-12-03 18:42:51 +01:00
for i in v . iter ( ) {
let key : & [ u8 ] = & i . 0 ;
t . remove ( & key ) ;
}
}
2015-12-01 01:44:18 +01:00
2015-12-04 18:05:59 +01:00
macro_rules ! map ( { $( $key :expr = > $value :expr ) , + } = > {
{
let mut m = ::std ::collections ::HashMap ::new ( ) ;
$(
m . insert ( $key , $value ) ;
) +
m
}
} ; ) ;
2015-12-02 22:59:00 +01:00
#[ test ]
fn playpen ( ) {
env_logger ::init ( ) . ok ( ) ;
2015-12-04 18:05:59 +01:00
2015-12-07 15:00:54 +01:00
/* let maps = map!{
" six-low " = > StandardMap { alphabet : Alphabet ::Low , min_key : 6 , journal_key : 0 , count : 1000 } ,
" six-mid " = > StandardMap { alphabet : Alphabet ::Mid , min_key : 6 , journal_key : 0 , count : 1000 } ,
" six-all " = > StandardMap { alphabet : Alphabet ::All , min_key : 6 , journal_key : 0 , count : 1000 } ,
" mix-mid " = > StandardMap { alphabet : Alphabet ::Mid , min_key : 1 , journal_key : 5 , count : 1000 }
2015-12-04 18:05:59 +01:00
} ;
for sm in maps {
let m = sm . 1. make ( ) ;
let t = populate_trie ( & m ) ;
println! ( " {:?} : root= {:?} , hash_count= {:?} " , sm . 0 , t . root ( ) , t . hash_count ) ;
2015-12-07 15:00:54 +01:00
} ; * /
// panic!();
2015-12-04 18:05:59 +01:00
for test_i in 0 .. 1 {
if test_i % 50 = = 0 {
debug! ( " {:?} of 10000 stress tests done " , test_i ) ;
}
2015-12-03 18:42:51 +01:00
let mut x : Vec < ( Vec < u8 > , Vec < u8 > ) > = Vec ::new ( ) ;
let mut got : HashSet < Vec < u8 > > = HashSet ::new ( ) ;
2015-12-04 18:05:59 +01:00
let alphabet = b " @QWERTYUIOPASDFGHJKLZXCVBNM[/]^_ " ;
2015-12-19 13:53:05 +01:00
for j in 0 .. 100 usize {
2015-12-04 18:05:59 +01:00
let key = random_key ( alphabet , 5 , 0 ) ;
2015-12-03 18:42:51 +01:00
if ! got . contains ( & key ) {
2015-12-04 18:05:59 +01:00
x . push ( ( key . clone ( ) , random_value_indexed ( j ) ) ) ;
2015-12-03 18:42:51 +01:00
got . insert ( key ) ;
}
}
2015-12-02 22:59:00 +01:00
2015-12-03 18:42:51 +01:00
let real = trie_root ( x . clone ( ) ) ;
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
let mut memtrie = populate_trie ( & mut memdb , & mut root , & x ) ;
2015-12-03 18:42:51 +01:00
if * memtrie . root ( ) ! = real | | ! memtrie . db_items_remaining ( ) . is_empty ( ) {
println! ( " TRIE MISMATCH " ) ;
println! ( " " ) ;
println! ( " {:?} vs {:?} " , memtrie . root ( ) , real ) ;
for i in x . iter ( ) {
println! ( " {:?} -> {:?} " , i . 0. pretty ( ) , i . 1. pretty ( ) ) ;
}
println! ( " {:?} " , memtrie ) ;
}
assert_eq! ( * memtrie . root ( ) , real ) ;
assert! ( memtrie . db_items_remaining ( ) . is_empty ( ) ) ;
unpopulate_trie ( & mut memtrie , & x ) ;
if * memtrie . root ( ) ! = SHA3_NULL_RLP | | ! memtrie . db_items_remaining ( ) . is_empty ( ) {
2016-01-15 04:02:24 +01:00
println! ( " - TRIE MISMATCH " ) ;
2015-12-03 18:42:51 +01:00
println! ( " " ) ;
2016-01-15 04:02:24 +01:00
println! ( " remaining: {:?} " , memtrie . db_items_remaining ( ) ) ;
2015-12-03 18:42:51 +01:00
println! ( " {:?} vs {:?} " , memtrie . root ( ) , real ) ;
for i in x . iter ( ) {
println! ( " {:?} -> {:?} " , i . 0. pretty ( ) , i . 1. pretty ( ) ) ;
}
println! ( " {:?} " , memtrie ) ;
}
assert_eq! ( * memtrie . root ( ) , SHA3_NULL_RLP ) ;
assert! ( memtrie . db_items_remaining ( ) . is_empty ( ) ) ;
2015-12-02 22:59:00 +01:00
}
}
#[ test ]
fn init ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
assert_eq! ( * t . root ( ) , SHA3_NULL_RLP ) ;
assert! ( t . is_empty ( ) ) ;
}
#[ test ]
fn insert_on_empty ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [ ( vec! [ 0x01 u8 , 0x23 ] , vec! [ 0x01 u8 , 0x23 ] ) ] ) ) ;
}
#[ test ]
fn remove_to_empty ( ) {
2015-12-03 18:42:51 +01:00
let big_value = b " 00000000000000000000000000000000 " ;
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t1 = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-03 18:42:51 +01:00
t1 . insert ( & [ 0x01 , 0x23 ] , & big_value . to_vec ( ) ) ;
t1 . insert ( & [ 0x01 , 0x34 ] , & big_value . to_vec ( ) ) ;
2016-01-15 04:02:24 +01:00
println! ( " ********************** keys remaining {:?} " , t1 . db_items_remaining ( ) ) ;
2015-12-03 18:42:51 +01:00
assert! ( t1 . db_items_remaining ( ) . is_empty ( ) ) ;
2015-12-10 15:48:25 +01:00
let mut memdb2 = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root2 = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t2 = TrieDBMut ::new ( & mut memdb2 , & mut root2 ) ;
2015-12-03 18:42:51 +01:00
t2 . insert ( & [ 0x01 ] , & big_value . to_vec ( ) ) ;
t2 . insert ( & [ 0x01 , 0x23 ] , & big_value . to_vec ( ) ) ;
t2 . insert ( & [ 0x01 , 0x34 ] , & big_value . to_vec ( ) ) ;
t2 . remove ( & [ 0x01 ] ) ;
assert! ( t2 . db_items_remaining ( ) . is_empty ( ) ) ;
/* if t1.root() != t2.root() */ {
trace! ( " {:?} " , t1 ) ;
trace! ( " {:?} " , t2 ) ;
}
2015-12-02 22:59:00 +01:00
}
#[ test ]
fn insert_replace_root ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x23 u8 , 0x45 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [ ( vec! [ 0x01 u8 , 0x23 ] , vec! [ 0x23 u8 , 0x45 ] ) ] ) ) ;
}
#[ test ]
fn insert_make_branch_root ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
t . insert ( & [ 0x11 u8 , 0x23 ] , & [ 0x11 u8 , 0x23 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ 0x01 u8 , 0x23 ] , vec! [ 0x01 u8 , 0x23 ] ) ,
( vec! [ 0x11 u8 , 0x23 ] , vec! [ 0x11 u8 , 0x23 ] )
] ) ) ;
}
#[ test ]
fn insert_into_branch_root ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
t . insert ( & [ 0xf1 u8 , 0x23 ] , & [ 0xf1 u8 , 0x23 ] ) ;
t . insert ( & [ 0x81 u8 , 0x23 ] , & [ 0x81 u8 , 0x23 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ 0x01 u8 , 0x23 ] , vec! [ 0x01 u8 , 0x23 ] ) ,
( vec! [ 0x81 u8 , 0x23 ] , vec! [ 0x81 u8 , 0x23 ] ) ,
( vec! [ 0xf1 u8 , 0x23 ] , vec! [ 0xf1 u8 , 0x23 ] ) ,
] ) ) ;
}
#[ test ]
fn insert_value_into_branch_root ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
t . insert ( & [ ] , & [ 0x0 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ ] , vec! [ 0x0 ] ) ,
( vec! [ 0x01 u8 , 0x23 ] , vec! [ 0x01 u8 , 0x23 ] ) ,
] ) ) ;
}
#[ test ]
fn insert_split_leaf ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
t . insert ( & [ 0x01 u8 , 0x34 ] , & [ 0x01 u8 , 0x34 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ 0x01 u8 , 0x23 ] , vec! [ 0x01 u8 , 0x23 ] ) ,
( vec! [ 0x01 u8 , 0x34 ] , vec! [ 0x01 u8 , 0x34 ] ) ,
] ) ) ;
}
#[ test ]
fn insert_split_extenstion ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 , 0x23 , 0x45 ] , & [ 0x01 ] ) ;
t . insert ( & [ 0x01 , 0xf3 , 0x45 ] , & [ 0x02 ] ) ;
t . insert ( & [ 0x01 , 0xf3 , 0xf5 ] , & [ 0x03 ] ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ 0x01 , 0x23 , 0x45 ] , vec! [ 0x01 ] ) ,
( vec! [ 0x01 , 0xf3 , 0x45 ] , vec! [ 0x02 ] ) ,
( vec! [ 0x01 , 0xf3 , 0xf5 ] , vec! [ 0x03 ] ) ,
] ) ) ;
}
#[ test ]
fn insert_big_value ( ) {
let big_value0 = b " 00000000000000000000000000000000 " ;
let big_value1 = b " 11111111111111111111111111111111 " ;
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , big_value0 ) ;
t . insert ( & [ 0x11 u8 , 0x23 ] , big_value1 ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ 0x01 u8 , 0x23 ] , big_value0 . to_vec ( ) ) ,
( vec! [ 0x11 u8 , 0x23 ] , big_value1 . to_vec ( ) )
] ) ) ;
}
#[ test ]
fn insert_duplicate_value ( ) {
let big_value = b " 00000000000000000000000000000000 " ;
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-02 22:59:00 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , big_value ) ;
t . insert ( & [ 0x11 u8 , 0x23 ] , big_value ) ;
assert_eq! ( * t . root ( ) , trie_root ( vec! [
( vec! [ 0x01 u8 , 0x23 ] , big_value . to_vec ( ) ) ,
( vec! [ 0x11 u8 , 0x23 ] , big_value . to_vec ( ) )
] ) ) ;
}
2015-12-01 16:39:44 +01:00
#[ test ]
fn test_node_leaf ( ) {
let k = vec! [ 0x20 u8 , 0x01 , 0x23 , 0x45 ] ;
let v : Vec < u8 > = From ::from ( " cat " ) ;
let ( slice , is_leaf ) = NibbleSlice ::from_encoded ( & k ) ;
assert_eq! ( is_leaf , true ) ;
let leaf = Node ::Leaf ( slice , & v ) ;
let rlp = leaf . encoded ( ) ;
let leaf2 = Node ::decoded ( & rlp ) ;
assert_eq! ( leaf , leaf2 ) ;
}
#[ test ]
fn test_node_extension ( ) {
let k = vec! [ 0x00 u8 , 0x01 , 0x23 , 0x45 ] ;
// in extension, value must be valid rlp
2015-12-19 13:35:26 +01:00
let v = encode ( & " cat " ) ;
2015-12-01 16:39:44 +01:00
let ( slice , is_leaf ) = NibbleSlice ::from_encoded ( & k ) ;
assert_eq! ( is_leaf , false ) ;
2015-12-01 23:14:38 +01:00
let ex = Node ::Extension ( slice , & v ) ;
2015-12-01 16:39:44 +01:00
let rlp = ex . encoded ( ) ;
let ex2 = Node ::decoded ( & rlp ) ;
assert_eq! ( ex , ex2 ) ;
}
#[ test ]
fn test_node_empty_branch ( ) {
2015-12-02 23:50:14 +01:00
let null_rlp = NULL_RLP ;
let branch = Node ::Branch ( [ & null_rlp ; 16 ] , None ) ;
2015-12-01 16:39:44 +01:00
let rlp = branch . encoded ( ) ;
let branch2 = Node ::decoded ( & rlp ) ;
2015-12-02 23:50:14 +01:00
println! ( " {:?} " , rlp ) ;
2015-12-01 16:39:44 +01:00
assert_eq! ( branch , branch2 ) ;
}
#[ test ]
fn test_node_branch ( ) {
2015-12-19 13:35:26 +01:00
let k = encode ( & " cat " ) ;
2015-12-02 15:03:20 +01:00
let mut nodes : [ & [ u8 ] ; 16 ] = unsafe { ::std ::mem ::uninitialized ( ) } ;
for i in 0 .. 16 { nodes [ i ] = & k ; }
2015-12-01 16:39:44 +01:00
let v : Vec < u8 > = From ::from ( " dog " ) ;
2015-12-02 00:14:14 +01:00
let branch = Node ::Branch ( nodes , Some ( & v ) ) ;
2015-12-01 16:39:44 +01:00
let rlp = branch . encoded ( ) ;
let branch2 = Node ::decoded ( & rlp ) ;
assert_eq! ( branch , branch2 ) ;
}
#[ test ]
fn test_at_empty ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
assert_eq! ( t . get ( & [ 0x5 ] ) , None ) ;
2015-12-01 16:39:44 +01:00
}
#[ test ]
fn test_at_one ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-01 16:39:44 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
2015-12-17 12:43:50 +01:00
assert_eq! ( t . get ( & [ 0x1 , 0x23 ] ) . unwrap ( ) , & [ 0x1 u8 , 0x23 ] ) ;
2015-12-01 16:39:44 +01:00
}
2015-12-01 17:03:54 +01:00
#[ test ]
fn test_at_three ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-01 17:03:54 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
t . insert ( & [ 0xf1 u8 , 0x23 ] , & [ 0xf1 u8 , 0x23 ] ) ;
t . insert ( & [ 0x81 u8 , 0x23 ] , & [ 0x81 u8 , 0x23 ] ) ;
2015-12-17 12:43:50 +01:00
assert_eq! ( t . get ( & [ 0x01 , 0x23 ] ) . unwrap ( ) , & [ 0x01 u8 , 0x23 ] ) ;
assert_eq! ( t . get ( & [ 0xf1 , 0x23 ] ) . unwrap ( ) , & [ 0xf1 u8 , 0x23 ] ) ;
assert_eq! ( t . get ( & [ 0x81 , 0x23 ] ) . unwrap ( ) , & [ 0x81 u8 , 0x23 ] ) ;
assert_eq! ( t . get ( & [ 0x82 , 0x23 ] ) , None ) ;
2015-12-01 17:03:54 +01:00
}
2015-12-01 18:25:47 +01:00
#[ test ]
fn test_print_trie ( ) {
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-01 18:25:47 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
2015-12-01 18:43:44 +01:00
t . insert ( & [ 0x02 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
2015-12-01 18:25:47 +01:00
t . insert ( & [ 0xf1 u8 , 0x23 ] , & [ 0xf1 u8 , 0x23 ] ) ;
t . insert ( & [ 0x81 u8 , 0x23 ] , & [ 0x81 u8 , 0x23 ] ) ;
println! ( " trie: " ) ;
println! ( " {:?} " , t ) ;
2015-12-01 19:20:48 +01:00
//assert!(false);
2015-12-01 18:25:47 +01:00
}
2015-12-02 02:37:26 +01:00
#[ test ]
fn stress ( ) {
2015-12-19 13:53:05 +01:00
for _ in 0 .. 50 {
2015-12-02 02:37:26 +01:00
let mut x : Vec < ( Vec < u8 > , Vec < u8 > ) > = Vec ::new ( ) ;
2015-12-04 18:05:59 +01:00
let alphabet = b " @QWERTYUIOPASDFGHJKLZXCVBNM[/]^_ " ;
2015-12-02 15:03:20 +01:00
for j in 0 .. 4 u32 {
2015-12-04 18:05:59 +01:00
let key = random_key ( alphabet , 5 , 1 ) ;
2015-12-19 13:35:26 +01:00
x . push ( ( key , encode ( & j ) ) ) ;
2015-12-02 02:37:26 +01:00
}
let real = trie_root ( x . clone ( ) ) ;
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
let memtrie = populate_trie ( & mut memdb , & mut root , & x ) ;
2015-12-02 15:03:20 +01:00
let mut y = x . clone ( ) ;
y . sort_by ( | ref a , ref b | a . 0. cmp ( & b . 0 ) ) ;
2015-12-10 15:48:25 +01:00
let mut memdb2 = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root2 = H256 ::new ( ) ;
let memtrie_sorted = populate_trie ( & mut memdb2 , & mut root2 , & y ) ;
2015-12-02 15:03:20 +01:00
if * memtrie . root ( ) ! = real | | * memtrie_sorted . root ( ) ! = real {
println! ( " TRIE MISMATCH " ) ;
println! ( " " ) ;
println! ( " ORIGINAL... {:?} " , memtrie . root ( ) ) ;
for i in x . iter ( ) {
println! ( " {:?} -> {:?} " , i . 0. pretty ( ) , i . 1. pretty ( ) ) ;
}
println! ( " {:?} " , memtrie ) ;
println! ( " SORTED... {:?} " , memtrie_sorted . root ( ) ) ;
for i in y . iter ( ) {
println! ( " {:?} -> {:?} " , i . 0. pretty ( ) , i . 1. pretty ( ) ) ;
}
println! ( " {:?} " , memtrie_sorted ) ;
}
assert_eq! ( * memtrie . root ( ) , real ) ;
assert_eq! ( * memtrie_sorted . root ( ) , real ) ;
2015-12-02 02:37:26 +01:00
}
}
2015-12-03 00:29:31 +01:00
#[ test ]
fn test_trie_json ( ) {
println! ( " Json trie test: " ) ;
execute_tests_from_directory ::< trie ::TrieTest , _ > ( " json-tests/json/trie/*.json " , & mut | file , input , output | {
println! ( " file: {} " , file ) ;
2015-12-10 15:48:25 +01:00
let mut memdb = MemoryDB ::new ( ) ;
2015-12-11 03:00:39 +01:00
let mut root = H256 ::new ( ) ;
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut memdb , & mut root ) ;
2015-12-03 00:29:31 +01:00
for operation in input . into_iter ( ) {
match operation {
trie ::Operation ::Insert ( key , value ) = > t . insert ( & key , & value ) ,
trie ::Operation ::Remove ( key ) = > t . remove ( & key )
}
}
assert_eq! ( * t . root ( ) , H256 ::from_slice ( & output ) ) ;
} ) ;
}
2015-12-11 03:00:39 +01:00
#[ test ]
fn test_trie_existing ( ) {
let mut root = H256 ::new ( ) ;
let mut db = MemoryDB ::new ( ) ;
{
2015-12-17 12:43:50 +01:00
let mut t = TrieDBMut ::new ( & mut db , & mut root ) ;
2015-12-11 03:00:39 +01:00
t . insert ( & [ 0x01 u8 , 0x23 ] , & [ 0x01 u8 , 0x23 ] ) ;
}
{
2016-01-08 22:30:45 +01:00
let _ = TrieDBMut ::from_existing ( & mut db , & mut root ) ;
2015-12-11 03:00:39 +01:00
}
}
2015-12-01 16:39:44 +01:00
}