区块链学习笔记 | 比特币中的数据结构

这一篇来讲讲比特币中的数据结构,数据结构没学好的同学也是可以看懂的哟~O(∩_∩)O


1、哈希指针

​这里需要用到的一个重要的概念就是哈希指针(hash pointers)一般用H( )表示。

​普通的指针存储的是某个结构体在内存中的地址,哈希指针除了要存地址以外,还要存这个结构体的哈希值,这样做的好处是:通过这个哈希指针不仅能够找到结构体的位置,还能检测出结构体的内容是否被篡改。

2、区块链

“ Block chain is a linked list using hash pointers ”

区块链是啥?顾名思义区块链就是一个个区块组成的链表,它和普通的链表区别之一就是用哈希指针代替了普通指针。如图是一个小型的区块链:
区块链学习笔记 | 比特币中的数据结构_第1张图片

最前面的区块是系统中产生的第一个区块(genesis block),最后一个是最近产生的区块(most recent block),每个区块都包含指向前一个区块的哈希指针H( ),最后一个区块也有一个指向它的H( )保存在系统里。H( )是对前面一个区块的所有内容取哈希得到的,这里所指的所有内容当然就包括前一个区块的hash pointer

想一想这样的数据结构有什么好处?

通过这样的数据结构能够实现tamper-evident log,意思是如果区块链中的某一个区块的内容被篡改,那么就会导致后续的区块的内容全部发生变化。

由于比特币系统是去中心化的,所以有些节点可能是恶意的,无法确定某些节点是否正确,那么这个时候哈希指针就派上用场了。因为下一个区块的H( )是由上一个区块的所有内容取哈希得到的,如果某一个区块的内容被篡改过,就会导致最终系统中保留的最后一个H( )发生改变。

因此,对于一条区块链,我们只需保存指向最后一个区块的哈希指针就可以检测出整条区块的内容是否被修改。正是因为有了这样的性质,比特币系统中的一些节点就无需保存整条区块链的内容

区块链学习笔记 | 比特币中的数据结构_第2张图片

例如:小A同学只保存了区块Y和之后的区块的信息,前面的区块信息都没有保存,有一天他需要用到前面区块X中的信息,于是他找到了小B同学让他提供区块X的信息,那小A如何确定小B提供的区块信息是正确的呢?这时,他只需要将区块X中的所有信息取哈希,将得到的结果与区块Y中的H( )作比较,如果一致这说明区块X中的信息未被篡改过。

3、Merkle tree

也许大家对Merkle tree这个名词有点陌生,但是对于binary tree(二叉树)就会熟悉许多,可以将Merkle tree 当成是特殊的二叉树,Merkle tree 和binary tree的一个区别就是Merkle tree用哈希指针代替了普通的指针。

下面看一个Merkle tree的例子:

区块链学习笔记 | 比特币中的数据结构_第3张图片
最下面一层是数据块data blocks,上面的块都是哈希指针hash pointers,每两个相邻的块各自取哈希共同放入一个块中,依次往上,得到最上面的根节点,对于根节点也可以取哈希—root hash

对于这样的结构,只需要通过root hash就可以检测出对树中任何部位的修改,原理同上述第二点 区块链中最后一个hash pointer的作用是一样的。只要data blocks中的某一个块中数据发生了变化,就会影响到上一层的H( ) 的变化,最终影响到root hash的改变。

比特币当中,各个区块之间用哈希指针链接在一起,每个区块所包含的交易组织成一个merkle tree ,也就是 Merkle tree 中每一个data blocks就对应着一笔交易。

区块链中的每一个块包括两部分:块头(block header)和块身(block body),block header中包含着由块中所有交易组成的Merkle tree所得到的根哈希值root hash,但并没有包括交易的信息,交易的信息是存放在block body中。

Merkle tree有什么用呢?

一个用途就是提供 Merkle proof ,比特币中节点分为两类,一类是全节点,一类是轻节点。全节点保存了整个区块的内容,但是轻节点,比如说手机上的比特币钱包的应用就是轻节点,它只包含了block header。那么就存在一个问题,如何向一个轻节点证明某笔交易写入到了区块链中 ?

比如说,小A向小C转一笔钱,但是小C是个轻节点,因为他只能在手机上查看,那小C怎么知道这笔交易是否已经写入了区块链呢?这里就要用到 Merkle proof 了。

区块链学习笔记 | 比特币中的数据结构_第4张图片

如图,最上面的蓝色部分是一条小型的区块链,最下面一行是该节点所包含的交易。

假设待证明的交易 tx 在如上图所示位置,merkle proof 指的就是该交易 tx 往上直到 Merkel Root 所在的路径,也就是红色H( )和绿色H( )所在的路径

​首先我们得知道,轻节点没有 Merkle tree 中的具体内容,只有一个根哈希值,因为根哈希值是保存在 block header 中的,接下来就来看看轻节点如何知道待证明的交易 tx 是否包含在区块链中。

​ 轻节点向某个全节点发出请求,请求一个待证明交易 tx 包含在这个 Merkle tree 中的 Merkle proof ,全节点收到请求后,只需要将图中标为红色的哈希值H( )传给轻节点就可以了。轻节点有了这些红色的哈希值后,就可以在本地计算出绿色部分的哈希值,从而最终算出根哈希值,将它与 block header 中的根哈希值一比较就可以得出交易是否是存在于这棵 Merkle tree 中,从而完成验证。

到这里,也许有同学会想,因为红色部分的H( )是无需轻节点验证的,我想要篡改待证明交易 tx, 那我只需要调整红色部分的H( ),可以使得它和被篡改交易的H( )所生成的哈希(也就是上一层的哈希)是正确的,这样不就实现了篡改的目的吗?那,这行得通吗?

理论上似乎可行,但实际上是做不到的,回想一下前面说的 collision resistance 这一性质,上述篡改的方案其实是在人为制造哈希碰撞,但是这是行不通的,对 collision resistance 这一性质不熟悉的话,可以再看看前面文章相关的内容。

综上,Merkle proof 可以实现对交易是否存在与 Merkle tree 中的证明,这一过程也叫做 proof of membership 或者 proof of inclusion。


文章也同步在微信公众号小震同学,觉得有用的话可以关注一下哟~

你可能感兴趣的:(区块链)