潍坊市论坛

注册

 

发新话题 回复该主题

Hash指针和数据结构区块链和默克尔 [复制链接]

1#

一、指针的一般定义

指针是每一个程序员都需要面对的难题,人们常说C语言效率高的原因之一就是因为它把操作内存的最高权限以指针的形式开放给了程序员,但这容易让程序员们为所欲为从而造成很多安全问题。高级语言golang退而求其次,虽然有显式的指针概念,但一般情况下(不一般的情况是golang确实也提供了一些可以进行指针运算的底层库)不允许像C或者CPP那样进行指针运算,只是单纯的指向某块内存地址。java更甚,语义层面上并没有指针的概念,取而代之的是更加安全也更加受限的引用(thinkinginjava中将其翻译成句柄,很形象)。

总而言之,无论是指针还是引用,或是句柄,本质上都是一个数据类型,编译的时候保存的是一段地址,其应用无处不在,从基础的数据结构如链表,到高级数据结构树,无处不在,btw,你会反转二叉树吗...

二、Hash指针

基于一般意义上的指针的含义,我们可以给出hash指针的概念:

hash指针可以指向一段被存储的信息

同时hash指针还保存了这段信息的hash值

如下图:

当我们拥有一个hash指针时,不仅可以取回信息,同时基于hash函数的碰撞阻力这一特性,我们可以轻松的判断取回的这段信息有没有被篡改/p>

基于此,理论上我们在任何使用了指针的数据结构中,用hash指针取代之,从而使该数据结构拥有探测数据是否在篡改的特性。

三、blockchain

最有名的应用就是我们熟悉的区块链,实际上区块链就是一个类似于单向链表的数据结构,只不过我们在其中应用了hash指针:

每一个新增加的数据块都持有对上一个数据块的引用,同时保存了上一个数据块中data+prehash的hash值,试想一下现在你想更改上图中中间位置的data值,由于碰撞阻力的存在,该数据块整体的hash值会发生变化,从而与下一数据块(最左边)中保存的prevhash不一致,为了掩盖这种不一致,你必须要更改中间这一数据块的prevhash,这又会导致中间这一块的prevhash与最右边的数据块的整体hash值不一致…意味着你要一直去改preblock直到创世区块,然而创世区块是硬编码的,运行时无法修改。这就是我们常说的区块链上数据无法被篡改的理论支撑。

四、默克尔树

hash指针另一个比较重要的应用是默克尔树,MerkleTree,又叫HashTree,直观的理解就是带有hash指针的二叉树:

如图所示,最下面的是一个个数据块,可能是由一个大文件分割而来,从下往上依次两两数据块的hash值,再往上则是两两hashstring的hash值,直到默克尔树的树根。

传统的B/S架构下,如果我们在网上下载一个比较重要的软件或者文件,服务提供商在给出软件下载地址的同时,还将其hash值一并给出,以确保在网络传输的过程中没有被篡改或者丢失(一般是一串md5,长心的同学可能会留意到),但在p2p架构下,为了更好的利用网络资源,提高下载效率,一个大文件往往被分割成许多小一点的数据块,存储在网络的不同节点上,等所有的数据块下载完毕,再将其恢复。

为了在下载的过程中验证数据块的完整性和正确性,我们可以事先在一个可信的源获取默克尔树根,再从其他不可信的源获取整个默克尔树或者仅仅是默克尔树的一个分支,主要roothash验证通过就行了。紧接着我们就可以在一个数据块下载完毕之后就去验证它的hash值,如果不一致,换个节点,重新下载一次就好了。

欢迎读者加入哈希区块链社区

分享 转发
TOP
发新话题 回复该主题