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);