1. 程式人生 > >golang[42]-區塊鏈-go實戰比特幣默克爾樹

golang[42]-區塊鏈-go實戰比特幣默克爾樹

go實戰比特幣默克爾樹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main

import (
"crypto/sha256"
"encoding/hex"
"fmt"
)


func min(a int,b int) int{


if(a>b){
return b
}
return a
}


//默克爾樹節點
type MerkleTree struct{
RootNode *MerkleNode
}

//默克爾根節點
type MerkleNode struct{
Left *MerkleNode
Right *MerkleNode
Data []byte
}
//生成默克爾樹中的節點,如果是葉子節點,則Left,right為nil ,如果為非葉子節點,根據Left,right生成當前節點的hash
func NewMerkleNode(left,right *MerkleNode,data []byte) *MerkleNode{
mnode := MerkleNode{}


if left ==nil && right==nil{
mnode.Data = data
}else{
prevhashes := append(left.Data,right.Data...)
firsthash:= sha256.Sum256(prevhashes)
hash:=sha256.Sum256(firsthash[:])
mnode.Data = hash[:]
}

mnode.Left = left
mnode.Right = right

return &mnode
}

//構建默克爾樹
func NewMerkleTree(data [][]byte) *MerkleTree{

var nodes []MerkleNode
//構建葉子節點。
for _,datum := range data{
node:= NewMerkleNode(nil,nil,datum)
nodes =  append(nodes,*node)
}
//j代表的是某一層的第一個元素
j:=0
//第一層迴圈代表 nSize代表某一層的個數,每迴圈一次減半
for nSize :=len(data);nSize >1;nSize = (nSize+1)/2{
//第二條迴圈i+=2代表兩兩拼接。 i2是為了當個數是基數的時候,拷貝最後的元素。
for i:=0 ; i<nSize ;i+=2{
i2 := min(i+1,nSize-1)

node := NewMerkleNode(&nodes[j+i],&nodes[j+i2],nil)
nodes = append(nodes,*node)
}
//j代表的是某一層的第一個元素
j+=nSize

}

mTree := MerkleTree{&(nodes[len(nodes)-1])}
return &mTree
}


func ReverseBytes3(data []byte){
for i,j :=0,len(data) - 1;i<j;i,j = i+1,j - 1{
data[i],data[j] = data[j],data[i]
}
}

func main(){
//測試網站下的5個hash是否能夠生成merkleRoot
//https://www.blockchain.com/btc/block/00000000000090ff2791fe41d80509af6ffbd6c5b10294e29cdf1b603acab92c
//傳遞hash
data1,_:=hex.DecodeString("6b6a4236fb06fead0f1bd7fc4f4de123796eb51675fb55dc18c33fe12e33169d")
data2,_:=hex.DecodeString("2af6b6f6bc6e613049637e32b1809dd767c72f912fef2b978992c6408483d77e")
data3,_:=hex.DecodeString("6d76d15213c11fcbf4cc7e880f34c35dae43f8081ef30c6901f513ce41374583")
data4,_:=hex.DecodeString("08c3b50053b010542dca85594af182f8fcf2f0d2bfe8a806e9494e4792222ad2")
data5,_:=hex.DecodeString("612d035670b7b9dad50f987dfa000a5324ecb3e08745cfefa10a4cefc5544553")

//大小段轉換
ReverseBytes3(data1)
ReverseBytes3(data2)
ReverseBytes3(data3)
ReverseBytes3(data4)
ReverseBytes3(data5)

hehe := [][]byte{
data1,
data2,
data3,
data4,
data5,
}
//生成默克爾樹
merleroot:= NewMerkleTree(hehe)
//反轉
ReverseBytes3(merleroot.RootNode.Data)
fmt.Printf("%x",merleroot.RootNode.Data)

}

參考資料

eth wiki:patricia-tree

[csdn 默克爾樹解釋]https://blog.csdn.net/wo541075754/article/details/54632929

https://github.com/ZtesoftCS/go-ethereum-code-analysis/blob/master/trie原始碼分析.md

image.png