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 =\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

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

时间: 2024-11-10 12:08:34

cpp 区块链模拟示例(七) 补充 Merkle树的相关文章

cpp 区块链模拟示例(二)工程代码解析

书接上文 我们先来看区块的结构 1 class Block { 2 public: 3 string sPrevHash; //记录上个块的哈希值 4 Block(uint32_t nIndexIn, const string &sDataIn); //构造函数 5 string GetHash(); //获取哈希函数 6 void MineBlock(uint32_t nDifficulty); //挖矿函数 7 private: 8 uint32_t _nIndex; //该区块的索引值 9

cpp 区块链模拟示例(三)新基本原形工程的建立

/* 作 者: itdef 欢迎转帖 请保持文本完整并注明出处 技术博客 http://www.cnblogs.com/itdef/ 技术交流群 群号码:432336863欢迎c c++ windows驱动爱好者 服务器程序员沟通交流部分老代码存放地点http://www.oschina.net/code/list_by_user?id=614253 */ 本章节相比前两节课程,增加了交易等处理,而在工作量证明,挖矿,创建区块,以及区块链的操作也细致了不少. 工程的具体建立可以参考前两章节内容,

区块链开发(七)从某保险积分案例谈区块链应用的风险与挑战

本文以现有的真实区块链应用案例为切入点,通过分析技术架构和实际数据验证,尝试性的测试了其风险,并对未来区块链应用所面临的不同风险进行了研究和探讨,最后针对不同的风险类型,尝试性的提出了相关的建议. 一.某保险区块链积分体系架构 1. 某保险积分应用简介 某保险于2016年3月采用区块链技术作为底层技术架构推出了"阳光贝"积分,用户在享受普通积分功能的基础上,还可以"发红包"的形式将通过积分向朋友转赠.与其他公司发行的区块链积分互换.某保险可以说是国内第一家区块链技术

1.4 [区块链] 共识算法之争(PBFT,Raft,PoW,PoS,DPoS,Ripple)

近几天对区块链中几种常见的共识机制(PBFT,Raft,PoW,PoS,DPoS,Ripple)进行了总结.尽量使用简单易懂语言,篇幅较大,想了解的可以只读每个算法介绍中前边的原理.本篇文章主要参考<区块链技术指南>,首先表示感谢! ---Begin--- 区块链架构是一种分布式的架构.其部署模式有公共链.联盟链.私有链三种,对应的是去中心化分布式系统.部分去中心化分布式系统和弱中心分布式系统. 在分布式系统中,多个主机通过异步通信方式组成网络集群.在这样的一个异步系统中,需要主机之间进行状态

比特币区块结构Merkle树及简单支付验证分析

在比特币网络中,不是每个节点都有能力储存完整的区块链数据,受限于存储空间的的限制,很多节点是以SPV(Simplified Payment Verification简单支付验证)钱包接入比特币网络,通过简单支付验证可以在不必存储完整区块链下对交易进行验证,本文将分析区块结构Merkle树及如何进行交易验证. 区块结构 在工作量证明中出现过一个区块信息截图: 细心的同学一定已经在里面发现了很多未讲的其他信息,如:时间戳,版本号,交易次数,二进制哈希树根(Merkle根)等. 我们来看看一个区块结构

什么是区块链

1.区块链的诞生 互联网上的贸易,几乎都需要借助可资信赖的第三方信用机构来处理电子支付信息.这类系统仍然内生性地受制于"基于信用的模式".区块链技术是构建比特币区块链网络与交易信息加密传输的基础技术.它基于密码学原理而不基于信用,使得任何达成一致的双方直接支付,从而不需要第三方中介的参与. 定义: 区块链是一个分布式账本,一种通过去中心化.去信任的方式集体维护一个可靠数据库的技术方案. 从数据的角度来看:区块链是一种几乎不可能被更改的分布式数据库.这里的"分布式"不

什么是区块链?

一.什么是区块链? 说到区块链,就不得不说比特币. 2008年底,比特币之父中本聪发表了一个关于他研究的电子现金系统的九页白皮书,2009年初,中本聪在位于芬兰赫尔辛基的一个小型服务器上挖出了比特币的第一个区块——创世区块,并将当天泰晤士报头版一则关于救助银行的新闻标题写入创世区块,这也代表着比特币诞生了. 区块链是比特币的底层技术,它可以理解为一种公共记账的机制(技术方案),它并不是一款具体的产品.其基本思想是:通过建立一组互联网上的公共账本,由网络中所有的用户共同在账本上记账与核账,来保证信

[易学易懂系列|rustlang语言|零基础|快速入门|(27)|实战4:从零实现BTC区块链]

项目实战 实战4:从零实现BTC区块链 我们今天来开发我们的BTC区块链系统. 简单来说,从数据结构的角度上来说,区块链,就是区块组成的链. 以下就是BTC区块链典型的结构: 那最小单元就是区块:block. 这个block包含两部分:区块头,区块体. 我们先忽略Merkle树,先简化所有数据结构,只保留最基本的数据结构. 那区块头,就包含:时间截:前一个区块地址 区块体,就包含交易数据,我们用一个vector来存储. 代码如下 : ///交易结构体 #[derive(Clone, Hash,

区块链快速入门(七)——比特币

区块链快速入门(七)--比特币 一.比特币简介 比特币(BitCoin,BTC)是基于区块链技术的一种数字货币实现,比特币网络是历史上首个经过大规模长时间检验的数字货币系统.自2009 年正式上线以来,比特币价格经历了数次的震荡,目前每枚比特币市场价格超过6000 美金,并曾经一度接近20000美金.比特币网络在功能上具有如下特点:A.去中心化没有任何独立个体可以对网络中交易进行破坏,任何交易请求都需要大多数参与者的共识.B.匿名性比特币网络中账户地址是匿名的,无法从交易信息关联到具体的个体,但