完整的比特币数据库(也就是区块链)需要超过 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 }
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 }
参考
https://blog.csdn.net/simple_the_best/article/details/78462129
原文:https://www.cnblogs.com/itdef/p/9503234.html