merkle tree: fix the implementation and add a test case

Merkle tree requires a full binary tree, which means the number of node is
power of 2 and the level of the tree is log(N) instead of N/2.

This patch duplicate the node to a power of 2 number and correct the level
calculation. Besides it adds a test case with 6 nodes.

Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
This commit is contained in:
Wei Yang 2017-10-16 12:41:40 +08:00
parent c0accf31e0
commit 5e43c770ee
2 changed files with 42 additions and 2 deletions

View File

@ -20,7 +20,8 @@ type MerkleNode struct {
func NewMerkleTree(data [][]byte) *MerkleTree {
var nodes []MerkleNode
if len(data)%2 != 0 {
// append node until number is power of 2
for (len(data) & (len(data) - 1)) != 0 {
data = append(data, data[len(data)-1])
}
@ -29,7 +30,8 @@ func NewMerkleTree(data [][]byte) *MerkleTree {
nodes = append(nodes, *node)
}
for i := 0; i < len(data)/2; i++ {
// up level until there is only 1 node
for len(nodes) > 1 {
var newLevel []MerkleNode
for j := 0; j < len(nodes); j += 2 {

View File

@ -73,3 +73,41 @@ func TestNewMerkleTree(t *testing.T) {
assert.Equal(t, rootHash, fmt.Sprintf("%x", mTree.RootNode.Data), "Merkle tree root hash is correct")
}
func TestNewMerkleTree8(t *testing.T) {
data := [][]byte{
[]byte("node1"),
[]byte("node2"),
[]byte("node3"),
[]byte("node4"),
[]byte("node5"),
[]byte("node6"),
}
// Level 0
n01 := NewMerkleNode(nil, nil, data[0])
n02 := NewMerkleNode(nil, nil, data[1])
n03 := NewMerkleNode(nil, nil, data[2])
n04 := NewMerkleNode(nil, nil, data[3])
n05 := NewMerkleNode(nil, nil, data[4])
n06 := NewMerkleNode(nil, nil, data[5])
n07 := NewMerkleNode(nil, nil, data[5])
n08 := NewMerkleNode(nil, nil, data[5])
// Level 1
n11 := NewMerkleNode(n01, n02, nil)
n12 := NewMerkleNode(n03, n04, nil)
n13 := NewMerkleNode(n05, n06, nil)
n14 := NewMerkleNode(n07, n08, nil)
// Level 2
n21 := NewMerkleNode(n11, n12, nil)
n22 := NewMerkleNode(n13, n14, nil)
// Level 3
n31 := NewMerkleNode(n21, n22, nil)
rootHash := fmt.Sprintf("%x", n31.Data)
mTree := NewMerkleTree(data)
assert.Equal(t, rootHash, fmt.Sprintf("%x", mTree.RootNode.Data), "Merkle tree root hash is correct")
}