二叉树之默克尔树(Merkle Tree)

wiki文档

前言

在加密学和计算机科学中,哈希树或默克尔树是一种树形数据结构,其中每个"叶子"节点都被标记为数据块的密码学哈希值,而不是叶子的节点(称为分支、内部节点或inode)则被标记为其子节点标签的密码学哈希值。哈希树允许有效和安全地验证大型数据结构的内容。哈希树是哈希列表和哈希链的一种推广。

证明叶子节点是给定二进制哈希树的一部分需要计算与叶子节点数量的对数成正比的哈希值。相比之下,在哈希列表中,所需的哈希值数量与叶子节点数量本身成正比。因此,默克尔树是加密承诺方案的一个高效示例,其中树的根被视为一个承诺,而叶子节点可以被揭示并证明是原始承诺的一部分。

定义

  • 默克尔树是一种基于哈希算法的树形数据结构。它的每个非叶子节点包含其子节点哈希值的组合,根节点的哈希值能够唯一标识整个树中包含的所有数据。

在这里插入图片描述

默克尔树的有序性

默克尔树是一种有序的数据结构时,并不是指它的节点数据本身存在大小关系,而是指它的结构存在明确的关联性,从而能够高效地查找和验证数据。

具体来说:

  • 默克尔树中的节点并不需要按照任何大小顺序排列,它们可以是无序的原始数据。
  • 但是,默克尔树的结构本身是有序的,因为每个非叶子节点的哈希值都是由其两个子节点的哈希值计算得出的。
  • 这种自底向上的哈希计算过程,建立了节点之间的有序关联关系,使得整棵树可以被高效地遍历和验证。
  • 根节点的哈希值作为整棵树的数字签名,可以快速确认树中任意节点的完整性。

产生背景

  • 默克尔树由拉尔夫·默克尔(Ralph Merkle)在1979年提出,旨在解决数字签名的问题。
  • 在分布式系统中,如何有效地验证数据的完整性和一致性是一个重要问题。
  • 传统的方法是对整个数据集进行哈希计算,但这需要下载整个数据集,效率低下。

工作原理

  • 将需要存储的数据分割成固定大小的数据块。
  • 计算每个数据块的哈希值,作为默克尔树的叶子节点。
  • 将相邻的两个叶子节点的哈希值组合起来,计算出父节点的哈希值。
  • 依此递归计算,直到得到整个树的根节点哈希值。
  • 根节点的哈希值就是整个默克尔树的标识符,也称为根哈希值。

优势

  • 默克尔树可以高效地验证数据的完整性和一致性。
  • 在分布式系统中,只需要下载根哈希值,就可以验证某个数据块是否包含在整个数据集中,大大减少了带宽开销。
  • 默克尔树的存储开销也很低,只需要存储根哈希值就可以。

数据的构建

这种基于固定大小数据块的默克尔树结构非常灵活和通用。它可以适用于各种类型的二进制数据,只要能够将数据划分成固定大小的块。这样做的好处包括:

  • 简单易实现
  • 可以并行处理数据块
  • 支持增量更新和部分验证
  • 适用于各种分布式系统和存储应用

数据块格式

每个数据块都可以是任意格式的二进制数据,比如字符串、图片、视频等。关键是这些数据块的大小需要是固定的。

数据块列表

这些固定大小的数据块会被组织成一个列表或数组,作为输入传递给默克尔树的构建函数。

构建过程

默克尔树的构建函数会遍历这个数据块列表,计算每个数据块的哈希值,然后递归地构建出默克尔树的层级结构,最终得到根节点的哈希值。

应用场景

区块链技术

  • 在比特币和以太坊等区块链系统中,默克尔树被广泛应用于存储和验证交易数据。
  • 每个区块中都包含一个默克尔树的根哈希值,用于验证该区块中所有交易的完整性。
  • 这样即使只下载区块头部信息(包含根哈希值),也可以验证某笔交易是否包含在区块中。

分布式存储

  • 在分布式云存储系统中,默克尔树用于存储和验证存储在不同节点上的文件块。
  • 只需下载根哈希值,就可以验证某个文件块是否存在于整个文件系统中。这大大减少了下载开销。

数字版权管理

  • 在数字内容版权管理中,默克尔树可用于有效地管理和验证数字资产的所有权。
  • 每个数字内容可以对应一棵默克尔树,根哈希值作为该内容的唯一标识。

数据完整性验证

  • 在任何需要验证数据完整性的场景中,默克尔树都可以发挥作用。
  • 例如在软件更新包、数字证书、日志文件等场景中,使用默克尔树可以有效地验证数据的完整性。

点对点网络

  • 在点对点(P2P)网络中,默克尔树可用于有效地传输和验证文件。
  • 只需下载文件的根哈希值,就可以验证文件的完整性,而不需要下载整个文件。

python构建默克尔树

import hashlib
from typing import List, Optional, Tuple

class MerkleNode:
    def __init__(self, data: bytes = None, left: 'MerkleNode' = None, right: 'MerkleNode' = None):
        self.data = data
        self.left = left
        self.right = right
        self.hash = None

    def calculate_hash(self, hash_function=hashlib.sha256) -> None:
        if self.data:
            self.hash = hash_function(self.data).digest()
        elif self.left and self.right:
            self.hash = hash_function(self.left.hash + self.right.hash).digest()
        else:
            self.hash = None

class MerkleTree:
    def __init__(self, data_blocks: List[bytes], hash_function=hashlib.sha256):
        self.hash_function = hash_function
        self.root = self.build_merkle_tree(data_blocks)

    def build_merkle_tree(self, data_blocks: List[bytes]) -> Optional[MerkleNode]:
        """
        递归构建默克尔树
        :param data_blocks: 数据块列表
        :return: 根节点
        """
        if not data_blocks:
            return None

        if len(data_blocks) == 1:
            return MerkleNode(data=data_blocks[0])

        mid = len(data_blocks) // 2
        left_root = self.build_merkle_tree(data_blocks[:mid])
        right_root = self.build_merkle_tree(data_blocks[mid:])
        root = MerkleNode(left=left_root, right=right_root)
        self.update_hashes(root)
        return root

    def update_hashes(self, node: MerkleNode) -> None:
        """
        递归更新节点的哈希值
        :param node: 当前节点
        """
        if node:
            self.update_hashes(node.left)
            self.update_hashes(node.right)
            node.calculate_hash(self.hash_function)

    def update_data_block(self, index: int, new_data: bytes) -> None:
        """
        递归更新指定位置的数据块,并重构默克尔树
        :param index: 数据块索引
        :param new_data: 新的数据块内容
        """
        self.root = self.rebuild_from_index(self.root, index, new_data)

    def add_data_block(self, new_data: bytes) -> None:
        """
        递归添加新的数据块,并重构默克尔树
        :param new_data: 新的数据块内容
        """
        self.root = self.rebuild_from_index(self.root, len(self.get_leaves()), new_data)

    def remove_data_block(self, index: int) -> None:
        """
        递归删除指定位置的数据块,并重构默克尔树
        :param index: 数据块索引
        """
        self.root = self.rebuild_from_index(self.root, index)

    def rebuild_from_index(self, node: MerkleNode, index: int, new_data: bytes = None) -> MerkleNode:
        """
        递归从指定索引开始重构默克尔树
        :param node: 当前节点
        :param index: 数据块索引
        :param new_data: 可选的新数据块内容
        :return: 重构后的根节点
        """
        if not node:
            return None

        if index == 0:
            if new_data:
                return MerkleNode(data=new_data)
            else:
                return self.build_merkle_tree(self.get_leaves()[1:])

        left_count = self.get_leaf_count(node.left)
        if index < left_count:
            node.left = self.rebuild_from_index(node.left, index, new_data)
        else:
            node.right = self.rebuild_from_index(node.right, index - left_count, new_data)

        self.update_hashes(node)
        return node

    def get_leaves(self) -> List[MerkleNode]:
        """
        递归获取所有叶子节点
        :return: 叶子节点列表
        """
        return self.get_leaves_helper(self.root, [])

    def get_leaves_helper(self, node: MerkleNode, leaves: List[MerkleNode]) -> List[MerkleNode]:
        if not node:
            return leaves
        if not node.left and not node.right:
            leaves.append(node)
        else:
            leaves = self.get_leaves_helper(node.left, leaves)
            leaves = self.get_leaves_helper(node.right, leaves)
        return leaves

    def get_leaf_count(self, node: MerkleNode) -> int:
        """
        递归获取叶子节点的数量
        :param node: 当前节点
        :return: 叶子节点数量
        """
        if not node:
            return 0
        if not node.left and not node.right:
            return 1
        return self.get_leaf_count(node.left) + self.get_leaf_count(node.right)

    def verify_proof(self, data: bytes, proof: List[bytes]) -> bool:
        """
        递归验证数据块的默克尔证明
        :param data: 待验证的数据块
        :param proof: 默克尔证明列表
        :return: 验证结果
        """
        return self.verify_proof_helper(data, proof, self.root)

    def verify_proof_helper(self, data: bytes, proof: List[bytes], node: MerkleNode) -> bool:
        if not node:
            return False

        computed_hash = self.hash_function(data).digest()
        for node_hash in proof:
            computed_hash = self.hash_function(computed_hash + node_hash).digest()

        return computed_hash == node.hash

# 示例用法
data_blocks = [b"block1", b"block2", b"block3", b"block4"]
merkle_tree = MerkleTree(data_blocks)
print(f"Merkle tree root hash: {merkle_tree.root.hash.hex()}")

# 更新数据块
merkle_tree.update_data_block(1, b"updated_block2")
print(f"Merkle tree root hash after update: {merkle_tree.root.hash.hex()}")

# 添加数据块
merkle_tree.add_data_block(b"block5")
print(f"Merkle tree root hash after addition: {merkle_tree.root.hash.hex()}")

# 删除数据块
merkle_tree.remove_data_block(0)
print(f"Merkle tree root hash after deletion: {merkle_tree.root.hash.hex()}")

# 验证数据块
block = b"block2"
proof = [node.hash for node in merkle_tree.get_leaves() if node.data != block]
print(f"Verified: {merkle_tree.verify_proof(block, proof)}")

这个实现使用了递归方式来构建、更新、重构和验证默克尔树。主要功能如下:

构建默克尔树: 通过递归地构建二叉树结构,计算每个节点的哈希值。
更新数据块: 可以递归地更新指定位置的数据块,并重构整个默克尔树。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/707364.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

某信用合作社数据架构规划方案(115页PPT)

方案介绍&#xff1a;为应对数字化转型挑战&#xff0c;某信用合作社计划实施一套新的数据架构&#xff0c;以提高数据处理效率、确保数据安全&#xff0c;并满足业务快速发展的需求。预期成效是完善的数据架构能够全面地提升我社六个方面的竞争能力&#xff0c;更好地服务于目…

HTML初体验

可参考jd.com官网&#xff0c;ctrlu查看当前页面源代码 找到你的项目&#xff0c;在项目中创建html类型的网页文件 标准的HTML正确书写格式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title&…

数据分析-Excel基础函数的使用

Excel基础函数&#xff1a; sum:求和 sumif:单条件求和 sumifs:多条件求和 subtotal:根据筛选求和 if:逻辑判断 vlookup:连接匹配数据 match:查找数值在区域中的位置 index:根据区域的位置返回数值 match、index:一起使用&#xff1a;自动根据列名查找数据 sumifs、match、ind…

RabbitMQ实践——配置Prometheus和Grafana报表

大纲 启用rabbitmq_prometheus插件安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动配置数据源 在《RabbitMQ实践——在Ubuntu上安装并启用管理后台》中我们已经安装成功RabbitMQ及其管理后台。在此基础上&#xff0c;我们将打通它和Prometheus、Gra…

Unity Protobuf+RPC+UniTask

远程过程调用&#xff08;RPC&#xff09;协议详解 什么是RPC协议RPC的基本原理RPC的关键组件RPC的优缺点Protobuf函数绑定CallEncodeRecvDecodeSocket.Send和Recv项目地址 什么是RPC协议 远程过程调用&#xff08;Remote Procedure Call&#xff0c;简称RPC&#xff09;是一种…

C语言| 把数组a赋给数组b

把数组a赋给数组b, 正确的写法是用for循环&#xff0c;将数组a中的元素一个一个赋给数组b的元素。 #include <stdio.h> int main(void) { int a[5] {11, 22, 33, 44, 55}; int b[5]; int i; for(i0; i<5; i) { b[i] a[i]; printf(…

手机连接ESP8266的WIFI,进入内置网页,输入要显示的内容,在OLED显示屏上显示文本

在这篇技术博客中&#xff0c;我们将探讨如何使用ESP8266 Wi-Fi 模块和SSD1306 OLED显示屏&#xff0c;构建一个简易的信息显示和交互系统。此系统能够让用户通过一个简单的Web界面输入信息&#xff0c;并将其显示在OLED屏幕上。这种设备的应用非常广泛&#xff0c;可以用于智能…

多应用对接企业微信授权和扫码登录

多应用对接企业微信授权和扫码登录是一种常见的企业级解决方案&#xff0c;它可以帮助企业实现统一的身份验证和管理&#xff0c;提升用户体验和安全性。本文将介绍如何实现多应用对接企业微信授权和扫码登录的方法和步骤。 # 第一步&#xff1a;注册企业微信开放平台应用 首…

Java——IO流(一)-(4/8):前置知识-字符集、UTF-8、GBK、ASCII、乱码问题、编码和解码等

目录 常见字符集介绍 标准ASCII字符集 GBK&#xff08;汉字内码扩展规范&#xff0c;国标&#xff09; Unicode字符集&#xff08;统一码&#xff0c;万国码&#xff09; 小结 字符集的编码、解码操作 方法 实例演示 常见字符集介绍 标准ASCII字符集 ASCll(American St…

u-boot(四)-顶层目录链接脚本文件(u-boot.lds)介绍

一&#xff0c;IMX6ULL映像文件 1&#xff0c;格式概述 对于IMX6ULL&#xff0c;烧写在EMMC、SD/TF卡上的程序&#xff0c;并不能“自己复制自己”&#xff0c;是“别人把它复制到内存里”。一上电首先运行的是boot ROM上的程序&#xff0c;它从EMMC、SD/TF卡上把程序复制进内…

京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设

京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 水库大坝监测系统主要包括渗流监测系统、流量监测系统、雨量监测系统、沉降监测系统组成。每一个监测系统由监测仪器及自动化数据采集装置&#xff08;内置通信装…

AI引领项目管理新时代:效率与智能并驾齐驱

在数字化浪潮的推动下&#xff0c;项目管理领域正迎来一场由AI技术引领的革新。从自动化任务执行到智能决策支持&#xff0c;AI技术的应用正让项目管理变得更加高效、精准和智能化。本文将探讨项目管理人员及其实施团队如何运用AI技术&#xff0c;以及这些技术如何助力项目管理…

如何用Xinstall CPS结算系统打破传统营销桎梏,实现用户增长?

在互联网流量红利逐渐衰退的今天&#xff0c;App推广和运营面临着前所未有的挑战。如何快速搭建起满足用户需求的运营体系&#xff0c;成为了众多企业急待解决的问题。而在这个关键时刻&#xff0c;Xinstall CPS结算系统应运而生&#xff0c;以其独特的优势帮助企业解决了一系列…

iptables教程

1.iptables安装 1.1 iptables和iptables-service的关系 iptables 是基于内核的&#xff0c;和 iptables-services 没有关系&#xff0c;不用安装任何工具包就可以使用 iptable 命令添加的防火墙规则&#xff0c; 但是iptables添加的规则是临时的&#xff0c;基于内存的&…

SK海力士计划于2024年第四季度启动GDDR7大规模生产

SK海力士&#xff0c;作为HBM市场的领头羊&#xff0c;于6月13日宣布&#xff0c;公司目标于2024年第四季度开始其GDDR7芯片的大规模生产。 与此同时&#xff0c;美光科技在Computex展会上也宣布推出其GDDR7图形内存&#xff0c;目前正处于样品测试阶段。据AnandTech报道&#…

CRC计算单元

CRC计算单元 CRC是Cyclic Redundancy Check,循环冗余校验的缩写. 是一种检测数据错误的技术,主要用在数据通信和数据存储的方面. 但是这种技术只能检测到传输或存储的数据是否有误,没有将错误纠正的功能. 而CRC计算单元是一个独立的具备CRC计算功能的外设. AT32 MCU片上CRC计…

当JS遇上NLP:开启图片分析的奇幻之旅

前言 在当今科技飞速发展的时代&#xff0c;JavaScript&#xff08;JS&#xff09;作为广泛应用的编程语言&#xff0c;展现出了强大的活力与无限的可能性。与此同时&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域也正在经历着深刻的变革与进步。 当这两者碰撞在一…

phpcms仿蚁乐购淘宝客网站模板

phpcms仿蚁乐购网站模板&#xff0c;淘宝客行业模板免费下载&#xff0c;该模板网站很容易吸引访客点击&#xff0c;提升ip流量和pv是非常有利的。本套模板采用现在非常流行的全屏自适应布局设计&#xff0c;且栏目列表以简洁&#xff0c;非常时尚大气。页面根据分辨率大小而自…

《现代通信原理与技术》--数字信号的最佳接收实验报告

《现代通信原理与技术》 数字信号的最佳接收实验报告 实 验&#xff1a;数字信号的最佳接收实验报告 目录 摘要......................................................................................................3 引言........................................…

Linux---系统的初步学习【 项目二 管理Linux文件和目录】

项目二 管理Linux文件和目录 2.1项目知识准备 ​ 文件是存储在计算机上的数据集合。在Windows系统中&#xff0c;我们理解的文件可以是文本文档、图片、程序、音乐、视频等。在Linux中&#xff0c;一切皆文件&#xff0c;也就是除了Windows中所理解的文件&#xff0c;目录、字…