-
Notifications
You must be signed in to change notification settings - Fork 40
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
feat: merkle tree verifier implementation to support all numbers of leaves #253
Conversation
@coderabbitai review |
WalkthroughThe changes primarily revolve around the enhancement of the Changes
TipsChat with CodeRabbit Bot (
|
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.
Review Status
Actionable comments generated: 1
Configuration used: CodeRabbit UI
Files selected for processing (5)
- src/lib/tree/Utils.sol (1 hunks)
- src/lib/tree/binary/BinaryMerkleTree.sol (1 hunks)
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol (2 hunks)
- src/lib/tree/namespace/NamespaceMerkleTree.sol (1 hunks)
- wrappers/Blobstream.sol/wrapper.go (1 hunks)
Files not summarized due to errors (1)
- wrappers/Blobstream.sol/wrapper.go: Error: Message exceeds token limit
Files not reviewed due to errors (1)
- wrappers/Blobstream.sol/wrapper.go (Error: diff too large)
Files skipped from review due to trivial changes (3)
- src/lib/tree/Utils.sol
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol
- src/lib/tree/namespace/NamespaceMerkleTree.sol
Additional comments: 2
src/lib/tree/binary/BinaryMerkleTree.sol (2)
42-47: The
verify
function has been updated to handle cases where the number of leaves is 0 or 1. It checks the length ofsideNodes
to ensure it is correct. The function also computes the root hash by calling thecomputeRootHash
function.58-78: The
computeRootHash
function has been updated to handle cases where the number of leaves is 0 or 1. It checks the length ofsideNodes
to ensure it is correct. The function also recursively computes the root hash by splitting the tree into left and right subtrees.
…ix-merkle-implementatio
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- src/lib/tree/binary/BinaryMerkleTree.sol (1 hunks)
Additional comments: 3
src/lib/tree/binary/BinaryMerkleTree.sol (3)
42-47: The
verify
function has been updated to use the newcomputeRootHash
function. Ensure that the new function behaves as expected and doesn't introduce any regressions.53-78: The
computeRootHash
function has been updated to handle cases with 0 or 1 leaves and to recursively compute the root hash by splitting the tree into left and right subtrees. This is a significant change and should be thoroughly tested.80-93: The
slice
function has been added to create a slice ofbytes32
from a given range of elements in an array. This function should be tested to ensure it behaves as expected.
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- src/lib/tree/binary/BinaryMerkleTree.sol (1 hunks)
Additional comments: 3
src/lib/tree/binary/BinaryMerkleTree.sol (3)
42-48: The
verify
function has been updated to use the newcomputeRootHash
function. Ensure that the function is being called correctly and that the returned value is being used as expected.53-78: The
computeRootHash
function has been updated to handle cases with 0 or 1 leaves and to recursively compute the root hash by splitting the tree into left and right subtrees. This is a significant change and should be thoroughly tested.80-96: The new
slice
function creates a slice ofbytes32
from a given range of elements in an array. This function should be tested to ensure it behaves as expected, especially in edge cases (e.g., when_begin
is equal to_end
, when_begin
is greater than_end
, when_begin
or_end
are out of bounds, etc.).
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.
left one comment for adding tests for false positives, other than that this implementation makes sense to me
BinaryMerkleProof memory proof = BinaryMerkleProof(sideNodes, key, numLeaves); | ||
bytes memory data = hex"03"; | ||
bool isValid = BinaryMerkleTree.verify(root, proof, data); | ||
assertTrue(isValid); |
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.
can we also include a test where we expect the verification to fail?
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.
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.
It was a good idea to add invalid proofs 👍 Found a bug :D
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.
actually not a bug, but an edge case:
Assume you have a merkle tree of 5 leaves. When creating the proof, if you set the number of leaves = [5, 8]
, the proof going to pass even if {6, 7, 8}
are invalid values because with those numbers of leaves, the verifier will behave the same.
Verified with the implementation of tendermint and it also has the same behaviour.
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.
Could you expand on this? What does number of leaves = [5, 8]
mean? That's a range, not a number.
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.
My bad, i meant any number from that range will result in a valid proof. The verifier won't complain about it.
So if you have a tree of 5 leaves, and in the proof you set the total number to 7, the proof is still considered valid
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.
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (3)
- src/lib/tree/binary/BinaryMerkleTree.sol (1 hunks)
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol (2 hunks)
- wrappers/Blobstream.sol/wrapper.go (1 hunks)
Files not summarized due to errors (1)
- wrappers/Blobstream.sol/wrapper.go: Error: Message exceeds token limit
Files not reviewed due to errors (1)
- wrappers/Blobstream.sol/wrapper.go (Error: diff too large)
Files skipped from review due to trivial changes (1)
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol
Additional comments: 3
src/lib/tree/binary/BinaryMerkleTree.sol (3)
42-48: The
verify
function has been updated to handle the case when the number of leaves is 0 or 1. It checks for the correct number of inner hashes and returns the root hash accordingly. This is a good update as it makes the function more robust and able to handle edge cases.53-78: The
computeRootHash
function has been updated to handle the case when the number of leaves is 0 or 1. It now checks for the correct number of inner hashes and returns the root hash accordingly. This is a good update as it makes the function more robust and able to handle edge cases.80-99: The
slice
function has been added to create a slice ofbytes32
from a given range of elements in an array. This function is useful for creating subarrays from a larger array, which can be useful in many different contexts. However, it's important to ensure that the_begin
and_end
parameters are validated to prevent out-of-bounds errors.
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol (2 hunks)
Files skipped from review due to trivial changes (1)
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- wrappers/Blobstream.sol/wrapper.go (1 hunks)
Files not summarized due to errors (1)
- wrappers/Blobstream.sol/wrapper.go: Error: Message exceeds token limit
Files not reviewed due to errors (1)
- wrappers/Blobstream.sol/wrapper.go (Error: diff too large)
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- wrappers/Blobstream.sol/wrapper.go (1 hunks)
Files not summarized due to errors (1)
- wrappers/Blobstream.sol/wrapper.go: Error: Message exceeds token limit
Files not reviewed due to errors (1)
- wrappers/Blobstream.sol/wrapper.go (Error: diff too large)
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.
lgtm. given the importance of this lib I think it would be worth setting up a fuzzer.
|
…ix-merkle-implementatio
# Conflicts: # wrappers/Blobstream.sol/wrapper.go
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- src/lib/tree/binary/test/BinaryMerkleTree.t.sol (4 hunks)
Additional comments: 12
src/lib/tree/binary/test/BinaryMerkleTree.t.sol (12)
2-8: The new import
import "forge-std/Vm.sol";
is added. Ensure that this library is available in the project dependencies.107-120: The new test function
testVerifyLeafTwoOfEight
is added. It seems to be testing the verification of the second leaf in a Merkle tree with eight leaves.122-135: The new test function
testVerifyLeafThreeOfEight
is added. It seems to be testing the verification of the third leaf in a Merkle tree with eight leaves.173-186: The new test function
testVerifyProofOfFiveLeaves
is added. It seems to be testing the verification of a proof with five leaves.188-202: The new test function
testVerifyInvalidProofRoot
is added. It seems to be testing the verification of a proof with an invalid root.204-218: The new test function
testVerifyInvalidProofKey
is added. It seems to be testing the verification of a proof with an invalid key.220-234: The new test function
testVerifyInvalidProofNumberOfLeaves
is added. It seems to be testing the verification of a proof with an invalid number of leaves.236-250: The new test function
testVerifyInvalidProofSideNodes
is added. It seems to be testing the verification of a proof with invalid side nodes.252-266: The new test function
testVerifyInvalidProofData
is added. It seems to be testing the verification of a proof with invalid data.268-279: The new test function
testValidSlice
is added. It seems to be testing the slicing of an array with valid indices.281-290: The new test function
testInvalidSliceBeginEnd
is added. It seems to be testing the slicing of an array with invalid indices where the beginning index is greater than the end index.292-301: The new test function
testOutOfBoundsSlice
is added. It seems to be testing the slicing of an array with indices that are out of bounds.
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- wrappers/Blobstream.sol/wrapper.go (1 hunks)
Files not summarized due to errors (1)
- wrappers/Blobstream.sol/wrapper.go: Error: Message exceeds token limit
Files not reviewed due to errors (1)
- wrappers/Blobstream.sol/wrapper.go (Error: diff too large)
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.
refreshing this approve
We will go on and merge this PR as it's blocking mocha's deployment. The only concern about this implementation is documented in #259. We can open subsequent PRs if any issues arise with it. |
return false; | ||
if (numLeaves == 1) { | ||
if (sideNodes.length != 0) { | ||
revert("unexpected inner hashes"); |
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.
Do we want to revert in this library?
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.
I'll create an issue to return error codes instead, thanks 👍
Overview
Closes #249
The implementation is taken from: https://github.com/celestiaorg/celestia-core/blob/0498541b8db00c7fefa918d906877ef2ee0a3710/crypto/merkle/proof.go#L166-L197
Checklist
Summary by CodeRabbit
The existing bullet-point list is still valid based on the provided information. No changes are required.