cpp 區塊鏈模擬示例(七) 補充 Merkle樹

Merkle 樹

完整的比特幣數據庫(也就是區塊鏈)須要超過 140 Gb 的磁盤空間。由於比特幣的去中心化特性,網絡中的每一個節點必須是獨立,自給自足的,也就是每一個節點必須存儲一個區塊鏈的完整副本。隨着愈來愈多的人使用比特幣,這條規則變得愈來愈難以遵照:由於不太可能每一個人都去運行一個全節點。而且,因爲節點是網絡中的徹底參與者,它們負有相關責任:節點必須驗證交易和區塊。另外,要想與其餘節點交互和下載新塊,也有必定的網絡流量需求。html

在中本聰的 比特幣原始論文 中,對這個問題也有一個解決方案:簡易支付驗證(Simplified Payment Verification, SPV)。SPV 是一個比特幣輕節點,它不須要下載整個區塊鏈,也不須要驗證區塊和交易。相反,它會在區塊鏈查找交易(爲了驗證支付),而且須要鏈接到一個全節點來檢索必要的數據。這個機制容許在僅運行一個全節點的狀況下有多個輕錢包。node

爲了實現 SPV,須要有一個方式來檢查是否一個區塊包含了某筆交易,而無須下載整個區塊。這就是 Merkle 樹所要完成的事情。ios

比特幣用 Merkle 樹來獲取交易哈希,哈希被保存在區塊頭中,並會用於工做量證實系統。到目前爲止,咱們只是將一個塊裏面的每筆交易哈希鏈接了起來,將在上面應用了 SHA-256 算法。雖然這是一個用於獲取區塊交易惟一表示的一個不錯的途徑,可是它沒有利用到 Merkle 樹。c++

來看一下 Merkle 樹:算法

每一個塊都會有一個 Merkle 樹,它從葉子節點(樹的底部)開始,一個葉子節點就是一個交易哈希(比特幣使用雙 SHA256 哈希)。葉子節點的數量必須是雙數,可是並不是每一個塊都包含了雙數的交易。由於,若是一個塊裏面的交易數爲單數,那麼就將最後一個葉子節點(也就是 Merkle 樹的最後一個交易,不是區塊的最後一筆交易)複製一份湊成雙數。數據庫

從下往上,兩兩成對,鏈接兩個節點哈希,將組合哈希做爲新的哈希。新的哈希就成爲新的樹節點。重複該過程,直到僅有一個節點,也就是樹根。根哈希而後就會當作是整個塊交易的惟一標示,將它保存到區塊頭,而後用於工做量證實。網絡

Merkle 樹的好處就是一個節點能夠在不下載整個塊的狀況下,驗證是否包含某筆交易。而且這些只須要一個交易哈希,一個 Merkle 樹根哈希和一個 Merkle 路徑。app

最後,來寫代碼:ide

  1 package main
  2 
  3 import (
  4     "crypto/sha256"
  5     "fmt"
  6     "encoding/hex"
  7 )
  8 
  9 type MerkleTree struct{
 10     RootNode * MerkleNode
 11 }
 12 
 13 type MerkleNode struct{
 14     Left     *MerkleNode
 15     Right     *MerkleNode
 16     Data     []byte
 17 }
 18 
 19 func NewMerkleTree(data [][]byte) * MerkleTree{
 20     var nodes []MerkleNode
 21     if len(data)%2 != 0{
 22         data = append(data,data[len(data)-1])
 23     }
 24 
 25     for _,datum := range data{
 26         node := NewMerkleNode(nil,nil,datum)
 27         nodes = append(nodes,*node)
 28     }
 29 
 30     for i := 0;i < len(data)/2;i++{
 31         var newLevel []MerkleNode
 32 
 33         for j := 0;j < len(nodes);j += 2{
 34             node := NewMerkleNode(&nodes[j],&nodes[j+1],nil)
 35             newLevel = append(newLevel,*node)
 36         }
 37         nodes = newLevel
 38     }
 39 
 40     mTree := MerkleTree{&nodes[0]}
 41     return &mTree
 42 }
 43 
 44 func NewMerkleNode(left,right *MerkleNode,data []byte)*MerkleNode{
 45     mNode := MerkleNode{}
 46 
 47     if left == nil && right == nil{
 48         hash := sha256.Sum256(data)
 49         mNode.Data = hash[:]
 50     }else{
 51         prevHashes := append(left.Data,right.Data...)
 52         hash := sha256.Sum256(prevHashes)
 53         mNode.Data = hash[:]
 54     }
 55 
 56     mNode.Left = left
 57     mNode.Right = right
 58 
 59     return &mNode
 60 }
 61 //==============================================================
 62 
 63 func testNewMerkleNode1(){
 64     data := [][]byte{
 65         []byte("node1"),
 66         []byte("node2"),
 67         []byte("node3"),
 68     }
 69 
 70     n1 := NewMerkleNode(nil,nil,data[0])
 71     n2 := NewMerkleNode(nil,nil,data[1])
 72     n3 := NewMerkleNode(nil,nil,data[2])
 73     n4 := NewMerkleNode(nil,nil,data[2])
 74 
 75 
 76     n5 := NewMerkleNode(n1,n2,nil)
 77     n6 := NewMerkleNode(n3,n4,nil)
 78 
 79     n7 := NewMerkleNode(n5,n6,nil)
 80 
 81     fmt.Println("n5 = ",hex.EncodeToString(n5.Data))
 82     fmt.Println("n6 = ",hex.EncodeToString(n6.Data))
 83     fmt.Println("n7 = ",hex.EncodeToString(n7.Data))
 84 }
 85 
 86 func testNewMerkleNode2(){
 87     data := [][]byte{
 88         []byte("node1"),
 89         []byte("node2"),
 90         []byte("node3"),
 91     }
 92     // Level 1
 93     n1 := NewMerkleNode(nil, nil, data[0])
 94     n2 := NewMerkleNode(nil, nil, data[1])
 95     n3 := NewMerkleNode(nil, nil, data[2])
 96     n4 := NewMerkleNode(nil, nil, data[2])
 97 
 98     // Level 2
 99     n5 := NewMerkleNode(n1, n2, nil)
100     n6 := NewMerkleNode(n3, n4, nil)
101 
102     // Level 3
103     n7 := NewMerkleNode(n5, n6, nil)
104 
105     rootHash := fmt.Sprintf("%x", n7.Data)
106     mTree := NewMerkleTree(data)
107 
108     fmt.Println("roothash =\t",(rootHash))
109     fmt.Println("mTree =\t\t",hex.EncodeToString(mTree.RootNode.Data))
110 }
111 
112 
113 
114 func main() {
115     testNewMerkleNode1()
116     testNewMerkleNode2()
117 }
Merkle_go

c++須要導入以前的sha256  https://www.cnblogs.com/itdef/p/9435218.html區塊鏈

sha256.cpp    sha256.h

  1 // 1111.cpp: 定義控制檯應用程序的入口點。
  2 //
  3 
  4 #include "sha256.h"
  5 #include <string>
  6 #include <vector>
  7 #include <iostream>
  8 
  9 
 10 using namespace std;
 11 
 12 
 13 typedef struct merklenode {
 14     struct merklenode* left;
 15     struct merklenode* right;
 16     string data;
 17 }MerkleNode;
 18 
 19 
 20 typedef struct merkletree {
 21     MerkleNode* merkleNode;
 22 }MerkleTree;
 23 
 24 MerkleNode* NewMerkleNode(MerkleNode* left, MerkleNode* right, string data) {
 25     MerkleNode* mNode = new MerkleNode{};
 26 
 27     if (left == nullptr && right == nullptr) {
 28         string hash = sha256(data);
 29         mNode->data = hash;
 30     }
 31     else {
 32         string prevHashes = left->data + right->data;
 33         string hash = sha256(prevHashes);
 34         mNode->data = hash;
 35     }
 36 
 37     mNode->left = left;
 38     mNode->right = right;
 39 
 40     return mNode;
 41 }
 42 
 43 MerkleTree* NewMerkleTree(vector<string> data) {
 44     vector<MerkleNode*>  nodes;
 45 
 46     if ((data.size() % 2) != 0) {
 47         data.push_back(data[data.size() - 1]);
 48     }
 49 
 50     for (const auto& datum : data) {
 51         MerkleNode* node = NewMerkleNode(nullptr, nullptr, datum);
 52         nodes.push_back(node);
 53     }
 54 
 55     for (int i = 0; i < (data.size() / 2); i++) {
 56         vector<MerkleNode*> newLevel;
 57 
 58         for (int j = 0; j < nodes.size(); j += 2) {
 59             MerkleNode* node = NewMerkleNode(nodes[j], nodes[j + 1], "");
 60             newLevel.push_back(node);
 61         }
 62         nodes = newLevel;
 63     }
 64 
 65     MerkleTree* mTree = new MerkleTree{ nodes[0] };
 66     return mTree;
 67 }
 68 
 69 void testNewMerkleNode1() {
 70     vector<string> data{ "node1","node2","node3" };
 71 
 72     MerkleNode* n1 = NewMerkleNode(nullptr, nullptr, data[0]);
 73     MerkleNode* n2 = NewMerkleNode(nullptr, nullptr, data[1]);
 74     MerkleNode* n3 = NewMerkleNode(nullptr, nullptr, data[2]);
 75     MerkleNode* n4 = NewMerkleNode(nullptr, nullptr, data[2]);
 76 
 77     MerkleNode* n5 = NewMerkleNode(n1, n2, "");
 78     MerkleNode* n6 = NewMerkleNode(n3, n4, "");
 79 
 80     MerkleNode* n7 = NewMerkleNode(n5, n6, "");
 81 
 82     std::cout << "n5 = " << n5->data << std::endl;
 83     std::cout << "n6 = " << n6->data << std::endl;
 84     std::cout << "n7 = " << n7->data << std::endl;
 85 }
 86 
 87 void testNewMerkleNode2() {
 88     vector<string> data{ "node1","node2","node3" };
 89 
 90     MerkleNode* n1 = NewMerkleNode(nullptr, nullptr, data[0]);
 91     MerkleNode* n2 = NewMerkleNode(nullptr, nullptr, data[1]);
 92     MerkleNode* n3 = NewMerkleNode(nullptr, nullptr, data[2]);
 93     MerkleNode* n4 = NewMerkleNode(nullptr, nullptr, data[2]);
 94 
 95     MerkleNode* n5 = NewMerkleNode(n1, n2, "");
 96     MerkleNode* n6 = NewMerkleNode(n3, n4, "");
 97 
 98     MerkleNode* n7 = NewMerkleNode(n5, n6, "");
 99 
100     MerkleTree* mTree = NewMerkleTree(data);
101 
102     std::cout << "roothash = "<< n7->data << std::endl;
103     std::cout << "mTree = " << mTree->merkleNode->data <<  std::endl;
104 
105 
106 }
107 
108 
109 
110 int main()
111 {
112     testNewMerkleNode1();
113     testNewMerkleNode2();
114     return 0;
115 }
Merkle_cpp

 

參考

https://blog.csdn.net/simple_the_best/article/details/78462129

相關文章
相關標籤/搜索