普通的指针存储的是某个数据在内存中的首地址。哈希指针不仅要保存地址,还要保存结构体的哈希值。通过哈希指针不仅能找到数据的位置,还能检测出数据有没有被篡改(因为保存了哈希值)。
二、区块链区块链就是一个个区块(block)组成的链表。和普通的链表相比有一些区别。
区块链用哈希指针代替了普通的指针
取哈希的时候是把整个区块的内容(包括其保存的指向下一个区块的哈希指针)一块取哈希
使用这种数据结构可以实现tamper-evident log
这个性质是说,不论是在哪个区块做了改动,都会导致系统中保存的哈希值的变化,也就是只要记录那一个哈希值就能检测出区块链任何位置有发生了修改。前一个区块发生了改变,后面的区块会连带发生变化,直到系统中的哈希指针发生变化。
这个也就是和普通链表的区别,普通链表可以修改里面任何一个结点,对整个链表其它结点没有影响,但在区块链里修改一个区块就会影响到所有比它后产生的区块。
有了这个性质,某一个用户也就没必要保存系统中的所有区块了,可以只保存最近的一些区块,如果要用到先前产生的区块,再向别人要就可以。
比如只保存了下图中红线右侧的较新区块,如果要用到圈出来的区块,可以向别人要。保存的哈希指针在这里可以校验给的区块是不是正确的,只要用自己保存的哈希指针往下个区块校验,然后再拿校验好的区块的哈希指针再往下校验,如此反复就可以了。
三、Merkle TreeMerkle Tree:用哈希指针代替了普通二叉树中的普通指针,最底下的一层叶子结点是数据块,其上的若干层非叶子结点都是存储哈希指针的。
在Merkle Tree中,只要记录下根哈希值,就能检测出对树中任何部位的修改,也就是用根哈希值保护了整棵树上没有篡改。相比前面的区块链这个效率更高。
在比特币系统中,Merkle Tree的每个数据块代表着一个交易,整棵树也就是在记录比特币系统中的交易,用根哈希值防止这些交易信息被篡改。
结点在区块链中,每个区块分为两部分,块头(block header)和块身(block body)。在块头中存储了这个区块所包含的所有交易组成的Merkle Tree的根哈希值。只在块身中存储了交易列表。
比特币中的结点分为两类:全节点和轻结点
1️⃣ 全结点:既有块头又有块身的区块,保存了交易的具体信息。
2️⃣ 轻结点:只保存了块头,没有保存块身。例如手机上的比特币钱包就使用的是轻结点。
❓ 如何向轻结点证明某个交易是写入了区块链的?例如有人向自己转账比特币,如何证明这个交易已经在区块链中的了
使用Merkle Proof:
通过区块中的块头中的Merkle Tree的根哈希值证明某个交易是存在于这个区块所对应的Merkle Tree中的,简单的说就是验证一下Merkle Tree中存在某个交易,这也叫作proof of membership或proof of inclusion。这涉及在Merkle Tree中从指定交易的数据结点到根节点的路径。
轻结点要向全结点请求图中标红的三个哈希值,然后就只需在本地为交易的数据结点向上一步步计算和拼接计算哈希值,最终和根哈希值对比,来知晓这个交易是不是真实存在这个Merkle Tree中的了。
❓ 全节点请求的如何得到: 可以要求转账的人发过来,因为第一课学过
collision resistance
的性质,没有办法伪造这些红色部分,以使得交易的哈希值和他们拼接后取哈希值保持不变。——人为制造哈希碰撞不可行
假设有n个交易(叶子结点)
Merkle proof 验证Merkle Tree中某个交易存在,Merkle proof的时间复杂度是 θ ( log n ) \theta (\log n) θ(logn)
验证Merkle Tree中某个交易不存在:使用**sorted Merkle Tree
**,排好序以后二分查找,当查找到这个交易时,要对其做Merkle proof,如果没有查找到这个交易,要对比它哈希值小和比它哈希值大的(即哈希值排序后的邻居)结点进行Merkle proof。
比特币中不需要证明某个交易不存在,所以不需要上面的sorted Merkle Tree
只要数据结构是无环的,都可以用哈希指针代替普通指针。有环的会以引起所保存的哈希值的循环依赖。
参考资料1、BitCoin and Cryptocurrency Technologies:A Comprehensive Introduction
2、以太坊白皮书、黄皮书、源代码
3、Solidity文档
4、北京大学肖臻老师《区块链技术与应用》公开课系列笔记
5、【区块链学习笔记】2:比特币中的数据结构
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)