diff --git a/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs b/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs index b7c08b61..26f61139 100644 --- a/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs +++ b/crates/committer/src/patricia_merkle_tree/filled_tree/tree_test.rs @@ -1,16 +1,15 @@ use std::collections::HashMap; use std::sync::Arc; -use crate::block_committer::input::StarknetStorageValue; use crate::felt::Felt; use crate::hash::hash_trait::HashOutput; use crate::patricia_merkle_tree::filled_tree::node::FilledNode; use crate::patricia_merkle_tree::filled_tree::tree::{FilledTree, FilledTreeImpl}; +use crate::patricia_merkle_tree::internal_test_utils::{MockLeaf, OriginalSkeletonMockTrieConfig}; use crate::patricia_merkle_tree::node_data::inner_node::{ BinaryData, EdgeData, EdgePathLength, NodeData, PathToBottom, }; use crate::patricia_merkle_tree::node_data::leaf::SkeletonLeaf; -use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonStorageTrieConfig; use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeImpl; use crate::patricia_merkle_tree::types::{NodeIndex, SortedLeafIndices}; use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunctionImpl; @@ -24,7 +23,7 @@ use crate::storage::map_storage::MapStorage; /// This test is a sanity test for computing the root hash of the patricia merkle tree with a single node that is a leaf with hash==1. async fn test_filled_tree_sanity() { let mut skeleton_tree: UpdatedSkeletonNodeMap = HashMap::new(); - let new_filled_leaf = StarknetStorageValue(Felt::ONE); + let new_filled_leaf = MockLeaf(Felt::ONE); let new_leaf_index = NodeIndex::ROOT; skeleton_tree.insert(new_leaf_index, UpdatedSkeletonNode::Leaf); let modifications = HashMap::from([(new_leaf_index, new_filled_leaf)]); @@ -84,7 +83,7 @@ async fn test_small_filled_tree() { .map(|(index, value)| { ( NodeIndex::from(*index), - StarknetStorageValue(Felt::from_hex(value).unwrap()), + MockLeaf(Felt::from_hex(value).unwrap()), ) }) .collect(); @@ -100,53 +99,17 @@ async fn test_small_filled_tree() { let root_hash = filled_tree.get_root_hash(); // The expected hash values were computed separately. - let expected_root_hash = HashOutput( - Felt::from_hex("0xe8899e8c731a35f5e9ce4c4bc32aabadcc81c5cdcc1aeba74fa7509046c338").unwrap(), - ); + let expected_root_hash = HashOutput(Felt::from_hex("0x21").unwrap()); let expected_filled_tree_map = HashMap::from([ - create_binary_entry_for_testing( - 1, - "0xe8899e8c731a35f5e9ce4c4bc32aabadcc81c5cdcc1aeba74fa7509046c338", - "0x4e970ad06a06486b44fff5606c4f65486d31e05e323d65a618d4ef8cdf6d3a0", - "0x2955a96b09495fb2ce4ed65cf679c54e54aefc2c6972d7f3042590000bb7543", - ), - create_edge_entry_for_testing( - 2, - "0x4e970ad06a06486b44fff5606c4f65486d31e05e323d65a618d4ef8cdf6d3a0", - 0, - 1, - "0x5d36a1ae900ef417a5696417dde9a0244b873522f40b552e4a60acde0991bc9", - ), - create_edge_entry_for_testing( - 3, - "0x2955a96b09495fb2ce4ed65cf679c54e54aefc2c6972d7f3042590000bb7543", - 15, - 4, - "0x3", - ), - create_binary_entry_for_testing( - 4, - "0x5d36a1ae900ef417a5696417dde9a0244b873522f40b552e4a60acde0991bc9", - "0x582d984e4005c27b9c886cd00ec9a82ed5323aa629f6ea6b3ed7c0386ae6256", - "0x39eb7b85bcc9deac314406d6b73154b09b008f8af05e2f58ab623f4201d0b88", - ), - create_edge_entry_for_testing( - 8, - "0x582d984e4005c27b9c886cd00ec9a82ed5323aa629f6ea6b3ed7c0386ae6256", - 3, - 2, - "0x1", - ), - create_edge_entry_for_testing( - 9, - "0x39eb7b85bcc9deac314406d6b73154b09b008f8af05e2f58ab623f4201d0b88", - 0, - 2, - "0x2", - ), - create_leaf_entry_for_testing(35, "0x1"), - create_leaf_entry_for_testing(36, "0x2"), - create_leaf_entry_for_testing(63, "0x3"), + create_mock_binary_entry_for_testing(1, "0x21", "0xb", "0x16"), + create_mock_edge_entry_for_testing(2, "0xb", 0, 1, "0xa"), + create_mock_edge_entry_for_testing(3, "0x16", 15, 4, "0x3"), + create_mock_binary_entry_for_testing(4, "0xa", "0x6", "0x4"), + create_mock_edge_entry_for_testing(8, "0x6", 3, 2, "0x1"), + create_mock_edge_entry_for_testing(9, "0x4", 0, 2, "0x2"), + create_mock_leaf_entry_for_testing(35, "0x1"), + create_mock_leaf_entry_for_testing(36, "0x2"), + create_mock_leaf_entry_for_testing(63, "0x3"), ]); assert_eq!(filled_tree_map, &expected_filled_tree_map); assert_eq!(root_hash, expected_root_hash, "Root hash mismatch"); @@ -158,12 +121,12 @@ async fn test_small_filled_tree() { /// i=1: binary /// / \ /// i=2: edge i=3: unmodified -/// l=1, p=0 hash=0x2955a96b09495fb2ce4ed65cf679c54e54aefc2c6972d7f3042590000bb7543 +/// l=1, p=0 hash=0x3 /// / /// i=4: binary /// / \ /// i=8: edge i=9: unmodified -/// l=2, p=3 hash=0x39eb7b85bcc9deac314406d6b73154b09b008f8af05e2f58ab623f4201d0b88 +/// l=2, p=3 hash=0x4 /// \ /// \ /// i=35: leaf @@ -174,16 +137,10 @@ async fn test_small_tree_with_unmodified_nodes() { let nodes_in_skeleton_tree = [ create_binary_updated_skeleton_node_for_testing(1), create_path_to_bottom_edge_updated_skeleton_node_for_testing(2, 0, 1), - create_unmodified_updated_skeleton_node_for_testing( - 3, - "0x2955a96b09495fb2ce4ed65cf679c54e54aefc2c6972d7f3042590000bb7543", - ), + create_unmodified_updated_skeleton_node_for_testing(3, "0x3"), create_binary_updated_skeleton_node_for_testing(4), create_path_to_bottom_edge_updated_skeleton_node_for_testing(8, 3, 2), - create_unmodified_updated_skeleton_node_for_testing( - 9, - "0x39eb7b85bcc9deac314406d6b73154b09b008f8af05e2f58ab623f4201d0b88", - ), + create_unmodified_updated_skeleton_node_for_testing(9, "0x4"), create_leaf_updated_skeleton_node_for_testing(new_leaf_index), ]; let skeleton_tree: UpdatedSkeletonNodeMap = nodes_in_skeleton_tree.into_iter().collect(); @@ -191,7 +148,7 @@ async fn test_small_tree_with_unmodified_nodes() { let updated_skeleton_tree = UpdatedSkeletonTreeImpl { skeleton_tree }; let modifications = HashMap::from([( NodeIndex::from(new_leaf_index), - StarknetStorageValue(Felt::from_hex(new_leaf).unwrap()), + MockLeaf(Felt::from_hex(new_leaf).unwrap()), )]); // Compute the hash values. @@ -207,37 +164,13 @@ async fn test_small_tree_with_unmodified_nodes() { // The expected hash values were computed separately. Note that the unmodified nodes are not // computed in the filled tree, but the hash values are directly used. The hashes of unmodified // nodes should not appear in the filled tree. - let expected_root_hash = HashOutput( - Felt::from_hex("0xe8899e8c731a35f5e9ce4c4bc32aabadcc81c5cdcc1aeba74fa7509046c338").unwrap(), - ); + let expected_root_hash = HashOutput(Felt::from_hex("0xe").unwrap()); let expected_filled_tree_map = HashMap::from([ - create_binary_entry_for_testing( - 1, - "0xe8899e8c731a35f5e9ce4c4bc32aabadcc81c5cdcc1aeba74fa7509046c338", - "0x4e970ad06a06486b44fff5606c4f65486d31e05e323d65a618d4ef8cdf6d3a0", - "0x2955a96b09495fb2ce4ed65cf679c54e54aefc2c6972d7f3042590000bb7543", - ), - create_edge_entry_for_testing( - 2, - "0x4e970ad06a06486b44fff5606c4f65486d31e05e323d65a618d4ef8cdf6d3a0", - 0, - 1, - "0x5d36a1ae900ef417a5696417dde9a0244b873522f40b552e4a60acde0991bc9", - ), - create_binary_entry_for_testing( - 4, - "0x5d36a1ae900ef417a5696417dde9a0244b873522f40b552e4a60acde0991bc9", - "0x582d984e4005c27b9c886cd00ec9a82ed5323aa629f6ea6b3ed7c0386ae6256", - "0x39eb7b85bcc9deac314406d6b73154b09b008f8af05e2f58ab623f4201d0b88", - ), - create_edge_entry_for_testing( - 8, - "0x582d984e4005c27b9c886cd00ec9a82ed5323aa629f6ea6b3ed7c0386ae6256", - 3, - 2, - "0x1", - ), - create_leaf_entry_for_testing(35, "0x1"), + create_mock_binary_entry_for_testing(1, "0xe", "0xb", "0x3"), + create_mock_edge_entry_for_testing(2, "0b", 0, 1, "0xa"), + create_mock_binary_entry_for_testing(4, "0xa", "0x6", "0x4"), + create_mock_edge_entry_for_testing(8, "0x6", 3, 2, "0x1"), + create_mock_leaf_entry_for_testing(35, "0x1"), ]); assert_eq!(filled_tree_map, &expected_filled_tree_map); assert_eq!(root_hash, expected_root_hash, "Root hash mismatch"); @@ -246,8 +179,8 @@ async fn test_small_tree_with_unmodified_nodes() { #[tokio::test(flavor = "multi_thread")] /// Test that deleting a leaf that does not exist in the tree succeeds. async fn test_delete_leaf_from_empty_tree() { - let storage_modifications: HashMap = - HashMap::from([(NodeIndex::FIRST_LEAF, StarknetStorageValue(Felt::ZERO))]); + let storage_modifications: HashMap = + HashMap::from([(NodeIndex::FIRST_LEAF, MockLeaf(Felt::ZERO))]); let mut indices = [NodeIndex::FIRST_LEAF]; // Create an empty original skeleton tree with a single leaf modified. @@ -257,7 +190,7 @@ async fn test_delete_leaf_from_empty_tree() { }, HashOutput::ROOT_OF_EMPTY_TREE, SortedLeafIndices::new(&mut indices), - &OriginalSkeletonStorageTrieConfig::new(&storage_modifications, false), + &OriginalSkeletonMockTrieConfig::new(&storage_modifications, false), ) .unwrap(); @@ -268,8 +201,7 @@ async fn test_delete_leaf_from_empty_tree() { UpdatedSkeletonTreeImpl::create(&mut original_skeleton_tree, &skeleton_modifications) .unwrap(); - let leaf_modifications = - HashMap::from([(NodeIndex::FIRST_LEAF, StarknetStorageValue(Felt::ZERO))]); + let leaf_modifications = HashMap::from([(NodeIndex::FIRST_LEAF, MockLeaf(Felt::ZERO))]); // Compute the filled tree. let filled_tree = FilledTreeImpl::create::( updated_skeleton_tree.into(), @@ -318,12 +250,12 @@ fn create_leaf_updated_skeleton_node_for_testing(index: u128) -> (NodeIndex, Upd (NodeIndex::from(index), UpdatedSkeletonNode::Leaf) } -fn create_binary_entry_for_testing( +fn create_mock_binary_entry_for_testing( index: u128, hash: &str, left_hash: &str, right_hash: &str, -) -> (NodeIndex, FilledNode) { +) -> (NodeIndex, FilledNode) { ( NodeIndex::from(index), FilledNode { @@ -336,13 +268,13 @@ fn create_binary_entry_for_testing( ) } -fn create_edge_entry_for_testing( +fn create_mock_edge_entry_for_testing( index: u128, hash: &str, path: u128, length: u8, bottom_hash: &str, -) -> (NodeIndex, FilledNode) { +) -> (NodeIndex, FilledNode) { ( NodeIndex::from(index), FilledNode { @@ -359,15 +291,15 @@ fn create_edge_entry_for_testing( ) } -fn create_leaf_entry_for_testing( +fn create_mock_leaf_entry_for_testing( index: u128, hash: &str, -) -> (NodeIndex, FilledNode) { +) -> (NodeIndex, FilledNode) { ( NodeIndex::from(index), FilledNode { hash: HashOutput(Felt::from_hex(hash).unwrap()), - data: NodeData::Leaf(StarknetStorageValue(Felt::from_hex(hash).unwrap())), + data: NodeData::Leaf(MockLeaf(Felt::from_hex(hash).unwrap())), }, ) } diff --git a/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs b/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs index f6e70a8a..d83054b9 100644 --- a/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs +++ b/crates/committer/src/patricia_merkle_tree/internal_test_utils.rs @@ -4,17 +4,20 @@ use crate::felt::Felt; use crate::hash::hash_trait::HashOutput; use crate::patricia_merkle_tree::external_test_utils::get_random_u256; -use super::node_data::errors::LeafResult; -use super::node_data::leaf::{Leaf, LeafModifications}; -use super::updated_skeleton_tree::hash_function::HashFunction; use crate::generate_trie_config; +use crate::patricia_merkle_tree::node_data::errors::LeafResult; +use crate::patricia_merkle_tree::node_data::inner_node::NodeData; use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; use crate::patricia_merkle_tree::node_data::leaf::SkeletonLeaf; +use crate::patricia_merkle_tree::node_data::leaf::{Leaf, LeafModifications}; use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonTreeConfig; use crate::patricia_merkle_tree::original_skeleton_tree::errors::OriginalSkeletonTreeError; use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTreeResult; use crate::patricia_merkle_tree::types::{NodeIndex, SubTreeHeight}; +use crate::patricia_merkle_tree::updated_skeleton_tree::hash_function::{ + HashFunction, TreeHashFunction, TreeHashFunctionImpl, +}; use crate::patricia_merkle_tree::updated_skeleton_tree::node::UpdatedSkeletonNode; use crate::patricia_merkle_tree::updated_skeleton_tree::tree::UpdatedSkeletonTreeImpl; use crate::storage::db_object::{DBObject, Deserializable}; @@ -61,6 +64,16 @@ impl Leaf for MockLeaf { } } +impl TreeHashFunction for TreeHashFunctionImpl { + fn compute_leaf_hash(leaf_data: &MockLeaf) -> HashOutput { + HashOutput(leaf_data.0) + } + + fn compute_node_hash(node_data: &NodeData) -> HashOutput { + Self::compute_node_hash_with_inner_hash_function::(node_data) + } +} + generate_trie_config!(OriginalSkeletonMockTrieConfig, MockLeaf); struct MockHashFunction; diff --git a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs index f45e3911..bb43b99c 100644 --- a/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs +++ b/crates/committer/src/patricia_merkle_tree/original_skeleton_tree/create_tree_test.rs @@ -3,11 +3,11 @@ use crate::block_committer::input::StarknetStorageValue; use crate::felt::Felt; use crate::hash::hash_trait::HashOutput; use crate::patricia_merkle_tree::filled_tree::node::{ClassHash, CompiledClassHash, Nonce}; -use crate::patricia_merkle_tree::internal_test_utils::small_tree_index_to_full; +use crate::patricia_merkle_tree::internal_test_utils::OriginalSkeletonMockTrieConfig; +use crate::patricia_merkle_tree::internal_test_utils::{small_tree_index_to_full, MockLeaf}; use crate::patricia_merkle_tree::node_data::inner_node::EdgePath; use crate::patricia_merkle_tree::node_data::inner_node::{EdgePathLength, PathToBottom}; use crate::patricia_merkle_tree::node_data::leaf::{ContractState, LeafModifications}; -use crate::patricia_merkle_tree::original_skeleton_tree::config::OriginalSkeletonStorageTrieConfig; use crate::patricia_merkle_tree::original_skeleton_tree::create_tree::SubTree; use crate::patricia_merkle_tree::original_skeleton_tree::node::OriginalSkeletonNode; use crate::patricia_merkle_tree::original_skeleton_tree::tree::OriginalSkeletonTree; @@ -56,12 +56,12 @@ use std::collections::HashMap; create_binary_entry(17, 13), create_edge_entry(15, 3, 2), create_binary_entry(30, 20), - create_storage_leaf_entry(8), - create_storage_leaf_entry(9), - create_storage_leaf_entry(11), - create_storage_leaf_entry(15) + create_mock_leaf_entry(8), + create_mock_leaf_entry(9), + create_mock_leaf_entry(11), + create_mock_leaf_entry(15) ]).into(), - create_leaf_modifications(vec![(8, 8), (10, 3), (13, 2)]), + create_mock_leaf_modifications(vec![(8, 8), (10, 3), (13, 2)]), HashOutput(Felt::from(50_u128 + 248_u128)), create_expected_skeleton_nodes( vec![ @@ -110,13 +110,13 @@ use std::collections::HashMap; create_edge_entry(12, 0, 1), create_binary_entry(5, 11), create_binary_entry(13, 16), - create_storage_leaf_entry(10), - create_storage_leaf_entry(2), - create_storage_leaf_entry(3), - create_storage_leaf_entry(4), - create_storage_leaf_entry(7) + create_mock_leaf_entry(10), + create_mock_leaf_entry(2), + create_mock_leaf_entry(3), + create_mock_leaf_entry(4), + create_mock_leaf_entry(7) ]).into(), - create_leaf_modifications(vec![(8, 5), (11, 1), (13, 3)]), + create_mock_leaf_modifications(vec![(8, 5), (11, 1), (13, 3)]), HashOutput(Felt::from(29_u128 + 248_u128)), create_expected_skeleton_nodes( vec![ @@ -169,14 +169,14 @@ use std::collections::HashMap; create_edge_entry(24, 0, 2), create_binary_entry(25, 65), create_binary_entry(26, 90), - create_storage_leaf_entry(11), - create_storage_leaf_entry(13), - create_storage_leaf_entry(20), - create_storage_leaf_entry(5), - create_storage_leaf_entry(19), - create_storage_leaf_entry(40), + create_mock_leaf_entry(11), + create_mock_leaf_entry(13), + create_mock_leaf_entry(20), + create_mock_leaf_entry(5), + create_mock_leaf_entry(19), + create_mock_leaf_entry(40), ]).into(), - create_leaf_modifications(vec![(18, 5), (25, 1), (29, 15), (30, 19)]), + create_mock_leaf_modifications(vec![(18, 5), (25, 1), (29, 15), (30, 19)]), HashOutput(Felt::from(116_u128 + 247_u128)), create_expected_skeleton_nodes( vec![ @@ -198,21 +198,20 @@ use std::collections::HashMap; )] fn test_create_tree( #[case] storage: MapStorage, - #[case] leaf_modifications: LeafModifications, + #[case] leaf_modifications: LeafModifications, #[case] root_hash: HashOutput, #[case] expected_skeleton_nodes: HashMap, #[case] subtree_height: SubTreeHeight, #[values(true, false)] compare_modified_leaves: bool, ) { - let leaf_modifications: LeafModifications = leaf_modifications + let leaf_modifications: LeafModifications = leaf_modifications .into_iter() .map(|(idx, leaf)| (NodeIndex::from_subtree_index(idx, subtree_height), leaf)) .collect(); - let config = - OriginalSkeletonStorageTrieConfig::new(&leaf_modifications, compare_modified_leaves); + let config = OriginalSkeletonMockTrieConfig::new(&leaf_modifications, compare_modified_leaves); let mut sorted_leaf_indices: Vec = leaf_modifications.keys().copied().collect(); let sorted_leaf_indices = SortedLeafIndices::new(&mut sorted_leaf_indices); - let skeleton_tree = OriginalSkeletonTreeImpl::create::( + let skeleton_tree = OriginalSkeletonTreeImpl::create::( &storage, root_hash, sorted_leaf_indices, @@ -418,6 +417,11 @@ pub(crate) fn create_32_bytes_entry(simple_val: u128) -> [u8; 32] { U256::from(simple_val).to_be_bytes() } +pub(crate) fn create_mock_leaf_entry(val: u128) -> (StorageKey, StorageValue) { + let leaf = MockLeaf(Felt::from(val)); + (leaf.get_db_key(&leaf.0.to_bytes_be()), leaf.serialize()) +} + pub(crate) fn create_storage_leaf_entry(val: u128) -> (StorageKey, StorageValue) { let leaf = StarknetStorageValue(Felt::from(val)); (leaf.get_db_key(&leaf.0.to_bytes_be()), leaf.serialize()) @@ -464,12 +468,12 @@ fn create_edge_val(hash: u128, path: u128, length: u8) -> StorageValue { ) } -fn create_leaf_modifications( +fn create_mock_leaf_modifications( leaf_modifications: Vec<(u128, u128)>, -) -> LeafModifications { +) -> LeafModifications { leaf_modifications .into_iter() - .map(|(idx, val)| (NodeIndex::from(idx), StarknetStorageValue(Felt::from(val)))) + .map(|(idx, val)| (NodeIndex::from(idx), MockLeaf(Felt::from(val)))) .collect() }