学习视频来源:https://www.bilibili.com/video/BV1Vt411X7JF/?p=3
本博客除了记录视频内容学习笔记外,还包含少部分自己扩展的内容。
文章目录
- [1. 哈希指针](#1. 哈希指针)
- [2. Merkle tree(默克尔树)](#2. Merkle tree(默克尔树))
-
- [2.1 Proof of membership(成员证明)](#2.1 Proof of membership(成员证明))
-
- [2.1.1 方法1 默克尔证明](#2.1.1 方法1 默克尔证明)
- [2.2 Proof of non-membership(非成员证明)](#2.2 Proof of non-membership(非成员证明))
-
- [2.2.1 方法1](#2.2.1 方法1)
- [2.2.2 方法2](#2.2.2 方法2)
1. 哈希指针
区块链使用哈希指针代替了普通指针,将相邻区块连接起来。普通指针存储的是某个数据结构体在内存/磁盘中的地址,哈希指针除了保存这个地址,还要保存这个结构体的哈希值,通过这个哈希值我们知道这个结构体有没有被篡改。
在区块链中,每个区块都包含一个指向前一个区块的哈希指针,创世区块除外,因为它没有前驱。 具体来说,区块头中包含一个字段 prev_block_hash,其值就是前一个区块完整内容的哈希值(在比特币中为双 SHA256 哈希,即 SHA256(SHA256(block)))。 这个哈希值覆盖了前一个区块的所有关键字段,包括其自身的交易默克尔根、时间戳、Nonce 以及它所指向的更早区块的哈希指针------形成递归嵌套的完整性依赖。
这种由哈希指针串联而成的链式结构,构成了一个 防篡改日志(Tamper-Evident Log):
- 如果攻击者试图修改某个历史区块(例如区块 N)中的任意数据(如交易内容、时间戳等),
那么区块 N 的哈希值将随之改变; - 但区块 N+1 中存储的 prev_block_hash 仍然是原始的、未被修改的哈希值;
- 因此,区块 N 的新哈希值 ≠ 区块 N+1 中记录的前驱哈希值,系统即可检测到不一致;
- 若攻击者想掩盖篡改,就必须重新计算区块 N 的哈希,并修改区块 N+1 的 prev_block_hash 字段;
- 而这又会导致区块 N+1 的哈希值改变,进而需要修改区块 N+2......如此连锁反应,一直延续到链的末端。
这就是所谓的"牵一发而动全身"------篡改任一历史区块,必须同时重做其后所有区块的工作量证明(如 PoW),在具备足够算力安全假设的系统中(如比特币),这是计算上不可行的。因此,只需保存并信任最新区块的哈希值,就能通过向后逐级验证哈希指针,高效地确认整条链从创世区块至今的完整性。任何对历史数据的篡改都会破坏这一哈希链,从而被立即发现。
2. Merkle tree(默克尔树)
区块链各个区块之间是通过哈希指针连接起来的,每个区块所包含的交易是组装成一个Merkle Tree的形式。树的最后一层是交易,其他的节点全是哈希指针。每个区块分为2部分,块头和块身。树的根哈希值是存在区块头中,但是区块头中不包含交易,块身中是有交易列表的。
默克尔树可以是二叉树,也可以是多叉树。但比特币中使用的默克尔树是严格的二叉树。
2.1 Proof of membership(成员证明)
即验证一笔交易在区块链或默克尔树中。
2.1.1 方法1 默克尔证明
比特币节点有两类:全节点和轻节点 。全节点包含整个区块的内容:区块头和区块体,轻节点只包含区块头,可以通过Merkle
Proof验证一笔交易已经写入了区块链,步骤如下:
- 获取交易哈希。轻节点要知道目标交易的唯一标识,即交易哈希。
- 向全节点请求默克尔证明。
轻节点向一个或多个全节点发送请求,要求提供该交易在特定区块中的默克尔路径或称默克尔证明。默克尔证明包括
- 该交易在默克尔树中的所有兄弟哈希(下图中红色H())。
- 该交易在叶子节点中的位置索引:确定每层中当前节点是左/右,从而正确拼接兄弟哈希。
- 目标区块的区块头(含 Merkle Root):提供权威的 Merkle Root 用于最终比对,用于最后和本地计算出的做对比。
- 本地重建默克尔根
轻节点使用目标交易的交易哈希、收到的兄弟哈希列表(按从底到顶顺序),按照默克尔树的构建规则,逐层向上哈希(下图中绿色H()),最终计算出一个默克尔根。 - 区块头中的默克尔根比对
如果计算出的默克尔根等于区块头中记录的默克尔根,并且该区块头已被确认(例如通过工作量证明 PoW 有效,且处于最长链上),则说明该交易确实被包含在该区块中。因为如果默克尔根没变,就说明区块中树中所有的数据都是没有被篡改的。

注意
查询的时候,全节点只返回待验证交易相关路路径的哈希值,就是图中红色H(),其他不相关的哈希值是不返回的。
红色的H()是不被验证的,理论上一个恶意的全节点,可以构造一个哈希值,使得交易改了或者某个哈希值改了但最终的根哈希不变,但实际上这种概率是非常低的。
2.2 Proof of non-membership(非成员证明)
即验证一笔交易不在区块链或默克尔树中。
2.2.1 方法1
全节点把整个树传给轻节点,轻节点收到后,验证这棵树的构造是对的,即交易、哈希值等都是正确的,则说明这个树的所有交易都在这里了,然后看要目标交易是否在这个树里就可以了。 这个一种比较慢的方法。复杂度的O(n)。
2.2.2 方法2
如果对每个叶节点按照哈希值从小到大排序,组成默克尔树,被称为Sorted Merker tree。验证目标交易时看目标交易的哈希值在叶子节点的哪个位置。如果是在2个节点之间,向全节点请求这两个叶子节点各自的默克尔路径,分别验证这两条路径是否能正确重构出区块头中的 Merkle Root。若两者均有效,则说明这两个叶子节点确实存在于原区块中,且它们在排序后的节点是相邻的,不一定非得是兄弟节点,而目标交易哈希严格位于二者之间却未出现,因此目标交易一定不在该区块中。复杂度O(logn)
比特币当中没有用到sorted Merker tree,因为比特币中没有Proof of non-membership 这种场景需求。