Skip to content

Commit

Permalink
Fix single node tree verification bug
Browse files Browse the repository at this point in the history
Signed-off-by: litt3 <102969658+litt3@users.noreply.github.com>
  • Loading branch information
litt3 committed Dec 18, 2024
1 parent bd3de3a commit 942f5c7
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
9 changes: 7 additions & 2 deletions verify/merkle.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

// ProcessInclusionProof processes the Merkle root proof
// ProcessInclusionProof computes the merkle root hash based on the provided leaf and proof, returning the result.
// An error is returned if the proof param is malformed.
//
// NOTE: this method returning a nil error does NOT indicate that the proof is valid. Rather, it merely indicates that
// the proof was well-formed. The hash returned by this method must be compared to the claimed root hash, to
// determine if the proof is valid.
func ProcessInclusionProof(proof []byte, leaf common.Hash, index uint64) (common.Hash, error) {
if len(proof) == 0 || len(proof)%32 != 0 {
if len(proof)%32 != 0 {
return common.Hash{}, errors.New("proof length should be a multiple of 32 bytes or 256 bits")
}

Expand Down
46 changes: 46 additions & 0 deletions verify/merkle_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package verify

import (
"encoding/hex"
"testing"

"github.com/stretchr/testify/assert"
"github.com/wealdtech/go-merkletree/v2"
"github.com/wealdtech/go-merkletree/v2/keccak256"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -39,3 +44,44 @@ func TestProcessInclusionProofFail(t *testing.T) {

require.NotEqual(t, expectedRoot, actualRoot.Bytes())
}

// TestProcessInclusionProofSingleNode confirms that a merkle tree containing a single node is successfully confirmed
func TestProcessInclusionProofSingleNode(t *testing.T) {
leaf, err := hex.DecodeString("616C6C206861696C20746865206772656174207361746F736869")
assert.NotNil(t, leaf)
assert.NoError(t, err)

tree, err := merkletree.NewTree(merkletree.WithData([][]byte{leaf}), merkletree.WithHashType(keccak256.New()))
assert.NotNil(t, tree)
require.NoError(t, err)

merkleProof, err := tree.GenerateProofWithIndex(0, 0)
assert.NotNil(t, merkleProof)
require.NoError(t, err)

// sanity check: there shouldn't be any sibling hashes for this tree
assert.Equal(t, 0, len(merkleProof.Hashes))

emptyProof := make([]byte, 0)

computedRoot, err := ProcessInclusionProof(
emptyProof,
common.BytesToHash(keccak256.New().Hash(leaf)),
0)
assert.NotNil(t, computedRoot)
require.NoError(t, err)
assert.Equal(t, computedRoot.Bytes(), tree.Root())

// create an alternate leaf, and make sure that the inclusion proof fails the comparison check
badLeaf, err := hex.DecodeString("ab")
assert.NotNil(t, badLeaf)
assert.NoError(t, err)

computedRoot, err = ProcessInclusionProof(
emptyProof,
common.BytesToHash(keccak256.New().Hash(badLeaf)),
0)
assert.NotNil(t, computedRoot)
assert.NoError(t, err)
assert.NotEqual(t, computedRoot.Bytes(), tree.Root())
}

0 comments on commit 942f5c7

Please sign in to comment.