Skip to content

Commit 92902fa

Browse files
committed
2018.1.30
1 parent 75c5670 commit 92902fa

File tree

5 files changed

+340
-0
lines changed

5 files changed

+340
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Merkle Tree
2+
3+
## Merkle Tree 特性
4+
5+
Merkle Tree 又称 Merkle Hash Tree
6+
7+
1. 本质为二叉树,叶子节点存储数据
8+
2. 非叶子节点根据它的两个孩子的值进行 hash 计算
9+
3. 整棵树的根结点存储整个 Tree 的最终 Hash 值
10+
11+
## Merkle Tree 与区块链
12+
13+
区块链的区块利用 Merkle Tree 把区块重的大量信息缩成一个 Hash 值
14+
这个值会被记录到区块头中被验证
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Author: Juntaran
3+
* Email: Jacinthmail@gmail.com
4+
* Date: 2018/1/30 14:12
5+
*/
6+
7+
package main
8+
9+
10+
import (
11+
"crypto/md5"
12+
"fmt"
13+
"io/ioutil"
14+
"Golang_Algorithm/Data_Structure/Merkle_Tree"
15+
)
16+
17+
func splitData(data []byte, size int) [][]byte {
18+
// Splits data into an array of slices of len(size)
19+
count := len(data) / size
20+
blocks := make([][]byte, 0, count)
21+
for i := 0; i < count; i++ {
22+
block := data[i*size : (i+1)*size]
23+
blocks = append(blocks, block)
24+
}
25+
if len(data) % size != 0 {
26+
blocks = append(blocks, data[len(blocks)*size:])
27+
}
28+
return blocks
29+
}
30+
31+
func main() {
32+
// Grab some data to make the tree out of, and partition
33+
data, err := ioutil.ReadFile("Data_Structure/Merkle_Tree/testdata.txt") // assume testdata.txt exists
34+
if err != nil {
35+
fmt.Println(err)
36+
return
37+
}
38+
blocks := splitData(data, 32)
39+
40+
// Create & generate the tree
41+
tree := Merkle_Tree.NewMerkleTree()
42+
err = tree.Init(blocks, md5.New())
43+
if err != nil {
44+
fmt.Println(err)
45+
return
46+
}
47+
48+
fmt.Printf("Height: %d\n", tree.GetMerkleTreeHeight())
49+
fmt.Printf("Root: %v\n", tree.GetMerkleTreeRoot())
50+
fmt.Printf("N Leaves: %v\n", len(tree.GetMerkleTreeLeaves()))
51+
fmt.Printf("Height 2: %v\n", tree.GetMerkleTreeNLevelNode(2))
52+
fmt.Println(tree.Level)
53+
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/**
2+
* Author: Juntaran
3+
* Email: Jacinthmail@gmail.com
4+
* Date: 2018/1/30 14:10
5+
*/
6+
7+
package Merkle_Tree
8+
9+
import (
10+
"hash"
11+
"errors"
12+
)
13+
14+
// Merkle Tree 节点结构
15+
type MerkleNode struct {
16+
HashValue []byte
17+
lchild *MerkleNode
18+
rchild *MerkleNode
19+
}
20+
21+
// Merkle Tree 树结构
22+
type MerkleTree struct {
23+
Size uint64 // 节点数
24+
Nodes []MerkleNode // 所有 node
25+
Level [][]MerkleNode // 每层的 node
26+
}
27+
28+
// 创建一个节点
29+
func NewMerkleNode(h hash.Hash, block []byte) (MerkleNode, error){
30+
if h == nil || block == nil {
31+
return MerkleNode{}, nil
32+
}
33+
defer h.Reset()
34+
_, err := h.Write(block)
35+
if err != nil {
36+
return MerkleNode{}, err
37+
}
38+
return MerkleNode{
39+
HashValue: h.Sum(nil),
40+
}, nil
41+
}
42+
43+
// 创建一棵树
44+
func NewMerkleTree() *MerkleTree {
45+
return &MerkleTree{
46+
Size: 0,
47+
Nodes: nil,
48+
Level: nil,
49+
}
50+
}
51+
52+
//// 返回树的根
53+
//func (merkleTree *MerkleTree) GetMerkleTreeRoot() *MerkleNode {
54+
// if merkleTree.Nodes == nil {
55+
// return nil
56+
// }
57+
// return merkleTree.Root
58+
//}
59+
60+
// 返回树的高度
61+
func (merkleTree *MerkleTree) GetMerkleTreeHeight() uint64 {
62+
return uint64(len(merkleTree.Level))
63+
}
64+
65+
// 获取第 n 层的节点
66+
func (merkleTree *MerkleTree) GetMerkleTreeNLevelNode(n uint64) []MerkleNode {
67+
if merkleTree.Level == nil || n == 0 || n > uint64(len(merkleTree.Level)) {
68+
return nil
69+
}
70+
return merkleTree.Level[n - 1]
71+
}
72+
73+
// 返回 root
74+
func (merkleTree *MerkleTree) GetMerkleTreeRoot() *MerkleNode {
75+
if merkleTree.Nodes == nil {
76+
return nil
77+
} else {
78+
return &merkleTree.Level[0][0]
79+
}
80+
}
81+
82+
// 返回叶子节点
83+
func (merkleTree *MerkleTree) GetMerkleTreeLeaves() []MerkleNode {
84+
if merkleTree.Level == nil {
85+
return nil
86+
}
87+
return merkleTree.Level[len(merkleTree.Level) - 1]
88+
}
89+
90+
// 根据节点数量判断树的高度
91+
func getMerkleTreeHeight(nodeCount uint64) uint64 {
92+
if nodeCount == 0 {
93+
return 0
94+
} else if nodeCount == 1 {
95+
return 2
96+
} else {
97+
return logBaseTwo(nextPowerOfTwo(nodeCount)) + 1
98+
}
99+
}
100+
101+
// 计算节点数
102+
func getNodeCount(height, size uint64) uint64 {
103+
if isPowerOfTwo(size) {
104+
return 2 * size - 1
105+
}
106+
count := size
107+
prev := size
108+
for i := uint64(1); i < height; i++ {
109+
next := (prev + prev % 2) / 2
110+
count += next
111+
prev = next
112+
}
113+
return count
114+
}
115+
116+
// 生成 MerkleTree
117+
func (merkleTree *MerkleTree) Init(blocks [][]byte, h hash.Hash) error {
118+
blockCount := uint64(len(blocks))
119+
if blockCount == 0 {
120+
return errors.New("Empty tree")
121+
}
122+
height := getMerkleTreeHeight(blockCount)
123+
nodeCount := getNodeCount(height, blockCount)
124+
levels := make([][]MerkleNode, height)
125+
nodes := make([]MerkleNode, nodeCount)
126+
size := nodeCount
127+
128+
// 创建叶子节点
129+
for k, v := range blocks {
130+
node, err := NewMerkleNode(h, v)
131+
if err != nil {
132+
return err
133+
}
134+
nodes[k] = node
135+
}
136+
levels[height - 1] = nodes[:len(blocks)]
137+
138+
// 创建每个节点层
139+
current := nodes[len(blocks):]
140+
var i uint64
141+
for i = height - 1; i > 0; i-- {
142+
below := levels[i]
143+
wrote, err := merkleTree.initNodeLevel(below, current, h)
144+
if err != nil {
145+
return err
146+
}
147+
levels[i-1] = current[:wrote]
148+
current = current[wrote:]
149+
}
150+
merkleTree.Nodes = nodes
151+
merkleTree.Level = levels
152+
merkleTree.Size = size
153+
154+
return nil
155+
}
156+
157+
// 生成所有非叶子节点
158+
func (merkleTree *MerkleTree)initNodeLevel(below []MerkleNode, current []MerkleNode, h hash.Hash) (uint64, error) {
159+
h.Reset()
160+
size := h.Size()
161+
data := make([]byte, size*2)
162+
end := (len(below) + len(below) % 2) / 2
163+
for i := 0; i < end; i++ {
164+
node := MerkleNode{}
165+
ileft := 2 * i
166+
iright := 2 * i + 1
167+
left := &below[ileft]
168+
var right *MerkleNode = nil
169+
if len(below) > iright {
170+
right = &below[iright]
171+
}
172+
if right == nil {
173+
b := data[:size]
174+
copy(b, left.HashValue)
175+
node = MerkleNode{
176+
HashValue: b,
177+
}
178+
} else {
179+
copy(data[:size], below[ileft].HashValue)
180+
copy(data[size:], below[iright].HashValue)
181+
var err error
182+
node, err = NewMerkleNode(h, data)
183+
if err != nil {
184+
return 0, err
185+
}
186+
}
187+
// Point the new node to its children and save
188+
node.lchild = left
189+
node.rchild = right
190+
current[i] = node
191+
192+
// Reset the data slice
193+
data = data[:]
194+
}
195+
return uint64(end), nil
196+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* Author: Juntaran
3+
* Email: Jacinthmail@gmail.com
4+
* Date: 2018/1/30 17:28
5+
*/
6+
7+
package Merkle_Tree
8+
9+
// 判断 n 是否为 2 的幂
10+
func isPowerOfTwo(n uint64) bool {
11+
// http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
12+
return n != 0 && (n&(n-1)) == 0
13+
}
14+
15+
// 返回比 n 大的最小的 2 的幂
16+
func nextPowerOfTwo(n uint64) uint64 {
17+
if n == 0 {
18+
return 1
19+
}
20+
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
21+
n --
22+
n |= n >> 1
23+
n |= n >> 2
24+
n |= n >> 4
25+
n |= n >> 8
26+
n |= n >> 16
27+
n |= n >> 32
28+
n ++
29+
return n
30+
}
31+
32+
// 计算 log2(n)
33+
func logBaseTwo(n uint64) uint64 {
34+
if n == 0 {
35+
return 0
36+
}
37+
ret := uint64(0)
38+
for n != 0 {
39+
n >>= 1
40+
ret ++
41+
}
42+
return ret - 1
43+
}
44+
45+
// Returns the ceil'd log2 value of n
46+
// See: http://stackoverflow.com/a/15327567
47+
48+
var log2lookup []uint64 = []uint64{
49+
0xFFFFFFFF00000000,
50+
0x00000000FFFF0000,
51+
0x000000000000FF00,
52+
0x00000000000000F0,
53+
0x000000000000000C,
54+
0x0000000000000002,
55+
}
56+
57+
func ceilLogBaseTwo(x uint64) uint64 {
58+
y := uint64(1)
59+
if (x & (x - 1)) == 0 {
60+
y = 0
61+
}
62+
j := uint64(32)
63+
i := uint64(0)
64+
65+
for ; i < 6; i++ {
66+
k := j
67+
if (x & log2lookup[i]) == 0 {
68+
k = 0
69+
}
70+
y += k
71+
x >>= k
72+
j >>= 1
73+
}
74+
75+
return y
76+
}

0 commit comments

Comments
 (0)