Prove inclusion of subtree into another tree #119
Replies: 5 comments 2 replies
-
Do we have this data? I was under the impression that chains were signing the
What does In the pseudo-code, I think there's a missing check that the two nodes at
As @invocamanman noted - we don't need to binary-decompose the index given that we already have the pivots in |
Beta Was this translation helpful? Give feedback.
-
The bridge service provides the Merkle proofs for all claims/exits so it has access to all the leaves and to the
The frontier is a set (of size max
I'm not sure this is needed because if the prover takes 2 different
Could you explain what you mean by pivots?
I'm probably misunderstanding what you mean, but since the |
Beta Was this translation helpful? Give feedback.
-
Want to close the loop here - fixing the above pseudo-code: # Formerly: Generate the proof that the tree structures are preserved up to the same leaf
# This method didn't have sufficient information to compute the merkle proof of the leaf at index leaf_count_a - 1 in B
# The frontier already serves as the Merkle path for the right-most leaf in A, so it doesn't make sense to compute it
# Instead, let's just delete
# def generate_proof(leaf_count_A, frontier_A, leaf_count_B, frontier_B):
# Verifies that A is a subtree of B
# Note that merkle_proof_B is the inclusion proof of the node at position leaf_count_A in B
def verify_subtree(leaf_count_A, frontier_A, root_A, merkle_proof_B, root_B):
# Only reconstruct the root for A, verifying that all leaves with index >= leaf_count_A are empty
# Reference the from_parts and get_root methods in the Rust implementation of the LET
if root_A != get_root(frontier_A, leaf_count_A):
return False
# Verify individual Merkle proof for B
# Leaf should be included in the proof, don't need a separate var
if not verify_merkle_proof(proof_B, root_B):
return False
# We don't technically need the merkle path from A - I think that we just need to verify that every element of
# frontier_A shows up in the merkle proof for the leaf at position leaf_count_A in B.
# Remove position = leaf_count_a - 1 ---- should be the 1-indexed position of the leaf, not the 0-indexed position.
# If we're following the Rust implementation of the LET, then the bit was backward.
# The nice thing is that this version will enforce that the nodes at position are identical in both trees
# Too lazy to look up python range syntax - I know that 0..TREE_DEPTH is not correct, but it'll be in rust anyway
# Note that I didn't find a definition of the Merkle Path in the Rust implementation, so indices may need to be adjusted.
for i in 0..TREE_DEPTH:
if get_bit_at(leaf_count_A, i) == 1 and frontier_A[i] != proof_B[i]:
return False
return True |
Beta Was this translation helpful? Give feedback.
-
The
I don't think this works, I think we need to compare
In both cases the frontier and Merkle path are not the same at the 1-indices and so the check would fail. That's why we need to compare the frontier given the address of the leaf in the tree and not the leaf count i.e.,
Now we have the check that passes at the 1-indices. |
Beta Was this translation helpful? Give feedback.
-
Indeed - it consists of the roots of all maximal power-of-2-sized subtrees. But you don't construct it properly in your examples. For instance, the frontier for the tree of max 8 leaves consisting of 5 leaves has the following structure:
This might be a source of the confusion. I linked the code in my last comment, but it's here. For subtree inclusion, it suffices to show that every non-zero entry in the frontier of A is contained in B. Your proposal to bit-decompose To your example, for the 5th leaf ( For the 6th leaf (
We want to check Your example (bit-decomposing 5) checks We can see in simpler examples, ex n=8, why bit-decomposing
In a comment on my last post, I did handwave the indexing of the path in B a bit as it wasn't defined, but when we implement we can make sure that it's indexed properly. The important point is that bit-decomposing |
Beta Was this translation helpful? Give feedback.
-
This discussion continues from #115, where the topic of subtree inclusion has been started.
To keep the original thread focused, let's use this discussion here on the subtree inclusion!
I don't think we need this step as the first step in the proof would be to use the
leaf_count
andfrontier
of the respective trees to recompute the root hashes in both trees against which the Merkle proofs for the same leaf will be generated, and if the root oftree_A
can be properly derived from itsleaf_count
andfrontier
, it means that the leaf at indexk = leaf_count - 1
we are trying to prove inclusion of is the last element oftree_A
The rest follows nicely as briefly discussed face to face with @bpfarmer and @hadjiszs earlier this week.
Below is the pseudo code:
Beta Was this translation helpful? Give feedback.
All reactions