From 38cfbd37202e3b1c7e8d9815a6998a01eab2ebb9 Mon Sep 17 00:00:00 2001 From: darshan <8559992+lakshya-sky@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:54:08 +0530 Subject: [PATCH 1/2] chore(l1): use ref instead for `remove` in ethrex-trie. --- crates/common/trie/trie.rs | 22 +++++++++++----------- crates/common/trie/verify_range.rs | 2 +- crates/l2/prover/zkvm/interface/src/lib.rs | 4 ++-- crates/storage/store.rs | 4 ++-- crates/storage/trie_db/libmdbx.rs | 10 +++++----- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/common/trie/trie.rs b/crates/common/trie/trie.rs index 3ee69ec322..17054139aa 100644 --- a/crates/common/trie/trie.rs +++ b/crates/common/trie/trie.rs @@ -103,7 +103,7 @@ impl Trie { /// Remove a value from the trie given its RLP-encoded path. /// Returns the value if it was succesfully removed or None if it wasn't part of the trie - pub fn remove(&mut self, path: PathRLP) -> Result, TrieError> { + pub fn remove(&mut self, path: &PathRLP) -> Result, TrieError> { let root = self.root.take(); if let Some(root) = root { let root_node = self @@ -111,7 +111,7 @@ impl Trie { .get_node(root)? .ok_or(TrieError::InconsistentTree)?; let (root_node, old_value) = - root_node.remove(&mut self.state, Nibbles::from_bytes(&path))?; + root_node.remove(&mut self.state, Nibbles::from_bytes(path))?; self.root = root_node .map(|root| root.insert_self(&mut self.state)) .transpose()?; @@ -527,7 +527,7 @@ mod test { trie.insert(b"horse".to_vec(), b"stallion".to_vec()) .unwrap(); trie.insert(b"doge".to_vec(), b"coin".to_vec()).unwrap(); - trie.remove(b"horse".to_vec()).unwrap(); + trie.remove(&b"horse".to_vec()).unwrap(); assert_eq!(trie.get(&b"do".to_vec()).unwrap(), Some(b"verb".to_vec())); assert_eq!(trie.get(&b"doge".to_vec()).unwrap(), Some(b"coin".to_vec())); } @@ -538,7 +538,7 @@ mod test { trie.insert(vec![185], vec![185]).unwrap(); trie.insert(vec![185, 0], vec![185, 0]).unwrap(); trie.insert(vec![185, 1], vec![185, 1]).unwrap(); - trie.remove(vec![185, 1]).unwrap(); + trie.remove(&vec![185, 1]).unwrap(); assert_eq!(trie.get(&vec![185, 0]).unwrap(), Some(vec![185, 0])); assert_eq!(trie.get(&vec![185]).unwrap(), Some(vec![185])); assert!(trie.get(&vec![185, 1]).unwrap().is_none()); @@ -695,7 +695,7 @@ mod test { // Removals for (val, should_remove) in data.iter() { if *should_remove { - let removed = trie.remove(val.clone()).unwrap(); + let removed = trie.remove(val).unwrap(); prop_assert_eq!(removed, Some(val.clone())); } } @@ -726,7 +726,7 @@ mod test { // Removals for val in data.iter() { if remove(val) { - let removed = trie.remove(val.clone()).unwrap(); + let removed = trie.remove(val).unwrap(); prop_assert_eq!(removed, Some(val.clone())); } } @@ -772,7 +772,7 @@ mod test { // Removals for (val, should_remove) in data.iter() { if *should_remove { - trie.remove(val.clone()).unwrap(); + trie.remove(val).unwrap(); cita_trie.remove(val).unwrap(); } } @@ -800,7 +800,7 @@ mod test { // Removals for val in data.iter() { if remove(val) { - trie.remove(val.clone()).unwrap(); + trie.remove(val).unwrap(); cita_trie.remove(val).unwrap(); } } @@ -857,7 +857,7 @@ mod test { // Removals for (val, should_remove) in data.iter() { if *should_remove { - trie.remove(val.clone()).unwrap(); + trie.remove(val).unwrap(); cita_trie.remove(val).unwrap(); } } @@ -889,7 +889,7 @@ mod test { // Removals for val in data.iter() { if remove(val) { - trie.remove(val.clone()).unwrap(); + trie.remove(val).unwrap(); cita_trie.remove(val).unwrap(); } } @@ -986,7 +986,7 @@ mod test { cita_trie.insert(b.clone(), b.clone()).unwrap(); trie.insert(a.clone(), a.clone()).unwrap(); trie.insert(b.clone(), b.clone()).unwrap(); - trie.remove(a.clone()).unwrap(); + trie.remove(&a).unwrap(); cita_trie.remove(&a).unwrap(); let _ = cita_trie.root(); let cita_proof = cita_trie.get_proof(&a).unwrap(); diff --git a/crates/common/trie/verify_range.rs b/crates/common/trie/verify_range.rs index 8365354331..38cc9fae13 100644 --- a/crates/common/trie/verify_range.rs +++ b/crates/common/trie/verify_range.rs @@ -831,7 +831,7 @@ mod tests { let values = vec![data.iter().collect::>()[start].clone()]; let keys = values.iter().map(|a| H256::from_slice(a)).collect::>(); // Remove the value to generate a proof of non-existance - trie.remove(values[0].clone()).unwrap(); + trie.remove(&values[0]).unwrap(); // Generate proofs let proof = trie.get_proof(&values[0]).unwrap(); // Verify the range proof diff --git a/crates/l2/prover/zkvm/interface/src/lib.rs b/crates/l2/prover/zkvm/interface/src/lib.rs index a6f1c0321b..8cca5b6085 100644 --- a/crates/l2/prover/zkvm/interface/src/lib.rs +++ b/crates/l2/prover/zkvm/interface/src/lib.rs @@ -186,7 +186,7 @@ pub mod trie { let hashed_address = hash_address(&update.address); if update.removed { // Remove account from trie - state_trie.remove(hashed_address)?; + state_trie.remove(&hashed_address)?; } else { // Add or update AccountState in the trie // Fetch current state or create a new state to be inserted @@ -220,7 +220,7 @@ pub mod trie { for (storage_key, storage_value) in &update.added_storage { let hashed_key = hash_key(storage_key); if storage_value.is_zero() { - storage_trie.remove(hashed_key)?; + storage_trie.remove(&hashed_key)?; } else { storage_trie.insert(hashed_key, storage_value.encode_to_vec())?; } diff --git a/crates/storage/store.rs b/crates/storage/store.rs index cc219d2029..3721b1b012 100644 --- a/crates/storage/store.rs +++ b/crates/storage/store.rs @@ -442,7 +442,7 @@ impl Store { let hashed_address = hash_address(&update.address); if update.removed { // Remove account from trie - state_trie.remove(hashed_address)?; + state_trie.remove(&hashed_address)?; } else { // Add or update AccountState in the trie // Fetch current state or create a new state to be inserted @@ -468,7 +468,7 @@ impl Store { for (storage_key, storage_value) in &update.added_storage { let hashed_key = hash_key(storage_key); if storage_value.is_zero() { - storage_trie.remove(hashed_key)?; + storage_trie.remove(&hashed_key)?; } else { storage_trie.insert(hashed_key, storage_value.encode_to_vec())?; } diff --git a/crates/storage/trie_db/libmdbx.rs b/crates/storage/trie_db/libmdbx.rs index 67c602f888..75eba2dafe 100644 --- a/crates/storage/trie_db/libmdbx.rs +++ b/crates/storage/trie_db/libmdbx.rs @@ -126,9 +126,9 @@ mod test { let root = trie.hash().unwrap(); trie.insert([0; 32].to_vec(), vec![0x04]).unwrap(); - trie.remove([1; 32].to_vec()).unwrap(); + trie.remove(&[1; 32].to_vec()).unwrap(); trie.insert([2; 32].to_vec(), vec![0x05]).unwrap(); - trie.remove([0; 32].to_vec()).unwrap(); + trie.remove(&[0; 32].to_vec()).unwrap(); assert_eq!(trie.get(&[0; 32].to_vec()).unwrap(), None); assert_eq!(trie.get(&[1; 32].to_vec()).unwrap(), None); @@ -175,13 +175,13 @@ mod test { let root = trie.hash().unwrap(); trie.insert([0; 32].to_vec(), [4; 32].to_vec()).unwrap(); - trie.remove([1; 32].to_vec()).unwrap(); + trie.remove(&[1; 32].to_vec()).unwrap(); trie.insert([2; 32].to_vec(), [5; 32].to_vec()).unwrap(); - trie.remove([0; 32].to_vec()).unwrap(); + trie.remove(&[0; 32].to_vec()).unwrap(); let mut trie = Trie::open(Box::new(LibmdbxTrieDB::::new(db.clone())), root); - trie.remove([2; 32].to_vec()).unwrap(); + trie.remove(&[2; 32].to_vec()).unwrap(); assert_eq!(trie.get(&[0; 32].to_vec()).unwrap(), Some([0; 32].to_vec())); assert_eq!(trie.get(&[1; 32].to_vec()).unwrap(), Some([1; 32].to_vec())); From e9601bc55ff363eb6064024bf3d016bc006b835d Mon Sep 17 00:00:00 2001 From: darshan <8559992+lakshya-sky@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:56:22 +0530 Subject: [PATCH 2/2] chore(l1): add benchmark comparing cita and ethrex tries. --- Cargo.lock | 141 ++++++++++++++++++++ crates/common/trie/Cargo.toml | 6 + crates/common/trie/benches/trie.rs | 207 +++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 crates/common/trie/benches/trie.rs diff --git a/Cargo.lock b/Cargo.lock index d3137822e4..e53c478345 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -513,6 +513,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "ansi_term" version = "0.12.1" @@ -1431,6 +1437,12 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cbindgen" version = "0.27.0" @@ -1517,6 +1529,33 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.4.4" @@ -1781,6 +1820,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap 4.5.30", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -2897,6 +2972,7 @@ dependencies = [ "anyhow", "bytes", "cita_trie", + "criterion", "digest 0.10.7", "ethereum-types", "ethrex-rlp", @@ -2913,6 +2989,7 @@ dependencies = [ "tempdir", "thiserror 2.0.11", "tracing", + "uuid", ] [[package]] @@ -3464,6 +3541,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "halo2" version = "0.1.0-beta.2" @@ -4980,6 +5067,12 @@ version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -5603,6 +5696,34 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "portable-atomic" version = "1.10.0" @@ -8269,6 +8390,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.8.1" @@ -8837,6 +8968,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd8dcafa1ca14750d8d7a05aa05988c17aab20886e1f3ae33a40223c58d92ef7" +dependencies = [ + "getrandom 0.3.1", + "serde", +] + [[package]] name = "valuable" version = "0.1.1" diff --git a/crates/common/trie/Cargo.toml b/crates/common/trie/Cargo.toml index fdeeb4c24e..ec52895a88 100644 --- a/crates/common/trie/Cargo.toml +++ b/crates/common/trie/Cargo.toml @@ -31,6 +31,12 @@ proptest = "1.0.0" tempdir = "0.3.7" cita_trie = "4.0.0" # used for proptest comparisons hasher = "0.1.4" # cita_trie needs this +uuid = { version = "1.15", features = ["serde", "v4"] } +criterion = "0.5" [lib] path = "./trie.rs" + +[[bench]] +name = "trie" +harness = false diff --git a/crates/common/trie/benches/trie.rs b/crates/common/trie/benches/trie.rs new file mode 100644 index 0000000000..89b1664d41 --- /dev/null +++ b/crates/common/trie/benches/trie.rs @@ -0,0 +1,207 @@ +use std::collections::HashMap; +use std::sync::Arc; +use std::sync::Mutex; + +use criterion::{criterion_group, criterion_main, Criterion}; + +use hasher::HasherKeccak; +use uuid::Uuid; + +use cita_trie::{MemoryDB as CitaMemoryDB, PatriciaTrie as CitaPatriciaTrie, Trie as CitaTrie}; + +use ethrex_trie::{InMemoryTrieDB as EthrexMemoryDB, Trie as EthrexTrie}; + +fn cita_new_trie() -> CitaPatriciaTrie { + CitaPatriciaTrie::new( + Arc::new(CitaMemoryDB::new(false)), + Arc::new(HasherKeccak::new()), + ) +} + +fn ethrex_new_trie() -> EthrexTrie { + let hmap: HashMap, Vec> = HashMap::new(); + let map = Arc::new(Mutex::new(hmap)); + let db = EthrexMemoryDB::new(map); + EthrexTrie::new(Box::new(db)) +} + +fn cita_trie_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("CitaTrie"); + + group.bench_function("insert one", |b| { + let mut trie = cita_new_trie(); + + b.iter(|| { + let key = Uuid::new_v4().as_bytes().to_vec(); + let value = Uuid::new_v4().as_bytes().to_vec(); + trie.insert(key, value).unwrap() + }) + }); + + group.bench_function("insert 1k", |b| { + let mut trie = cita_new_trie(); + + let (keys, values) = random_data(1000); + b.iter(|| { + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + }); + }); + + group.bench_function("insert 10k", |b| { + let mut trie = cita_new_trie(); + + let (keys, values) = random_data(10000); + b.iter(|| { + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + }); + }); + + group.bench_function("get based 10k", |b| { + let mut trie = cita_new_trie(); + + let (keys, values) = random_data(10000); + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + + b.iter(|| { + let key = trie.get(&keys[7777]).unwrap(); + assert_ne!(key, None); + }); + }); + + group.bench_function("remove 1k", |b| { + let mut trie = cita_new_trie(); + + let (keys, values) = random_data(1000); + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + + b.iter(|| { + for key in keys.iter() { + trie.remove(key).unwrap(); + } + }); + }); + + group.bench_function("remove 10k", |b| { + let mut trie = cita_new_trie(); + + let (keys, values) = random_data(10000); + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + + b.iter(|| { + for key in keys.iter() { + trie.remove(key).unwrap(); + } + }); + }); + + group.finish(); +} + + +fn ethrex_trie_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("EthrexTrie"); + + group.bench_function("insert one", |b| { + let mut trie = ethrex_new_trie(); + + b.iter(|| { + let key = Uuid::new_v4().as_bytes().to_vec(); + let value = Uuid::new_v4().as_bytes().to_vec(); + trie.insert(key, value).unwrap() + }) + }); + + group.bench_function("insert 1k", |b| { + let mut trie = ethrex_new_trie(); + + let (keys, values) = random_data(1000); + b.iter(|| { + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + }); + }); + + group.bench_function("insert 10k", |b| { + let mut trie = ethrex_new_trie(); + + let (keys, values) = random_data(10000); + b.iter(|| { + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + }); + }); + + group.bench_function("get based 10k", |b| { + let mut trie = ethrex_new_trie(); + + let (keys, values) = random_data(10000); + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + + b.iter(|| { + let key = trie.get(&keys[7777]).unwrap(); + assert_ne!(key, None); + }); + }); + + group.bench_function("remove 1k", |b| { + let mut trie = ethrex_new_trie(); + + let (keys, values) = random_data(1000); + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + + b.iter(|| { + for key in keys.iter() { + trie.remove(key).unwrap(); + } + }); + }); + + group.bench_function("remove 10k", |b| { + let mut trie = ethrex_new_trie(); + + let (keys, values) = random_data(10000); + for i in 0..keys.len() { + trie.insert(keys[i].clone(), values[i].clone()).unwrap() + } + + b.iter(|| { + for key in keys.iter() { + trie.remove(key).unwrap(); + } + }); + }); + + group.finish(); +} + +fn random_data(n: usize) -> (Vec>, Vec>) { + let mut keys = Vec::with_capacity(n); + let mut values = Vec::with_capacity(n); + for _ in 0..n { + let key = Uuid::new_v4().as_bytes().to_vec(); + let value = Uuid::new_v4().as_bytes().to_vec(); + keys.push(key); + values.push(value); + } + + (keys, values) +} + +criterion_group!(benches, cita_trie_benchmark, ethrex_trie_benchmark); +criterion_main!(benches);