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


    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 =	",(rootHash))
    109     fmt.Println("mTree =		",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

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Dubbo与Eureka
    对称加密与非对称加密
    [转] SpringBoot2.0集成WebSocket,实现后台向前端推送信息
    [转] Druid简介(Spring Boot + Mybatis + Druid数据源【自己定制】)
    [转] rsync+inotify实现文件实时同步
    [转] windows server 几大实时同步软件比较
    [转] Springboot 整合RabbitMq ,用心看完这一篇就够了
    [转] Windows环境下部署RabbitMQ
    [转] 分布式缓存 Redis 集群搭建
    [转] 吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
  • 原文地址:https://www.cnblogs.com/itdef/p/9503234.html
Copyright © 2020-2023  润新知