Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tree_hash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ typenum = "1.12.0"
rand = "0.8.5"
tree_hash_derive = { path = "../tree_hash_derive", version = "0.10.0" }
ethereum_ssz_derive = "0.9.0"
ssz_types = "0.11.0"

[features]
arbitrary = ["alloy-primitives/arbitrary"]
1 change: 1 addition & 0 deletions tree_hash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod impls;
mod merkle_hasher;
mod merkleize_padded;
mod merkleize_standard;
pub mod prototype;

pub use merkle_hasher::{Error, MerkleHasher};
pub use merkleize_padded::merkleize_padded;
Expand Down
90 changes: 90 additions & 0 deletions tree_hash/src/prototype.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use crate::{Hash256, TreeHash, TreeHashType, BYTES_PER_CHUNK};
use std::marker::PhantomData;

pub enum Error {
Oops,
}

pub trait MerkleProof: TreeHash {
fn compute_proof<F>(&self) -> Result<Vec<Hash256>, Error>
where
Self: Resolve<F>,
{
let gindex = <Self as Resolve<F>>::gindex(1);
self.compute_proof_for_gindex(gindex)

Check warning on line 14 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L13-L14

Added lines #L13 - L14 were not covered by tests
}

fn compute_proof_for_gindex(&self, gindex: usize) -> Result<Vec<Hash256>, Error>;
}

// A path is a sequence of field accesses like `self.foo.bar`.
//
// We can resolve these at compile time, because we're sickos.
pub struct Path<First, Rest>(PhantomData<(First, Rest)>);

// The field trait is implemented for all struct fields.
//
// It provides conversion from a named field type to a numeric field index.
pub trait Field {
const NUM_FIELDS: usize;
const INDEX: usize;
}

// If T implements Resolve<Field> it means T has a field named Field of type Output.
pub trait Resolve<Field> {
type Output;

fn gindex(parent_index: usize) -> usize;
}

// This impl defines how paths are resolved and converted to gindices.
impl<T, First, Rest> Resolve<Path<First, Rest>> for T
where
Self: Resolve<First>,
First: Field,
<Self as Resolve<First>>::Output: Resolve<Rest>,
{
type Output = <<Self as Resolve<First>>::Output as Resolve<Rest>>::Output;

fn gindex(parent_index: usize) -> usize {

Check warning on line 49 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L49

Added line #L49 was not covered by tests
// From `get_generalized_index`:
// https://github.com/ethereum/consensus-specs/blob/dev/ssz/merkle-proofs.md#ssz-object-to-index
let new_parent_index = <Self as Resolve<First>>::gindex(parent_index);
<Self as Resolve<First>>::Output::gindex(new_parent_index)

Check warning on line 53 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L52-L53

Added lines #L52 - L53 were not covered by tests
}
}

// FIXME: we don't currently enforce I < N at compile-time
pub struct VecIndex<const I: usize, const N: usize>;

impl<const I: usize, const N: usize> Field for VecIndex<I, N> {
const NUM_FIELDS: usize = N;
const INDEX: usize = I;
}

pub fn item_length<T: TreeHash>() -> usize {
if T::tree_hash_type() == TreeHashType::Basic {
BYTES_PER_CHUNK / T::tree_hash_packing_factor()

Check warning on line 67 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L65-L67

Added lines #L65 - L67 were not covered by tests
} else {
BYTES_PER_CHUNK

Check warning on line 69 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L69

Added line #L69 was not covered by tests
}
}

pub fn vector_chunk_count<T: TreeHash>(length: usize) -> usize {
(length * item_length::<T>()).div_ceil(BYTES_PER_CHUNK)

Check warning on line 74 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L73-L74

Added lines #L73 - L74 were not covered by tests
}

pub fn get_vector_item_position<T: TreeHash>(index: usize) -> usize {
let start = index * item_length::<T>();
start / BYTES_PER_CHUNK

Check warning on line 79 in tree_hash/src/prototype.rs

View check run for this annotation

Codecov / codecov/patch

tree_hash/src/prototype.rs#L77-L79

Added lines #L77 - L79 were not covered by tests
}

/*
impl TreeHash for u64 {
fn get_field(&self, _: usize) -> Result<&dyn TreeHash, Error> {
Err(Error::Oops)
}

fn merkle_proof(&self)
}
*/
Loading