Skip to content

Commit

Permalink
feat: support hashtree sha256 lib
Browse files Browse the repository at this point in the history
  • Loading branch information
estensen committed Dec 7, 2024
1 parent 74acc3d commit 850560d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
2 changes: 2 additions & 0 deletions ssz-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ exclude = ["tests/data"]

[features]
default = ["serde", "std"]
hashtree = ["dep:hashtree"]
std = ["bitvec/default", "sha2/default", "alloy-primitives/default"]
sha2-asm = ["sha2/asm"]
serde = ["dep:serde", "alloy-primitives/serde"]

[dependencies]
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
rayon = "1.10"
hashtree = { version = "0.2.0", optional = true, package = "hashtree-rs" }
ssz_rs_derive = { path = "../ssz-rs-derive", version = "0.9.0" }
sha2 = { version = "0.9.8", default-features = false }
serde = { version = "1.0", default-features = false, features = [
Expand Down
44 changes: 41 additions & 3 deletions ssz-rs/src/merkleization/hasher.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
#[cfg(feature = "hashtree")]
use std::sync::Once;

use super::BYTES_PER_CHUNK;

#[cfg(not(feature = "hashtree"))]
use ::sha2::{Digest, Sha256};

#[cfg(feature = "hashtree")]
static INIT: Once = Once::new();

#[inline]
#[cfg(feature = "hashtree")]
fn hash_chunks_hashtree(left: impl AsRef<[u8]>, right: impl AsRef<[u8]>) -> [u8; BYTES_PER_CHUNK] {
// Initialize the hashtree library (once)
INIT.call_once(|| {
hashtree::init();
});

let mut out = [0u8; BYTES_PER_CHUNK];

let mut chunks = [0u8; 2 * BYTES_PER_CHUNK];

chunks[..BYTES_PER_CHUNK].copy_from_slice(left.as_ref());
chunks[BYTES_PER_CHUNK..].copy_from_slice(right.as_ref());

// NOTE: hashtree "chunks" are 64 bytes long, not 32. That's why we
// specify "1" as the chunk count.
hashtree::hash(&mut out, &chunks, 1);

out
}

// Hashes two chunks together using sha256
// Defaults to sha256
// sha256-asm can be enabled with the "sha2-asm" feature flag
#[inline]
#[cfg(not(feature = "hashtree"))]
fn hash_chunks_sha256(left: impl AsRef<[u8]>, right: impl AsRef<[u8]>) -> [u8; BYTES_PER_CHUNK] {
let mut hasher = Sha256::new();
hasher.update(left.as_ref());
Expand All @@ -13,11 +46,16 @@ fn hash_chunks_sha256(left: impl AsRef<[u8]>, right: impl AsRef<[u8]>) -> [u8; B
/// Function that hashes 2 [BYTES_PER_CHUNK] (32) len byte slices together. Depending on the feature
/// flags, this will either use:
/// - sha256 (default)
/// - TODO: sha256 with assembly support (with the "sha2-asm" feature flag)
/// - TODO: hashtree (with the "hashtree" feature flag)
/// - sha256 with assembly support (with the "sha2-asm" feature flag)
/// - hashtree (with the "hashtree" feature flag)
#[inline]
pub fn hash_chunks(left: impl AsRef<[u8]>, right: impl AsRef<[u8]>) -> [u8; BYTES_PER_CHUNK] {
debug_assert!(left.as_ref().len() == BYTES_PER_CHUNK);
debug_assert!(right.as_ref().len() == BYTES_PER_CHUNK);
hash_chunks_sha256(left, right)

#[cfg(feature = "hashtree")]
return hash_chunks_hashtree(left, right);

#[cfg(not(feature = "hashtree"))]
return hash_chunks_sha256(left, right);
}

0 comments on commit 850560d

Please sign in to comment.