概述
Merkle Tree
Merkle Tree 是由计算机科学家 Ralph Merkle 在很多年前提出的,并以他本人的名字来命名。通常也被称作Hash Tree,就是存储hash值的一棵树。Merkle树的叶子是数据块的hash值。非叶节点是其对应子节点串联字符串的hash。
merkle tree(变体例如 merkle patricia tree:MPT)广泛地应用于比特币,以太坊,fabric等区块链项目上;也广泛地应用于一致性验证,数据校验,数据同步等服务中。
比特币与merkle tree
SPV
完整的比特币数据库(也就是区块链)已截止本文超过 200 GB 。因为比特币的去中心化特性,网络中的每个节点必须是独立,自给自足的,也就是每个节点必须存储一个区块链的完整副本。随着越来越多的人使用比特币,这条规则使得开销非常大,所以不太可能每个人都去运行一个全节点。由于节点是网络中的完全参与者,它们负有相关责任:节点必须验证交易和区块。
另外,要想与其他节点交互和下载新块,也有一定的网络流量需求。中本聪的比特币原始论文中,对这个问题也有一个解决方案:简易支付验证(Simplified Payment Verification, SPV)。轻钱包并不保存完整的区块链,而是只保存每一个区块的区块头。区块体保存了完整的交易信息,而交易信息需要的存储量大部分都是交易头的千倍以上。所以,如果只保存交易头,就可以极大的减少本地客户端存储的区块链信息。
如果这个时候SPV要对某一个交易进行验证,而本地又没有这个交易的信息,那怎么验证呢?这时,区块头里面的merkle root,以及区块对应的merkle tree就要起作用了。
比特币用 Merkle tree来获取交易哈希,哈希被保存在区块头中,并会用于工作量证明系统。每个块都会有一个 Merkle 树,它从叶子节点(树的底部)开始,一个叶子节点就是一个交易哈希(比特币使用双 SHA256 哈希)。叶子节点的数量必须是双数,但是并非每个块都包含了双数的交易。因为,如果一个块里面的交易数为单数,那么就将最后一个叶子节点复制一份凑成双数。
Merkle 树的好处就是一个节点可以在不下载整个块的情况下,验证是否包含某笔交易。并且这些只需要一个交易哈希,一个 Merkle 树根哈希和一个 Merkle 路径。
验证交易真实性
在比特币网络中的交易,只有已经被记录到区块链,并且已经得到6个确认的,才被认为是真实的,只有基于这些真实交易发起的新交易(输入与输出的概念),才是合法的。
交易真实性前提:
- 交易是否已被记录到区块链中
- 交易所在的区块链是最长的一条,没有在分叉链上
- 每个节点接收到一条交易广播时,要查询作为一笔新交易的输入的真实性
- 矿工对交易进行打包之前,对所有的输入进行真实性验证
全节点: SPV会把该交易信息向一个全节点发送merkle block message的请求,全节点会利用传过来的交易信息在自己的区块链数据库上查询,得到交易对应的区块,此时可以获得该区块的merkle tree, 再通过遍历的方法把该交易的验证路径生成并发给SPV。
SPV 收到返回时,会把该交易的hash值和验证路径的hash值会做一次merkle校验,如果和可信的merkle root hash (从全节点对应的区块上获取)一致,则认为该交易是可信的。
例子:验证data1。 如图,验证路径为黄色节点,虚线部分是计算出的节点,然后和merkle root:0123比较,他们是一致的,所以data1是存在的,可信的。
fabric与merkle tree
在fabric1.2中,block 结构中,blockHeader中的datahash把blockdata的bytes采用sha256得出,其中涉及到merkle tree暂时并没有实现。
在fabric0.6中的世界状态采用bucket tree来组织,但是在fabric1.0以后随着pbft一起删掉了。
在这里既然没有采用,就不在细述。
以太坊与merkle tree
以太坊中采用了Merkle tree 与 Patricia Tree,即MPT。这部分阅读以太坊源码后再进行分析。
Merkle Tree操作示例代码
package main
import (
"crypto/sha256"
"fmt"
)
type MerkleTree struct {
RootNode *MerkleNode
}
type MerkleNode struct {
Left *MerkleNode
Right *MerkleNode
Data []byte
}
func NewMerkleNode(left, right *MerkleNode, data []byte) *MerkleNode {
mNode := MerkleNode{}
if left == nil && right == nil {
hash := sha256.Sum256(data)
mNode.Data = hash[:]
} else {
var data []byte
if right != nil {
data = append(left.Data, right.Data...)
} else {
data = left.Data
}
hash := sha256.Sum256(data)
mNode.Data = hash[:]
}
mNode.Left = left
mNode.Right = right
return &mNode
}
func NewMerkleTree(data [][]byte) *MerkleTree {
var nodes []MerkleNode
if data == nil {
fmt.Print("args error")
}
if len(data)%2 != 0 {
data = append(data, data[len(data)-1])
}
for _, idata := range data {
node := NewMerkleNode(nil, nil, idata)
nodes = append(nodes, *node)
}
for i := 0; i < len(data)/2; i++ {
var fathernodes []MerkleNode
if len(nodes) == 1 {
break
}
for j := 0; j < len(nodes); j += 2 {
if j+1 >= len(nodes) {
node := NewMerkleNode(&nodes[j], nil, nil)
fathernodes = append(fathernodes, *node)
} else {
node := NewMerkleNode(&nodes[j], &nodes[j+1], nil)
fathernodes = append(fathernodes, *node)
}
}
nodes = fathernodes
}
mTree := MerkleTree{
RootNode: &nodes[0],
}
return &mTree
}
最后
以上就是多情书本为你收集整理的区块链与merkle treeMerkle Tree比特币与merkle treefabric与merkle tree以太坊与merkle treeMerkle Tree操作示例代码的全部内容,希望文章能够帮你解决区块链与merkle treeMerkle Tree比特币与merkle treefabric与merkle tree以太坊与merkle treeMerkle Tree操作示例代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复