1. 哈希指针
保存区块地址及hash,两者组合称为哈希指针(具体要看实现),类似于
struct HashPointer{
void* p_blocker_;
s_sha256 hash_;
}
一个链表形式如下:
- 每个区块保存的是前一个区块的hash 指针
- 前一个区块的整体(不一定包含交易,但一定包含其头部的hash指针(prev prev block))也参与hash运算,作为当前区块的hash指针
- Tamper-evident log
下图展示了区块链的结构,genesis block 称作创世区块
上图中,如果有人篡改了blk1的数据,则blk2 中的hash指针需要修改,进而blk2 本身的hash变化,从而blk3的hash指针也需要修改,依次类推,从篡改的节点开始一直到MRB(Most recent block) 都需要修改。在分布式系统中,单个节点完成这种修改几乎不可能。这个性质也可以叫做Tamper-evident log
基于这个性质,比特币系统中的某些节点,可以只保存区块链中的一部分连续区块(完整链的一部分),比如2020.1.1 之后的区块,如果需要在这之前的区块,那么可以向比特币中的节点请求。对于请求到的数据,只需要计算hash指针即可验证数据是否被篡改
图中 prev block 是节点中尚未保存的区块,如果需要该区块时,节点向其他节点申请,然后计算得到的区块的hash值,和2020.1.1的区块对比,如果不一致,说明数据被篡改
2. 默克尔树 Merkle Tree
Merkle 树就是哈希树,哈希树就是除了叶子节点(最后一层)是数据外,其余的节点都是保存的hash值,hash树的优势在于验证大型数据内的部分数据没有被篡改。比如在比特币中的应用。
Merkle 树是如何解决了大型数据的验证问题呢?
- 传输的过程是分片的,增量的,因此Merkle tree 可以很好的进行增量验证,避免了每次传一部分数据就要整体校验(大规模数据可能十分耗时)的问题
- 这个通常在传文件分块时,我们对文件分块校验一样,相当于分层
- 可以快速定位哪个区块除了问题(即便接收完后),从而可以要求对方重传
- 分层验证
- 验证少量关键数据(比如比特币的SPV验证),即可确认内容是否被篡改
下图中HPL 代表左子树hash指针, HPR 代表右...
特点:
- 叶子结点都是数据块,非叶子节点存储的都是hash指针,根节点取hash值叫根hash值
- 满二叉树?完全二叉树?
- 上图中的Data block 都是交易信息,即区块链中的区块是以Merkle tree的形式保存交易信息的
- 只要记录根hash值即可验证一颗merkle tree 中任意数据是否被篡改
- block header 中存储了该区块中的所有交易形成merkle tree的根hash值,不包含交易具体信息
- 提供merkle proof
- block body 中保存了具体的交易信息
全节点:保存Block header + block body
轻节点:保存Block header only.(如比特币钱包)
关键业务:
- proof of membership
- proof of non membership
- 比特币中未采用
Merkle Tree和二叉树的区别:
- Merkle tree 中使用hash指针代替普通指针
假设轻节点想要验证 tx2被包含的话,其流程图如下
最后的结果中,如果计算得到的hash与root hash一致,说明tx2是被包含在该区块中的,如果hash 不一致,则说明不存在。
可见轻节点由下往上逐个验证交易的合法性
问题1. 轻节点如何知道该请求哪个位置的hash?比如上图中的请求tx3 的hash这一步
参考:简单交易验证
从这个文章可知,实际实现和课程中的讲述差异还是较大的, 交易验证被称为SPV(简单交易验证),SPV实现中。
- 节点一次性请求包含该交易的merkle tree路径,节点沿着这个路径验证交易有效性。
- merkle tree 并不是直接存储在block body 中的,而是每次请求运算出来的(动态生成出来的)
- merkle tree 路径伪造是不可能的(hash函数性质),但是轻节点仍然需要闭环验证
浙公网安备 33010602011771号