Cache zero hash results. (#24)

* Cache zero hash results.

* Fix clippy.
This commit is contained in:
peilun-conflux 2024-03-01 10:08:10 +08:00 committed by GitHub
parent 3e2068d363
commit 39ca3113d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 21 deletions

5
Cargo.lock generated
View File

@ -150,6 +150,7 @@ dependencies = [
"eth2_ssz_derive", "eth2_ssz_derive",
"ethereum-types 0.14.1", "ethereum-types 0.14.1",
"lazy_static", "lazy_static",
"once_cell",
"serde", "serde",
"tiny-keccak", "tiny-keccak",
"tracing", "tracing",
@ -4615,9 +4616,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.18.0" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "oorandom" name = "oorandom"

View File

@ -11,4 +11,5 @@ eth2_ssz = "0.4.0"
eth2_ssz_derive = "0.3.0" eth2_ssz_derive = "0.3.0"
serde = { version = "1.0.137", features = ["derive"] } serde = { version = "1.0.137", features = ["derive"] }
lazy_static = "1.4.0" lazy_static = "1.4.0"
tracing = "0.1.36" tracing = "0.1.36"
once_cell = "1.19.0"

View File

@ -2,7 +2,7 @@ use crate::sha3::Sha3Algorithm;
use crate::Proof; use crate::Proof;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use ethereum_types::H256; use ethereum_types::H256;
use lazy_static::lazy_static; use once_cell::sync::Lazy;
use ssz::{Decode, Encode}; use ssz::{Decode, Encode};
use std::fmt::Debug; use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
@ -28,22 +28,21 @@ impl HashElement for H256 {
} }
} }
lazy_static! { pub static ZERO_HASHES: Lazy<[H256; 64]> = Lazy::new(|| {
static ref ZERO_HASHES: [H256; 64] = { let leaf_zero_hash: H256 = Sha3Algorithm::leaf_raw(&[0u8; 256]);
let leaf_zero_hash: H256 = Sha3Algorithm::leaf(&[0u8; 256]); let mut list = [H256::zero(); 64];
let mut list = [H256::zero(); 64]; list[0] = leaf_zero_hash;
list[0] = leaf_zero_hash; for i in 1..list.len() {
for i in 1..list.len() { list[i] = Sha3Algorithm::parent_raw(&list[i - 1], &list[i - 1]);
list[i] = Sha3Algorithm::parent(&list[i - 1], &list[i - 1]); }
} list
list });
};
}
pub trait Algorithm<E: HashElement> { pub trait Algorithm<E: HashElement> {
fn parent(left: &E, right: &E) -> E; fn parent(left: &E, right: &E) -> E;
fn parent_single(r: &E, height: usize) -> E { fn parent_single(r: &E, height: usize) -> E {
Self::parent(r, &E::end_pad(height)) let right = E::end_pad(height);
Self::parent(r, &right)
} }
fn leaf(data: &[u8]) -> E; fn leaf(data: &[u8]) -> E;
} }

View File

@ -1,23 +1,52 @@
use crate::merkle_tree::ZERO_HASHES;
use crate::{Algorithm, HashElement}; use crate::{Algorithm, HashElement};
use ethereum_types::H256;
use once_cell::sync::Lazy;
use std::collections::BTreeMap;
use tiny_keccak::{Hasher, Keccak}; use tiny_keccak::{Hasher, Keccak};
pub struct Sha3Algorithm {} pub struct Sha3Algorithm {}
impl<E: HashElement> Algorithm<E> for Sha3Algorithm { static ZERO_HASHES_MAP: Lazy<BTreeMap<H256, H256>> = Lazy::new(|| {
fn parent(left: &E, right: &E) -> E { let mut map = BTreeMap::new();
for i in 1..ZERO_HASHES.len() {
map.insert(ZERO_HASHES[i - 1], ZERO_HASHES[i]);
}
map
});
impl Sha3Algorithm {
pub fn parent_raw(left: &H256, right: &H256) -> H256 {
let mut h = Keccak::v256(); let mut h = Keccak::v256();
let mut e = E::null(); let mut e = H256::null();
h.update(left.as_ref()); h.update(left.as_ref());
h.update(right.as_ref()); h.update(right.as_ref());
h.finalize(e.as_mut()); h.finalize(e.as_mut());
e e
} }
fn leaf(data: &[u8]) -> E { pub fn leaf_raw(data: &[u8]) -> H256 {
let mut h = Keccak::v256(); let mut h = Keccak::v256();
let mut e = E::null(); let mut e = H256::null();
h.update(data.as_ref()); h.update(data.as_ref());
h.finalize(e.as_mut()); h.finalize(e.as_mut());
e e
} }
} }
impl Algorithm<H256> for Sha3Algorithm {
fn parent(left: &H256, right: &H256) -> H256 {
if left == right {
if let Some(v) = ZERO_HASHES_MAP.get(left) {
return *v;
}
}
Self::parent_raw(left, right)
}
fn leaf(data: &[u8]) -> H256 {
if *data == [0u8; 256] {
return ZERO_HASHES[0];
}
Self::leaf_raw(data)
}
}