• 注册
    • 查看作者
    • 《重新创造比特币》第16章:Block Chain

      0.前言

      Bitcoin的点对点网络架构中,已经实现了交易的同步和账本的同步。

      虽然,账本的同步是一个依赖中心化单点Timestamp Server的临时方案,但是我们先不管它。

      我们先来关注Gilfoyle想到的新点子,即,账本的拆解。

      1.失控中的即兴

      咖啡馆,Gilfoyle一进来就看到中本聪已经喝着咖啡在等他了。

      中本聪说:“来来,我们继续讨论,昨天你提到的账本拆解的点子。”

      Gilfoyle说:“好,等我也要杯咖啡去。”

      老板Bob把咖啡端过来:“最近哥俩咖啡喝的挺频啊,来灵感啦?快点升级好,早点让Bitcoin恢复上线啊!”

      中本聪说:“好好,我们正努力呢!你再等等,快好啦!”

      中本聪嘴上说快了,其实心里一点谱都没有。

      这一次系统的演进,可谓Bitcoin的质变,精确系统变成复杂系统,可谓物种级别的突变。

      中本聪和Gilfoyle就像是两个探险家,在一片原始丛林中前行,没有地图,甚至没有道路,一切都要根据当下情况,即兴的选择路线。前方是否能走出去,是否存在陷阱,两人都无法预知,只能靠着直觉,在失控中走好下一步。

      当然,中本聪喜欢这种失控感,因为失控中的控制力才是真正的控制力。这种体验就像是在悬崖上进行徒手攀岩,精微控制着身体,像壁虎一样吸附在镜面般的岩壁上,品尝着生与死的边缘,那才是真正活着的感觉。

      to be or not to be that is a question.


      2.一石二鸟

      中本聪说:“你再把昨天说的点子详细说说呗,账本如何拆解?”

      Gilfoyle说:“昨天我说到,账本现在是一个大文件:transaction.txt。频繁全网广播太浪费资源。我们可以将账本文件分割成多个小文件,每个小文件就是一个账页,账页按照顺序串连起来还等价与之前的账本。这样,每次同步只需要广播最新的账页即可。

      不过,昨天回去我又有了些新的理解。

      账本的本质是什么?

      账本的本质是系统中过往交易数据的总和。所以账本代表着系统的过去。

      而交易内存池中的数据是系统实时进行的行为,所以交易内存池代表着系统的当下。

      记账这个动作,本质就是在做数据备份。

      由于全网都要依赖这份数据备份,所以拥有记账权的节点责任重大。在这个10分钟内,它承载着系统的正确性。

      所以,记账这个行为,也要记录在系统中。目的是可以追究记账者责任,当然除了追究责任,也可以给记账者一些利益,例如给记账者送几个Bitcoin作为奖励。这些都需要依赖这份行为记录。

      那么记录在哪呢?

      传统系统的设计思路,是将记账行为独立写入一个日志文件中,日志文件再与账本关联。

      但是,我昨天晚上忽然明白了,我们可以借助账本的拆解,来实现记账行为的记录。

      换句话说,账本的拆解可以一石二鸟。

      即可以,避免全量数据传播的资源浪费。

      又可以,让记账行为关联的责任和奖励有的放矢。”

      3.账页的连接

      中本聪赞叹到:“精彩!具体如何落地呢,账页如何顺序连接起来呢?”

      Gilfoyle详细的解释起来。

      我们把每个账页称为:Block,就是区块的意思。每个Block在物理上是一个独立文件:block.txt。

      每个Block中装的是具体的交易记录,我们将交易记录抽象为:Item。(见下图)

      账页

      现在我们的目标是将Block按照顺序前后连接起来,这样就形成了一个类似珍珠项链一样的一条链,英文为:Chain。

      如何实现连接呢?

      我们自然会想到,唯一ID的关联,让后面的Block在自己文件的第一行写入前一个Block的唯一ID。这样后面的Block就伸手主动的抓住了前面的Block。一个抓一个就形成一条链了,直到创世区块:MetaBlock。

      那么如何获得Block的唯一ID呢?

      这就需要再次请出之前我们讨论过的概念:Hash(哈希)。

      Hash算法是一个全世界公开的算法。任何人用任何编程语言都可以实现逻辑相同的Hash函数。

      任何数据作为参数,输入到Hash函数中,函数运行,输出唯一且不变的Hash值,用公式表达,即,HashID=FuncHash(Block)

      HashID可以看成为这段数据在宇宙中的唯一坐标,或者看成在宇宙中的唯一身份证号,再或者看成是这段数据的唯一指纹。

      这里要注意一点,Hash函数是不可逆的,什么意思呢?

      意思就是说,我们只能根据数据得到HashID,不能根据HashID反过来得到数据。

      这就好比,我们无法根据一个人的指纹来创造出这个人的肉体。

      但是,如果这个人站在我们面前,我们可以通过Hash函数瞬间得到他的指纹。

      所以,一个人可以被任何人验证,某个指纹是不是属于他的。

      例如:这个人将自己的指纹按在一个房产合同上,这样房子和这个人的实体产生了连接。

      因为,指纹可以映射宇宙唯一的个人。所以,在文字符号的世界里,指纹就是实体在法律上的等价代理。

      所以,关联了HashID,就等于在关系层面上关联了实体。

       

      接下来我们看看如何落地

      记账节点构建Block Chain的步骤:

      1.记账节点获得记账权。

      2.节点使用Hash函数,计算出前一个Block的HashID。具体做法是将前一个Block的文件(例如Block1.txt)作为参数,输入到Hash函数中,运行结果就是前Block的HashID。

      3.节点创建一个新的Block文件(例如Block2.txt),然后将上一步骤中的HashID写入到当前Block文件(Block2.txt)的第一行。

      4.节点从第二行开始,继续写入交易数据。

      5.节点写完所有交易数据之后,将当前Block广播到记账网络。

      这样记账网络中就通过节点轮流记账,构建出了一个,基于HashID关联的Block Chain,即,区块链。(见下图)

      Block Chain

       

       

      4.区块奖励

      中本聪赞叹到:“精彩!继续说说第二只鸟,在哪记录节点的记账行为?”

      Gilfoyle说:“我们可以借鉴现实中的会计记账。

      现实中账本的每一页都会分为两个部分:

      通常,这一页纸的上半部分通常都会保留一个空间,用来记录记账人的姓名,记账时间,还要按手印呢。

      然后,下半部分才记录具体的业务数据,即账目数据。

      我们也可这样来设计Block,给Block文件划分为2个部分:

      第一个部分叫做区块头:Block Header,用来记录非业务数据:系统数据。

      第二个部分叫做交易集:Transactions,用来记录业务数据:交易记录。(见下图)

      Block

      Gilfoyle说:“Transactions中的数据很单一,就是交易记录。

      Header中数据还需要设计一下,究竟要记录哪些数据?”

      中本聪说:“关联前Block的HashID就可以放入Header中。”

      Gilfoyle说:“对,只要是非交易数据,都可以放入Header部分。”

      中本聪说:“还有,能够描述记账行为的数据,例如记账时间,记账的节点IP。”

      Gilfoyle说:“对,这些也要放进来。我在思考,如何描述对记账者的奖励。

      如果能实现记账的奖励机制,那么Bitcoin系统就可以吸引到越来越多的节点加入。

      这样一来,Bitcoin系统就真的可以称为一个“永动机”了。”

      中本聪说:“这个思路太棒了!之前老板Bob还问我提供机器能得到什么好处呢!好处就是获得bitcoin的奖励啊!”

      那么如何表示,节点获得Bitcoin呢?

      能够表示节点的现在只有IP,IP是没法接收Bitcoin的,只有公钥地址可以接受Bitcoin。

      中本聪忽然灵感闪现:“只要让每个节点都拥有公钥地址就行啦,节点记账的时候,凭空创建出来一条交易记录,给自己的地址转50个Bitcoin。”

      Gilfoyle说:“牛牛牛!凭空创造交易,而不是引用之前的UTXO,这在本质上岂不是在铸币和货币发行嘛,又是一个一石二鸟!即解决了吸引节点加入的激励问题,又解决了铸币和发行的问题。”

      中本聪说:“对啊,今天咱倆运气爆棚了,收获了这么多意外之喜!

      这样一来货币的发行就不再使用之前的丑陋方案了。

      之前的临时方案是,将2100万个Bitcoin一次性的写死在satoshi的地址中,由satoshi来单点发行货币。

      改为区块奖励机制之后,货币发现就由单点变成多点,货币的铸币和发型就会越来越分散,Bitcoin就好像散落在地下的黄金,无中生有的被随机开采出来,流入民间。”

      Gilfoyle问:“那么如何让节点关联公钥地址呢?”

      中本聪说:“我们在代码中加入一个配置文件,节点的拥有者部署代码之前,先手工改一下这个配置文件,将自己的公钥地址写入进去,这样节点启动后读取这条地址,就可以当成是自己的记账奖励要转入的地址了。”

      Gilfoyle继续问:“这条无中生有的交易记录,写在Block Header里吗?”

      中本聪思考了一下说:“我感觉写到Header不合适,因为虽然是对记账行为的奖励,但是本质上也是一笔交易,是交易就应该属于业务数据,就应该写入到Transactions中。这样,我们就约定,每次节点获取记账权,开始写Transactions部分时候,第一条都无中生有的创建一条50Bitcoin的区块奖励转账给自己的公钥地址。”(备注:为了保证2100万个Bitcoin的总量上限,区块奖励减半的策略大家应该都耳熟能详,就不在文章中啰嗦了。)

      Gilfoyle说:“可以,这样看上去很flow了。还有一点差点忘了,交易记录中的手续费也应该奖励给记账节点,否则手续费就会凭空消失了,Bitcoin就等于在慢慢燃烧,越来越少。”

      中本聪说:“对对,还好你提醒我了,创建区块奖励这笔交易时候,先计算下所有交易的手续费总和,也要和那50个Bitcoin一起转给自己。”(见下图)

      区块字段

      具体的字段:

      Header部分:
      1.前区块的HashID:Previous Block Hash
      2.记账的时间戳:Time
      3.记账节点的IP:IP(备注:真实世界的Bitcoin没有此字段)

      Transactions部分:
      1.第1条交易为区块奖励,交易记录中的不引用过去的UTXO,而是在in部分加一个字段coinbase来表示此UTXO是无中生有的铸币。
      2.第2条之后为正常的交易记录。

      (备注:这里的字段描述做了简化处理,具体技术细节请参考arron67'blog:[学习笔记] 比特币的区块和区块链-https://aaron67.cc/2019/01/05/bitcoin-blockchain/)

      5.后记

      本篇完,直到这篇,我们才引出Block Chain区块链这个概念,可以看出来,区块链的地位在整个系统中并不是那么核心。

      正是由于账本的拆解,我们可以有机会来表达对于记账行为的奖励。记账的奖励将会激励更多的陌生节点加入,我们将会遇到网络发现,陌生节点作恶等难题。

    • 0
    • 0
    • 0
    • 69
    • 单栏布局 侧栏位置: