From 1df1350c200a07e697e6557624494df96a56c11b Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Thu, 21 Mar 2024 19:02:39 +0200 Subject: [PATCH 01/13] refactor: refactoring mpt_trie to use more Results --- mpt_trie/Cargo.toml | 1 + mpt_trie/examples/hash_nodes.rs | 18 ++-- mpt_trie/examples/simple.rs | 8 +- mpt_trie/src/debug_tools/diff.rs | 4 +- mpt_trie/src/debug_tools/stats.rs | 6 +- mpt_trie/src/partial_trie.rs | 34 ++++--- mpt_trie/src/special_query.rs | 4 +- mpt_trie/src/testing_utils.rs | 12 +-- mpt_trie/src/trie_hashing.rs | 5 +- mpt_trie/src/trie_ops.rs | 155 +++++++++++++++++------------- mpt_trie/src/trie_subsets.rs | 16 +-- trace_decoder/src/decoding.rs | 2 +- 12 files changed, 147 insertions(+), 118 deletions(-) diff --git a/mpt_trie/Cargo.toml b/mpt_trie/Cargo.toml index 41b4f704c..77bc5c2d8 100644 --- a/mpt_trie/Cargo.toml +++ b/mpt_trie/Cargo.toml @@ -14,6 +14,7 @@ exclude = [ ] [dependencies] +anyhow = "1.0.40" bytes = { workspace = true } enum-as-inner = { workspace = true } ethereum-types = { workspace = true } diff --git a/mpt_trie/examples/hash_nodes.rs b/mpt_trie/examples/hash_nodes.rs index 0a27dd72d..4e4d4a0c1 100644 --- a/mpt_trie/examples/hash_nodes.rs +++ b/mpt_trie/examples/hash_nodes.rs @@ -56,7 +56,7 @@ use mpt_trie::{ partial_trie::{HashedPartialTrie, Node}, }; -fn main() { +fn main() -> anyhow::Result<()> { pretty_env_logger::try_init().unwrap(); // Lets build the (binary) tries in the module-level docs. Since the example @@ -66,10 +66,10 @@ fn main() { // Note the nibbles read the most significant nibble first (eg. `0x12` reads `1` // first). - full_trie.insert(Nibbles::from_str("0x00").unwrap(), large_val(1)); // 1st from left. - full_trie.insert(Nibbles::from_str("0x01").unwrap(), large_val(2)); // 2nd from left. - full_trie.insert(Nibbles::from(0x10_u64), large_val(3)); // 3rd from left. - full_trie.insert(Nibbles::from(0x11_u64), large_val(4)); // 4th from left. + full_trie.insert(Nibbles::from_str("0x00").unwrap(), large_val(1))?; // 1st from left. + full_trie.insert(Nibbles::from_str("0x01").unwrap(), large_val(2))?; // 2nd from left. + full_trie.insert(Nibbles::from(0x10_u64), large_val(3))?; // 3rd from left. + full_trie.insert(Nibbles::from(0x11_u64), large_val(4))?; // 4th from left. let full_trie_hash = full_trie.hash(); @@ -83,14 +83,16 @@ fn main() { // Hash version. `0` branch is replaced with a `Hash` node. let mut hash_trie = HashedPartialTrie::default(); - hash_trie.insert(Nibbles::from_str("0x0").unwrap(), left_side_hash); // Hash node - hash_trie.insert(0x10_u64, large_val(3)); // 3rd from left. - hash_trie.insert(0x11_u64, large_val(4)); // 4th from left. + hash_trie.insert(Nibbles::from_str("0x0").unwrap(), left_side_hash)?; // Hash node + hash_trie.insert(0x10_u64, large_val(3))?; // 3rd from left. + hash_trie.insert(0x11_u64, large_val(4))?; // 4th from left. let hash_trie_hash = hash_trie.hash(); // Hashes should be equal. assert_eq!(full_trie_hash, hash_trie_hash); + + Ok(()) } /// We want to ensure that all leafs are >= 32 bytes when RLP encoded in order diff --git a/mpt_trie/examples/simple.rs b/mpt_trie/examples/simple.rs index 15917e843..9e6f44896 100644 --- a/mpt_trie/examples/simple.rs +++ b/mpt_trie/examples/simple.rs @@ -9,7 +9,7 @@ use mpt_trie::{ trie_ops::ValOrHash, }; -fn main() { +fn main() -> anyhow::Result<()>{ // Construct an empty trie: let mut trie = StandardTrie::default(); @@ -17,7 +17,7 @@ fn main() { trie.insert( Nibbles::from_bytes_be(b"hello").unwrap(), b"world!".to_vec(), - ); + )?; // Or by initializing the trie with an iterator of key value pairs: let mut trie = StandardTrie::from_iter(vec![ @@ -44,7 +44,7 @@ fn main() { // Values can be deleted: let del_val = trie.delete(0x1234_u32); - assert_eq!(del_val, Some(b"some data".to_vec())); + assert_eq!(del_val.ok().unwrap(), Some(b"some data".to_vec())); assert_eq!(trie.get(0x1234_u32), None); // It's important to note how types are converted to `Nibbles`. This is @@ -76,4 +76,6 @@ fn main() { format!("{:x}", Nibbles::from_bytes_le(&[69, 35, 1]).unwrap()), "0x012345" ); + + Ok(()) } diff --git a/mpt_trie/src/debug_tools/diff.rs b/mpt_trie/src/debug_tools/diff.rs index fd280c749..44fcf45b1 100644 --- a/mpt_trie/src/debug_tools/diff.rs +++ b/mpt_trie/src/debug_tools/diff.rs @@ -423,11 +423,11 @@ mod tests { fn depth_single_node_hash_diffs_work() { // TODO: Reduce duplication once we identify common structures across tests... let mut a = HashedPartialTrie::default(); - a.insert(0x1234, vec![0]); + assert!(a.insert(0x1234, vec![0]).is_ok()); let a_hash = a.hash(); let mut b = a.clone(); - b.insert(0x1234, vec![1]); + assert!(b.insert(0x1234, vec![1]).is_ok()); let b_hash = b.hash(); let diff = create_diff_between_tries(&a, &b); diff --git a/mpt_trie/src/debug_tools/stats.rs b/mpt_trie/src/debug_tools/stats.rs index 6a23ab496..ee2330c1a 100644 --- a/mpt_trie/src/debug_tools/stats.rs +++ b/mpt_trie/src/debug_tools/stats.rs @@ -323,7 +323,7 @@ mod tests { #[test] fn hand_made_trie_has_correct_node_stats() { - let (trie, _) = handmade_trie_1(); + let (trie, _) = handmade_trie_1().unwrap(); let stats = get_trie_stats(&trie); assert_eq!(stats.counts.leaf, 4); @@ -370,8 +370,8 @@ mod tests { let hash_entries = generate_n_random_fixed_trie_hash_entries(n_hash_nodes, seed + 1); let mut trie = HashedPartialTrie::default(); - trie.extend(val_entries); - trie.extend(hash_entries); + assert!(trie.extend(val_entries).is_ok()); + assert!(trie.extend(hash_entries).is_ok()); let stats = get_trie_stats(&trie); diff --git a/mpt_trie/src/partial_trie.rs b/mpt_trie/src/partial_trie.rs index c1a04c4bf..756076b71 100644 --- a/mpt_trie/src/partial_trie.rs +++ b/mpt_trie/src/partial_trie.rs @@ -58,13 +58,13 @@ pub trait PartialTrie: fn new(n: Node) -> Self; /// Inserts a node into the trie. - fn insert(&mut self, k: K, v: V) + fn insert(&mut self, k: K, v: V) -> anyhow::Result<()> where K: Into, V: Into; /// Add more nodes to the trie through an iterator - fn extend(&mut self, nodes: I) + fn extend(&mut self, nodes: I) -> anyhow::Result<()> where K: Into, V: Into, @@ -89,7 +89,7 @@ pub trait PartialTrie: /// are meant for parts of the trie that are not relevant, traversing one /// means that a `Hash` node was created that potentially should not have /// been. - fn delete(&mut self, k: K) -> Option> + fn delete(&mut self, k: K) -> anyhow::Result>> where K: Into; @@ -214,15 +214,16 @@ impl PartialTrie for StandardTrie { Self(n) } - fn insert(&mut self, k: K, v: V) + fn insert(&mut self, k: K, v: V) -> anyhow::Result<()> where K: Into, V: Into, { - self.0.trie_insert(k, v); + self.0.trie_insert(k, v)?; + Ok(()) } - fn extend(&mut self, nodes: I) + fn extend(&mut self, nodes: I) -> anyhow::Result<()> where K: Into, V: Into, @@ -238,7 +239,7 @@ impl PartialTrie for StandardTrie { self.0.trie_get(k) } - fn delete(&mut self, k: K) -> Option> + fn delete(&mut self, k: K) -> anyhow::Result>> where K: Into, { @@ -327,23 +328,25 @@ impl PartialTrie for HashedPartialTrie { } } - fn insert(&mut self, k: K, v: V) + fn insert(&mut self, k: K, v: V) -> anyhow::Result<()> where K: Into, V: Into, { - self.node.trie_insert(k, v); + self.node.trie_insert(k, v)?; self.set_hash(None); + Ok(()) } - fn extend(&mut self, nodes: I) + fn extend(&mut self, nodes: I) -> anyhow::Result<()> where K: Into, V: Into, I: IntoIterator, { - self.node.trie_extend(nodes); + self.node.trie_extend(nodes)?; self.set_hash(None); + Ok(()) } fn get(&self, k: K) -> Option<&[u8]> @@ -353,7 +356,7 @@ impl PartialTrie for HashedPartialTrie { self.node.trie_get(k) } - fn delete(&mut self, k: K) -> Option> + fn delete(&mut self, k: K) -> anyhow::Result>> where K: Into, { @@ -434,7 +437,8 @@ where V: Into, { let mut root = N::new(Node::Empty); - root.extend(nodes); - - root + match root.extend(nodes) { + Ok(_) => root, + Err(e) => panic!("Error extending trie: {}", e), + } } diff --git a/mpt_trie/src/special_query.rs b/mpt_trie/src/special_query.rs index 5c74cbab8..26ed36053 100644 --- a/mpt_trie/src/special_query.rs +++ b/mpt_trie/src/special_query.rs @@ -131,7 +131,7 @@ mod test { #[test] fn query_iter_works_no_last_node() { common_setup(); - let (trie, ks) = handmade_trie_1(); + let (trie, ks) = handmade_trie_1().unwrap(); // ks --> vec![0x1234, 0x1324, 0x132400005_u64, 0x2001, 0x2002]; let res = vec![ @@ -175,7 +175,7 @@ mod test { #[test] fn query_iter_works_with_last_node() { common_setup(); - let (trie, _) = handmade_trie_1(); + let (trie, _) = handmade_trie_1().unwrap(); let extension_expected = vec![ TrieSegment::Branch(1), diff --git a/mpt_trie/src/testing_utils.rs b/mpt_trie/src/testing_utils.rs index 51b40e541..8d345b303 100644 --- a/mpt_trie/src/testing_utils.rs +++ b/mpt_trie/src/testing_utils.rs @@ -192,19 +192,19 @@ fn gen_rand_u256_bytes(rng: &mut StdRng) -> Vec { /// Initializes a trie with keys large enough to force hashing (nodes less than /// 32 bytes are not hashed). -pub(crate) fn create_trie_with_large_entry_nodes + Copy>(keys: &[T]) -> TrieType { +pub(crate) fn create_trie_with_large_entry_nodes + Copy>(keys: &[T]) -> anyhow::Result { let mut trie = TrieType::default(); for (k, v) in keys.iter().map(|k| (*k).into()).map(large_entry) { - trie.insert(k, v.clone()); + trie.insert(k, v.clone())?; } - trie + Ok(trie) } -pub(crate) fn handmade_trie_1() -> (TrieType, Vec) { +pub(crate) fn handmade_trie_1() -> anyhow::Result<(TrieType, Vec)> { let ks = vec![0x1234, 0x1324, 0x132400005_u64, 0x2001, 0x2002]; let ks_nibbles: Vec = ks.into_iter().map(|k| k.into()).collect(); - let trie = create_trie_with_large_entry_nodes(&ks_nibbles); + let trie = create_trie_with_large_entry_nodes(&ks_nibbles)?; // Branch (0x) --> 1, 2 // Branch (0x1) --> 2, 3 @@ -219,5 +219,5 @@ pub(crate) fn handmade_trie_1() -> (TrieType, Vec) { // Leaf (0x2001) --> (n: 0x1, v: [3]) // Leaf (0x2002) --> (n: 0x2, v: [4]) - (trie, ks_nibbles) + Ok((trie, ks_nibbles)) } diff --git a/mpt_trie/src/trie_hashing.rs b/mpt_trie/src/trie_hashing.rs index b6dc864eb..dd293ffe0 100644 --- a/mpt_trie/src/trie_hashing.rs +++ b/mpt_trie/src/trie_hashing.rs @@ -232,7 +232,7 @@ mod tests { let mut trie = HashedPartialTrie::new(Node::Empty); entries.map(move |(k, v)| { - trie.insert(k, v); + assert!(trie.insert(k, v).is_ok()); trie.get_hash() }) } @@ -376,7 +376,8 @@ mod tests { let half_entries = entries.len() / 2; let entries_to_delete = entries.into_iter().take(half_entries); for (k, _) in entries_to_delete { - our_trie.delete(k); + let res = our_trie.delete(k); + assert_eq!(res.is_ok(), true, "Failed to delete key: {:?}", k); truth_trie.remove(&k.bytes_be()).unwrap(); let truth_root_hash = H256(truth_trie.root_hash().unwrap().0); diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index 1208be70e..4d3c855b1 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -263,7 +263,7 @@ impl Iterator for PartialTrieIter { } impl Node { - pub(crate) fn trie_insert(&mut self, k: K, v: V) + pub(crate) fn trie_insert(&mut self, k: K, v: V) -> anyhow::Result<()> where K: Into, V: Into, @@ -272,19 +272,21 @@ impl Node { trace!("Inserting new node {:?}...", ins_entry); // Inserts are guaranteed to update the root node. - let node_ref: &Node = &insert_into_trie_rec(self, ins_entry).unwrap(); + let node_ref: &Node = &insert_into_trie_rec(self, ins_entry)?.unwrap(); *self = node_ref.clone(); + Ok(()) } - pub(crate) fn trie_extend(&mut self, nodes: I) + pub(crate) fn trie_extend(&mut self, nodes: I) -> anyhow::Result<()> where K: Into, V: Into, I: IntoIterator, { for (k, v) in nodes { - self.trie_insert(k, v); + self.trie_insert(k, v)?; } + Ok(()) } pub(crate) fn trie_get(&self, k: K) -> Option<&[u8]> @@ -330,19 +332,20 @@ impl Node { } } - pub(crate) fn trie_delete(&mut self, k: K) -> Option> + pub(crate) fn trie_delete(&mut self, k: K) -> anyhow::Result>> where K: Into, { let k = k.into(); trace!("Deleting a leaf node with key {} if it exists", k); - delete_intern(&self.clone(), k).map(|(updated_root, deleted_val)| { + delete_intern(&self.clone(), k)?.map_or(Ok(None), |(updated_root, deleted_val)| { // Final check at the root if we have an extension node - let node_ref: &Node = &try_collapse_if_extension(updated_root); + let wrapped_node = try_collapse_if_extension(updated_root)?; + let node_ref: &Node = &wrapped_node; *self = node_ref.clone(); - deleted_val + Ok(Some(deleted_val)) }) } @@ -365,32 +368,36 @@ impl Node { fn insert_into_trie_rec( node: &Node, mut new_node: InsertEntry, -) -> Option> { +) -> anyhow::Result>> { match node { Node::Empty => { trace!("Insert traversed Empty"); - Some(create_node_from_insert_val(new_node.nibbles, new_node.v)) + Ok(Some(create_node_from_insert_val( + new_node.nibbles, + new_node.v, + ))) } Node::Hash(_) => { trace!("Insert traversed {:?}", node); - panic!( - "Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert!" - ) + Err(anyhow::Error::msg("Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert!")) } Node::Branch { children, value } => { if new_node.nibbles.count == 0 { trace!("Insert traversed branch and placed value in node"); - return Some(branch_from_insert_val(children.clone(), new_node.v)); + return Ok(Some(branch_from_insert_val(children.clone(), new_node.v)?)); } let nibble = new_node.nibbles.pop_next_nibble_front(); trace!("Insert traversed Branch (nibble: {:x})", nibble); - insert_into_trie_rec(&children[nibble as usize], new_node).map(|updated_child| { - let mut updated_children = children.clone(); - updated_children[nibble as usize] = updated_child; - branch(updated_children, value.clone()) - }) + insert_into_trie_rec(&children[nibble as usize], new_node)?.map_or( + Ok(None), + |updated_child| { + let mut updated_children = children.clone(); + updated_children[nibble as usize] = updated_child; + Ok(Some(branch(updated_children, value.clone()))) + }, + ) } Node::Extension { nibbles, child } => { trace!("Insert traversed Extension (nibbles: {:?})", nibbles); @@ -402,8 +409,9 @@ fn insert_into_trie_rec( if nibbles.nibbles_are_identical_up_to_smallest_count(&new_node.nibbles) { new_node.truncate_n_nibbles(nibbles.count); - return insert_into_trie_rec(child, new_node) - .map(|updated_child| extension(*nibbles, updated_child)); + return insert_into_trie_rec(child, new_node)?.map_or(Ok(None), |updated_child| { + Ok(Some(extension(*nibbles, updated_child))) + }); } // Drop one since branch will cover one nibble. @@ -418,18 +426,18 @@ fn insert_into_trie_rec( _ => extension(existing_postfix_adjusted_for_branch, child.clone()), }; - Some(place_branch_and_potentially_ext_prefix( + Ok(Some(place_branch_and_potentially_ext_prefix( &info, updated_existing_node, new_node, - )) + ))) } Node::Leaf { nibbles, value } => { trace!("Insert traversed Leaf (nibbles: {:?})", nibbles); // Update existing node value if already present. if *nibbles == new_node.nibbles { - return Some(leaf_from_insert_val(*nibbles, new_node.v)); + return Ok(Some(leaf_from_insert_val(*nibbles, new_node.v)?)); } let info = get_pre_and_postfixes_for_existing_and_new_nodes(nibbles, &new_node.nibbles); @@ -441,11 +449,11 @@ fn insert_into_trie_rec( value.clone(), ); - Some(place_branch_and_potentially_ext_prefix( + Ok(Some(place_branch_and_potentially_ext_prefix( &info, existing_node_truncated, new_node, - )) + ))) } } } @@ -453,24 +461,24 @@ fn insert_into_trie_rec( fn delete_intern( node: &Node, mut curr_k: Nibbles, -) -> Option<(WrappedNode, Vec)> { +) -> anyhow::Result, Vec)>> { match node { Node::Empty => { trace!("Delete traversed Empty"); - None + Ok(None) } - Node::Hash(_) => { - panic!("Attempted to delete a value that ended up inside a hash node") - } // TODO: Find a nice way to get the full key path... + Node::Hash(_) => Err(anyhow::Error::msg( + "Attempted to delete a value that ended up inside a hash node", + )), // TODO: Find a nice way to get the full key path... Node::Branch { children, value } => { if curr_k.is_empty() { - return Some((branch(children.clone(), Vec::new()), value.clone())); + return Ok(Some((branch(children.clone(), Vec::new()), value.clone()))); } let nibble = curr_k.pop_next_nibble_front(); trace!("Delete traversed Branch nibble {:x}", nibble); - delete_intern(&children[nibble as usize], curr_k).map( + delete_intern(&children[nibble as usize], curr_k)?.map_or(Ok(None), |(updated_child, value_deleted)| { // If the child we recursively called is deleted, then we may need to reduce // this branch to an extension/leaf. @@ -481,7 +489,7 @@ fn delete_intern( // Branch stays. let mut updated_children = children.clone(); updated_children[nibble as usize] = - try_collapse_if_extension(updated_child); + try_collapse_if_extension(updated_child)?; branch(updated_children, value.clone()) } true => { @@ -499,7 +507,7 @@ fn delete_intern( } }; - (updated_node, value_deleted) + Ok(Some((updated_node, value_deleted))) }, ) } @@ -513,34 +521,40 @@ fn delete_intern( .nibbles_are_identical_up_to_smallest_count(&curr_k) .then(|| { curr_k.truncate_n_nibbles_front_mut(ext_nibbles.count); - delete_intern(child, curr_k).map(|(updated_child, value_deleted)| { - let updated_node = collapse_ext_node_if_needed(ext_nibbles, &updated_child); - (updated_node, value_deleted) + + delete_intern(child, curr_k).and_then(|res| { + res.map_or(Ok(None), |(updated_child, value_deleted)| { + let updated_node = + collapse_ext_node_if_needed(ext_nibbles, &updated_child)?; + Ok(Some((updated_node, value_deleted))) + }) }) }) - .flatten() + .unwrap_or(Ok(None)) } Node::Leaf { nibbles, value } => { trace!("Delete traversed Leaf (nibbles: {:?})", nibbles); - (*nibbles == curr_k).then(|| { - trace!("Deleting leaf ({:x})", nibbles); - (Node::Empty.into(), value.clone()) - }) + (*nibbles == curr_k) + .then(|| { + trace!("Deleting leaf ({:x})", nibbles); + Ok(Some((Node::Empty.into(), value.clone()))) + }) + .unwrap_or(Ok(None)) } } } -fn try_collapse_if_extension(node: WrappedNode) -> WrappedNode { +fn try_collapse_if_extension(node: WrappedNode) -> anyhow::Result> { match node.as_ref() { Node::Extension { nibbles, child } => collapse_ext_node_if_needed(nibbles, child), - _ => node, + _ => Ok(node), } } fn collapse_ext_node_if_needed( ext_nibbles: &Nibbles, child: &WrappedNode, -) -> WrappedNode { +) -> anyhow::Result> { trace!( "Collapsing extension node ({:x}) with child {}...", ext_nibbles, @@ -548,23 +562,23 @@ fn collapse_ext_node_if_needed( ); match child.as_ref() { - Node::Branch { .. } => extension(*ext_nibbles, child.clone()), + Node::Branch { .. } => Ok(extension(*ext_nibbles, child.clone())), Node::Extension { nibbles: other_ext_nibbles, child: other_ext_child, - } => extension( + } => Ok(extension( ext_nibbles.merge_nibbles(other_ext_nibbles), other_ext_child.clone(), - ), + )), Node::Leaf { nibbles: leaf_nibbles, value, - } => leaf(ext_nibbles.merge_nibbles(leaf_nibbles), value.clone()), - Node::Hash(_) => extension(*ext_nibbles, child.clone()), - _ => panic!( + } => Ok(leaf(ext_nibbles.merge_nibbles(leaf_nibbles), value.clone())), + Node::Hash(_) => Ok(extension(*ext_nibbles, child.clone())), + _ => Err(anyhow::Error::msg(format!( "Extension managed to get a child node type that is impossible! (child: {})", TrieNodeType::from(child) - ), + ))), } } @@ -717,7 +731,7 @@ pub(crate) fn branch( fn branch_from_insert_val( children: [WrappedNode; 16], value: ValOrHash, -) -> WrappedNode { +) -> anyhow::Result> { create_node_if_ins_val_not_hash(value, |value| Node::Branch { children, value }.into()) } @@ -729,7 +743,7 @@ fn leaf(nibbles: Nibbles, value: Vec) -> WrappedNode { Node::Leaf { nibbles, value }.into() } -fn leaf_from_insert_val(nibbles: Nibbles, value: ValOrHash) -> WrappedNode { +fn leaf_from_insert_val(nibbles: Nibbles, value: ValOrHash) -> anyhow::Result> { create_node_if_ins_val_not_hash(value, |value| Node::Leaf { nibbles, value }.into()) } @@ -759,12 +773,13 @@ fn create_node_from_insert_val( fn create_node_if_ins_val_not_hash) -> WrappedNode>( value: ValOrHash, create_node_f: F, -) -> WrappedNode { +) -> anyhow::Result> { match value { - ValOrHash::Val(leaf_v) => create_node_f(leaf_v), - ValOrHash::Hash(h) => { - panic!("Attempted to place a hash node on an existing node! (hash: {h})") - } + ValOrHash::Val(leaf_v) => Ok(create_node_f(leaf_v)), + ValOrHash::Hash(h) => Err(anyhow::Error::msg(format!( + "Attempted to place a hash node on an existing node! (hash: {})", + h + ))), } } @@ -893,7 +908,7 @@ mod tests { let trie = T::from_iter(once(entry(0x1234))); let mut cloned_trie = trie.clone(); - cloned_trie.extend(once(entry(0x5678))); + assert!(cloned_trie.extend(once(entry(0x5678))).is_ok()); assert_ne!(trie, cloned_trie); assert_ne!(trie.hash(), cloned_trie.hash()); @@ -929,7 +944,7 @@ mod tests { MASSIVE_TRIE_SIZE / 10, 51, ); - trie.extend(extra_hash_entries.iter().cloned()); + assert!(trie.extend(extra_hash_entries.iter().cloned()).is_ok()); let all_nodes: HashSet<_> = trie.items().collect(); @@ -990,7 +1005,7 @@ mod tests { } #[test] - fn held_trie_cow_references_do_not_change_as_trie_changes() { + fn held_trie_cow_references_do_not_change_as_trie_changes() -> anyhow::Result<()> { common_setup(); let entries = generate_n_random_variable_trie_value_entries(COW_TEST_TRIE_SIZE, 9002); @@ -1000,7 +1015,7 @@ mod tests { let mut trie = StandardTrie::default(); for (k, v) in entries { - trie.insert(k, v); + trie.insert(k, v)?; all_nodes_in_trie_after_each_insert.push(get_non_hash_values_in_trie(&trie)); root_node_after_each_insert.push(trie.clone()); @@ -1013,6 +1028,8 @@ mod tests { let nodes_retrieved = get_non_hash_values_in_trie(&old_root_node); assert_eq!(old_trie_nodes_truth, nodes_retrieved) } + + Ok(()) } #[test] @@ -1037,9 +1054,10 @@ mod tests { common_setup(); let mut trie = StandardTrie::default(); - trie.insert(0x1234, vec![91]); + assert!(trie.insert(0x1234, vec![91]).is_ok()); - assert!(trie.delete(0x5678).is_none()) + assert!(trie.delete(0x5678).is_ok()); + assert!(trie.delete(0x5678).unwrap().is_none()) } #[test] @@ -1047,7 +1065,8 @@ mod tests { common_setup(); let mut trie = StandardTrie::default(); - assert!(trie.delete(0x1234).is_none()); + assert!(trie.delete(0x1234).is_ok()); + assert!(trie.delete(0x1234).unwrap().is_none()) } #[test] @@ -1066,7 +1085,7 @@ mod tests { let res = trie.delete(*k); assert!(trie.get(*k).is_none()); - assert_eq!(res.as_ref(), Some(v)); + assert_eq!(res.ok().unwrap().as_ref(), Some(v)); } let entries_that_still_should_exist = entries.into_iter().skip(half_entries); diff --git a/mpt_trie/src/trie_subsets.rs b/mpt_trie/src/trie_subsets.rs index 483c86baf..9588fbac6 100644 --- a/mpt_trie/src/trie_subsets.rs +++ b/mpt_trie/src/trie_subsets.rs @@ -503,7 +503,7 @@ mod tests { common_setup(); let mut trie = TrieType::default(); - trie.insert(0x1234, vec![0, 1, 2]); + assert!(trie.insert(0x1234, vec![0, 1, 2]).is_ok()); let res = create_trie_subset(&trie, once(0x5678)); assert!(res.is_ok()); @@ -524,7 +524,7 @@ mod tests { common_setup(); let mut trie = TrieType::default(); - trie.insert(0x1234, vec![0, 1, 2]); + assert!(trie.insert(0x1234, vec![0, 1, 2]).is_ok()); let trie_subset = create_trie_subset(&trie, once(0x1234)).unwrap(); assert_eq!(trie, trie_subset); @@ -534,7 +534,7 @@ mod tests { fn multi_node_trie_returns_proper_subset() { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345_u64]); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345_u64]).unwrap(); let trie_subset = create_trie_subset(&trie, vec![0x1234, 0x56]).unwrap(); let leaf_keys = get_all_nibbles_of_leaf_nodes_in_trie(&trie_subset); @@ -548,7 +548,7 @@ mod tests { fn intermediate_nodes_are_included_in_subset() { common_setup(); - let (trie, ks_nibbles) = handmade_trie_1(); + let (trie, ks_nibbles) = handmade_trie_1().unwrap(); let trie_subset_all = create_trie_subset(&trie, ks_nibbles.iter().cloned()).unwrap(); let subset_keys = get_all_nibbles_of_leaf_nodes_in_trie(&trie_subset_all); @@ -703,7 +703,7 @@ mod tests { #[test] fn hash_of_single_leaf_trie_partial_trie_matches_original_trie() { - let trie = create_trie_with_large_entry_nodes(&[0x0]); + let trie = create_trie_with_large_entry_nodes(&[0x0]).unwrap(); let base_hash = trie.hash(); let partial_trie = create_trie_subset(&trie, [0x1234]).unwrap(); @@ -715,7 +715,7 @@ mod tests { fn sub_trie_that_includes_branch_but_not_children_hashes_out_children() { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x12345, 0x12346, 0x1234f]); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x12345, 0x12346, 0x1234f]).unwrap(); let partial_trie = create_trie_subset(&trie, [0x1234f]).unwrap(); assert_nodes_are_hash_nodes(&partial_trie, [0x12345, 0x12346]); @@ -725,7 +725,7 @@ mod tests { fn sub_trie_for_non_existent_key_that_hits_branch_leaf_does_not_hash_out_leaf() { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x1234589, 0x12346]); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x1234589, 0x12346]).unwrap(); let partial_trie = create_trie_subset(&trie, [0x1234567]).unwrap(); // Note that `0x1234589` gets hashed at the branch slot at `0x12345`. @@ -735,7 +735,7 @@ mod tests { #[test] fn hash_of_branch_partial_tries_matches_original_trie() { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345]); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345]).unwrap(); let base_hash: H256 = trie.hash(); let partial_tries = vec![ diff --git a/trace_decoder/src/decoding.rs b/trace_decoder/src/decoding.rs index b697fcaac..b718dce6e 100644 --- a/trace_decoder/src/decoding.rs +++ b/trace_decoder/src/decoding.rs @@ -316,7 +316,7 @@ impl ProcessedBlockTrace { { // If we are writing a zero, then we actually need to perform a delete. match val == &ZERO_STORAGE_SLOT_VAL_RLPED { - false => storage_trie.insert(slot, val.clone()), + false => storage_trie.insert(slot, val.clone()).unwrap(), true => { if let Some(remaining_slot_key) = Self::delete_node_and_report_remaining_key_if_branch_collapsed( From 301e9a2e10a925a3a4cb722cefc4a19568ce6d13 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 12:04:48 +0200 Subject: [PATCH 02/13] fix: replace anyhow with this-error for mpt_trie --- mpt_trie/Cargo.toml | 1 - mpt_trie/examples/hash_nodes.rs | 3 +- mpt_trie/examples/simple.rs | 4 +- mpt_trie/src/partial_trie.rs | 20 +++++----- mpt_trie/src/testing_utils.rs | 6 +-- mpt_trie/src/trie_ops.rs | 66 +++++++++++++++++++++------------ 6 files changed, 60 insertions(+), 40 deletions(-) diff --git a/mpt_trie/Cargo.toml b/mpt_trie/Cargo.toml index 77bc5c2d8..41b4f704c 100644 --- a/mpt_trie/Cargo.toml +++ b/mpt_trie/Cargo.toml @@ -14,7 +14,6 @@ exclude = [ ] [dependencies] -anyhow = "1.0.40" bytes = { workspace = true } enum-as-inner = { workspace = true } ethereum-types = { workspace = true } diff --git a/mpt_trie/examples/hash_nodes.rs b/mpt_trie/examples/hash_nodes.rs index 4e4d4a0c1..2b18d33fc 100644 --- a/mpt_trie/examples/hash_nodes.rs +++ b/mpt_trie/examples/hash_nodes.rs @@ -54,9 +54,10 @@ use mpt_trie::partial_trie::PartialTrie; use mpt_trie::{ nibbles::Nibbles, partial_trie::{HashedPartialTrie, Node}, + trie_ops::TrieOpResult, }; -fn main() -> anyhow::Result<()> { +fn main() -> TrieOpResult<()> { pretty_env_logger::try_init().unwrap(); // Lets build the (binary) tries in the module-level docs. Since the example diff --git a/mpt_trie/examples/simple.rs b/mpt_trie/examples/simple.rs index 9e6f44896..0c7c3a95a 100644 --- a/mpt_trie/examples/simple.rs +++ b/mpt_trie/examples/simple.rs @@ -6,10 +6,10 @@ use mpt_trie::partial_trie::PartialTrie; use mpt_trie::{ nibbles::{Nibbles, ToNibbles}, partial_trie::{HashedPartialTrie, StandardTrie}, - trie_ops::ValOrHash, + trie_ops::{ValOrHash, TrieOpResult}, }; -fn main() -> anyhow::Result<()>{ +fn main() -> TrieOpResult<()>{ // Construct an empty trie: let mut trie = StandardTrie::default(); diff --git a/mpt_trie/src/partial_trie.rs b/mpt_trie/src/partial_trie.rs index 756076b71..a7dd5d0a4 100644 --- a/mpt_trie/src/partial_trie.rs +++ b/mpt_trie/src/partial_trie.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use crate::{ nibbles::Nibbles, trie_hashing::{hash_trie, rlp_encode_and_hash_node, EncodedNode}, - trie_ops::ValOrHash, + trie_ops::{TrieOpResult, ValOrHash}, utils::bytes_to_h256, }; @@ -58,13 +58,13 @@ pub trait PartialTrie: fn new(n: Node) -> Self; /// Inserts a node into the trie. - fn insert(&mut self, k: K, v: V) -> anyhow::Result<()> + fn insert(&mut self, k: K, v: V) -> TrieOpResult<()> where K: Into, V: Into; /// Add more nodes to the trie through an iterator - fn extend(&mut self, nodes: I) -> anyhow::Result<()> + fn extend(&mut self, nodes: I) -> TrieOpResult<()> where K: Into, V: Into, @@ -89,7 +89,7 @@ pub trait PartialTrie: /// are meant for parts of the trie that are not relevant, traversing one /// means that a `Hash` node was created that potentially should not have /// been. - fn delete(&mut self, k: K) -> anyhow::Result>> + fn delete(&mut self, k: K) -> TrieOpResult>> where K: Into; @@ -214,7 +214,7 @@ impl PartialTrie for StandardTrie { Self(n) } - fn insert(&mut self, k: K, v: V) -> anyhow::Result<()> + fn insert(&mut self, k: K, v: V) -> TrieOpResult<()> where K: Into, V: Into, @@ -223,7 +223,7 @@ impl PartialTrie for StandardTrie { Ok(()) } - fn extend(&mut self, nodes: I) -> anyhow::Result<()> + fn extend(&mut self, nodes: I) -> TrieOpResult<()> where K: Into, V: Into, @@ -239,7 +239,7 @@ impl PartialTrie for StandardTrie { self.0.trie_get(k) } - fn delete(&mut self, k: K) -> anyhow::Result>> + fn delete(&mut self, k: K) -> TrieOpResult>> where K: Into, { @@ -328,7 +328,7 @@ impl PartialTrie for HashedPartialTrie { } } - fn insert(&mut self, k: K, v: V) -> anyhow::Result<()> + fn insert(&mut self, k: K, v: V) -> TrieOpResult<()> where K: Into, V: Into, @@ -338,7 +338,7 @@ impl PartialTrie for HashedPartialTrie { Ok(()) } - fn extend(&mut self, nodes: I) -> anyhow::Result<()> + fn extend(&mut self, nodes: I) -> TrieOpResult<()> where K: Into, V: Into, @@ -356,7 +356,7 @@ impl PartialTrie for HashedPartialTrie { self.node.trie_get(k) } - fn delete(&mut self, k: K) -> anyhow::Result>> + fn delete(&mut self, k: K) -> TrieOpResult>> where K: Into, { diff --git a/mpt_trie/src/testing_utils.rs b/mpt_trie/src/testing_utils.rs index 8d345b303..8dac20159 100644 --- a/mpt_trie/src/testing_utils.rs +++ b/mpt_trie/src/testing_utils.rs @@ -10,7 +10,7 @@ use rand::{rngs::StdRng, seq::IteratorRandom, Rng, RngCore, SeedableRng}; use crate::{ nibbles::Nibbles, partial_trie::{HashedPartialTrie, Node, PartialTrie}, - trie_ops::ValOrHash, + trie_ops::{TrieOpResult, ValOrHash}, utils::is_even, }; @@ -192,7 +192,7 @@ fn gen_rand_u256_bytes(rng: &mut StdRng) -> Vec { /// Initializes a trie with keys large enough to force hashing (nodes less than /// 32 bytes are not hashed). -pub(crate) fn create_trie_with_large_entry_nodes + Copy>(keys: &[T]) -> anyhow::Result { +pub(crate) fn create_trie_with_large_entry_nodes + Copy>(keys: &[T]) -> TrieOpResult { let mut trie = TrieType::default(); for (k, v) in keys.iter().map(|k| (*k).into()).map(large_entry) { trie.insert(k, v.clone())?; @@ -201,7 +201,7 @@ pub(crate) fn create_trie_with_large_entry_nodes + Copy>(keys: Ok(trie) } -pub(crate) fn handmade_trie_1() -> anyhow::Result<(TrieType, Vec)> { +pub(crate) fn handmade_trie_1() -> TrieOpResult<(TrieType, Vec)> { let ks = vec![0x1234, 0x1324, 0x132400005_u64, 0x2001, 0x2002]; let ks_nibbles: Vec = ks.into_iter().map(|k| k.into()).collect(); let trie = create_trie_with_large_entry_nodes(&ks_nibbles)?; diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index 4d3c855b1..7f8c4928f 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -12,6 +12,32 @@ use crate::{ partial_trie::{Node, PartialTrie, WrappedNode}, utils::TrieNodeType, }; +use thiserror::Error; + + +/// Stores the result of trie operations. Returns a [TrieOpError] upon +/// failure. +pub type TrieOpResult = Result; + +/// An error type for trie operation. +#[derive(Debug, Error)] +pub enum TrieOpError { + /// An error that occurs when a hash node is found during an insert operation. + #[error("Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert!")] + HashNodeInsertError(), + + /// An error that occurs when a hash node is found during a delete operation. + #[error("Attempted to delete a value that ended up inside a hash node")] + HashNodeDeleteError(), + + /// An error that occurs when a hash node is found during an extension node collapse. + #[error("Extension managed to get a child node type that is impossible! (child: {0})")] + HashNodeExtError(TrieNodeType), + + /// Failed to insert a hash node into the trie. + #[error("Attempted to place a hash node on an existing node! (hash: {0})")] + ExistingHashNodeError(H256), +} /// A entry to be inserted into a `PartialTrie`. #[derive(Clone, Debug, Eq, Hash, PartialEq)] @@ -263,7 +289,7 @@ impl Iterator for PartialTrieIter { } impl Node { - pub(crate) fn trie_insert(&mut self, k: K, v: V) -> anyhow::Result<()> + pub(crate) fn trie_insert(&mut self, k: K, v: V) -> TrieOpResult<()> where K: Into, V: Into, @@ -277,7 +303,7 @@ impl Node { Ok(()) } - pub(crate) fn trie_extend(&mut self, nodes: I) -> anyhow::Result<()> + pub(crate) fn trie_extend(&mut self, nodes: I) -> TrieOpResult<()> where K: Into, V: Into, @@ -332,7 +358,7 @@ impl Node { } } - pub(crate) fn trie_delete(&mut self, k: K) -> anyhow::Result>> + pub(crate) fn trie_delete(&mut self, k: K) -> TrieOpResult>> where K: Into, { @@ -368,7 +394,7 @@ impl Node { fn insert_into_trie_rec( node: &Node, mut new_node: InsertEntry, -) -> anyhow::Result>> { +) -> TrieOpResult>> { match node { Node::Empty => { trace!("Insert traversed Empty"); @@ -379,7 +405,7 @@ fn insert_into_trie_rec( } Node::Hash(_) => { trace!("Insert traversed {:?}", node); - Err(anyhow::Error::msg("Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert!")) + Err(TrieOpError::HashNodeInsertError()) } Node::Branch { children, value } => { if new_node.nibbles.count == 0 { @@ -461,15 +487,14 @@ fn insert_into_trie_rec( fn delete_intern( node: &Node, mut curr_k: Nibbles, -) -> anyhow::Result, Vec)>> { +) -> TrieOpResult, Vec)>> { match node { Node::Empty => { trace!("Delete traversed Empty"); Ok(None) } - Node::Hash(_) => Err(anyhow::Error::msg( - "Attempted to delete a value that ended up inside a hash node", - )), // TODO: Find a nice way to get the full key path... + Node::Hash(_) => Err(TrieOpError::HashNodeDeleteError()), + // TODO: Find a nice way to get the full key path... Node::Branch { children, value } => { if curr_k.is_empty() { return Ok(Some((branch(children.clone(), Vec::new()), value.clone()))); @@ -544,7 +569,7 @@ fn delete_intern( } } -fn try_collapse_if_extension(node: WrappedNode) -> anyhow::Result> { +fn try_collapse_if_extension(node: WrappedNode) -> TrieOpResult> { match node.as_ref() { Node::Extension { nibbles, child } => collapse_ext_node_if_needed(nibbles, child), _ => Ok(node), @@ -554,7 +579,7 @@ fn try_collapse_if_extension(node: WrappedNode) -> anyhow::Re fn collapse_ext_node_if_needed( ext_nibbles: &Nibbles, child: &WrappedNode, -) -> anyhow::Result> { +) -> TrieOpResult> { trace!( "Collapsing extension node ({:x}) with child {}...", ext_nibbles, @@ -575,10 +600,7 @@ fn collapse_ext_node_if_needed( value, } => Ok(leaf(ext_nibbles.merge_nibbles(leaf_nibbles), value.clone())), Node::Hash(_) => Ok(extension(*ext_nibbles, child.clone())), - _ => Err(anyhow::Error::msg(format!( - "Extension managed to get a child node type that is impossible! (child: {})", - TrieNodeType::from(child) - ))), + _ => Err(TrieOpError::HashNodeExtError(TrieNodeType::from(child))), } } @@ -731,7 +753,7 @@ pub(crate) fn branch( fn branch_from_insert_val( children: [WrappedNode; 16], value: ValOrHash, -) -> anyhow::Result> { +) -> TrieOpResult> { create_node_if_ins_val_not_hash(value, |value| Node::Branch { children, value }.into()) } @@ -743,7 +765,7 @@ fn leaf(nibbles: Nibbles, value: Vec) -> WrappedNode { Node::Leaf { nibbles, value }.into() } -fn leaf_from_insert_val(nibbles: Nibbles, value: ValOrHash) -> anyhow::Result> { +fn leaf_from_insert_val(nibbles: Nibbles, value: ValOrHash) -> TrieOpResult> { create_node_if_ins_val_not_hash(value, |value| Node::Leaf { nibbles, value }.into()) } @@ -773,13 +795,10 @@ fn create_node_from_insert_val( fn create_node_if_ins_val_not_hash) -> WrappedNode>( value: ValOrHash, create_node_f: F, -) -> anyhow::Result> { +) -> TrieOpResult> { match value { ValOrHash::Val(leaf_v) => Ok(create_node_f(leaf_v)), - ValOrHash::Hash(h) => Err(anyhow::Error::msg(format!( - "Attempted to place a hash node on an existing node! (hash: {})", - h - ))), + ValOrHash::Hash(h) => Err(TrieOpError::ExistingHashNodeError(h)), } } @@ -801,6 +820,7 @@ mod tests { unwrap_iter_item_to_val, TestInsertValEntry, }, utils::create_mask_of_1s, + trie_ops::TrieOpResult, }; const MASSIVE_TRIE_SIZE: usize = 100000; @@ -1005,7 +1025,7 @@ mod tests { } #[test] - fn held_trie_cow_references_do_not_change_as_trie_changes() -> anyhow::Result<()> { + fn held_trie_cow_references_do_not_change_as_trie_changes() -> TrieOpResult<()> { common_setup(); let entries = generate_n_random_variable_trie_value_entries(COW_TEST_TRIE_SIZE, 9002); From 4e3df652ea79d63ac1dbacdca0432dbb15e05905 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 13:07:01 +0200 Subject: [PATCH 03/13] style: formatting --- mpt_trie/examples/simple.rs | 4 ++-- mpt_trie/src/testing_utils.rs | 4 +++- mpt_trie/src/trie_ops.rs | 21 +++++++++++++-------- mpt_trie/src/trie_subsets.rs | 3 ++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/mpt_trie/examples/simple.rs b/mpt_trie/examples/simple.rs index 0c7c3a95a..70ed14544 100644 --- a/mpt_trie/examples/simple.rs +++ b/mpt_trie/examples/simple.rs @@ -6,10 +6,10 @@ use mpt_trie::partial_trie::PartialTrie; use mpt_trie::{ nibbles::{Nibbles, ToNibbles}, partial_trie::{HashedPartialTrie, StandardTrie}, - trie_ops::{ValOrHash, TrieOpResult}, + trie_ops::{TrieOpResult, ValOrHash}, }; -fn main() -> TrieOpResult<()>{ +fn main() -> TrieOpResult<()> { // Construct an empty trie: let mut trie = StandardTrie::default(); diff --git a/mpt_trie/src/testing_utils.rs b/mpt_trie/src/testing_utils.rs index 8dac20159..58b344d79 100644 --- a/mpt_trie/src/testing_utils.rs +++ b/mpt_trie/src/testing_utils.rs @@ -192,7 +192,9 @@ fn gen_rand_u256_bytes(rng: &mut StdRng) -> Vec { /// Initializes a trie with keys large enough to force hashing (nodes less than /// 32 bytes are not hashed). -pub(crate) fn create_trie_with_large_entry_nodes + Copy>(keys: &[T]) -> TrieOpResult { +pub(crate) fn create_trie_with_large_entry_nodes + Copy>( + keys: &[T], +) -> TrieOpResult { let mut trie = TrieType::default(); for (k, v) in keys.iter().map(|k| (*k).into()).map(large_entry) { trie.insert(k, v.clone())?; diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index 7f8c4928f..3cc777ca1 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -6,14 +6,13 @@ use std::{fmt::Display, mem::size_of}; use enum_as_inner::EnumAsInner; use ethereum_types::{H256, U128, U256, U512}; use log::trace; +use thiserror::Error; use crate::{ nibbles::{Nibble, Nibbles}, partial_trie::{Node, PartialTrie, WrappedNode}, utils::TrieNodeType, }; -use thiserror::Error; - /// Stores the result of trie operations. Returns a [TrieOpError] upon /// failure. @@ -22,15 +21,18 @@ pub type TrieOpResult = Result; /// An error type for trie operation. #[derive(Debug, Error)] pub enum TrieOpError { - /// An error that occurs when a hash node is found during an insert operation. + /// An error that occurs when a hash node is found during an insert + /// operation. #[error("Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert!")] HashNodeInsertError(), - /// An error that occurs when a hash node is found during a delete operation. + /// An error that occurs when a hash node is found during a delete + /// operation. #[error("Attempted to delete a value that ended up inside a hash node")] HashNodeDeleteError(), - /// An error that occurs when a hash node is found during an extension node collapse. + /// An error that occurs when a hash node is found during an extension node + /// collapse. #[error("Extension managed to get a child node type that is impossible! (child: {0})")] HashNodeExtError(TrieNodeType), @@ -493,7 +495,7 @@ fn delete_intern( trace!("Delete traversed Empty"); Ok(None) } - Node::Hash(_) => Err(TrieOpError::HashNodeDeleteError()), + Node::Hash(_) => Err(TrieOpError::HashNodeDeleteError()), // TODO: Find a nice way to get the full key path... Node::Branch { children, value } => { if curr_k.is_empty() { @@ -765,7 +767,10 @@ fn leaf(nibbles: Nibbles, value: Vec) -> WrappedNode { Node::Leaf { nibbles, value }.into() } -fn leaf_from_insert_val(nibbles: Nibbles, value: ValOrHash) -> TrieOpResult> { +fn leaf_from_insert_val( + nibbles: Nibbles, + value: ValOrHash, +) -> TrieOpResult> { create_node_if_ins_val_not_hash(value, |value| Node::Leaf { nibbles, value }.into()) } @@ -819,8 +824,8 @@ mod tests { generate_n_random_variable_trie_value_entries, get_non_hash_values_in_trie, unwrap_iter_item_to_val, TestInsertValEntry, }, - utils::create_mask_of_1s, trie_ops::TrieOpResult, + utils::create_mask_of_1s, }; const MASSIVE_TRIE_SIZE: usize = 100000; diff --git a/mpt_trie/src/trie_subsets.rs b/mpt_trie/src/trie_subsets.rs index 9588fbac6..8dd8ac724 100644 --- a/mpt_trie/src/trie_subsets.rs +++ b/mpt_trie/src/trie_subsets.rs @@ -715,7 +715,8 @@ mod tests { fn sub_trie_that_includes_branch_but_not_children_hashes_out_children() { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x12345, 0x12346, 0x1234f]).unwrap(); + let trie = + create_trie_with_large_entry_nodes(&[0x1234, 0x12345, 0x12346, 0x1234f]).unwrap(); let partial_trie = create_trie_subset(&trie, [0x1234f]).unwrap(); assert_nodes_are_hash_nodes(&partial_trie, [0x12345, 0x12346]); From f2ccdd59439e5d1e7f85c6a9ab6607107eab0440 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 14:12:55 +0200 Subject: [PATCH 04/13] fix: fix results --- evm_arithmetization/tests/add11_yml.rs | 14 ++--- .../tests/basic_smart_contract.rs | 2 +- evm_arithmetization/tests/erc20.rs | 49 ++++++++--------- evm_arithmetization/tests/erc721.rs | 49 ++++++++--------- evm_arithmetization/tests/log_opcode.rs | 54 +++++++++---------- .../tests/self_balance_gas_cost.rs | 14 ++--- evm_arithmetization/tests/selfdestruct.rs | 8 +-- evm_arithmetization/tests/simple_transfer.rs | 2 +- evm_arithmetization/tests/withdrawals.rs | 2 +- mpt_trie/src/trie_hashing.rs | 2 +- 10 files changed, 99 insertions(+), 97 deletions(-) diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index 772bd4774..00d7e56b4 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -63,9 +63,9 @@ fn add11_yml() -> anyhow::Result<()> { state_trie_before.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_before).to_vec(), - ); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); + )?; + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; let tries_before = TrieInputs { state_trie: state_trie_before, @@ -119,10 +119,10 @@ fn add11_yml() -> anyhow::Result<()> { expected_state_trie_after.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), - ); + )?; expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; expected_state_trie_after }; @@ -136,7 +136,7 @@ fn add11_yml() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x80").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), diff --git a/evm_arithmetization/tests/basic_smart_contract.rs b/evm_arithmetization/tests/basic_smart_contract.rs index 6f9bfc8d2..fd0948d80 100644 --- a/evm_arithmetization/tests/basic_smart_contract.rs +++ b/evm_arithmetization/tests/basic_smart_contract.rs @@ -168,7 +168,7 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x80").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index ef4b22878..e875d1ec6 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -62,13 +62,13 @@ fn test_erc20() -> anyhow::Result<()> { let token_nibbles = Nibbles::from_bytes_be(token_state_key.as_bytes()).unwrap(); let mut state_trie_before = HashedPartialTrie::from(Node::Empty); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account()).to_vec()); - state_trie_before.insert(giver_nibbles, rlp::encode(&giver_account()).to_vec()); - state_trie_before.insert(token_nibbles, rlp::encode(&token_account()).to_vec()); + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account()).to_vec())?; + state_trie_before.insert(giver_nibbles, rlp::encode(&giver_account()).to_vec())?; + state_trie_before.insert(token_nibbles, rlp::encode(&token_account()).to_vec())?; let storage_tries = vec![ - (giver_state_key, giver_storage()), - (token_state_key, token_storage()), + (giver_state_key, giver_storage()?), + (token_state_key, token_storage()?), ]; let tries_before = TrieInputs { @@ -107,13 +107,13 @@ fn test_erc20() -> anyhow::Result<()> { balance: sender_account.balance - gas_used * 0xa, ..sender_account }; - state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - state_trie_after.insert(giver_nibbles, rlp::encode(&giver_account()).to_vec()); + state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + state_trie_after.insert(giver_nibbles, rlp::encode(&giver_account()).to_vec())?; let token_account_after = AccountRlp { - storage_root: token_storage_after().hash(), + storage_root: token_storage_after()?.hash(), ..token_account() }; - state_trie_after.insert(token_nibbles, rlp::encode(&token_account_after).to_vec()); + state_trie_after.insert(token_nibbles, rlp::encode(&token_account_after).to_vec())?; state_trie_after }; @@ -144,7 +144,7 @@ fn test_erc20() -> anyhow::Result<()> { }], }; let mut receipts_trie = HashedPartialTrie::from(Node::Empty); - receipts_trie.insert(Nibbles::from_str("0x80").unwrap(), receipt_0.encode(2)); + receipts_trie.insert(Nibbles::from_str("0x80").unwrap(), receipt_0.encode(2))?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), @@ -192,60 +192,61 @@ fn token_bytecode() -> Vec { hex!("608060405234801561001057600080fd5b50600436106100935760003560e01c8063313ce56711610066578063313ce567146100fe57806370a082311461010d57806395d89b4114610136578063a9059cbb1461013e578063dd62ed3e1461015157600080fd5b806306fdde0314610098578063095ea7b3146100b657806318160ddd146100d957806323b872dd146100eb575b600080fd5b6100a061018a565b6040516100ad919061056a565b60405180910390f35b6100c96100c43660046105d4565b61021c565b60405190151581526020016100ad565b6002545b6040519081526020016100ad565b6100c96100f93660046105fe565b610236565b604051601281526020016100ad565b6100dd61011b36600461063a565b6001600160a01b031660009081526020819052604090205490565b6100a061025a565b6100c961014c3660046105d4565b610269565b6100dd61015f36600461065c565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101999061068f565b80601f01602080910402602001604051908101604052809291908181526020018280546101c59061068f565b80156102125780601f106101e757610100808354040283529160200191610212565b820191906000526020600020905b8154815290600101906020018083116101f557829003601f168201915b5050505050905090565b60003361022a818585610277565b60019150505b92915050565b600033610244858285610289565b61024f85858561030c565b506001949350505050565b6060600480546101999061068f565b60003361022a81858561030c565b610284838383600161036b565b505050565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461030657818110156102f757604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b6103068484848403600061036b565b50505050565b6001600160a01b03831661033657604051634b637e8f60e11b8152600060048201526024016102ee565b6001600160a01b0382166103605760405163ec442f0560e01b8152600060048201526024016102ee565b610284838383610440565b6001600160a01b0384166103955760405163e602df0560e01b8152600060048201526024016102ee565b6001600160a01b0383166103bf57604051634a1406b160e11b8152600060048201526024016102ee565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561030657826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161043291815260200190565b60405180910390a350505050565b6001600160a01b03831661046b57806002600082825461046091906106c9565b909155506104dd9050565b6001600160a01b038316600090815260208190526040902054818110156104be5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016102ee565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166104f957600280548290039055610518565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161055d91815260200190565b60405180910390a3505050565b600060208083528351808285015260005b818110156105975785810183015185820160400152820161057b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146105cf57600080fd5b919050565b600080604083850312156105e757600080fd5b6105f0836105b8565b946020939093013593505050565b60008060006060848603121561061357600080fd5b61061c846105b8565b925061062a602085016105b8565b9150604084013590509250925092565b60006020828403121561064c57600080fd5b610655826105b8565b9392505050565b6000806040838503121561066f57600080fd5b610678836105b8565b9150610686602084016105b8565b90509250929050565b600181811c908216806106a357607f821691505b6020821081036106c357634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561023057634e487b7160e01b600052601160045260246000fdfea2646970667358221220266a323ae4a816f6c6342a5be431fedcc0d45c44b02ea75f5474eb450b5d45b364736f6c63430008140033").into() } -fn insert_storage(trie: &mut HashedPartialTrie, slot: U256, value: U256) { +fn insert_storage(trie: &mut HashedPartialTrie, slot: U256, value: U256) -> anyhow::Result<()> { let mut bytes = [0; 32]; slot.to_big_endian(&mut bytes); let key = keccak(bytes); let nibbles = Nibbles::from_bytes_be(key.as_bytes()).unwrap(); let r = rlp::encode(&value); let r = r.freeze().to_vec(); - trie.insert(nibbles, r); + trie.insert(nibbles, r)?; + Ok(()) } fn sd2u(s: &str) -> U256 { U256::from_dec_str(s).unwrap() } -fn giver_storage() -> HashedPartialTrie { +fn giver_storage() -> anyhow::Result { let mut trie = HashedPartialTrie::from(Node::Empty); insert_storage( &mut trie, U256::zero(), sd2u("546584486846459126461364135121053344201067465379"), - ); - trie + )?; + Ok(trie) } -fn token_storage() -> HashedPartialTrie { +fn token_storage() -> anyhow::Result { let mut trie = HashedPartialTrie::from(Node::Empty); insert_storage( &mut trie, sd2u("82183438603287090451672504949863617512989139203883434767553028632841710582583"), sd2u("1000000000000000000000"), - ); - trie + )?; + Ok(trie) } -fn token_storage_after() -> HashedPartialTrie { +fn token_storage_after() -> anyhow::Result { let mut trie = HashedPartialTrie::from(Node::Empty); insert_storage( &mut trie, sd2u("82183438603287090451672504949863617512989139203883434767553028632841710582583"), sd2u("900000000000000000000"), - ); + )?; insert_storage( &mut trie, sd2u("53006154680716014998529145169423020330606407246856709517064848190396281160729"), sd2u("100000000000000000000"), - ); - trie + )?; + Ok(trie) } fn giver_account() -> AccountRlp { AccountRlp { nonce: 1.into(), balance: 0.into(), - storage_root: giver_storage().hash(), + storage_root: giver_storage().expect("storage insert failure").hash(), code_hash: keccak(giver_bytecode()), } } @@ -254,7 +255,7 @@ fn token_account() -> AccountRlp { AccountRlp { nonce: 1.into(), balance: 0.into(), - storage_root: token_storage().hash(), + storage_root: token_storage().expect("storage insert failure").hash(), code_hash: keccak(token_bytecode()), } } diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index 207fa69db..9b79ff16e 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -62,10 +62,10 @@ fn test_erc721() -> anyhow::Result<()> { let contract_nibbles = Nibbles::from_bytes_be(contract_state_key.as_bytes()).unwrap(); let mut state_trie_before = HashedPartialTrie::from(Node::Empty); - state_trie_before.insert(owner_nibbles, rlp::encode(&owner_account()).to_vec()); - state_trie_before.insert(contract_nibbles, rlp::encode(&contract_account()).to_vec()); + state_trie_before.insert(owner_nibbles, rlp::encode(&owner_account()).to_vec())?; + state_trie_before.insert(contract_nibbles, rlp::encode(&contract_account()).to_vec())?; - let storage_tries = vec![(contract_state_key, contract_storage())]; + let storage_tries = vec![(contract_state_key, contract_storage()?)]; let tries_before = TrieInputs { state_trie: state_trie_before, @@ -90,15 +90,15 @@ fn test_erc721() -> anyhow::Result<()> { balance: owner_account.balance - gas_used * 0xa, ..owner_account }; - state_trie_after.insert(owner_nibbles, rlp::encode(&owner_account_after).to_vec()); + state_trie_after.insert(owner_nibbles, rlp::encode(&owner_account_after).to_vec())?; let contract_account_after = AccountRlp { - storage_root: contract_storage_after().hash(), + storage_root: contract_storage_after()?.hash(), ..contract_account() }; state_trie_after.insert( contract_nibbles, rlp::encode(&contract_account_after).to_vec(), - ); + )?; state_trie_after }; @@ -128,7 +128,7 @@ fn test_erc721() -> anyhow::Result<()> { logs, }; let mut receipts_trie = HashedPartialTrie::from(Node::Empty); - receipts_trie.insert(Nibbles::from_str("0x80").unwrap(), receipt_0.encode(0)); + receipts_trie.insert(Nibbles::from_str("0x80").unwrap(), receipt_0.encode(0))?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), @@ -191,14 +191,15 @@ fn contract_bytecode() -> Vec { hex!("608060405234801561000f575f80fd5b5060043610610109575f3560e01c8063715018a6116100a0578063a22cb4651161006f578063a22cb465146102a1578063b88d4fde146102bd578063c87b56dd146102d9578063e985e9c514610309578063f2fde38b1461033957610109565b8063715018a61461023f5780638da5cb5b1461024957806395d89b4114610267578063a14481941461028557610109565b806323b872dd116100dc57806323b872dd146101a757806342842e0e146101c35780636352211e146101df57806370a082311461020f57610109565b806301ffc9a71461010d57806306fdde031461013d578063081812fc1461015b578063095ea7b31461018b575b5f80fd5b61012760048036038101906101229190611855565b610355565b604051610134919061189a565b60405180910390f35b610145610436565b604051610152919061193d565b60405180910390f35b61017560048036038101906101709190611990565b6104c5565b60405161018291906119fa565b60405180910390f35b6101a560048036038101906101a09190611a3d565b6104e0565b005b6101c160048036038101906101bc9190611a7b565b6104f6565b005b6101dd60048036038101906101d89190611a7b565b6105f5565b005b6101f960048036038101906101f49190611990565b610614565b60405161020691906119fa565b60405180910390f35b61022960048036038101906102249190611acb565b610625565b6040516102369190611b05565b60405180910390f35b6102476106db565b005b6102516106ee565b60405161025e91906119fa565b60405180910390f35b61026f610716565b60405161027c919061193d565b60405180910390f35b61029f600480360381019061029a9190611a3d565b6107a6565b005b6102bb60048036038101906102b69190611b48565b6107bc565b005b6102d760048036038101906102d29190611cb2565b6107d2565b005b6102f360048036038101906102ee9190611990565b6107ef565b604051610300919061193d565b60405180910390f35b610323600480360381019061031e9190611d32565b610855565b604051610330919061189a565b60405180910390f35b610353600480360381019061034e9190611acb565b6108e3565b005b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061041f57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061042f575061042e82610967565b5b9050919050565b60605f805461044490611d9d565b80601f016020809104026020016040519081016040528092919081815260200182805461047090611d9d565b80156104bb5780601f10610492576101008083540402835291602001916104bb565b820191905f5260205f20905b81548152906001019060200180831161049e57829003601f168201915b5050505050905090565b5f6104cf826109d0565b506104d982610a56565b9050919050565b6104f282826104ed610a8f565b610a96565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610566575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161055d91906119fa565b60405180910390fd5b5f6105798383610574610a8f565b610aa8565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105ef578382826040517f64283d7b0000000000000000000000000000000000000000000000000000000081526004016105e693929190611dcd565b60405180910390fd5b50505050565b61060f83838360405180602001604052805f8152506107d2565b505050565b5f61061e826109d0565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610696575f6040517f89c62b6400000000000000000000000000000000000000000000000000000000815260040161068d91906119fa565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6106e3610cb3565b6106ec5f610d3a565b565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461072590611d9d565b80601f016020809104026020016040519081016040528092919081815260200182805461075190611d9d565b801561079c5780601f106107735761010080835404028352916020019161079c565b820191905f5260205f20905b81548152906001019060200180831161077f57829003601f168201915b5050505050905090565b6107ae610cb3565b6107b88282610dfd565b5050565b6107ce6107c7610a8f565b8383610e1a565b5050565b6107dd8484846104f6565b6107e984848484610f83565b50505050565b60606107fa826109d0565b505f610804611135565b90505f8151116108225760405180602001604052805f81525061084d565b8061082c8461114b565b60405160200161083d929190611e3c565b6040516020818303038152906040525b915050919050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6108eb610cb3565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361095b575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161095291906119fa565b60405180910390fd5b61096481610d3a565b50565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f806109db83611215565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610a4d57826040517f7e273289000000000000000000000000000000000000000000000000000000008152600401610a449190611b05565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b610aa3838383600161124e565b505050565b5f80610ab384611215565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610af457610af381848661140d565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b7f57610b335f855f8061124e565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614610bfe57600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b610cbb610a8f565b73ffffffffffffffffffffffffffffffffffffffff16610cd96106ee565b73ffffffffffffffffffffffffffffffffffffffff1614610d3857610cfc610a8f565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401610d2f91906119fa565b60405180910390fd5b565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b610e16828260405180602001604052805f8152506114d0565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e8a57816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401610e8191906119fa565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610f76919061189a565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b111561112f578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02610fc6610a8f565b8685856040518563ffffffff1660e01b8152600401610fe89493929190611eb1565b6020604051808303815f875af192505050801561102357506040513d601f19601f820116820180604052508101906110209190611f0f565b60015b6110a4573d805f8114611051576040519150601f19603f3d011682016040523d82523d5f602084013e611056565b606091505b505f81510361109c57836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161109391906119fa565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461112d57836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161112491906119fa565b60405180910390fd5b505b50505050565b606060405180602001604052805f815250905090565b60605f6001611159846114eb565b0190505f8167ffffffffffffffff81111561117757611176611b8e565b5b6040519080825280601f01601f1916602001820160405280156111a95781602001600182028036833780820191505090505b5090505f82602001820190505b60011561120a578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816111ff576111fe611f3a565b5b0494505f85036111b6575b819350505050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061128657505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b156113b8575f611295846109d0565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156112ff57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561131257506113108184610855565b155b1561135457826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161134b91906119fa565b60405180910390fd5b81156113b657838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b61141883838361163c565b6114cb575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361148c57806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016114839190611b05565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016114c2929190611f67565b60405180910390fd5b505050565b6114da83836116fc565b6114e65f848484610f83565b505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611547577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161153d5761153c611f3a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611584576d04ee2d6d415b85acef8100000000838161157a57611579611f3a565b5b0492506020810190505b662386f26fc1000083106115b357662386f26fc1000083816115a9576115a8611f3a565b5b0492506010810190505b6305f5e10083106115dc576305f5e10083816115d2576115d1611f3a565b5b0492506008810190505b61271083106116015761271083816115f7576115f6611f3a565b5b0492506004810190505b60648310611624576064838161161a57611619611f3a565b5b0492506002810190505b600a8310611633576001810190505b80915050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156116f357508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806116b457506116b38484610855565b5b806116f257508273ffffffffffffffffffffffffffffffffffffffff166116da83610a56565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361176c575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161176391906119fa565b60405180910390fd5b5f61177883835f610aa8565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146117ea575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016117e191906119fa565b60405180910390fd5b505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61183481611800565b811461183e575f80fd5b50565b5f8135905061184f8161182b565b92915050565b5f6020828403121561186a576118696117f8565b5b5f61187784828501611841565b91505092915050565b5f8115159050919050565b61189481611880565b82525050565b5f6020820190506118ad5f83018461188b565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156118ea5780820151818401526020810190506118cf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61190f826118b3565b61191981856118bd565b93506119298185602086016118cd565b611932816118f5565b840191505092915050565b5f6020820190508181035f8301526119558184611905565b905092915050565b5f819050919050565b61196f8161195d565b8114611979575f80fd5b50565b5f8135905061198a81611966565b92915050565b5f602082840312156119a5576119a46117f8565b5b5f6119b28482850161197c565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6119e4826119bb565b9050919050565b6119f4816119da565b82525050565b5f602082019050611a0d5f8301846119eb565b92915050565b611a1c816119da565b8114611a26575f80fd5b50565b5f81359050611a3781611a13565b92915050565b5f8060408385031215611a5357611a526117f8565b5b5f611a6085828601611a29565b9250506020611a718582860161197c565b9150509250929050565b5f805f60608486031215611a9257611a916117f8565b5b5f611a9f86828701611a29565b9350506020611ab086828701611a29565b9250506040611ac18682870161197c565b9150509250925092565b5f60208284031215611ae057611adf6117f8565b5b5f611aed84828501611a29565b91505092915050565b611aff8161195d565b82525050565b5f602082019050611b185f830184611af6565b92915050565b611b2781611880565b8114611b31575f80fd5b50565b5f81359050611b4281611b1e565b92915050565b5f8060408385031215611b5e57611b5d6117f8565b5b5f611b6b85828601611a29565b9250506020611b7c85828601611b34565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b611bc4826118f5565b810181811067ffffffffffffffff82111715611be357611be2611b8e565b5b80604052505050565b5f611bf56117ef565b9050611c018282611bbb565b919050565b5f67ffffffffffffffff821115611c2057611c1f611b8e565b5b611c29826118f5565b9050602081019050919050565b828183375f83830152505050565b5f611c56611c5184611c06565b611bec565b905082815260208101848484011115611c7257611c71611b8a565b5b611c7d848285611c36565b509392505050565b5f82601f830112611c9957611c98611b86565b5b8135611ca9848260208601611c44565b91505092915050565b5f805f8060808587031215611cca57611cc96117f8565b5b5f611cd787828801611a29565b9450506020611ce887828801611a29565b9350506040611cf98782880161197c565b925050606085013567ffffffffffffffff811115611d1a57611d196117fc565b5b611d2687828801611c85565b91505092959194509250565b5f8060408385031215611d4857611d476117f8565b5b5f611d5585828601611a29565b9250506020611d6685828601611a29565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680611db457607f821691505b602082108103611dc757611dc6611d70565b5b50919050565b5f606082019050611de05f8301866119eb565b611ded6020830185611af6565b611dfa60408301846119eb565b949350505050565b5f81905092915050565b5f611e16826118b3565b611e208185611e02565b9350611e308185602086016118cd565b80840191505092915050565b5f611e478285611e0c565b9150611e538284611e0c565b91508190509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f611e8382611e5f565b611e8d8185611e69565b9350611e9d8185602086016118cd565b611ea6816118f5565b840191505092915050565b5f608082019050611ec45f8301876119eb565b611ed160208301866119eb565b611ede6040830185611af6565b8181036060830152611ef08184611e79565b905095945050505050565b5f81519050611f098161182b565b92915050565b5f60208284031215611f2457611f236117f8565b5b5f611f3184828501611efb565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f604082019050611f7a5f8301856119eb565b611f876020830184611af6565b939250505056fea2646970667358221220432b30673e00c0eb009e1718c271f4cfdfbeded17345829703b06d322360990164736f6c63430008160033").into() } -fn insert_storage(trie: &mut HashedPartialTrie, slot: U256, value: U256) { +fn insert_storage(trie: &mut HashedPartialTrie, slot: U256, value: U256) -> anyhow::Result<()> { let mut bytes = [0; 32]; slot.to_big_endian(&mut bytes); let key = keccak(bytes); let nibbles = Nibbles::from_bytes_be(key.as_bytes()).unwrap(); let r = rlp::encode(&value); let r = r.freeze().to_vec(); - trie.insert(nibbles, r); + trie.insert(nibbles, r)?; + Ok(()) } fn sd2u(s: &str) -> U256 { @@ -209,64 +210,64 @@ fn sh2u(s: &str) -> U256 { U256::from_str_radix(s, 16).unwrap() } -fn contract_storage() -> HashedPartialTrie { +fn contract_storage() -> anyhow::Result { let mut trie = HashedPartialTrie::from(Node::Empty); insert_storage( &mut trie, U256::zero(), sh2u("0x54657374546f6b656e0000000000000000000000000000000000000000000012"), - ); + )?; insert_storage( &mut trie, U256::one(), sh2u("0x5445535400000000000000000000000000000000000000000000000000000008"), - ); + )?; insert_storage( &mut trie, sd2u("6"), sh2u("0x5b38da6a701c568545dcfcb03fcb875f56beddc4"), - ); + )?; insert_storage( &mut trie, sh2u("0x343ff8127bd64f680be4e996254dc3528603c6ecd54364b4cf956ebdd28f0028"), sh2u("0x5b38da6a701c568545dcfcb03fcb875f56beddc4"), - ); + )?; insert_storage( &mut trie, sh2u("0x118c1ea466562cb796e30ef705e4db752f5c39d773d22c5efd8d46f67194e78a"), sd2u("1"), - ); - trie + )?; + Ok(trie) } -fn contract_storage_after() -> HashedPartialTrie { +fn contract_storage_after() -> anyhow::Result { let mut trie = HashedPartialTrie::from(Node::Empty); insert_storage( &mut trie, U256::zero(), sh2u("0x54657374546f6b656e0000000000000000000000000000000000000000000012"), - ); + )?; insert_storage( &mut trie, U256::one(), sh2u("0x5445535400000000000000000000000000000000000000000000000000000008"), - ); + )?; insert_storage( &mut trie, sd2u("6"), sh2u("0x5b38da6a701c568545dcfcb03fcb875f56beddc4"), - ); + )?; insert_storage( &mut trie, sh2u("0x343ff8127bd64f680be4e996254dc3528603c6ecd54364b4cf956ebdd28f0028"), sh2u("0xab8483f64d9c6d1ecf9b849ae677dd3315835cb2"), - ); + )?; insert_storage( &mut trie, sh2u("0xf3aa6a8a9f7e3707e36cc99c499a27514922afe861ec3d80a1a314409cba92f9"), sd2u("1"), - ); - trie + )?; + Ok(trie) } fn owner_account() -> AccountRlp { @@ -282,7 +283,7 @@ fn contract_account() -> AccountRlp { AccountRlp { nonce: 0.into(), balance: 0.into(), - storage_root: contract_storage().hash(), + storage_root: contract_storage().expect("storage insert failure").hash(), code_hash: keccak(contract_bytecode()), } } diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 56e5bbf6d..6ec3e59a6 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -88,9 +88,9 @@ fn test_log_opcodes() -> anyhow::Result<()> { state_trie_before.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_before).to_vec(), - ); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); + )?; + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; // We now add two receipts with logs and data. This updates the receipt trie as // well. @@ -119,7 +119,7 @@ fn test_log_opcodes() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x1337").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let tries_before = TrieInputs { state_trie: state_trie_before, @@ -193,16 +193,16 @@ fn test_log_opcodes() -> anyhow::Result<()> { let receipt_nibbles = Nibbles::from_str("0x80").unwrap(); // RLP(0) = 0x80 - receipts_trie.insert(receipt_nibbles, rlp::encode(&receipt).to_vec()); + receipts_trie.insert(receipt_nibbles, rlp::encode(&receipt).to_vec())?; // Update the state trie. let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); expected_state_trie_after.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), - ); - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + )?; + expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), @@ -319,13 +319,13 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { state_trie_before.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_before).to_vec(), - ); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); + )?; + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; state_trie_before.insert( to_second_nibbles, rlp::encode(&to_account_second_before).to_vec(), - ); + )?; let checkpoint_state_trie_root = state_trie_before.hash(); let tries_before = TrieInputs { @@ -389,13 +389,13 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { expected_state_trie_after.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), - ); - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + )?; + expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; expected_state_trie_after.insert( to_second_nibbles, rlp::encode(&to_account_second_before).to_vec(), - ); + )?; // Compute new receipt trie. let mut receipts_trie = HashedPartialTrie::from(Node::Empty); @@ -408,7 +408,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x80").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let mut transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), @@ -530,22 +530,22 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { let receipt_nibbles = Nibbles::from_str("0x01").unwrap(); // RLP(1) = 0x1 - receipts_trie.insert(receipt_nibbles, rlp::encode(&receipt).to_vec()); + receipts_trie.insert(receipt_nibbles, rlp::encode(&receipt).to_vec())?; // Update the state trie. let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); expected_state_trie_after.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), - ); - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + )?; + expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; expected_state_trie_after.insert( to_second_nibbles, rlp::encode(&to_account_second_after).to_vec(), - ); + )?; - transactions_trie.insert(Nibbles::from_str("0x01").unwrap(), txn_2.to_vec()); + transactions_trie.insert(Nibbles::from_str("0x01").unwrap(), txn_2.to_vec())?; let block_1_state_root = expected_state_trie_after.hash(); @@ -687,7 +687,7 @@ fn test_txn_and_receipt_trie_hash() -> anyhow::Result<()> { example_txn_trie.insert( Nibbles::from_str("0x80").unwrap(), // RLP(0) = 0x80 rlp::encode(&transaction_0).to_vec(), - ); + )?; let transaction_1 = LegacyTransactionRlp { nonce: 157824u64.into(), @@ -707,7 +707,7 @@ fn test_txn_and_receipt_trie_hash() -> anyhow::Result<()> { example_txn_trie.insert( Nibbles::from_str("0x01").unwrap(), rlp::encode(&transaction_1).to_vec(), - ); + )?; // Receipts: let mut example_receipt_trie = HashedPartialTrie::from(Node::Empty); @@ -735,7 +735,7 @@ fn test_txn_and_receipt_trie_hash() -> anyhow::Result<()> { example_receipt_trie.insert( Nibbles::from_str("0x80").unwrap(), // RLP(0) is 0x80 rlp::encode(&receipt_0).to_vec(), - ); + )?; let log_1 = LogRlp { address: hex!("7ef66b77759e12Caf3dDB3E4AFF524E577C59D8D").into(), @@ -760,7 +760,7 @@ fn test_txn_and_receipt_trie_hash() -> anyhow::Result<()> { example_receipt_trie.insert( Nibbles::from_str("0x01").unwrap(), rlp::encode(&receipt_1).to_vec(), - ); + )?; // Check that the trie hashes are correct. assert_eq!( diff --git a/evm_arithmetization/tests/self_balance_gas_cost.rs b/evm_arithmetization/tests/self_balance_gas_cost.rs index 979e43abd..510c33cb3 100644 --- a/evm_arithmetization/tests/self_balance_gas_cost.rs +++ b/evm_arithmetization/tests/self_balance_gas_cost.rs @@ -77,9 +77,9 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { state_trie_before.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_before).to_vec(), - ); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); + )?; + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; let tries_before = TrieInputs { state_trie: state_trie_before, @@ -138,10 +138,10 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { expected_state_trie_after.insert( beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), - ); + )?; expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; expected_state_trie_after }; @@ -155,7 +155,7 @@ fn self_balance_gas_cost() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x80").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index f48248f69..0ef48d2f4 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -57,8 +57,8 @@ fn test_selfdestruct() -> anyhow::Result<()> { }; let mut state_trie_before = HashedPartialTrie::from(Node::Empty); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; let tries_before = TrieInputs { state_trie: state_trie_before, @@ -93,7 +93,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { storage_root: HashedPartialTrie::from(Node::Empty).hash(), code_hash: keccak([]), }; - state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); + state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; state_trie_after }; @@ -107,7 +107,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x80").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index 3fb3b08f6..8adbc1c42 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -123,7 +123,7 @@ fn test_simple_transfer() -> anyhow::Result<()> { receipts_trie.insert( Nibbles::from_str("0x80").unwrap(), rlp::encode(&receipt_0).to_vec(), - ); + )?; let transactions_trie: HashedPartialTrie = Node::Leaf { nibbles: Nibbles::from_str("0x80").unwrap(), value: txn.to_vec(), diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index 28dc6da59..7f133518b 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -50,7 +50,7 @@ fn test_withdrawals() -> anyhow::Result<()> { balance: withdrawals[0].1, ..AccountRlp::default() }; - trie.insert(addr_nibbles, rlp::encode(&account).to_vec()); + trie.insert(addr_nibbles, rlp::encode(&account).to_vec())?; trie }; diff --git a/mpt_trie/src/trie_hashing.rs b/mpt_trie/src/trie_hashing.rs index dd293ffe0..0c6352a99 100644 --- a/mpt_trie/src/trie_hashing.rs +++ b/mpt_trie/src/trie_hashing.rs @@ -377,7 +377,7 @@ mod tests { let entries_to_delete = entries.into_iter().take(half_entries); for (k, _) in entries_to_delete { let res = our_trie.delete(k); - assert_eq!(res.is_ok(), true, "Failed to delete key: {:?}", k); + assert!(res.is_ok(), "Failed to delete key: {:?}", k); truth_trie.remove(&k.bytes_be()).unwrap(); let truth_root_hash = H256(truth_trie.root_hash().unwrap().0); From 0c3a75c923f8b55ffc4388296d9596ba43299a85 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 16:41:50 +0200 Subject: [PATCH 05/13] fix: pr fixes --- evm_arithmetization/tests/log_opcode.rs | 9 +++-- mpt_trie/examples/ethereum_trie.rs | 45 ++++++++++++++++--------- mpt_trie/examples/simple.rs | 21 +++++++----- mpt_trie/src/partial_trie.rs | 20 +++++------ mpt_trie/src/trie_hashing.rs | 17 ++++++---- mpt_trie/src/trie_ops.rs | 30 ++++++++++------- mpt_trie/src/trie_subsets.rs | 4 +-- mpt_trie/src/utils.rs | 11 ++++++ trace_decoder/src/decoding.rs | 14 +++++++- 9 files changed, 113 insertions(+), 58 deletions(-) diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 6ec3e59a6..75cdd44f5 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -201,7 +201,8 @@ fn test_log_opcodes() -> anyhow::Result<()> { beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), )?; - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; let transactions_trie: HashedPartialTrie = Node::Leaf { @@ -390,7 +391,8 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), )?; - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; expected_state_trie_after.insert( to_second_nibbles, @@ -538,7 +540,8 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { beneficiary_nibbles, rlp::encode(&beneficiary_account_after).to_vec(), )?; - expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; expected_state_trie_after.insert( to_second_nibbles, diff --git a/mpt_trie/examples/ethereum_trie.rs b/mpt_trie/examples/ethereum_trie.rs index 53e3ad70e..e39a51927 100644 --- a/mpt_trie/examples/ethereum_trie.rs +++ b/mpt_trie/examples/ethereum_trie.rs @@ -13,6 +13,8 @@ use std::ops::RangeInclusive; use ethereum_types::{H160, H256, U256}; use keccak_hash::keccak; use mpt_trie::partial_trie::PartialTrie; +use mpt_trie::trie_ops::TrieOpResult; +use mpt_trie::utils::TryFromIterator; use mpt_trie::{ nibbles::Nibbles, partial_trie::{HashedPartialTrie, StandardTrie}, @@ -36,34 +38,43 @@ struct StateTrieEntry { code_hash: H256, } -fn main() { +fn main() -> TrieOpResult<()> { let mut rng = StdRng::seed_from_u64(0); - let (account_entries, account_storage_tries): (Vec<_>, Vec<_>) = (0..NUM_ACCOUNTS_TO_GEN) + let generated: Result, _> = (0..NUM_ACCOUNTS_TO_GEN) .map(|_| generate_fake_account_and_storage_trie(&mut rng)) - .unzip(); + .collect(); - let _state_trie = StandardTrie::from_iter( + let (account_entries, account_storage_tries): (Vec<_>, Vec<_>) = match generated { + Ok(pairs) => pairs.into_iter().unzip(), + Err(e) => { + return Err(e); + } + }; + + let _state_trie = StandardTrie::try_from_iter( account_entries .into_iter() .map(|(k, acc)| (Nibbles::from_h256_be(k), acc.rlp_bytes().to_vec())), - ); + )?; let _account_storage_tries: Vec<(AccountAddr, HashedPartialTrie)> = account_storage_tries; + Ok(()) + // TODO: Generate remaining tries... } fn generate_fake_account_and_storage_trie( rng: &mut StdRng, -) -> ( +) -> TrieOpResult<( (HashedAccountAddr, StateTrieEntry), (AccountAddr, HashedPartialTrie), -) { +)> { let account_addr: H160 = rng.gen(); let hashed_account_addr = keccak(account_addr.as_bytes()); - let account_storage_trie = generate_fake_account_storage_trie(rng); + let account_storage_trie = generate_fake_account_storage_trie(rng)?; let acc_entry = StateTrieEntry { nonce: gen_u256(rng), @@ -73,21 +84,23 @@ fn generate_fake_account_and_storage_trie( * "fake" it here. */ }; - ( + Ok(( (hashed_account_addr, acc_entry), (account_addr, account_storage_trie), - ) + )) } -fn generate_fake_account_storage_trie(rng: &mut StdRng) -> HashedPartialTrie { +fn generate_fake_account_storage_trie(rng: &mut StdRng) -> TrieOpResult { let num_storage_entries = rng.gen_range(RANGE_OF_STORAGE_ENTRIES_AN_ACCOUNT_CAN_HAVE); - HashedPartialTrie::from_iter((0..num_storage_entries).map(|_| { - let hashed_storage_addr = Nibbles::from_h256_be(rng.gen::()); - let storage_data = gen_u256(rng).rlp_bytes().to_vec(); + Ok(HashedPartialTrie::try_from_iter( + (0..num_storage_entries).map(|_| { + let hashed_storage_addr = Nibbles::from_h256_be(rng.gen::()); + let storage_data = gen_u256(rng).rlp_bytes().to_vec(); - (hashed_storage_addr, storage_data) - })) + (hashed_storage_addr, storage_data) + }), + )?) } fn gen_u256(rng: &mut StdRng) -> U256 { diff --git a/mpt_trie/examples/simple.rs b/mpt_trie/examples/simple.rs index 70ed14544..e0e7d585e 100644 --- a/mpt_trie/examples/simple.rs +++ b/mpt_trie/examples/simple.rs @@ -3,6 +3,7 @@ use std::iter::once; use mpt_trie::partial_trie::PartialTrie; +use mpt_trie::utils::TryFromIterator; use mpt_trie::{ nibbles::{Nibbles, ToNibbles}, partial_trie::{HashedPartialTrie, StandardTrie}, @@ -20,10 +21,10 @@ fn main() -> TrieOpResult<()> { )?; // Or by initializing the trie with an iterator of key value pairs: - let mut trie = StandardTrie::from_iter(vec![ + let mut trie = StandardTrie::try_from_iter(vec![ (0x1234_u32, b"some data".to_vec()), (9001_u32, vec![1, 2, 3]), - ]); + ])?; // Tries can be queried: assert_eq!(trie.get(0x1234_u32), Some(b"some data".as_slice())); @@ -43,8 +44,10 @@ fn main() -> TrieOpResult<()> { ); // Values can be deleted: - let del_val = trie.delete(0x1234_u32); - assert_eq!(del_val.ok().unwrap(), Some(b"some data".to_vec())); + let del_val = trie + .delete(0x1234_u32)? + .expect("Failed to delete from trie"); + assert_eq!(del_val, b"some data".to_vec()); assert_eq!(trie.get(0x1234_u32), None); // It's important to note how types are converted to `Nibbles`. This is @@ -59,11 +62,13 @@ fn main() -> TrieOpResult<()> { // Note that `From` just calls `to_nibbles` by default instead of // `to_nibbles_byte_padded`. - let hash_1 = - HashedPartialTrie::from_iter(once((0x19002_u32.to_nibbles_byte_padded(), vec![4, 5, 6]))) - .hash(); + let hash_1 = HashedPartialTrie::try_from_iter(once(( + 0x19002_u32.to_nibbles_byte_padded(), + vec![4, 5, 6], + )))? + .hash(); let hash_2 = - HashedPartialTrie::from_iter(once((0x19002_u32.to_nibbles(), vec![4, 5, 6]))).hash(); + HashedPartialTrie::try_from_iter(once((0x19002_u32.to_nibbles(), vec![4, 5, 6])))?.hash(); assert_ne!(hash_1, hash_2); // Finally note that `Nibbles` which are constructed from bytes are always diff --git a/mpt_trie/src/partial_trie.rs b/mpt_trie/src/partial_trie.rs index a7dd5d0a4..3d29e8c05 100644 --- a/mpt_trie/src/partial_trie.rs +++ b/mpt_trie/src/partial_trie.rs @@ -14,7 +14,7 @@ use crate::{ nibbles::Nibbles, trie_hashing::{hash_trie, rlp_encode_and_hash_node, EncodedNode}, trie_ops::{TrieOpResult, ValOrHash}, - utils::bytes_to_h256, + utils::{bytes_to_h256, TryFromIterator}, }; macro_rules! impl_from_for_trie_type { @@ -283,12 +283,12 @@ impl DerefMut for StandardTrie { } } -impl FromIterator<(K, V)> for StandardTrie +impl TryFromIterator<(K, V)> for StandardTrie where K: Into, V: Into, { - fn from_iter>(nodes: T) -> Self { + fn try_from_iter>(nodes: T) -> TrieOpResult { from_iter_common(nodes) } } @@ -421,24 +421,24 @@ impl PartialEq for HashedPartialTrie { } } -impl FromIterator<(K, V)> for HashedPartialTrie +impl TryFromIterator<(K, V)> for HashedPartialTrie where K: Into, V: Into, { - fn from_iter>(nodes: T) -> Self { + fn try_from_iter>(nodes: T) -> TrieOpResult { from_iter_common(nodes) } } -fn from_iter_common, K, V>(nodes: T) -> N +fn from_iter_common, K, V>( + nodes: T, +) -> TrieOpResult where K: Into, V: Into, { let mut root = N::new(Node::Empty); - match root.extend(nodes) { - Ok(_) => root, - Err(e) => panic!("Error extending trie: {}", e), - } + root.extend(nodes)?; + Ok(root) } diff --git a/mpt_trie/src/trie_hashing.rs b/mpt_trie/src/trie_hashing.rs index 0c6352a99..79acaa5d1 100644 --- a/mpt_trie/src/trie_hashing.rs +++ b/mpt_trie/src/trie_hashing.rs @@ -113,6 +113,7 @@ mod tests { generate_n_random_variable_trie_value_entries, large_entry, TestInsertValEntry, }, trie_hashing::hash_bytes, + utils::TryFromIterator, }; const PYEVM_TRUTH_VALS_JSON_PATH: &str = "test_data/pyevm_account_ground_truth.json"; @@ -232,7 +233,7 @@ mod tests { let mut trie = HashedPartialTrie::new(Node::Empty); entries.map(move |(k, v)| { - assert!(trie.insert(k, v).is_ok()); + trie.insert(k, v).expect("Failed to insert into trie"); trie.get_hash() }) } @@ -274,7 +275,9 @@ mod tests { get_lib_trie_root_hashes_after_each_insert(once(ins_entry.clone())) .next() .unwrap(); - let our_hash = HashedPartialTrie::from_iter(once(ins_entry)).get_hash(); + let our_hash = HashedPartialTrie::try_from_iter(once(ins_entry)) + .expect("Failed to create trie") + .get_hash(); assert_eq!(py_evm_truth_val, our_hash); assert_eq!(eth_trie_lib_truth_val, our_hash); @@ -366,7 +369,8 @@ mod tests { ) .collect(); - let mut our_trie = HashedPartialTrie::from_iter(entries.iter().cloned()); + let mut our_trie = HashedPartialTrie::try_from_iter(entries.iter().cloned()) + .expect("Failed to create trie"); let mut truth_trie = create_truth_trie(); for (k, v) in entries.iter() { @@ -387,12 +391,13 @@ mod tests { #[test] fn replacing_branch_of_leaves_with_hash_nodes_produced_same_hash() { - let mut trie = HashedPartialTrie::from_iter([ + let mut trie = HashedPartialTrie::try_from_iter([ large_entry(0x1), large_entry(0x2), large_entry(0x3), large_entry(0x4), - ]); + ]) + .expect("Failed to create trie"); let orig_hash = trie.hash(); @@ -429,7 +434,7 @@ mod tests { }) }); - let mut trie = HashedPartialTrie::from_iter(entries); + let mut trie = HashedPartialTrie::try_from_iter(entries).expect("Failed to create trie"); let orig_hash = trie.get_hash(); let root_branch_children = match &mut *trie { diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index 3cc777ca1..b0c604610 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -825,14 +825,15 @@ mod tests { unwrap_iter_item_to_val, TestInsertValEntry, }, trie_ops::TrieOpResult, - utils::create_mask_of_1s, + utils::{create_mask_of_1s, TryFromIterator}, }; const MASSIVE_TRIE_SIZE: usize = 100000; const COW_TEST_TRIE_SIZE: usize = 500; fn insert_entries_and_assert_all_exist_in_trie_with_no_extra(entries: &[TestInsertValEntry]) { - let trie = StandardTrie::from_iter(entries.iter().cloned()); + let trie = + StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); assert_all_entries_in_trie(entries, &trie) } @@ -914,7 +915,7 @@ mod tests { let mut entries = [entry(0x1234), entry(0x1234)]; entries[1].1 = vec![100]; - let trie = StandardTrie::from_iter(entries); + let trie = StandardTrie::try_from_iter(entries).expect("Failed to create trie"); assert_eq!(trie.get(0x1234), Some([100].as_slice())); } @@ -928,9 +929,9 @@ mod tests { fn assert_cloning_works_for_tries() where - T: FromIterator<(Nibbles, Vec)> + PartialTrie, + T: TryFromIterator<(Nibbles, Vec)> + PartialTrie, { - let trie = T::from_iter(once(entry(0x1234))); + let trie = T::try_from_iter(once(entry(0x1234))).expect("Failed to create trie"); let mut cloned_trie = trie.clone(); assert!(cloned_trie.extend(once(entry(0x5678))).is_ok()); @@ -962,7 +963,8 @@ mod tests { common_setup(); let non_hash_entries: Vec<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 0).collect(); - let mut trie = StandardTrie::from_iter(non_hash_entries.iter().cloned()); + let mut trie = StandardTrie::try_from_iter(non_hash_entries.iter().cloned()) + .expect("Failed to create trie"); let extra_hash_entries = generate_n_hash_nodes_entries_for_empty_slots_in_trie( &trie, @@ -993,11 +995,11 @@ mod tests { ); let entries = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 0); - let big_trie_1 = StandardTrie::from_iter(entries); + let big_trie_1 = StandardTrie::try_from_iter(entries).expect("Failed to create trie"); assert_eq!(big_trie_1, big_trie_1); let entries = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 1); - let big_trie_2 = StandardTrie::from_iter(entries); + let big_trie_2 = StandardTrie::try_from_iter(entries).expect("Failed to create trie"); assert_ne!(big_trie_1, big_trie_2) } @@ -1007,7 +1009,8 @@ mod tests { common_setup(); let entries = [entry_with_value(0x1234, 1), entry_with_value(0x12345678, 2)]; - let trie = StandardTrie::from_iter(entries.iter().cloned()); + let trie = + StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); assert_eq!(trie.get(0x1234), Some([1].as_slice())); assert_eq!(trie.get(0x12345678), Some([2].as_slice())); @@ -1019,7 +1022,8 @@ mod tests { let random_entries: Vec<_> = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 9001).collect(); - let trie = StandardTrie::from_iter(random_entries.iter().cloned()); + let trie = StandardTrie::try_from_iter(random_entries.iter().cloned()) + .expect("Failed to create trie"); for (k, v) in random_entries.into_iter() { debug!("Attempting to retrieve {:?}...", (k, &v)); @@ -1063,7 +1067,8 @@ mod tests { let entries: HashSet<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 9003).collect(); - let trie = StandardTrie::from_iter(entries.iter().cloned()); + let trie = + StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); let trie_items: HashSet<_> = trie .items() @@ -1100,7 +1105,8 @@ mod tests { let entries: Vec<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 7).collect(); - let mut trie = StandardTrie::from_iter(entries.iter().cloned()); + let mut trie = + StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); // Delete half of the elements let half_entries = entries.len() / 2; diff --git a/mpt_trie/src/trie_subsets.rs b/mpt_trie/src/trie_subsets.rs index 8dd8ac724..1ff0d026f 100644 --- a/mpt_trie/src/trie_subsets.rs +++ b/mpt_trie/src/trie_subsets.rs @@ -397,7 +397,7 @@ mod tests { generate_n_random_fixed_trie_value_entries, handmade_trie_1, TrieType, }, trie_ops::ValOrHash, - utils::TrieNodeType, + utils::{TrieNodeType, TryFromIterator}, }; const MASSIVE_TEST_NUM_SUB_TRIES: usize = 10; @@ -800,7 +800,7 @@ mod tests { let random_entries: Vec<_> = generate_n_random_fixed_trie_value_entries(trie_size, seed).collect(); let entry_keys: Vec<_> = random_entries.iter().map(|(k, _)| k).cloned().collect(); - let trie = TrieType::from_iter(random_entries); + let trie = TrieType::try_from_iter(random_entries).expect("Failed to create trie"); let keys_of_subsets: Vec> = (0..MASSIVE_TEST_NUM_SUB_TRIES) .map(|i| { diff --git a/mpt_trie/src/utils.rs b/mpt_trie/src/utils.rs index 8c457f07a..211c08861 100644 --- a/mpt_trie/src/utils.rs +++ b/mpt_trie/src/utils.rs @@ -13,6 +13,7 @@ use num_traits::PrimInt; use crate::{ nibbles::{Nibble, Nibbles}, partial_trie::{Node, PartialTrie}, + trie_ops::TrieOpResult, }; #[derive(Clone, Debug, Eq, Hash, PartialEq)] @@ -243,6 +244,16 @@ pub(crate) fn get_segment_from_node_and_key_piece( } } +/// Conversion from an [`Iterator`] within an allocator. +/// +/// By implementing `TryFromIteratorIn` for a type, you define how it will be +/// created from an iterator. This is common for types which describe a +/// collection of some kind. +pub trait TryFromIterator: Sized { + /// Creates a value from an iterator within an allocator. + fn try_from_iter>(iter: T) -> TrieOpResult; +} + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/trace_decoder/src/decoding.rs b/trace_decoder/src/decoding.rs index b718dce6e..dd4e1a552 100644 --- a/trace_decoder/src/decoding.rs +++ b/trace_decoder/src/decoding.rs @@ -14,6 +14,7 @@ use mpt_trie::{ nibbles::Nibbles, partial_trie::{HashedPartialTrie, Node, PartialTrie}, special_query::path_for_query, + trie_ops::TrieOpError, trie_subsets::{create_trie_subset, SubsetTrieError}, utils::{IntoTrieKey, TriePath, TrieSegment}, }; @@ -56,6 +57,17 @@ pub enum TraceParsingError { /// Failure due to trying to withdraw from a missing account #[error("No account present at {0:x} (hashed: {1:x}) to withdraw {2} Gwei from!")] MissingWithdrawalAccount(Address, HashedAccountAddr, U256), + + /// Failure due to a trie operation error. + #[error("Trie operation error: {0}")] + TrieOpError(TrieOpError), +} + +impl From for TraceParsingError { + fn from(err: TrieOpError) -> Self { + // Convert TrieOpError into TraceParsingError + TraceParsingError::TrieOpError(err) + } } /// An enum to cover all Ethereum trie types (see https://ethereum.github.io/yellowpaper/paper.pdf for details). @@ -316,7 +328,7 @@ impl ProcessedBlockTrace { { // If we are writing a zero, then we actually need to perform a delete. match val == &ZERO_STORAGE_SLOT_VAL_RLPED { - false => storage_trie.insert(slot, val.clone()).unwrap(), + false => storage_trie.insert(slot, val.clone())?, true => { if let Some(remaining_slot_key) = Self::delete_node_and_report_remaining_key_if_branch_collapsed( From d5be97359d68530183ae796be61781037c99c20e Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 16:47:32 +0200 Subject: [PATCH 06/13] fix: fix error message --- mpt_trie/src/trie_ops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index b0c604610..c243c1190 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -31,9 +31,9 @@ pub enum TrieOpError { #[error("Attempted to delete a value that ended up inside a hash node")] HashNodeDeleteError(), - /// An error that occurs when a hash node is found during an extension node + /// An error that occurs when encontered an unexisting type of node during an extension node /// collapse. - #[error("Extension managed to get a child node type that is impossible! (child: {0})")] + #[error("Extension managed to get an unexisting child node type! (child: {0})")] HashNodeExtError(TrieNodeType), /// Failed to insert a hash node into the trie. From af13dc490b77d48adb32bfa91312995b010b4629 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 16:47:50 +0200 Subject: [PATCH 07/13] fix: format --- mpt_trie/src/trie_ops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index c243c1190..938490b51 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -31,8 +31,8 @@ pub enum TrieOpError { #[error("Attempted to delete a value that ended up inside a hash node")] HashNodeDeleteError(), - /// An error that occurs when encontered an unexisting type of node during an extension node - /// collapse. + /// An error that occurs when encontered an unexisting type of node during + /// an extension node collapse. #[error("Extension managed to get an unexisting child node type! (child: {0})")] HashNodeExtError(TrieNodeType), From 475a6c6d3ff810bae8eb612e43852464f3554930 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 17:03:30 +0200 Subject: [PATCH 08/13] fix: fix unusefull return type --- mpt_trie/examples/ethereum_trie.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpt_trie/examples/ethereum_trie.rs b/mpt_trie/examples/ethereum_trie.rs index e39a51927..8529963ff 100644 --- a/mpt_trie/examples/ethereum_trie.rs +++ b/mpt_trie/examples/ethereum_trie.rs @@ -93,14 +93,14 @@ fn generate_fake_account_and_storage_trie( fn generate_fake_account_storage_trie(rng: &mut StdRng) -> TrieOpResult { let num_storage_entries = rng.gen_range(RANGE_OF_STORAGE_ENTRIES_AN_ACCOUNT_CAN_HAVE); - Ok(HashedPartialTrie::try_from_iter( + HashedPartialTrie::try_from_iter( (0..num_storage_entries).map(|_| { let hashed_storage_addr = Nibbles::from_h256_be(rng.gen::()); let storage_data = gen_u256(rng).rlp_bytes().to_vec(); (hashed_storage_addr, storage_data) }), - )?) + ) } fn gen_u256(rng: &mut StdRng) -> U256 { From 2225181d08dd64dfb56756ded76ebd24516ded0d Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Fri, 22 Mar 2024 17:05:42 +0200 Subject: [PATCH 09/13] fix: fix formatting --- mpt_trie/examples/ethereum_trie.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mpt_trie/examples/ethereum_trie.rs b/mpt_trie/examples/ethereum_trie.rs index 8529963ff..0e26013cb 100644 --- a/mpt_trie/examples/ethereum_trie.rs +++ b/mpt_trie/examples/ethereum_trie.rs @@ -93,14 +93,12 @@ fn generate_fake_account_and_storage_trie( fn generate_fake_account_storage_trie(rng: &mut StdRng) -> TrieOpResult { let num_storage_entries = rng.gen_range(RANGE_OF_STORAGE_ENTRIES_AN_ACCOUNT_CAN_HAVE); - HashedPartialTrie::try_from_iter( - (0..num_storage_entries).map(|_| { - let hashed_storage_addr = Nibbles::from_h256_be(rng.gen::()); - let storage_data = gen_u256(rng).rlp_bytes().to_vec(); - - (hashed_storage_addr, storage_data) - }), - ) + HashedPartialTrie::try_from_iter((0..num_storage_entries).map(|_| { + let hashed_storage_addr = Nibbles::from_h256_be(rng.gen::()); + let storage_data = gen_u256(rng).rlp_bytes().to_vec(); + + (hashed_storage_addr, storage_data) + })) } fn gen_u256(rng: &mut StdRng) -> U256 { From 737030f70e113be2caf0222e740fee1e0d9c3123 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Mon, 25 Mar 2024 11:45:18 +0200 Subject: [PATCH 10/13] fix: pr fixes --- mpt_trie/examples/ethereum_trie.rs | 13 +-- mpt_trie/examples/simple.rs | 6 +- mpt_trie/src/debug_tools/diff.rs | 9 +- mpt_trie/src/debug_tools/stats.rs | 27 +++--- mpt_trie/src/trie_hashing.rs | 35 ++++---- mpt_trie/src/trie_ops.rs | 136 ++++++++++++++++------------- mpt_trie/src/trie_subsets.rs | 31 ++++--- 7 files changed, 142 insertions(+), 115 deletions(-) diff --git a/mpt_trie/examples/ethereum_trie.rs b/mpt_trie/examples/ethereum_trie.rs index 0e26013cb..d1aa1f799 100644 --- a/mpt_trie/examples/ethereum_trie.rs +++ b/mpt_trie/examples/ethereum_trie.rs @@ -41,16 +41,11 @@ struct StateTrieEntry { fn main() -> TrieOpResult<()> { let mut rng = StdRng::seed_from_u64(0); - let generated: Result, _> = (0..NUM_ACCOUNTS_TO_GEN) + let (account_entries, account_storage_tries): (Vec<_>, Vec<_>) = (0..NUM_ACCOUNTS_TO_GEN) .map(|_| generate_fake_account_and_storage_trie(&mut rng)) - .collect(); - - let (account_entries, account_storage_tries): (Vec<_>, Vec<_>) = match generated { - Ok(pairs) => pairs.into_iter().unzip(), - Err(e) => { - return Err(e); - } - }; + .collect::, _>>()? + .into_iter() + .unzip(); let _state_trie = StandardTrie::try_from_iter( account_entries diff --git a/mpt_trie/examples/simple.rs b/mpt_trie/examples/simple.rs index e0e7d585e..eb70a52b1 100644 --- a/mpt_trie/examples/simple.rs +++ b/mpt_trie/examples/simple.rs @@ -44,10 +44,8 @@ fn main() -> TrieOpResult<()> { ); // Values can be deleted: - let del_val = trie - .delete(0x1234_u32)? - .expect("Failed to delete from trie"); - assert_eq!(del_val, b"some data".to_vec()); + let del_val = trie.delete(0x1234_u32)?; + assert_eq!(del_val.unwrap(), b"some data".to_vec()); assert_eq!(trie.get(0x1234_u32), None); // It's important to note how types are converted to `Nibbles`. This is diff --git a/mpt_trie/src/debug_tools/diff.rs b/mpt_trie/src/debug_tools/diff.rs index 44fcf45b1..8b01dfa7b 100644 --- a/mpt_trie/src/debug_tools/diff.rs +++ b/mpt_trie/src/debug_tools/diff.rs @@ -416,18 +416,19 @@ mod tests { use crate::{ nibbles::Nibbles, partial_trie::{HashedPartialTrie, PartialTrie}, + trie_ops::TrieOpResult, utils::TrieNodeType, }; #[test] - fn depth_single_node_hash_diffs_work() { + fn depth_single_node_hash_diffs_work() -> TrieOpResult<()> { // TODO: Reduce duplication once we identify common structures across tests... let mut a = HashedPartialTrie::default(); - assert!(a.insert(0x1234, vec![0]).is_ok()); + a.insert(0x1234, vec![0])?; let a_hash = a.hash(); let mut b = a.clone(); - assert!(b.insert(0x1234, vec![1]).is_ok()); + b.insert(0x1234, vec![1])?; let b_hash = b.hash(); let diff = create_diff_between_tries(&a, &b); @@ -455,6 +456,8 @@ mod tests { }; assert_eq!(diff.latest_diff_res, Some(expected)); + + Ok(()) } // TODO: Will finish these tests later (low-priority). diff --git a/mpt_trie/src/debug_tools/stats.rs b/mpt_trie/src/debug_tools/stats.rs index ee2330c1a..b2f922730 100644 --- a/mpt_trie/src/debug_tools/stats.rs +++ b/mpt_trie/src/debug_tools/stats.rs @@ -317,13 +317,14 @@ mod tests { generate_n_random_fixed_trie_hash_entries, generate_n_random_fixed_trie_value_entries, handmade_trie_1, }, + trie_ops::TrieOpResult, }; const MASSIVE_TRIE_SIZE: usize = 100_000; #[test] - fn hand_made_trie_has_correct_node_stats() { - let (trie, _) = handmade_trie_1().unwrap(); + fn hand_made_trie_has_correct_node_stats() -> TrieOpResult<()> { + let (trie, _) = handmade_trie_1()?; let stats = get_trie_stats(&trie); assert_eq!(stats.counts.leaf, 4); @@ -333,6 +334,8 @@ mod tests { // empty = (n_branch * 4) - n_leaf - (n_branch - 1) assert_eq!(stats.counts.empty, 57); + + Ok(()) } // TODO: Low-priority. Finish later. @@ -343,40 +346,42 @@ mod tests { } #[test] - fn massive_leaf_trie_has_correct_leaf_node_stats() { - create_trie_and_stats_from_entries_and_assert(MASSIVE_TRIE_SIZE, 0, 9522); + fn massive_leaf_trie_has_correct_leaf_node_stats() -> TrieOpResult<()> { + create_trie_and_stats_from_entries_and_assert(MASSIVE_TRIE_SIZE, 0, 9522) } #[test] - fn massive_hash_trie_has_correct_hash_node_stats() { - create_trie_and_stats_from_entries_and_assert(0, MASSIVE_TRIE_SIZE, 9855); + fn massive_hash_trie_has_correct_hash_node_stats() -> TrieOpResult<()> { + create_trie_and_stats_from_entries_and_assert(0, MASSIVE_TRIE_SIZE, 9855) } #[test] - fn massive_mixed_trie_has_correct_hash_node_stats() { + fn massive_mixed_trie_has_correct_hash_node_stats() -> TrieOpResult<()> { create_trie_and_stats_from_entries_and_assert( MASSIVE_TRIE_SIZE / 2, MASSIVE_TRIE_SIZE / 2, 1992, - ); + ) } fn create_trie_and_stats_from_entries_and_assert( n_leaf_nodes: usize, n_hash_nodes: usize, seed: u64, - ) { + ) -> TrieOpResult<()> { let val_entries = generate_n_random_fixed_trie_value_entries(n_leaf_nodes, seed); let hash_entries = generate_n_random_fixed_trie_hash_entries(n_hash_nodes, seed + 1); let mut trie = HashedPartialTrie::default(); - assert!(trie.extend(val_entries).is_ok()); - assert!(trie.extend(hash_entries).is_ok()); + trie.extend(val_entries)?; + trie.extend(hash_entries)?; let stats = get_trie_stats(&trie); assert_eq!(stats.counts.leaf, n_leaf_nodes); assert_eq!(stats.counts.hash, n_hash_nodes); + + Ok(()) } // TODO: Low-priority. Finish later. diff --git a/mpt_trie/src/trie_hashing.rs b/mpt_trie/src/trie_hashing.rs index 79acaa5d1..f2f960d88 100644 --- a/mpt_trie/src/trie_hashing.rs +++ b/mpt_trie/src/trie_hashing.rs @@ -113,6 +113,7 @@ mod tests { generate_n_random_variable_trie_value_entries, large_entry, TestInsertValEntry, }, trie_hashing::hash_bytes, + trie_ops::TrieOpResult, utils::TryFromIterator, }; @@ -258,7 +259,7 @@ mod tests { } #[test] - fn single_account_leaf_hash_is_correct() { + fn single_account_leaf_hash_is_correct() -> TrieOpResult<()> { common_setup(); let acc_and_hash_entry = &load_pyevm_truth_vals()[0]; @@ -275,12 +276,12 @@ mod tests { get_lib_trie_root_hashes_after_each_insert(once(ins_entry.clone())) .next() .unwrap(); - let our_hash = HashedPartialTrie::try_from_iter(once(ins_entry)) - .expect("Failed to create trie") - .get_hash(); + let our_hash = HashedPartialTrie::try_from_iter(once(ins_entry))?.get_hash(); assert_eq!(py_evm_truth_val, our_hash); assert_eq!(eth_trie_lib_truth_val, our_hash); + + Ok(()) } #[test] @@ -360,7 +361,7 @@ mod tests { } #[test] - fn massive_trie_data_deletion_agrees_with_eth_trie() { + fn massive_trie_data_deletion_agrees_with_eth_trie() -> Result<(), Box> { common_setup(); let entries: Vec<_> = generate_n_random_fixed_even_nibble_padded_trie_value_entries( @@ -369,12 +370,11 @@ mod tests { ) .collect(); - let mut our_trie = HashedPartialTrie::try_from_iter(entries.iter().cloned()) - .expect("Failed to create trie"); + let mut our_trie = HashedPartialTrie::try_from_iter(entries.iter().cloned())?; let mut truth_trie = create_truth_trie(); for (k, v) in entries.iter() { - truth_trie.insert(&k.bytes_be(), v).unwrap(); + truth_trie.insert(&k.bytes_be(), v)?; } let half_entries = entries.len() / 2; @@ -382,22 +382,23 @@ mod tests { for (k, _) in entries_to_delete { let res = our_trie.delete(k); assert!(res.is_ok(), "Failed to delete key: {:?}", k); - truth_trie.remove(&k.bytes_be()).unwrap(); + truth_trie.remove(&k.bytes_be())?; - let truth_root_hash = H256(truth_trie.root_hash().unwrap().0); + let truth_root_hash = H256(truth_trie.root_hash()?.0); assert_eq!(our_trie.get_hash(), truth_root_hash); } + + Ok(()) } #[test] - fn replacing_branch_of_leaves_with_hash_nodes_produced_same_hash() { + fn replacing_branch_of_leaves_with_hash_nodes_produced_same_hash() -> TrieOpResult<()> { let mut trie = HashedPartialTrie::try_from_iter([ large_entry(0x1), large_entry(0x2), large_entry(0x3), large_entry(0x4), - ]) - .expect("Failed to create trie"); + ])?; let orig_hash = trie.hash(); @@ -407,6 +408,8 @@ mod tests { let new_hash = trie.hash(); assert_eq!(orig_hash, new_hash); + + Ok(()) } fn get_branch_children_expected( @@ -419,7 +422,7 @@ mod tests { } #[test] - fn replacing_part_of_a_trie_with_a_hash_node_produces_same_hash() { + fn replacing_part_of_a_trie_with_a_hash_node_produces_same_hash() -> TrieOpResult<()> { let entries = (0..16).flat_map(|i| { generate_n_random_variable_trie_value_entries( NODES_PER_BRANCH_FOR_HASH_REPLACEMENT_TEST, @@ -434,7 +437,7 @@ mod tests { }) }); - let mut trie = HashedPartialTrie::try_from_iter(entries).expect("Failed to create trie"); + let mut trie = HashedPartialTrie::try_from_iter(entries)?; let orig_hash = trie.get_hash(); let root_branch_children = match &mut *trie { @@ -450,5 +453,7 @@ mod tests { let new_hash = trie.get_hash(); assert_eq!(orig_hash, new_hash); + + Ok(()) } } diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index 938490b51..c5d056dfe 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -23,13 +23,13 @@ pub type TrieOpResult = Result; pub enum TrieOpError { /// An error that occurs when a hash node is found during an insert /// operation. - #[error("Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert!")] - HashNodeInsertError(), + #[error("Found a `Hash` node during an insert in a `PartialTrie`! These should not be able to be traversed during an insert! (hash: {0})")] + HashNodeInsertError(H256), /// An error that occurs when a hash node is found during a delete /// operation. - #[error("Attempted to delete a value that ended up inside a hash node")] - HashNodeDeleteError(), + #[error("Attempted to delete a value that ended up inside a hash node! (hash: {0})")] + HashNodeDeleteError(H256), /// An error that occurs when encontered an unexisting type of node during /// an extension node collapse. @@ -405,9 +405,9 @@ fn insert_into_trie_rec( new_node.v, ))) } - Node::Hash(_) => { + Node::Hash(h) => { trace!("Insert traversed {:?}", node); - Err(TrieOpError::HashNodeInsertError()) + Err(TrieOpError::HashNodeInsertError(*h)) } Node::Branch { children, value } => { if new_node.nibbles.count == 0 { @@ -418,13 +418,12 @@ fn insert_into_trie_rec( let nibble = new_node.nibbles.pop_next_nibble_front(); trace!("Insert traversed Branch (nibble: {:x})", nibble); - insert_into_trie_rec(&children[nibble as usize], new_node)?.map_or( - Ok(None), - |updated_child| { + Ok( + insert_into_trie_rec(&children[nibble as usize], new_node)?.map(|updated_child| { let mut updated_children = children.clone(); updated_children[nibble as usize] = updated_child; - Ok(Some(branch(updated_children, value.clone()))) - }, + branch(updated_children, value.clone()) + }), ) } Node::Extension { nibbles, child } => { @@ -495,7 +494,7 @@ fn delete_intern( trace!("Delete traversed Empty"); Ok(None) } - Node::Hash(_) => Err(TrieOpError::HashNodeDeleteError()), + Node::Hash(h) => Err(TrieOpError::HashNodeDeleteError(*h)), // TODO: Find a nice way to get the full key path... Node::Branch { children, value } => { if curr_k.is_empty() { @@ -561,12 +560,10 @@ fn delete_intern( } Node::Leaf { nibbles, value } => { trace!("Delete traversed Leaf (nibbles: {:?})", nibbles); - (*nibbles == curr_k) - .then(|| { - trace!("Deleting leaf ({:x})", nibbles); - Ok(Some((Node::Empty.into(), value.clone()))) - }) - .unwrap_or(Ok(None)) + Ok((*nibbles == curr_k).then(|| { + trace!("Deleting leaf ({:x})", nibbles); + (Node::Empty.into(), value.clone()) + })) } } } @@ -831,10 +828,11 @@ mod tests { const MASSIVE_TRIE_SIZE: usize = 100000; const COW_TEST_TRIE_SIZE: usize = 500; - fn insert_entries_and_assert_all_exist_in_trie_with_no_extra(entries: &[TestInsertValEntry]) { - let trie = - StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); - assert_all_entries_in_trie(entries, &trie) + fn insert_entries_and_assert_all_exist_in_trie_with_no_extra( + entries: &[TestInsertValEntry], + ) -> TrieOpResult<()> { + let trie = StandardTrie::try_from_iter(entries.iter().cloned())?; + Ok(assert_all_entries_in_trie(entries, &trie)) } fn assert_all_entries_in_trie(entries: &[TestInsertValEntry], trie: &Node) { @@ -872,99 +870,105 @@ mod tests { } #[test] - fn single_insert() { + fn single_insert() -> TrieOpResult<()> { common_setup(); - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&[entry(0x1234)]); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&[entry(0x1234)]) } #[test] - fn two_disjoint_inserts_works() { + fn two_disjoint_inserts_works() -> TrieOpResult<()> { common_setup(); let entries = [entry(0x1234), entry(0x5678)]; - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries) } #[test] - fn two_inserts_that_share_one_nibble_works() { + fn two_inserts_that_share_one_nibble_works() -> TrieOpResult<()> { common_setup(); let entries = [entry(0x1234), entry(0x1567)]; - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries) } #[test] - fn two_inserts_that_differ_on_last_nibble_works() { + fn two_inserts_that_differ_on_last_nibble_works() -> TrieOpResult<()> { common_setup(); let entries = [entry(0x1234), entry(0x1235)]; - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries) } #[test] - fn diagonal_inserts_to_base_of_trie_works() { + fn diagonal_inserts_to_base_of_trie_works() -> TrieOpResult<()> { common_setup(); let entries: Vec<_> = (0..=64).map(|i| entry(create_mask_of_1s(i * 4))).collect(); - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries) } #[test] - fn updating_an_existing_node_works() { + fn updating_an_existing_node_works() -> TrieOpResult<()> { common_setup(); let mut entries = [entry(0x1234), entry(0x1234)]; entries[1].1 = vec![100]; - let trie = StandardTrie::try_from_iter(entries).expect("Failed to create trie"); + let trie = StandardTrie::try_from_iter(entries)?; assert_eq!(trie.get(0x1234), Some([100].as_slice())); + + Ok(()) } #[test] - fn cloning_a_trie_creates_two_separate_tries() { + fn cloning_a_trie_creates_two_separate_tries() -> TrieOpResult<()> { common_setup(); - assert_cloning_works_for_tries::(); - assert_cloning_works_for_tries::(); + assert_cloning_works_for_tries::()?; + assert_cloning_works_for_tries::()?; + + Ok(()) } - fn assert_cloning_works_for_tries() + fn assert_cloning_works_for_tries() -> TrieOpResult<()> where T: TryFromIterator<(Nibbles, Vec)> + PartialTrie, { - let trie = T::try_from_iter(once(entry(0x1234))).expect("Failed to create trie"); + let trie = T::try_from_iter(once(entry(0x1234)))?; let mut cloned_trie = trie.clone(); assert!(cloned_trie.extend(once(entry(0x5678))).is_ok()); assert_ne!(trie, cloned_trie); assert_ne!(trie.hash(), cloned_trie.hash()); + + Ok(()) } #[test] - fn mass_inserts_fixed_sized_keys_all_entries_are_retrievable() { + fn mass_inserts_fixed_sized_keys_all_entries_are_retrievable() -> TrieOpResult<()> { common_setup(); let entries: Vec<_> = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 0).collect(); - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries) } #[test] - fn mass_inserts_variable_sized_keys_all_entries_are_retrievable() { + fn mass_inserts_variable_sized_keys_all_entries_are_retrievable() -> TrieOpResult<()> { common_setup(); let entries: Vec<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 0).collect(); - insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries); + insert_entries_and_assert_all_exist_in_trie_with_no_extra(&entries) } #[test] - fn mass_inserts_variable_sized_keys_with_hash_nodes_all_entries_are_retrievable() { + fn mass_inserts_variable_sized_keys_with_hash_nodes_all_entries_are_retrievable( + ) -> TrieOpResult<()> { common_setup(); let non_hash_entries: Vec<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 0).collect(); - let mut trie = StandardTrie::try_from_iter(non_hash_entries.iter().cloned()) - .expect("Failed to create trie"); + let mut trie = StandardTrie::try_from_iter(non_hash_entries.iter().cloned())?; let extra_hash_entries = generate_n_hash_nodes_entries_for_empty_slots_in_trie( &trie, @@ -983,10 +987,12 @@ mod tests { assert!(extra_hash_entries .into_iter() .all(|(k, h)| all_nodes.contains(&(k, ValOrHash::Hash(h))))); + + Ok(()) } #[test] - fn equivalency_check_works() { + fn equivalency_check_works() -> TrieOpResult<()> { common_setup(); assert_eq!( @@ -995,35 +1001,37 @@ mod tests { ); let entries = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 0); - let big_trie_1 = StandardTrie::try_from_iter(entries).expect("Failed to create trie"); + let big_trie_1 = StandardTrie::try_from_iter(entries)?; assert_eq!(big_trie_1, big_trie_1); let entries = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 1); - let big_trie_2 = StandardTrie::try_from_iter(entries).expect("Failed to create trie"); + let big_trie_2 = StandardTrie::try_from_iter(entries)?; + + assert_ne!(big_trie_1, big_trie_2); - assert_ne!(big_trie_1, big_trie_2) + Ok(()) } #[test] - fn two_variable_length_keys_with_overlap_are_queryable() { + fn two_variable_length_keys_with_overlap_are_queryable() -> TrieOpResult<()> { common_setup(); let entries = [entry_with_value(0x1234, 1), entry_with_value(0x12345678, 2)]; - let trie = - StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); + let trie = StandardTrie::try_from_iter(entries.iter().cloned())?; assert_eq!(trie.get(0x1234), Some([1].as_slice())); assert_eq!(trie.get(0x12345678), Some([2].as_slice())); + + Ok(()) } #[test] - fn get_massive_trie_works() { + fn get_massive_trie_works() -> TrieOpResult<()> { common_setup(); let random_entries: Vec<_> = generate_n_random_fixed_trie_value_entries(MASSIVE_TRIE_SIZE, 9001).collect(); - let trie = StandardTrie::try_from_iter(random_entries.iter().cloned()) - .expect("Failed to create trie"); + let trie = StandardTrie::try_from_iter(random_entries.iter().cloned())?; for (k, v) in random_entries.into_iter() { debug!("Attempting to retrieve {:?}...", (k, &v)); @@ -1031,6 +1039,8 @@ mod tests { assert_eq!(res, Some(v.as_slice())); } + + Ok(()) } #[test] @@ -1062,13 +1072,12 @@ mod tests { } #[test] - fn trie_iter_works() { + fn trie_iter_works() -> TrieOpResult<()> { common_setup(); let entries: HashSet<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 9003).collect(); - let trie = - StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); + let trie = StandardTrie::try_from_iter(entries.iter().cloned())?; let trie_items: HashSet<_> = trie .items() @@ -1077,6 +1086,8 @@ mod tests { assert!(entries.iter().all(|e| trie_items.contains(e))); assert!(trie_items.iter().all(|item| entries.contains(item))); + + Ok(()) } #[test] @@ -1100,13 +1111,12 @@ mod tests { } #[test] - fn deletion_massive_trie() { + fn deletion_massive_trie() -> TrieOpResult<()> { common_setup(); let entries: Vec<_> = generate_n_random_variable_trie_value_entries(MASSIVE_TRIE_SIZE, 7).collect(); - let mut trie = - StandardTrie::try_from_iter(entries.iter().cloned()).expect("Failed to create trie"); + let mut trie = StandardTrie::try_from_iter(entries.iter().cloned())?; // Delete half of the elements let half_entries = entries.len() / 2; @@ -1123,5 +1133,7 @@ mod tests { for (k, v) in entries_that_still_should_exist { assert_eq!(trie.get(k), Some(v.as_slice())); } + + Ok(()) } } diff --git a/mpt_trie/src/trie_subsets.rs b/mpt_trie/src/trie_subsets.rs index 1ff0d026f..101f2309e 100644 --- a/mpt_trie/src/trie_subsets.rs +++ b/mpt_trie/src/trie_subsets.rs @@ -396,7 +396,7 @@ mod tests { common_setup, create_trie_with_large_entry_nodes, generate_n_random_fixed_trie_value_entries, handmade_trie_1, TrieType, }, - trie_ops::ValOrHash, + trie_ops::{TrieOpResult, ValOrHash}, utils::{TrieNodeType, TryFromIterator}, }; @@ -690,15 +690,18 @@ mod tests { } #[test] - fn all_leafs_of_keys_to_create_subset_are_included_in_subset_for_giant_trie() { + fn all_leafs_of_keys_to_create_subset_are_included_in_subset_for_giant_trie() -> TrieOpResult<()> + { common_setup(); - let (_, trie_subsets, keys_of_subsets) = create_massive_trie_and_subsets(9009); + let (_, trie_subsets, keys_of_subsets) = create_massive_trie_and_subsets(9009)?; for (sub_trie, ks_used) in trie_subsets.into_iter().zip(keys_of_subsets.into_iter()) { let leaf_nibbles = get_all_nibbles_of_leaf_nodes_in_trie(&sub_trie); assert!(ks_used.into_iter().all(|k| leaf_nibbles.contains(&k))); } + + Ok(()) } #[test] @@ -752,22 +755,24 @@ mod tests { } #[test] - fn hash_of_giant_random_partial_tries_matches_original_trie() { + fn hash_of_giant_random_partial_tries_matches_original_trie() -> TrieOpResult<()> { common_setup(); - let (base_trie, trie_subsets, _) = create_massive_trie_and_subsets(9010); + let (base_trie, trie_subsets, _) = create_massive_trie_and_subsets(9010)?; let base_hash = base_trie.hash(); assert!(trie_subsets .into_iter() - .all(|p_tree| p_tree.hash() == base_hash)) + .all(|p_tree| p_tree.hash() == base_hash)); + + Ok(()) } #[test] - fn giant_random_partial_tries_hashes_leaves_correctly() { + fn giant_random_partial_tries_hashes_leaves_correctly() -> TrieOpResult<()> { common_setup(); - let (base_trie, trie_subsets, leaf_keys_per_trie) = create_massive_trie_and_subsets(9011); + let (base_trie, trie_subsets, leaf_keys_per_trie) = create_massive_trie_and_subsets(9011)?; let all_keys: Vec = base_trie.keys().collect(); for (partial_trie, leaf_trie_keys) in @@ -786,6 +791,8 @@ mod tests { // over a `Hash` node, we return `None`.) assert_all_keys_do_not_exist(&partial_trie, keys_of_hash_nodes); } + + Ok(()) } fn assert_all_keys_do_not_exist(trie: &TrieType, ks: impl Iterator) { @@ -794,13 +801,15 @@ mod tests { } } - fn create_massive_trie_and_subsets(seed: u64) -> (TrieType, Vec, Vec>) { + fn create_massive_trie_and_subsets( + seed: u64, + ) -> TrieOpResult<(TrieType, Vec, Vec>)> { let trie_size = MASSIVE_TEST_NUM_SUB_TRIES * MASSIVE_TEST_NUM_SUB_TRIE_SIZE; let random_entries: Vec<_> = generate_n_random_fixed_trie_value_entries(trie_size, seed).collect(); let entry_keys: Vec<_> = random_entries.iter().map(|(k, _)| k).cloned().collect(); - let trie = TrieType::try_from_iter(random_entries).expect("Failed to create trie"); + let trie = TrieType::try_from_iter(random_entries)?; let keys_of_subsets: Vec> = (0..MASSIVE_TEST_NUM_SUB_TRIES) .map(|i| { @@ -813,6 +822,6 @@ mod tests { let trie_subsets = create_trie_subsets(&trie, keys_of_subsets.iter().map(|v| v.iter().cloned())).unwrap(); - (trie, trie_subsets, keys_of_subsets) + Ok((trie, trie_subsets, keys_of_subsets)) } } From 4f1807afeb024fa04ccf38ec2da979ab67749a8d Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Mon, 25 Mar 2024 12:23:04 +0200 Subject: [PATCH 11/13] fix: pr fixes --- mpt_trie/src/trie_ops.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index c5d056dfe..5e5a26f83 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -832,7 +832,9 @@ mod tests { entries: &[TestInsertValEntry], ) -> TrieOpResult<()> { let trie = StandardTrie::try_from_iter(entries.iter().cloned())?; - Ok(assert_all_entries_in_trie(entries, &trie)) + assert_all_entries_in_trie(entries, &trie); + + Ok(()) } fn assert_all_entries_in_trie(entries: &[TestInsertValEntry], trie: &Node) { From dd9d8e15ac10d1ea690405c0a324f0b4e0c86925 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Mon, 25 Mar 2024 13:36:38 +0200 Subject: [PATCH 12/13] fix: pr fixes --- evm_arithmetization/tests/erc20.rs | 24 +++++++++++----------- evm_arithmetization/tests/erc721.rs | 13 ++++++------ mpt_trie/src/special_query.rs | 13 ++++++++---- mpt_trie/src/trie_hashing.rs | 5 ++--- mpt_trie/src/trie_subsets.rs | 31 +++++++++++++++++++---------- 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index e875d1ec6..609579af9 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -63,8 +63,8 @@ fn test_erc20() -> anyhow::Result<()> { let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account()).to_vec())?; - state_trie_before.insert(giver_nibbles, rlp::encode(&giver_account()).to_vec())?; - state_trie_before.insert(token_nibbles, rlp::encode(&token_account()).to_vec())?; + state_trie_before.insert(giver_nibbles, rlp::encode(&giver_account()?).to_vec())?; + state_trie_before.insert(token_nibbles, rlp::encode(&token_account()?).to_vec())?; let storage_tries = vec![ (giver_state_key, giver_storage()?), @@ -108,10 +108,10 @@ fn test_erc20() -> anyhow::Result<()> { ..sender_account }; state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; - state_trie_after.insert(giver_nibbles, rlp::encode(&giver_account()).to_vec())?; + state_trie_after.insert(giver_nibbles, rlp::encode(&giver_account()?).to_vec())?; let token_account_after = AccountRlp { storage_root: token_storage_after()?.hash(), - ..token_account() + ..token_account()? }; state_trie_after.insert(token_nibbles, rlp::encode(&token_account_after).to_vec())?; @@ -242,22 +242,22 @@ fn token_storage_after() -> anyhow::Result { Ok(trie) } -fn giver_account() -> AccountRlp { - AccountRlp { +fn giver_account() -> anyhow::Result { + Ok(AccountRlp { nonce: 1.into(), balance: 0.into(), - storage_root: giver_storage().expect("storage insert failure").hash(), + storage_root: giver_storage()?.hash(), code_hash: keccak(giver_bytecode()), - } + }) } -fn token_account() -> AccountRlp { - AccountRlp { +fn token_account() -> anyhow::Result { + Ok(AccountRlp { nonce: 1.into(), balance: 0.into(), - storage_root: token_storage().expect("storage insert failure").hash(), + storage_root: token_storage()?.hash(), code_hash: keccak(token_bytecode()), - } + }) } fn sender_account() -> AccountRlp { diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index 9b79ff16e..86dd34002 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -63,7 +63,7 @@ fn test_erc721() -> anyhow::Result<()> { let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert(owner_nibbles, rlp::encode(&owner_account()).to_vec())?; - state_trie_before.insert(contract_nibbles, rlp::encode(&contract_account()).to_vec())?; + state_trie_before.insert(contract_nibbles, rlp::encode(&contract_account()?).to_vec())?; let storage_tries = vec![(contract_state_key, contract_storage()?)]; @@ -93,7 +93,7 @@ fn test_erc721() -> anyhow::Result<()> { state_trie_after.insert(owner_nibbles, rlp::encode(&owner_account_after).to_vec())?; let contract_account_after = AccountRlp { storage_root: contract_storage_after()?.hash(), - ..contract_account() + ..contract_account()? }; state_trie_after.insert( contract_nibbles, @@ -199,6 +199,7 @@ fn insert_storage(trie: &mut HashedPartialTrie, slot: U256, value: U256) -> anyh let r = rlp::encode(&value); let r = r.freeze().to_vec(); trie.insert(nibbles, r)?; + Ok(()) } @@ -279,13 +280,13 @@ fn owner_account() -> AccountRlp { } } -fn contract_account() -> AccountRlp { - AccountRlp { +fn contract_account() -> anyhow::Result { + Ok(AccountRlp { nonce: 0.into(), balance: 0.into(), - storage_root: contract_storage().expect("storage insert failure").hash(), + storage_root: contract_storage()?.hash(), code_hash: keccak(contract_bytecode()), - } + }) } fn signed_tx() -> Vec { diff --git a/mpt_trie/src/special_query.rs b/mpt_trie/src/special_query.rs index 26ed36053..c133a6091 100644 --- a/mpt_trie/src/special_query.rs +++ b/mpt_trie/src/special_query.rs @@ -125,13 +125,14 @@ mod test { use crate::{ nibbles::Nibbles, testing_utils::{common_setup, handmade_trie_1}, + trie_ops::TrieOpResult, utils::TrieSegment, }; #[test] - fn query_iter_works_no_last_node() { + fn query_iter_works_no_last_node() -> TrieOpResult<()> { common_setup(); - let (trie, ks) = handmade_trie_1().unwrap(); + let (trie, ks) = handmade_trie_1()?; // ks --> vec![0x1234, 0x1324, 0x132400005_u64, 0x2001, 0x2002]; let res = vec![ @@ -170,12 +171,14 @@ mod test { let res: Vec<_> = path_for_query(&trie.node, q, false).collect(); assert_eq!(res, expected) } + + Ok(()) } #[test] - fn query_iter_works_with_last_node() { + fn query_iter_works_with_last_node() -> TrieOpResult<()> { common_setup(); - let (trie, _) = handmade_trie_1().unwrap(); + let (trie, _) = handmade_trie_1()?; let extension_expected = vec![ TrieSegment::Branch(1), @@ -212,5 +215,7 @@ mod test { path_for_query(&trie, 0x132400, true).collect::>(), leaf_expected ); + + Ok(()) } } diff --git a/mpt_trie/src/trie_hashing.rs b/mpt_trie/src/trie_hashing.rs index f2f960d88..25a8cff58 100644 --- a/mpt_trie/src/trie_hashing.rs +++ b/mpt_trie/src/trie_hashing.rs @@ -234,7 +234,7 @@ mod tests { let mut trie = HashedPartialTrie::new(Node::Empty); entries.map(move |(k, v)| { - trie.insert(k, v).expect("Failed to insert into trie"); + trie.insert(k, v).unwrap(); trie.get_hash() }) } @@ -380,8 +380,7 @@ mod tests { let half_entries = entries.len() / 2; let entries_to_delete = entries.into_iter().take(half_entries); for (k, _) in entries_to_delete { - let res = our_trie.delete(k); - assert!(res.is_ok(), "Failed to delete key: {:?}", k); + our_trie.delete(k)?; truth_trie.remove(&k.bytes_be())?; let truth_root_hash = H256(truth_trie.root_hash()?.0); diff --git a/mpt_trie/src/trie_subsets.rs b/mpt_trie/src/trie_subsets.rs index 101f2309e..ea593feaa 100644 --- a/mpt_trie/src/trie_subsets.rs +++ b/mpt_trie/src/trie_subsets.rs @@ -520,28 +520,32 @@ mod tests { } #[test] - fn single_node_trie_is_queryable() { + fn single_node_trie_is_queryable() -> Result<(), Box> { common_setup(); let mut trie = TrieType::default(); - assert!(trie.insert(0x1234, vec![0, 1, 2]).is_ok()); - let trie_subset = create_trie_subset(&trie, once(0x1234)).unwrap(); + trie.insert(0x1234, vec![0, 1, 2])?; + let trie_subset = create_trie_subset(&trie, once(0x1234))?; assert_eq!(trie, trie_subset); + + Ok(()) } #[test] - fn multi_node_trie_returns_proper_subset() { + fn multi_node_trie_returns_proper_subset() -> Result<(), Box> { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345_u64]).unwrap(); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345_u64])?; - let trie_subset = create_trie_subset(&trie, vec![0x1234, 0x56]).unwrap(); + let trie_subset = create_trie_subset(&trie, vec![0x1234, 0x56])?; let leaf_keys = get_all_nibbles_of_leaf_nodes_in_trie(&trie_subset); assert!(leaf_keys.contains(&(Nibbles::from(0x1234)))); assert!(leaf_keys.contains(&(Nibbles::from(0x56)))); assert!(!leaf_keys.contains(&Nibbles::from(0x12345))); + + Ok(()) } #[test] @@ -726,20 +730,23 @@ mod tests { } #[test] - fn sub_trie_for_non_existent_key_that_hits_branch_leaf_does_not_hash_out_leaf() { + fn sub_trie_for_non_existent_key_that_hits_branch_leaf_does_not_hash_out_leaf( + ) -> TrieOpResult<()> { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x1234589, 0x12346]).unwrap(); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x1234589, 0x12346])?; let partial_trie = create_trie_subset(&trie, [0x1234567]).unwrap(); // Note that `0x1234589` gets hashed at the branch slot at `0x12345`. assert_nodes_are_hash_nodes(&partial_trie, Vec::::default()); + + Ok(()) } #[test] - fn hash_of_branch_partial_tries_matches_original_trie() { + fn hash_of_branch_partial_tries_matches_original_trie() -> TrieOpResult<()> { common_setup(); - let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345]).unwrap(); + let trie = create_trie_with_large_entry_nodes(&[0x1234, 0x56, 0x12345])?; let base_hash: H256 = trie.hash(); let partial_tries = vec![ @@ -751,7 +758,9 @@ mod tests { ]; assert!(partial_tries .into_iter() - .all(|p_tree| p_tree.hash() == base_hash)) + .all(|p_tree| p_tree.hash() == base_hash)); + + Ok(()) } #[test] From 196cdafe0dbadb7b649fb78742d303edbe8be308 Mon Sep 17 00:00:00 2001 From: Vladimir Trifonov Date: Mon, 25 Mar 2024 13:45:37 +0200 Subject: [PATCH 13/13] tests: refactor some tests --- mpt_trie/src/trie_ops.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/mpt_trie/src/trie_ops.rs b/mpt_trie/src/trie_ops.rs index 5e5a26f83..64f7f70b4 100644 --- a/mpt_trie/src/trie_ops.rs +++ b/mpt_trie/src/trie_ops.rs @@ -938,7 +938,7 @@ mod tests { let trie = T::try_from_iter(once(entry(0x1234)))?; let mut cloned_trie = trie.clone(); - assert!(cloned_trie.extend(once(entry(0x5678))).is_ok()); + cloned_trie.extend(once(entry(0x5678)))?; assert_ne!(trie, cloned_trie); assert_ne!(trie.hash(), cloned_trie.hash()); @@ -1093,23 +1093,27 @@ mod tests { } #[test] - fn deleting_a_non_existent_node_returns_none() { + fn deleting_a_non_existent_node_returns_none() -> TrieOpResult<()> { common_setup(); let mut trie = StandardTrie::default(); - assert!(trie.insert(0x1234, vec![91]).is_ok()); + trie.insert(0x1234, vec![91])?; - assert!(trie.delete(0x5678).is_ok()); - assert!(trie.delete(0x5678).unwrap().is_none()) + let res = trie.delete(0x5678)?; + assert!(res.is_none()); + + Ok(()) } #[test] - fn deleting_from_an_empty_trie_returns_none() { + fn deleting_from_an_empty_trie_returns_none() -> TrieOpResult<()> { common_setup(); let mut trie = StandardTrie::default(); - assert!(trie.delete(0x1234).is_ok()); - assert!(trie.delete(0x1234).unwrap().is_none()) + let res = trie.delete(0x1234)?; + assert!(res.is_none()); + + Ok(()) } #[test] @@ -1125,10 +1129,10 @@ mod tests { let entries_to_delete = entries.iter().take(half_entries); for (k, v) in entries_to_delete { - let res = trie.delete(*k); + let res = trie.delete(*k)?; assert!(trie.get(*k).is_none()); - assert_eq!(res.ok().unwrap().as_ref(), Some(v)); + assert_eq!(res.as_ref(), Some(v)); } let entries_that_still_should_exist = entries.into_iter().skip(half_entries);