码迷,mamicode.com
首页 > 其他好文 > 详细

cpp 区块链模拟示例(七) 补充 Merkle树

时间:2018-08-19 23:49:54      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:enc   存在   工作量证明   方案   clu   2-2   sed   ...   pack   

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树

标签:enc   存在   工作量证明   方案   clu   2-2   sed   ...   pack   

原文地址:https://www.cnblogs.com/itdef/p/9503234.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!