Skip to content

Commit

Permalink
Add DoNotHashLeaves config (txaty#22)
Browse files Browse the repository at this point in the history
* Add DoNotHashLeaves config

* Add tests for DoNotHashLeaves config
  • Loading branch information
alrevuelta authored Jan 5, 2023
1 parent 2927e5b commit 9a402c1
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
15 changes: 13 additions & 2 deletions merkle_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ type Config struct {
// SortSiblingPairs is the parameter for OpenZeppelin compatibility.
// If set to `true`, the hashing sibling pairs are sorted.
SortSiblingPairs bool
// If true, the leaf nodes are NOT hashed before being added to the Merkle Tree.
DoNotHashLeaves bool
}

// MerkleTree implements the Merkle Tree structure
Expand Down Expand Up @@ -479,6 +481,10 @@ func (m *MerkleTree) leafGen(blocks []DataBlock) ([][]byte, error) {
if err != nil {
return nil, err
}
if m.DoNotHashLeaves {
leaves[i] = data
continue
}
var hash []byte
if hash, err = m.HashFunc(data); err != nil {
return nil, err
Expand Down Expand Up @@ -712,8 +718,13 @@ func (m *MerkleTree) GenerateProof(dataBlock DataBlock) (*Proof, error) {
return nil, err
}
var blockHash []byte
if blockHash, err = m.HashFunc(blockByte); err != nil {
return nil, err

if m.DoNotHashLeaves {
blockHash = blockByte
} else {
if blockHash, err = m.HashFunc(blockByte); err != nil {
return nil, err
}
}
val, ok := m.leafMap.Load(string(blockHash))
if !ok {
Expand Down
83 changes: 83 additions & 0 deletions merkle_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,89 @@ func TestMerkleTreeNew_proofGen(t *testing.T) {
}
}

func Test_doNotHashLeaves(t *testing.T) {
// Generate some random blocks
blocks := genTestDataBlocks(100)

// Manually hash the blocks
hashedBlocks := make([]DataBlock, 0)
for _, block := range blocks {
ser, _ := block.Serialize()
hashedBlock, _ := testHashFunc(ser)
hashedBlocks = append(hashedBlocks, &mockDataBlock{
data: hashedBlock,
})
}

// Create a tree that does not hash the leaves, using the already
// hashed blocks
mtNoHash, err := New(&Config{
DoNotHashLeaves: true,
Mode: ModeProofGenAndTreeBuild,
}, hashedBlocks)
if err != nil {
t.Errorf("error creating tree: %v", err)
return
}

// Create a tree that hashes the leaves, but provide unhashed blocks
mtHash, err := New(&Config{
Mode: ModeProofGenAndTreeBuild,
}, blocks)

// Assert that both trees are identical

if err != nil {
t.Errorf("error creating tree: %v", err)
return
}

if !bytes.Equal(mtNoHash.Root, mtHash.Root) {
fmt.Println("root1", mtNoHash.Root)
fmt.Println("root2", mtHash.Root)
t.Errorf("merkle root mismatch")
return
}

if !reflect.DeepEqual(mtNoHash.Leaves, mtHash.Leaves) {
fmt.Println("leaves1", mtNoHash.Leaves)
fmt.Println("leaves2", mtHash.Leaves)
t.Errorf("leaves mismatch")
return
}
if !reflect.DeepEqual(mtNoHash.Proofs, mtHash.Proofs) {
fmt.Println("proof1", mtNoHash.Proofs)
fmt.Println("proof2", mtHash.Proofs)
t.Errorf("proofs mismatch")
return
}
if mtNoHash.Depth != mtHash.Depth {
fmt.Println("depth1", mtNoHash.Depth)
fmt.Println("depth2", mtHash.Depth)
t.Errorf("merkle tree depth mismatch")
return
}

if len(mtNoHash.Proofs) != len(mtHash.Proofs) {
fmt.Println("len proofs 1", len(mtNoHash.Proofs))
fmt.Println("len proofs 2", len(mtHash.Proofs))
t.Errorf("proofs length mismatch")
return
}

for i := 0; i < len(blocks); i++ {
proofHash, _ := mtHash.GenerateProof(blocks[i])
proofNoHash, _ := mtNoHash.GenerateProof(hashedBlocks[i])

if !reflect.DeepEqual(proofHash, proofNoHash) {
fmt.Println("proof1", proofHash)
fmt.Println("proof2", proofNoHash)
t.Errorf("proof value mismatch")
return
}
}
}

func TestMerkleTreeNew_buildTree(t *testing.T) {
type args struct {
blocks []DataBlock
Expand Down

0 comments on commit 9a402c1

Please sign in to comment.