ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

比特币 二、数据结构

2021-02-09 22:35:58  阅读:198  来源: 互联网

标签:数据结构 比特 proof 哈希 merkle 区块 节点 指针


什么是数据结构?简言之,一个比特币区块中大约有4000多条交易,这4000多条交易,我们用一种怎样的结构进行排列。是像表格一样一个一个往下排,还是两个两个一对,两对两对一组……这样(这叫二叉树),或者其它的方法,就是数据结构。研究数据结构的目的,主要是为了查找的方便。
  • 复杂度为1表示,一下子就能找到。这种算法/数据结构是最好的
  • 复杂度为n表示,随着数据量的增大,找到特定数据的消耗时间与数据量成同比例增长,是比较差的
  • 复杂度为logn的算法/数据结构的好坏,是介于1与n之间的
    比特币的数据结构中用到的重要的概念就是哈希指针,普通的指针存储的是某个结构体在内存中的地址;哈希指针除了存储结构体的地址之外,还要保存这个结构体的哈希值,这样做的好处是不光能找到这个结构体的位置,同时还能检测出这个结构体的内容有没有被篡改,因为我们保存了他的哈希值。比特币中一个最基本数据结构就是区块链,区块链就是一个个区块组成的链表。区块链和普通的链表相比区别就是链接链表的时候,有无使用哈希指针   1.hash pointers ①哈希指针的定义 区块链底层数据结构就是我们熟悉的链表,但这个链表不同于普通链表,普通链表结构如下: 一个结构体B里面如果包括了一个指针pa,那这个结构体就可以指向另一个结构体A。一个结构体C里面如果包括了一个指针pb,那这个结构体就可以指向另一个结构体B。以此类推,通过指针,结构体就可以连起来。如下图所示: 而区块链是用哈希指针代替了普通指针。哈希指针是一个可以指向数据存储位置及位置的数据的哈希值的指针   ②哈希指针的防篡改性 区块链第一个区块叫作创世纪块(genesis block) ,最后一个区块是最近产生的区块(most recent block),每一个区块都包含指向前一个区块的哈希指针 一个区块的哈希指针怎么算:是把前面整个区块的内容,包括里面的hash pointer ,合在一起取哈希值。通过这种结构,可以实现tamper-evident log。如果有人改变了一个区块的内容,后面一个区块的哈希指针就对不上,因为后一个区块哈希指针是根据前一个区块的内容算出来的,所以后一个哈希指针也得改,以此类推,我们保留的是最后一个哈希值也会变化。   使用哈希指针,可以实现tamper-evident log (篡改证明记录),因为只要前面任意一个区块进行了修改,后面哈希指针存储的哈希值都会随之发生改变,产生多米诺骨牌效应 根据上面理论,举如下例子:
  • Ho保存了 1)创世区块整体求哈希的值与 2)创世区块的地址
  • Ha保存了 1)结构体A(包括了Ho)整体求哈希的值与 2)结构体A的地址
  • Hb保存了 1)结构体B(包括了Ha)整体求哈希的值与 2)结构体B的地址
  • ……
  • Hd保存了 1)结构体D(包括了Hc)整体求哈希的值与 2)结构体D的地址。Hd保存在了用户本地
  ③哈希指针在比特币中的应用 首先我们要了解到,比特币网络中的参与者,不仅有全节点,也有轻节点。
  • 全节点full node:全节点是是拥有完整区块链账本的节点,全节点需要占用内存同步所有的区块链数据,能够独立校验区块链上的所有交易并实时更新数据,主要负责区块链的交易的广播和验证。
  • 轻节点light node:没有拥有完整区块链账本的节点。比如,手机比特币钱包客户端就是一个轻节点,他没有必要去保存所有的账本。
  因为对区块链数据的篡改,有牵一发而动全身的效果,因此比特币结构中没有要保存所有区块的内容,可以只保留最近的几千个区块。如果要用到以前的区块,可以向系统中其他节点要这个区块。怎么防止有些节点是有恶意的呢?(伪造哈希值)也就是其他节点给你一个区块,如何判断它是正确的呢?只要算出它的哈希值,与保留的区块的哈希值对比即可。   假设我们修改了结构体B中的内容(变为B'),那么结构体B'与Ha整体的哈希值就发生了变化,变成了Hc',就和原来的Hc不一致,从而整个区块就一路不一致下去,直到Hd',这样,我们对比本地保存的Hd与我们获得的Hd',就可以知道区块中有数据被篡改。   2.Merkle tree 假设我有8笔交易需要加入在区块中,那merkle tree的数据结构,就是下图的样子。其中最下面一层是数据块(data blocks),上面三层内部节点都是哈希指针(hash pointers),第一层是根节点,根节点的区块也可以取个哈希,叫根哈希(root hash),只要记住根hash的hash值,就可以检测出整棵树中任意一个地方的修改(蓝色的是区块,表示每个区块中的数据都是这种结构) 8笔交易依次排开,然后分别取哈希。(tx是交易,H()是这笔交易的哈希值)。上图中红框内,就是下面8笔交易分别取哈希的结果。   而每个框内的两个哈希值,在一起取哈希,就是上框内的哈希值,如下图箭头表示 而最上面的两个哈希值取哈希(下图),取得的哈希值,我们称为根哈希值(Root Hash) 这种数据结构的好处在于,只要记住根哈希值,就能检测出该树下的任何数据的篡改。   如下图跟随箭头,圆圈内黄色的tx被修改,那么必然导致上方绿色的H()被修改,从而导致了上方绿色的H()被修改,从而导致了上方绿色的H()被修改,最终导致了root hash这个值的修改。   3.Merkle Proof 前面提到过,比特币网络参与者包括全节点和轻节点,全节点保存了区块的所有信息,包括block header和block body,而轻节点只保存了block header。   现在假设某轻节点想要知道某笔交易是否写入了某区块中,应当怎么做?(实际中,类似A向B买东西,使用比特币支付,A告诉B这笔交易已完成,钱已付,在某区块中,B是轻节点,他该如何验证?)即,问题:A-->B 10 BTC,B为轻节点,B如何验证这比交易在区块链中?   使用merkle proof就可以解决这个问题,具体操作步骤如下:假设下图中的黄色交易是这笔交易。
  • 全节点收到了B请求验证这笔交易的信息,全节点可以看到这笔在merkle tree中的位置,他给B提供三个数据,即上图中红色的H()。
  • B在本地通过运算得到上图手指绿色H(),再和获得的红色H()一起,再在本地算出上方的绿色H(),再和获得的红色H()一起,再在本地算出上方的绿色H()……最终算到root hash值,设为H1。
  • B将算出来的root hash值H1与本地的root hash值H进行对比,如果H1=H,则这笔交易存在在该区块中。
    或许有朋友要问,为什么全节点不直接告诉B结果呢?因为不能保证这个全节点就一定是友善的。   那又有朋友要问,是否有可能全节点为帮助A伪造交易,向B提供的哈希值(即即上图中红色的H())是经过调整的,使B最终算出来的root hash值与本地的root hash值一致呢?   答案是几乎不可能。大家可以通过#1中的collision resistance和hiding property两个特性,理解这是几乎不可能的!     4.proof of non-membership   上述我们为了证明某个交易在区块中,本质是proof of membership或者是proof of inclusion。上述方法的复杂度为对数级别。   那我们是否可证明某个交易不在区块中呢?即 proof of non-membership问题     思路1:遍历一遍树   这么做的复杂度是n     思路2:对所有叶节点(即交易)取哈希,将哈希值有小到大排列。将待查找的交易的哈希值,利用“二分法”进行查找   这么做的复杂度降为log n   这种排好序的merkle tree称为 sorted merkle tree。比特币中的merkle tree,因为不需要进行proof of non-membership,所以没有使用sorted merkle tree     提供merkle proof 比特币中的节点分为两类:全节点(保存整个区块的内容,即块头块身都有,有交易的具体信息)和轻节点(例如手机上的比特币钱包,只有块头) 这时存在一个问题:如何向一个轻节点证明某个交易是写入区块链的? 这时需要用到merkle proof:找到交易所在的位置(最底行的其中一个区块),这时该区块一直往上到根节点的路径就叫merkle proof。 最上面一行是小型的区块链,该图展现的是一个区块的merkle tree,最下面一行是包含的交易。假设某个轻节点想知道图中黄色的交易,是否包含在了merkle tree里面。该轻节点没有包含交易列表,没有这颗merkle tree的具体内容,只有一个根哈希值。这时轻节点向一个全节点发出请求,请求证明黄色的交易被包含在这颗merkle tree里面的merkle proof。全节点收到这个请求之后,只需要将图中标为红色的这三个哈希值发给轻节点即可。有了这些哈希值之后,轻节点可以在本地计算出图中标为绿色三个哈希值。首先算出黄色交易的哈希值,即它正上方的那个绿的哈希值,然后跟旁边红色的哈希值拼接起来,可以算出上层节点绿色的哈希值。然后再拼接,再算出上层绿色哈希值,再拼接,就可以算出整棵树的根哈希值。轻节点把这个根哈希值和block header里的根哈希值比较一下,就能知道黄色的交易是否在这颗merkle tree里。   全节点在merkle proof里提供的这几个哈希值,就是从黄色的交易所在的节点的位置到树根的路径上用到的这些哈希值。轻节点收到这样一个merkle proof之后,只要从下往上验证,沿途的哈希值都是正确的即可。(验证时只能验证该路径的哈希值,其他路径是验证不了的,即该图中红色的哈希值是验证不了的)   这样是否不安全呢?假如黄色交易被篡改,它的哈希值发生了变化,那能不能调整旁边红色的哈希值,使得它们拼接起来的哈希值是不变的呢?不行,根据collision resistance,这是不可行的。       merkle proof可以证明merkle tree里面包含了某个交易,所以这种证明又叫proof of membership或 proof of inclusion。 对于一个轻节点来说,验证一个merkle proof 复杂度是多少?假设最底层有n个交易,则merkle proof 复杂程度是θ(log(n))   有环的用哈希指针会出现循环依赖   这种结构的好处:只要记住根哈希值,就能检测出对树中任何部位的修改。 它们的区别:①用哈希指针代替了普通指针。   比特币当中各区块之间用哈希指针连接在一起,每个区块所包含的交易组织成一个merkle tree的形式,最下面一行data blocks每个区块实际上是一个交易,每个区块分为两部分,分别是块头和块身(block header ,block body)。块头里面有根哈希值,每个区块所包含的所有交易组成的merkle tree的根哈希值存在于区块的块头里面,但是,块头里没有交易的具体内容,只有一个根哈希值,块身里面是有交易的列表的。    

标签:数据结构,比特,proof,哈希,merkle,区块,节点,指针
来源: https://www.cnblogs.com/B1ueyuan/p/14394397.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有