1. 程式人生 > >cpp 區塊鏈模擬示例(七) 補充 Merkle樹

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

follow close sum 2-2 ash sha2 hashes ima 網絡

Merkle 樹

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

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

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

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

來看一下 Merkle 樹:

技術分享圖片

每個塊都會有一個 Merkle 樹,它從葉子節點(樹的底部)開始,一個葉子節點就是一個交易哈希(比特幣使用雙 SHA256 哈希)。葉子節點的數量必須是雙數,但是並非每個塊都包含了雙數的交易。因為,如果一個塊裏面的交易數為單數,那麽就將最後一個葉子節點(也就是 Merkle 樹的最後一個交易,不是區塊的最後一筆交易)復制一份湊成雙數。

從下往上,兩兩成對,連接兩個節點哈希,將組合哈希作為新的哈希。新的哈希就成為新的樹節點。重復該過程,直到僅有一個節點,也就是樹根。根哈希然後就會當做是整個塊交易的唯一標示,將它保存到區塊頭,然後用於工作量證明。

Merkle 樹的好處就是一個節點可以在不下載整個塊的情況下,驗證是否包含某筆交易。並且這些只需要一個交易哈希,一個 Merkle 樹根哈希和一個 Merkle 路徑。

最後,來寫代碼:

技術分享圖片
  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

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