比特币二之区块链中的数据结构

正在学习区块链,如果我哪里有错误希望大家指出,如果有任何想法也欢迎留言。这些笔记本身是在typora上写的,如果有显示不正确的敬请谅解。笔记本身也是给我自己写的,所以如果有侵权的请通知我,我立即删除。

2.1 哈希指针

其实就是一种特殊的链表而已。

链表中的首元节点就是创世区块,整个区块链中的第一个区块。链表中只存储前后节点指针就行,但是区块链还要存储前一个节点的哈希值,就是下图中的H(),一个链表节点就是一个区块。所以要想修改某一个区块,以后所有的区块全都要动。

因为哈希指针的存在,我其实只需要存储最后一个节点就能完成很多操作。如果我想知道倒数第二个节点呢?可以管其它节点要,那怎么知道其它节点给的对不对呢?用哈希指针算一下就好啦。

区块链和普通链表的区别就是用哈希指针代替普通指针,下面要讲的merkle tree也是,用哈希指针代替普通指针。

![avatar][pic2.1-1]

2.2 merkle tree

一根链表,只要记住头指针的哈希指针,整根链表就能验证了,因此也可以记住一棵树的根节点来验证整棵树。这个过程就叫merkle proof。

区块链就是区块的链表,区块中有什么呢?区块头block header和区块体block body。block header中存储了很多必要信息,例如merkle tree的根节点哈希。而block body中存储的就是这个块中的全部交易信息,这些信息是以merkle tree的形式存储的。下图就是一个区块链的例子。其中蓝色的是区块,树就是block body。tx是transaction的意思,就是交易。可知全部的交易tx都存在叶结点中,那中间节点呢?只是一个个哈希值。

![avatar][pic2.2-1]

2.2.1 merkle proof

区块分为两种,轻节点和全节点,这也就是block body为什么采用merkle tree的原因,可以减少空间复杂度。轻节点的block body中只会有这棵树的根哈希,全节点会存储整棵树。如果一个轻节点想知道某个交易记录,因为它自己不存,它就要向全节点要,而要的时候也不需要要整棵树,只需要要一些哈希值就好。比如上面那张图,我想知道黄色的tx节点是否在这棵树中,我需要向全节点要图中的三个H(),而图中 H()是我求出来的哈希值。

先看第一步,求出黄色块的哈希值,如下图

avatar

接着用上一步的结果同向全节点要来的H()结合,求出其父节点的哈希值,如下图

avatar

以此类推,可以求出最终的节点是否正确。

2.2.2 merkle proof的复杂度

这个分为两种,一种是树中是否有这个节点,一种是树中是否没有这个节点。

前者的时间复杂度,那就是树高嘛,O(logN)。

后者的时间复杂度有些问题,按照中本聪的方法,merkle tree是没有任何顺序的,因此时间复杂度是O(N),因为比特币没有找是否不存在这个需求。但是按照肖老师的说法,其实是可以提高的,比如在生成区块的时候,直接把merkle tree的叶节点进行排序,这样以后任何人在查的时候用二分就行了。比如可以用哈希值的大小排序。如果待查的交易哈希是20,二分找到一个a和b(a是小于等于20的最大节点,b是大于等于20的最小节点),轻节点取得a和b计算就行了。这里有点问题,肖老师举的例子中a和b的父节点是同一个,如果a和b的父节点是兄弟节点,我要不要做a和b父节点的merkle proof呢?我觉得需要。

2.3 区块链的结构

2.3.1 区块头 block header

上面也说了,区块链解释一个链表,链表中存有所有的block header,轻节点中没有block body,哈希指针只计算整个block haerder。
  bitcoin是没有问题的,但是在使用其它数据结构的时候,要注意,区块链表只能是一条链,不能是循环链表。因为哈希指针始终要依赖于前一个节点的哈希,但是循环链表的“前一个节点”是无限递归的,所以永远找不到。

下面是区块链中区块头的结构

Field Purpose Updated when… Size (Bytes)
Version Block version number You upgrade the software and it specifies a new version 4
hashPrevBlock 256-bit hash of the previous block header A new block comes in 32
hashMerkleRoot 256-bit hash based on all of the transactions in the block A transaction is accepted 32
Time Current block timestamp as seconds since 1970-01-01T00:00 UTC Every few seconds 4
Bits Current target in compact format The difficulty is adjusted 4
Nonce 32-bit number (starts at 0) A hash is tried (increments) 4

nonce只有4个字节,最大只能是2^32次方,然而现在这个挖矿难度,遍历完nonce可能也找不到满足挖矿要求的hash值,既然头部就这点东西,看看哪个值能改,改了之后能满足挖矿要求就行。

Version是区块链的版本号,不能变。

hashPrevBlock是前一个区块的哈希值,不能变。

Time是时间戳,其实可以变,不太离谱就好,因为区块链对时间的要求不是很高。不过有更好的

Bits是挖矿时的目标阈值,编码后的,不能变。

Nonce本来就要变的。

hashMerkleRoot这个是可以变的。因为每个区块的产生都有一个coinbase transaction,就是可以凭空造出比特币的那个交易,这个交易是可以改的。我的理解是,每个交易都要标明交易的发起方和接收方,接收方肯定是矿工,发起方就可以随便填。而这个交易一遍,整个根哈希值就变了,也就达到了修改block header的目的。实际中会使用coibase中的前8个字节也用来挖矿,总共就有2^96次方种情况。

2.3.2区块体中的实际交易transaction

avatar

红框左侧的output其实是之前交易的output,用于证明这部分钱是属于你的的UTXO,也就是0.05那个,0.049的是最终输出的,中间的Fees是矿工小费。

发布了19 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qigezuishuaide/article/details/104244310