-
Notifications
You must be signed in to change notification settings - Fork 28
Generate proofs for gindices #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -210,6 +210,14 @@ where | |
} | ||
} | ||
|
||
impl<T, N: Unsigned> tree_hash::prototype::MerkleProof for FixedVector<T, N> | ||
where | ||
T: tree_hash::TreeHash | ||
{ | ||
fn compute_proof_for_gindex(&self, gindex: usize) -> Result<Vec<Hash256>, tree_hash::prototype::Error>{ | ||
crate::tree_hash::generate_proof_for_vec::<T, N>(&self.vec, gindex) | ||
} | ||
} | ||
impl<T, N: Unsigned> ssz::Encode for FixedVector<T, N> | ||
where | ||
T: ssz::Encode, | ||
|
@@ -569,4 +577,74 @@ mod test { | |
let result: Result<FixedVector<u64, U4>, _> = serde_json::from_value(json); | ||
assert!(result.is_ok()); | ||
} | ||
|
||
#[test] | ||
fn merkle_proof_basic() { | ||
use tree_hash::prototype::MerkleProof; | ||
use typenum::U4; | ||
|
||
let vec: FixedVector<u64, U4> = FixedVector::new(vec![1, 2, 3, 4]).unwrap(); | ||
|
||
let proof = vec.compute_proof_for_gindex(1); | ||
assert!(proof.is_ok()); | ||
if let Ok(proof) = proof { | ||
assert_eq!(proof.len(), 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the proof should probably be length 1 here, and be exactly equal to the tree hash root? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was assuming that no one would ever request for a proof for the root. it's just a small change I can add that. do you think we should add it? |
||
} | ||
|
||
let proof = vec.compute_proof_for_gindex(2); | ||
assert!(proof.is_ok()); | ||
if let Ok(proof) = proof { | ||
assert!(!proof.is_empty()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could assert something more detailed here:
Alternatively we should write a function to check a merkle proof given a gindex, a leaf and a root There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could probably use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (would have to put these tests in Lighthouse, until LEAP happens and all these libraries are co-located in one repo) |
||
} | ||
|
||
let proof = vec.compute_proof_for_gindex(0); | ||
assert!(proof.is_err()); | ||
} | ||
|
||
#[test] | ||
fn merkle_proof_complex_types() { | ||
use tree_hash::prototype::MerkleProof; | ||
use typenum::U2; | ||
|
||
let a1 = A { a: 1, b: 2 }; | ||
let a2 = A { a: 3, b: 4 }; | ||
let vec: FixedVector<A, U2> = FixedVector::new(vec![a1, a2]).unwrap(); | ||
|
||
let proof = vec.compute_proof_for_gindex(2); | ||
assert!(proof.is_ok()); | ||
if let Ok(proof) = proof { | ||
assert!(!proof.is_empty()); | ||
|
||
for hash in proof { | ||
assert_eq!(hash.len(), 32); | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn merkle_proof_tree_depth() { | ||
use tree_hash::prototype::MerkleProof; | ||
use typenum::U8; | ||
|
||
let vec: FixedVector<u64, U8> = FixedVector::new(vec![1, 2, 3, 4, 5, 6, 7, 8]).unwrap(); | ||
|
||
let gindices = vec![1, 2, 3, 4, 5, 6, 7, 8, 15, 16]; | ||
|
||
for gindex in gindices { | ||
let proof = vec.compute_proof_for_gindex(gindex); | ||
Comment on lines
+633
to
+634
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could iterate through |
||
|
||
if gindex == 0 { | ||
assert!(proof.is_err()); | ||
} else if gindex == 1 { | ||
if let Ok(proof) = proof { | ||
assert_eq!(proof.len(), 0); | ||
} | ||
} else { | ||
if let Ok(proof) = proof { | ||
let expected_depth = 64 - gindex.leading_zeros() as usize - 1; | ||
assert_eq!(proof.len(), expected_depth); | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we want to be able to combine proofs in a nested way. E.g.
List<List<u64, U10>, U20>
should work.