From 0df21e420154c4c8e300a8e7afddcf6aac54bd93 Mon Sep 17 00:00:00 2001 From: Kolby Moroz Liebl <31669092+KolbyML@users.noreply.github.com> Date: Fri, 29 Mar 2024 00:08:49 -0600 Subject: [PATCH 1/7] chore(deps): change ethereum-types to alloy-primitives f --- tree_hash/Cargo.toml | 4 ++-- tree_hash/src/impls.rs | 39 +++++++++++++------------------ tree_hash/src/lib.rs | 10 ++++---- tree_hash/src/merkle_hasher.rs | 18 +++++++------- tree_hash/src/merkleize_padded.rs | 2 +- tree_hash/tests/tests.rs | 2 +- tree_hash_derive/src/lib.rs | 2 +- 7 files changed, 36 insertions(+), 41 deletions(-) diff --git a/tree_hash/Cargo.toml b/tree_hash/Cargo.toml index e3a8ca9..7a688de 100644 --- a/tree_hash/Cargo.toml +++ b/tree_hash/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["ethereum"] categories = ["cryptography::cryptocurrencies"] [dependencies] -ethereum-types = "0.14.1" +alloy-primitives = "0.7.0" ethereum_hashing = "0.6.0" smallvec = "1.6.1" @@ -22,4 +22,4 @@ ethereum_ssz = "0.5" ethereum_ssz_derive = "0.5" [features] -arbitrary = ["ethereum-types/arbitrary"] +arbitrary = ["alloy-primitives/arbitrary"] diff --git a/tree_hash/src/impls.rs b/tree_hash/src/impls.rs index 277aedf..58e8f2e 100644 --- a/tree_hash/src/impls.rs +++ b/tree_hash/src/impls.rs @@ -1,5 +1,6 @@ +use alloy_primitives::{Address, B256, U128, U256}; + use super::*; -use ethereum_types::{H160, H256, U128, U256}; use std::sync::Arc; fn int_to_hash256(int: u64) -> Hash256 { @@ -109,9 +110,7 @@ impl TreeHash for U128 { } fn tree_hash_packed_encoding(&self) -> PackedEncoding { - let mut result = [0; 16]; - self.to_little_endian(&mut result); - PackedEncoding::from_slice(&result) + PackedEncoding::from_slice(self.as_le_slice()) } fn tree_hash_packing_factor() -> usize { @@ -119,9 +118,7 @@ impl TreeHash for U128 { } fn tree_hash_root(&self) -> Hash256 { - let mut result = [0; HASHSIZE]; - self.to_little_endian(&mut result[0..16]); - Hash256::from_slice(&result) + Hash256::right_padding_from(self.as_le_slice()) } } @@ -131,9 +128,7 @@ impl TreeHash for U256 { } fn tree_hash_packed_encoding(&self) -> PackedEncoding { - let mut result = [0; 32]; - self.to_little_endian(&mut result); - PackedEncoding::from_slice(&result) + PackedEncoding::from_slice(self.as_le_slice()) } fn tree_hash_packing_factor() -> usize { @@ -141,20 +136,18 @@ impl TreeHash for U256 { } fn tree_hash_root(&self) -> Hash256 { - let mut result = [0; 32]; - self.to_little_endian(&mut result[..]); - Hash256::from_slice(&result) + Hash256::from_slice(self.as_le_slice()) } } -impl TreeHash for H160 { +impl TreeHash for Address { fn tree_hash_type() -> TreeHashType { TreeHashType::Vector } fn tree_hash_packed_encoding(&self) -> PackedEncoding { let mut result = [0; 32]; - result[0..20].copy_from_slice(self.as_bytes()); + result[0..20].copy_from_slice(self.as_slice()); PackedEncoding::from_slice(&result) } @@ -164,18 +157,18 @@ impl TreeHash for H160 { fn tree_hash_root(&self) -> Hash256 { let mut result = [0; 32]; - result[0..20].copy_from_slice(self.as_bytes()); + result[0..20].copy_from_slice(self.as_slice()); Hash256::from_slice(&result) } } -impl TreeHash for H256 { +impl TreeHash for B256 { fn tree_hash_type() -> TreeHashType { TreeHashType::Vector } fn tree_hash_packed_encoding(&self) -> PackedEncoding { - PackedEncoding::from_slice(self.as_bytes()) + PackedEncoding::from_slice(self.as_slice()) } fn tree_hash_packing_factor() -> usize { @@ -216,8 +209,8 @@ mod test { let false_bytes: Vec = vec![0; 32]; - assert_eq!(true.tree_hash_root().as_bytes(), true_bytes.as_slice()); - assert_eq!(false.tree_hash_root().as_bytes(), false_bytes.as_slice()); + assert_eq!(true.tree_hash_root().as_slice(), true_bytes.as_slice()); + assert_eq!(false.tree_hash_root().as_slice(), false_bytes.as_slice()); } #[test] @@ -229,16 +222,16 @@ mod test { #[test] fn int_to_bytes() { - assert_eq!(int_to_hash256(0).as_bytes(), &[0; 32]); + assert_eq!(int_to_hash256(0).as_slice(), &[0; 32]); assert_eq!( - int_to_hash256(1).as_bytes(), + int_to_hash256(1).as_slice(), &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ); assert_eq!( - int_to_hash256(u64::max_value()).as_bytes(), + int_to_hash256(u64::max_value()).as_slice(), &[ 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/tree_hash/src/lib.rs b/tree_hash/src/lib.rs index 2c0a5c5..18567e4 100644 --- a/tree_hash/src/lib.rs +++ b/tree_hash/src/lib.rs @@ -16,7 +16,7 @@ pub const MERKLE_HASH_CHUNK: usize = 2 * BYTES_PER_CHUNK; pub const MAX_UNION_SELECTOR: u8 = 127; pub const SMALLVEC_SIZE: usize = 32; -pub type Hash256 = ethereum_types::H256; +pub type Hash256 = alloy_primitives::B256; pub type PackedEncoding = SmallVec<[u8; SMALLVEC_SIZE]>; /// Convenience method for `MerkleHasher` which also provides some fast-paths for small trees. @@ -30,7 +30,7 @@ pub fn merkle_root(bytes: &[u8], minimum_leaf_count: usize) -> Hash256 { if leaves == 0 { // If there are no bytes then the hash is always zero. - Hash256::zero() + Hash256::ZERO } else if leaves == 1 { // If there is only one leaf, the hash is always those leaf bytes padded out to 32-bytes. let mut hash = [0; HASHSIZE]; @@ -64,7 +64,7 @@ pub fn mix_in_length(root: &Hash256, length: usize) -> Hash256 { let mut length_bytes = [0; BYTES_PER_CHUNK]; length_bytes[0..usize_len].copy_from_slice(&length.to_le_bytes()); - Hash256::from_slice(ðereum_hashing::hash32_concat(root.as_bytes(), &length_bytes)[..]) + Hash256::from_slice(ðereum_hashing::hash32_concat(root.as_slice(), &length_bytes)[..]) } /// Returns `Some(root)` created by hashing `root` and `selector`, if `selector <= @@ -88,7 +88,7 @@ pub fn mix_in_selector(root: &Hash256, selector: u8) -> Option { let mut chunk = [0; BYTES_PER_CHUNK]; chunk[0] = selector; - let root = ethereum_hashing::hash32_concat(root.as_bytes(), &chunk); + let root = ethereum_hashing::hash32_concat(root.as_slice(), &chunk); Some(Hash256::from_slice(&root)) } @@ -201,7 +201,7 @@ mod test { }; assert_eq!( - mix_in_length(&Hash256::from_slice(&[42; BYTES_PER_CHUNK]), 42).as_bytes(), + mix_in_length(&Hash256::from_slice(&[42; BYTES_PER_CHUNK]), 42).as_slice(), &hash[..] ); } diff --git a/tree_hash/src/merkle_hasher.rs b/tree_hash/src/merkle_hasher.rs index c188ba5..3ea841d 100644 --- a/tree_hash/src/merkle_hasher.rs +++ b/tree_hash/src/merkle_hasher.rs @@ -280,7 +280,7 @@ impl MerkleHasher { } else if self.next_leaf == 1 { // The next_leaf can only be 1 if the tree has a depth of one. If have been no // leaves supplied, assume a root of zero. - break Ok(Hash256::zero()); + break Ok(Hash256::ZERO); } else { // The only scenario where there are (a) no half nodes and (b) a tree of depth // two or more is where no leaves have been supplied at all. @@ -359,6 +359,8 @@ impl MerkleHasher { #[cfg(test)] mod test { + use alloy_primitives::U256; + use super::*; use crate::merkleize_padded; @@ -376,7 +378,7 @@ mod test { fn compare_with_reference(leaves: &[Hash256], depth: usize) { let reference_bytes = leaves .iter() - .flat_map(|hash| hash.as_bytes()) + .flat_map(|hash| hash.as_slice()) .copied() .collect::>(); @@ -385,7 +387,7 @@ mod test { let merklizer_root_32_bytes = { let mut m = MerkleHasher::with_depth(depth); for leaf in leaves.iter() { - m.write(leaf.as_bytes()).expect("should process leaf"); + m.write(leaf.as_slice()).expect("should process leaf"); } m.finish().expect("should finish") }; @@ -426,7 +428,7 @@ mod test { /// of leaves and a depth. fn compare_reference_with_len(leaves: u64, depth: usize) { let leaves = (0..leaves) - .map(Hash256::from_low_u64_be) + .map(|leaf| Hash256::from(U256::from(leaf))) .collect::>(); compare_with_reference(&leaves, depth) } @@ -435,13 +437,13 @@ mod test { /// results. fn compare_new_with_leaf_count(num_leaves: u64, depth: usize) { let leaves = (0..num_leaves) - .map(Hash256::from_low_u64_be) + .map(|leaf| Hash256::from(U256::from(leaf))) .collect::>(); let from_depth = { let mut m = MerkleHasher::with_depth(depth); for leaf in leaves.iter() { - m.write(leaf.as_bytes()).expect("should process leaf"); + m.write(leaf.as_slice()).expect("should process leaf"); } m.finish() }; @@ -449,7 +451,7 @@ mod test { let from_num_leaves = { let mut m = MerkleHasher::with_leaves(num_leaves as usize); for leaf in leaves.iter() { - m.process_leaf(leaf.as_bytes()) + m.process_leaf(leaf.as_slice()) .expect("should process leaf"); } m.finish() @@ -495,7 +497,7 @@ mod test { #[test] fn with_0_leaves() { let hasher = MerkleHasher::with_leaves(0); - assert_eq!(hasher.finish().unwrap(), Hash256::zero()); + assert_eq!(hasher.finish().unwrap(), Hash256::ZERO); } #[test] diff --git a/tree_hash/src/merkleize_padded.rs b/tree_hash/src/merkleize_padded.rs index 007155e..74d92bc 100644 --- a/tree_hash/src/merkleize_padded.rs +++ b/tree_hash/src/merkleize_padded.rs @@ -280,7 +280,7 @@ mod test { let input = vec![0; 10 * BYTES_PER_CHUNK]; let min_nodes = 2usize.pow(ZERO_HASHES_MAX_INDEX as u32); assert_eq!( - merkleize_padded(&input, min_nodes).as_bytes(), + merkleize_padded(&input, min_nodes).as_slice(), get_zero_hash(ZERO_HASHES_MAX_INDEX) ); } diff --git a/tree_hash/tests/tests.rs b/tree_hash/tests/tests.rs index b831614..352f223 100644 --- a/tree_hash/tests/tests.rs +++ b/tree_hash/tests/tests.rs @@ -44,7 +44,7 @@ fn mix_in_selector(a: Hash256, selector: u8) -> Hash256 { let mut b = [0; 32]; b[0] = selector; - Hash256::from_slice(ðereum_hashing::hash32_concat(a.as_bytes(), &b)) + Hash256::from_slice(ðereum_hashing::hash32_concat(a.as_slice(), &b)) } fn u8_hash_concat(v1: u8, v2: u8) -> Hash256 { diff --git a/tree_hash_derive/src/lib.rs b/tree_hash_derive/src/lib.rs index 21ff324..3358aa4 100644 --- a/tree_hash_derive/src/lib.rs +++ b/tree_hash_derive/src/lib.rs @@ -162,7 +162,7 @@ fn tree_hash_derive_struct(item: &DeriveInput, struct_data: &DataStruct) -> Toke let mut hasher = tree_hash::MerkleHasher::with_leaves(#num_leaves); #( - hasher.write(self.#idents.tree_hash_root().as_bytes()) + hasher.write(self.#idents.tree_hash_root().as_slice()) .expect("tree hash derive should not apply too many leaves"); )* From 0d0607e25c82afbf6444728f62f81b30a8c612e4 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 14 Aug 2024 14:44:36 +1000 Subject: [PATCH 2/7] Update sigp deps --- tree_hash/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tree_hash/Cargo.toml b/tree_hash/Cargo.toml index 7a688de..5debd90 100644 --- a/tree_hash/Cargo.toml +++ b/tree_hash/Cargo.toml @@ -12,14 +12,14 @@ categories = ["cryptography::cryptocurrencies"] [dependencies] alloy-primitives = "0.7.0" -ethereum_hashing = "0.6.0" +ethereum_hashing = "0.7.0" smallvec = "1.6.1" [dev-dependencies] rand = "0.8.5" tree_hash_derive = { path = "../tree_hash_derive", version = "0.6.0" } -ethereum_ssz = "0.5" -ethereum_ssz_derive = "0.5" +ethereum_ssz = "0.6" +ethereum_ssz_derive = "0.6" [features] arbitrary = ["alloy-primitives/arbitrary"] From eac7f6353d3ec27e9146ff85e210b01882f54f10 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 14 Aug 2024 15:15:15 +1000 Subject: [PATCH 3/7] Use to_le_bytes --- tree_hash/src/impls.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tree_hash/src/impls.rs b/tree_hash/src/impls.rs index 58e8f2e..53d28f4 100644 --- a/tree_hash/src/impls.rs +++ b/tree_hash/src/impls.rs @@ -1,6 +1,5 @@ -use alloy_primitives::{Address, B256, U128, U256}; - use super::*; +use alloy_primitives::{Address, B256, U128, U256}; use std::sync::Arc; fn int_to_hash256(int: u64) -> Hash256 { @@ -110,7 +109,7 @@ impl TreeHash for U128 { } fn tree_hash_packed_encoding(&self) -> PackedEncoding { - PackedEncoding::from_slice(self.as_le_slice()) + PackedEncoding::from_slice(&self.to_le_bytes::<{ Self::BYTES }>()) } fn tree_hash_packing_factor() -> usize { @@ -118,7 +117,7 @@ impl TreeHash for U128 { } fn tree_hash_root(&self) -> Hash256 { - Hash256::right_padding_from(self.as_le_slice()) + Hash256::right_padding_from(&self.to_le_bytes::<{ Self::BYTES }>()) } } @@ -128,7 +127,7 @@ impl TreeHash for U256 { } fn tree_hash_packed_encoding(&self) -> PackedEncoding { - PackedEncoding::from_slice(self.as_le_slice()) + PackedEncoding::from(self.to_le_bytes::<{ Self::BYTES }>()) } fn tree_hash_packing_factor() -> usize { @@ -136,7 +135,7 @@ impl TreeHash for U256 { } fn tree_hash_root(&self) -> Hash256 { - Hash256::from_slice(self.as_le_slice()) + Hash256::from(self.to_le_bytes::<{ Self::BYTES }>()) } } From 76f3511309d3743a20ca17da7751dc52de14a5f3 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 14 Aug 2024 16:00:38 +1000 Subject: [PATCH 4/7] Add packed encoding test --- tree_hash/tests/tests.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tree_hash/tests/tests.rs b/tree_hash/tests/tests.rs index 352f223..2284999 100644 --- a/tree_hash/tests/tests.rs +++ b/tree_hash/tests/tests.rs @@ -126,3 +126,22 @@ fn variable_union() { mix_in_selector(u8_hash_concat(2, 1), 1) ); } + +/// Test that the packed encodings for different types are equal. +#[test] +fn packed_encoding_example() { + let canonical = 0xfff0eee0ddd0ccc0_u64.tree_hash_packed_encoding(); + let encodings = [ + (0xccc0_u16.tree_hash_packed_encoding(), 0), + (0xddd0_u16.tree_hash_packed_encoding(), 2), + (0xeee0_u16.tree_hash_packed_encoding(), 4), + (0xfff0_u16.tree_hash_packed_encoding(), 6), + ]; + for (i, (encoding, offset)) in encodings.into_iter().enumerate() { + assert_eq!( + &encoding[..], + &canonical[offset..offset + encoding.len()], + "encoding {i} is wrong" + ); + } +} From 37a207e420bb4a76b611c5579c7899eb8c90e150 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Thu, 15 Aug 2024 11:30:56 +1000 Subject: [PATCH 5/7] Make coverage informational --- .github/workflows/test-suite.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index e5daf05..9fdfb7b 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -49,3 +49,4 @@ jobs: with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} + informational: true From 4763fd8dda77a4fa06a14c0717a400f21eca4617 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Thu, 15 Aug 2024 11:53:19 +1000 Subject: [PATCH 6/7] Farm coverage --- tree_hash/tests/tests.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/tree_hash/tests/tests.rs b/tree_hash/tests/tests.rs index 2284999..c190426 100644 --- a/tree_hash/tests/tests.rs +++ b/tree_hash/tests/tests.rs @@ -1,3 +1,4 @@ +use alloy_primitives::{U128, U256}; use ssz_derive::Encode; use tree_hash::{Hash256, MerkleHasher, PackedEncoding, TreeHash, BYTES_PER_CHUNK}; use tree_hash_derive::TreeHash; @@ -130,12 +131,30 @@ fn variable_union() { /// Test that the packed encodings for different types are equal. #[test] fn packed_encoding_example() { - let canonical = 0xfff0eee0ddd0ccc0_u64.tree_hash_packed_encoding(); + let val = 0xfff0eee0ddd0ccc0bbb0aaa099908880_u128; + let canonical = U256::from(val).tree_hash_packed_encoding(); let encodings = [ - (0xccc0_u16.tree_hash_packed_encoding(), 0), - (0xddd0_u16.tree_hash_packed_encoding(), 2), - (0xeee0_u16.tree_hash_packed_encoding(), 4), - (0xfff0_u16.tree_hash_packed_encoding(), 6), + (0x8880_u16.tree_hash_packed_encoding(), 0), + (0x9990_u16.tree_hash_packed_encoding(), 2), + (0xaaa0_u16.tree_hash_packed_encoding(), 4), + (0xbbb0_u16.tree_hash_packed_encoding(), 6), + (0xccc0_u16.tree_hash_packed_encoding(), 8), + (0xddd0_u16.tree_hash_packed_encoding(), 10), + (0xeee0_u16.tree_hash_packed_encoding(), 12), + (0xfff0_u16.tree_hash_packed_encoding(), 14), + (U128::from(val).tree_hash_packed_encoding(), 0), + (U128::from(0).tree_hash_packed_encoding(), 16), + ( + Hash256::from_slice(U256::from(val).as_le_slice()).tree_hash_packed_encoding(), + 0, + ), + ( + Hash256::from_slice(U256::from(val).as_le_slice()) + .tree_hash_root() + .to_vec() + .into(), + 0, + ), ]; for (i, (encoding, offset)) in encodings.into_iter().enumerate() { assert_eq!( From da23798038e35526d2b6efe2fc52442974b76a5f Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Thu, 15 Aug 2024 12:21:29 +1000 Subject: [PATCH 7/7] More coverage --- tree_hash/tests/tests.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tree_hash/tests/tests.rs b/tree_hash/tests/tests.rs index c190426..348a185 100644 --- a/tree_hash/tests/tests.rs +++ b/tree_hash/tests/tests.rs @@ -1,4 +1,4 @@ -use alloy_primitives::{U128, U256}; +use alloy_primitives::{Address, U128, U160, U256}; use ssz_derive::Encode; use tree_hash::{Hash256, MerkleHasher, PackedEncoding, TreeHash, BYTES_PER_CHUNK}; use tree_hash_derive::TreeHash; @@ -151,10 +151,22 @@ fn packed_encoding_example() { ( Hash256::from_slice(U256::from(val).as_le_slice()) .tree_hash_root() - .to_vec() + .0 .into(), 0, ), + (U256::from(val).tree_hash_root().0.into(), 0), + ( + Address::from(U160::from(val).to_le_bytes::<20>()) + .tree_hash_root() + .0 + .into(), + 0, + ), + ( + Address::from(U160::from(val).to_le_bytes::<20>()).tree_hash_packed_encoding(), + 0, + ), ]; for (i, (encoding, offset)) in encodings.into_iter().enumerate() { assert_eq!(