搞了半天,原来区块链的原理和Git如此相似!

899 阅读7分钟

背景

几年前比特币比较火的时候读了一些区块链相关的科普文章,粗略了解了其工作原理。最近阅读了Git内部原理,我发现这里面的很多概念和区块链非常类似,于是决定把他们俩拿出来对比,写一篇文章。

Git的工作原理

我们先来介绍一下Git的基本概念。Git的核心概念是版本和分支。当我们用Git在一个分支上创建了三个版本的时候,其内部数据存储结构如下图所示

截屏2022-11-13 15.31.54.png

右边白色方块是文件树,每个文件树有一个哈希值,这个哈希值是根据一个版本下所有文件计算出来的。而根据这个哈希值可以反过来查找到当前版本的完整项目文件,这里就不讨论文件树的实现细节了,

左边红色方块为版本节点,我们每commit一次就会生成一个这样的节点。当我创建一个版本时,Git会根据当前项目下的所有文件计算出文件树哈希,然后再根据文件树哈希、父节点哈希(第一个版本节点没有)、以及其它提交信息(如作者、commit message等)计算出版本的哈希。这一切计算并存储成功后,一个新的版本就创建完成了

这是我用git cat-file所获取到的这三个版本节点在git中的存储信息:

image.png

根据某个版本节点的父节点哈希(parent),就可以一层一层往上找到在此之前的所有提交记录,类似于单向链表。根据文件树哈希(tree),可以获取到该版本的完整项目文件。这样的话,版本节点信息的插入和查找就完成了。

这样实现有什么特点呢?

  • 首先,历史版本的文件更改起来很麻烦(并非不可更改),因为改了文件会导致文件树哈希值发生变化,这又会导致版本节点的哈希值发生变化。由于每个版本节点都会记录它的父节点,这会导致改一个节点就需要改它的子节点,子子节点,一直改到最新版本节点。

  • 其次,不仅是历史版本的文件改起来麻烦,就连commit message改起来也是一样的麻烦。只要是计算版本哈希值会用到的,都不好修改。

这时可能有人会想,那我偷偷改一个版本节点,其它节点不改会怎样。这样的话会导致链条断裂,你这个节点以及在它之前的节点就没有人能找到它了,例如我把第二个版本的commit message由“second commit”改成“hi”之后:

截屏2022-11-13 17.01.21.png

  • 如果我真的想改历史版本的文件那应该怎么办,答案是用分支。如果我想改第二个版本节点的某个文件,我可以在该节点上拉个新的分支,完成我的更改之后创建一个新的版本(643du9)

截屏2022-11-13 17.03.12.png

区块链和Git的对比

Git和区块链都是去中心化的,每个人电脑里都有一份完整的“账本”,每个电脑的“账本”都是平等的。并不存在一个中心服务器。

举个例子,你用支付宝的时候,支付宝服务器就是中心服务器,数据都存在那一个地方,你的手机是不存储数据的。当你需要转账的时候,需要发送一个请求让支付宝去更改数据库记录。而Git则是,每台电脑都有一份完整的数据拷贝,你完全可以断网操作。有人可能会误以为像GitHub这样的平台就是所谓的“中心”,其实并非如此,GitHub上的仓库和你本地电脑的仓库是完全平等的。假如GitHub有一天把你账号封了,那你依然可以在你电脑上正常工作。我们只是刚好借助GitHub这个节点去做信息同步。

区块链的区块与Git的版本节点对比

我们可以用Git的概念去类比区块链。区块链中每一个节点称为区块,区块中存储的是交易信息。这个区块可以和Git的版本节点类比。只不过Git版本节点存储的是文件信息(文件树)和commit相关的数据。区块和版本节点的共同点有:

  • 都有一个由内容生成的哈希值,只要内容变化,这个哈希值就会发生变化
  • 都存储着父节点的哈希值,这样一个节点发生变化都会导致其子节点也发生变化,产生连锁反应。这样增加了更改历史节点的难度
  • 产生一个新的节点时,都需要经过计算得到节点的哈希值。对于Git来讲,就是先计算文件树哈希再计算版本节点哈希。而对于像比特币所依赖的区块链,这个计算过程就是所谓的挖矿。计算完成后新的节点就可以加入到链中了。

区块链如何防止篡改?51%算力是怎么来的?

上面提到了Git并非无法修改历史版本数据,只不过比较麻烦。那区块链是如何防止数据被篡改呢?答案就是工作量证明机制(这里举的是比特币的区块链技术,实际上不一定是通过工作量证明,例如以太坊就是另一种形式)。说白了就是故意设计一个很耗费算力的规则,使得计算一个新节点的哈希值需要大量的计算。如果你想修改一个区块,那么也得把这个区块之后的区块重新算一遍。而每个区块的计算都要大量的算力。越早的区块更改难度越大。

假如整个区块链是静止的,那修改还是有可能的,只要你花足够多的时间总能把所有节点重新算完。但问题是不断有新的区块被计算出来并接入到链中。假设存在以下区块链,目前只有三个区块。

截屏2022-11-13 18.09.37.png

如果你想修改block2区块的内容,你需要基于block1区块拉一个分叉出来,于是你花了十分钟算出来它的新的哈希值,当你还没开始计算block3的时候,你会发现block3后面多出了几百个节点:

截屏2022-11-13 18.13.51.png

新的节点是除了你以外的全世界其他人算出来的,所以比你算的快多了。除非你掌握全世界51%的算力,那么你重新计算哈希值的速度就能赶上新节点加入的速度。这几乎不太可能。

用分支理解区块链的分叉

假如区块链中现在有三个节点。有两个人计算出第四个的结果不同,那就会出现这样的情况:

截屏2022-11-13 18.24.13.png

至于为什么会计算出两个不同的结果,原因可能是计算错误,或者有人故意篡改数据后算出一个假区块。

这里面必定只有一个是对的,这其实和Git中的分支非常类似。最终是以哪个分支为准呢,就得看哪个分支在后续发展中变得更长。而短的分支则逐渐被废弃。变得更长的分支之所以能够胜出是因为它得到更多人的认可,别人愿意基于它去计算新的区块。这也说明了一个道理,在中心化的系统里,唯一的权威就是中心数据库。而在去中心化的系统里面,没有所谓的正确与错误,多数人认可的就是正确的。