首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

区块链背后的密码学原理(2)

区块链背后的密码学原理(2)

Merkle Tree:

是一种树(数据结构中所说的树),可用于简易支付验证SPV

在比特币中,每个块都会有一个 Merkle 树,它从叶子节点(树的底部)开始,一个叶子节点就是一个交易哈希(比特币使用双 SHA256 哈希)。叶子节点的数量必须是双数,但是并非每个块都包含了双数的交易。因为,如果一个块里面的交易数为单数,那么就将最后一个叶子节点(也就是 Merkle 树的最后一个交易,不是区块的最后一笔交易)复制一份凑成双数。

从下往上,两两成对,连接两个节点哈希,将组合哈希作为新的哈希。新的哈希就成为新的树节点。重复该过程,直到仅有一个节点,也就是树根。根哈希然后就会当做是整个块交易的唯一标示,将它保存到区块头,然后用于工作量证明。

Merkle 树的好处就是一个节点可以在不下载整个块的情况下,验证是否包含某笔交易。并且这些只需要一个交易哈希,一个 Merkle 树根哈希和一个 Merkle 路径。


代码实现

    package main
     
    import "crypto/sha256"
     
    //Merkle 树的作用:一个节点可以在不下载整个块的情况下,验证是否包含某笔交易。
    // 并且这些只需要一个交易哈希,一个 Merkle 树根哈希和一个 Merkle 路径。
     
    //默克尔树
    type MerkleTree struct {
        RootNode *MerkleNode
    }
     
    //节点
    type MerkleNode struct {
        Left *MerkleNode
        Right *MerkleNode
        data []byte
    }
     
    //创建默克尔树
    func NewMerkleTree(data [][]byte) *MerkleTree {
        var nodes []MerkleNode
        if len(data) % 2 != 0 {         //如果节点数为单数,复制最后一个节点数据并追加
            data = append(data, data[len(data) - 1])
        }
        for _, datum := range data {
            node := NewMerkleNode(nil, nil, datum)
            nodes = append(nodes, *node)
        }
        for i := 0; i < len(data)/2; i++ {      //一层层向上合并
            var newlevel []MerkleNode
            for j := 0; j < len(nodes); j += 2 {
                node := NewMerkleNode(&nodes[j],&nodes[j+1],nil)
                newlevel = append(newlevel, *node)
            }
            nodes = newlevel
        }
        mTree := MerkleTree{&nodes[0]}
        return &mTree
    }
     
    //创建一个节点
    func NewMerkleNode(left ,right *MerkleNode, data []byte) *MerkleNode {
        mNode := MerkleNode{}
        if left == nil && right == nil {
            hash := sha256.Sum256(data)
            mNode.data = hash[:]
        } else {
            preHashes := append(left.data, right.data...)
            hash := sha256.Sum256(preHashes)
            mNode.data = hash[:]
        }
        mNode.Left = left
        mNode.Right = right
        return &mNode
    }

    func (b *Block) HashTransactions() []byte {
        var transactions [][]byte
     
        for _, tx := range b.Transactions {
            transactions = append(transactions, tx.Serialize())
        }
        mTree := NewMerkleTree(transactions)
     
        return mTree.RootNode.Data
    }
返回列表