p2p、分布式,区块链笔记: 通过代码理解 Merkle Trees 的结构(c++实现)

主要数据结构

节点Node

#ifndef NODE_H
#define NODE_H

#include <string>

struct Node {
    std::string hash;
    Node *left;
    Node *right;

    Node(std::string data);
};

#endif /* NODE_H */

MerkleTree

#ifndef MERKLE_TREE_H
#define MERKLE_TREE_H

#include "node.h"
#include "picosha2.h"
#include "misc.h"
#include <vector>
#include <string>

struct MerkleTree {
    Node* root;
    MerkleTree(std::vector<Node*> blocks);
    ~MerkleTree();
    void printTree(Node *n, int indent);
    void deleteTree(Node *n);
};


#endif /* MERKLE_TREE_H */

MerkleTree(std::vector<Node*> blocks)

  • 构造函数MerkleTree(std::vector<Node*> blocks) 将相邻的节点配对,并将它们的哈希值连接起来后进行哈希,生成新的父节点。如果节点数量为奇数,最后一个节点将不配对,直接加入 nodes 向量。
MerkleTree::MerkleTree(std::vector<Node*> blocks) {
    std::vector<Node*> nodes;
    while (blocks.size() != 1) {
        printNodeHashes(blocks);
        for (unsigned int l = 0, n = 0; l < blocks.size(); l = l + 2, n++) {
            if (l != blocks.size() - 1) { // checks for adjacent block
                nodes.push_back(new Node(hash_sha256(blocks[l]->hash + blocks[l+1]->hash))); // combine and hash adjacent blocks
                nodes[n]->left = blocks[l]; // assign children
                nodes[n]->right = blocks[l+1];
            } else {
                nodes.push_back(blocks[l]);
            }
        }
        std::cout << "\n";
        blocks = nodes;
        nodes.clear();

    }
    this->root = blocks[0];
}

过程图示

  • 初始状态
  • 假设有四个叶子节点,它们的哈希值分别是 H1, H2, H3, H4
叶子节点:
H1  H2  H3  H4
  • 第一轮合并

  • 将相邻的叶子节点配对并计算新的哈希值:

  • 左边的两个节点 H1H2 合并,得到一个新的哈希值 H12

  • 右边的两个节点 H3H4 合并,得到一个新的哈希值 H34

中间节点:
      H12  H34
     /   \ /   \
    H1    H2   H3  H4
  • 第二轮合并

  • 将中间节点再次配对,计算新的哈希值:

  • H12H34 合并,得到根节点 H1234

根节点:
         H1234
        /     \
      H12     H34
     /   \   /   \
    H1    H2 H3   H4

main.cpp运行过程

1. 创建叶子节点

  • 计算并存储 多个字符串的哈希值作为叶子节点。
  • std::vector<Node*> leaves;: 创建一个 Node* 类型的动态数组 leaves,用来存储叶子节点。
    //create sample data
    leaves.push_back(new Node(hash_sha256("abcdefg")));
    leaves.push_back(new Node(hash_sha256("qwerty12345")));
    leaves.push_back(new Node(hash_sha256("!@(@#)E&")));
    leaves.push_back(new Node(hash_sha256("ajosdhuhsdioa adsijd asjiod q9p0ad a.")));
    leaves.push_back(new Node(hash_sha256("test01234")));
    leaves.push_back(new Node(hash_sha256("7846546521")));
    leaves.push_back(new Node(hash_sha256("asd970123+_?>?< f")));
    leaves.push_back(new Node(hash_sha256("op_) 4654asd21")));
    leaves.push_back(new Node(hash_sha256("12893 d970123+_qweawdf")));

在这里插入图片描述

2.构建 Merkle 树

    MerkleTree *hashTree = new MerkleTree(leaves);// 创建一个 MerkleTree 对象 hashTree,并将 leaves 作为参数传递给构造函数。将根据 leaves 向量构建 Merkle 树。
    std::cout << hashTree->root->hash << std::endl;// 输出树的根节点的哈希值
    hashTree->printTree(hashTree->root, 0);// 调用 printTree 方法打印整个树的结构,从根节点开始,深度为 0。

在这里插入图片描述

3.释放内存

    // 遍历 leaves 向量并删除每个Node对象,释放动态分配的内存。
    for (unsigned int k = 0; k < leaves.size(); k++) {
        delete leaves[k];
    }

    delete hashTree; // 删除 hashTree 对象,释放动态分配的内存。

辅助函数

  • include/misc.h主要进行Hash计算,其中用于计算哈希函数的语句#include "picosha2.h"std::string hash_hex_str = picosha2::hash256_hex_string(src_str);,作者使用了项目a header-file-only, SHA256 hash generator in C++
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值