Golang Merkle tree
個人博客:https://www.huixinyixiao.xn–6qq986b3xl/
Golang 實現Merkle 樹
實現Merkle樹,需要使用:
"github.com/cbergoon/merkletree"
這個package中含有構造函數,以及接口函數,所有,通過這個包實現Merkle樹的相關操作,是很好的。
官方實例代碼
// 在這裏編寫代碼
package main
import (
"crypto/sha256"
"github.com/cbergoon/merkletree"
"log"
)
//TestContent implements the Content interface provided by merkletree and represents the content stored in the tree.
type TestContent struct {
x string
}
//CalculateHash hashes the values of a TestContent
func (t TestContent) CalculateHash() ([]byte, error) {
h := sha256.New()
if _, err := h.Write([]byte(t.x)); err != nil {
return nil, err
}
return h.Sum(nil), nil
}
//Equals tests for equality of two Contents
func (t TestContent) Equals(other merkletree.Content) (bool, error) {
return t.x == other.(TestContent).x, nil
}
func main() {
//Build list of Content to build tree
var list []merkletree.Content
/*測試文件*/
var list02 []merkletree.Content
list02 = append(list02, TestContent{
"shan"})
list = append(list, TestContent{
x: "Hello"})
list = append(list, TestContent{
x: "Hi"})
list = append(list, TestContent{
x: "Hey"})
list = append(list, TestContent{
x: "Hola"})
//Create a new Merkle Tree from the list of Content
t, err := merkletree.NewTree(list)
if err != nil {
log.Fatal(err)
}
//Get the Merkle Root of the tree
mr := t.MerkleRoot()
log.Println("Merkle Root:", mr)
//Verify the entire tree (hashes for each node) is valid
vt, err := t.VerifyTree()
if err != nil {
log.Fatal(err)
}
log.Println("Verify Tree: ", vt)
//Verify a specific content in in the tree
vc, err := t.VerifyContent(list02[0])
if err != nil {
log.Fatal(err)
}
log.Println("Verify Content: ", vc)
//String representation
log.Println(t)
}
Note:我改變了驗證的信息內容(list02),爲了驗證這個package 可用性。
1. 源package 解讀
在package 中的interface,需要實現兩個函數
//Content represents the data that is stored and verified by the tree. A type that
//implements this interface can be used as an item in the tree.
type Content interface {
CalculateHash() ([]byte, error)
Equals(other Content) (bool, error)
}
只是代碼實現中需要注意的,可以添加自己實現的算法,比如更改sha256等。
其他函數的調用,不需要做任何改變,直接調用就好。
從上圖中可以看出對於所有的交易數據,都是葉子,並且,如果添加的交易數是奇數,也就是黃色區域表示的那樣,那麼,就會複製最後一個交易,形成偶數個交易數,也就是最後的兩個交易其實是一樣的。
2. 查詢數據路徑,重新構造Merkle tree ,看看和我們想的是否一樣。
通過插入四個數據:
func appendListData(number int) {
// 隨機產生數據
for i := 0; i < number; i++ {
nodeId := "hello" + strconv.Itoa(i)
list = append(list, TestContent{
nodeId})
}
}
上述代碼,實現插入數據的功能。
主函數裏面直接調用。另外需要將list全局聲明。我們查詢兩個數據hello0和hello1的路徑,此時,設置number爲4:
從紅色區域可以知道,兩個葉子節點的父節點是一樣的,也就是hello0和hello1葉子共同hash得到。
我們再次查詢兩個數據hello2和hello3的路徑,此時,同樣設置number爲4:
看,結果如我們所說的那樣。
如果我們將上面的兩個圖中的紅色的數據進行hash,一定是root hash。