比特币底层设计剖析(不断更新)
转载请注明出处:http://www.jzgwind.com/?p=469 by joey
最近研究比特币的底层架构,试图去通过一个合理的逻辑去思考要完成一套能达成共识的比特币网络需要解决哪些问题。中本聪的论文分别从“交易”、“时间戳服务器”、“工作量证明”、“网络”、“激励”、“回收磁盘空间”、“简化支付验证”、“组合和拆分价值”、“隐私”、“计算”这10个部分去阐述了比特币网络。中神的论文写的相对比较言简意赅,把核心思想用尽可能小的篇幅完整地阐述了出来。
这篇论文作为刚入门比特币的同学读起来会相当晦涩难懂,里面涉及大量的数学、密码学、算法、经济学等思想,想全面研究懂需要下一定的功夫,并且需要针对论文中提到的关键思想做进一步的学习才行。
本文从产品的视角重新组织论文中阐述的思想,以提出问题(需求)和解决问题(设计)的方式来理解其设计思想的精髓。
一、产品目标
设计一套能达成共识的电子货币系统。
二、产品需求与设计
上图是为了实现这样一个产品的目标需要解决的问题(需求)。
如果用一小段话来概括中本聪的设计精髓,可以如下表述:
(1)基于(非对称加密与哈希),解决了“账号所属权“、”交易加密与隐私“问题
(2)开创性地设计了“基于P2P网络的区块链”这一记账方式,解决了“交易的存储”、“交易记录不可篡改不可抵赖”、“分布式记账的拜占庭将军问题”、“货币的发行”、“交易的双花”等一系列问题。
(3)最后又提出了”UTXO和SPV”验证,分别解决了”价值转移“及”支付确认“的问题。
三、详细设计
1、账号所属权问题
即如何证明你拥有这个账号的所有权。
2、交易密码与交易传输的安全性
既然是一个基于网络的电子现金系统,必须要考虑交易数据本身的安全性,例如传统的电子银行,账户的所有人需要提供账户的交易密码,银行网络需要确保客户在交易过程中的信息安全(通常要对交易进行加密)问题。
比特币都通过“非对称加密”技术同时解决了(1)和(2)。非对称加密通过一对“公钥”和“私钥”来完成加密和解密的过程,私钥由账户所有人自行保管,在发起交易时用私钥对交易进行“签名”,确保了交易在传输过程中的加密,接收方用“公钥”进行解密来确认发起方是否有相应账户的所有权。
由于比特币是去中心化的系统,账户的所有权不像传统银行账户一样还需要身份证等一系列开户验证资料,一但账户所有权人的私钥忘记或丢失,系统是没有挂失功能和止付功能的,一但私钥被其他人盗走,掌握私钥的人即拥有账户的所有权; 而如果私钥永久性丢失的话,账户上的对应的比特币也将永久性的丢失。
3、交易记录如何存储?
以什么的形式存储交易?传统的银行系统采用中心化的基于账户的存储方式,通常采用专门的数据库系统进行存储。
比特币由采用P2P网络,开创性地提出了区块链这一交易存储方式。
这种存储方式能同时解决(4)、(5)、(6)、(7)的问题。
如上图所示,这种P2P的网络结构具有如下特点:
每一个加入了比特币网络的节点,都以一定的方式保存着账本,各个节点之间互相交互、协同,每一个节点既可以充当服务器,又可以充当客户端,是一种扁平的网络结构。
账本对应于传统中心化系统的数据库。而这是一种特殊的数据存储结构,中本聪将它称之为区块链。如上图所示,每一个结点的内部是一个链式结构,这个链式结构由一个一个的区块相互连接而成。每一个区块通常可以“区块头”和“区块体”,区块头记录了这个区块的一些基本信息:例如时间戳、工作量证明的难度、父区块头的HASH值(类似于链表里连接用的指针)、交易Merkle树的根HASH值等; 区块体保留了这个区块内记录的所有的交易,这些交易以Merkle树(平衡二叉树)的方式存储,每一个交易的HASH值作为这棵树的所有叶子节点,两两组合拼接后再次哈希后作为父节点,以此类推,直接形成根哈希,并将该根哈希存放到区块头中。
中本聪利用Merkle树这种数据结构,结合HASH算法,巧妙地将所有的交易信息最终“浓缩”为一个根HASH并且放在区块头中,它的好处是网络上一部分节点可以只存储区块头,而不存储区块体,这样能大大地节省存储空间。这样的节点区别于全节点,被称之为SPV(Simplified Payment Verification)节点,中文翻译为“简单支付验证节点”,如上图中的SPV节点所示。
至于为什么叫“简单支付验证节点”呢? 中本聪的论文里提到,这样的SPV节点,通常可以用来验证某个支付是否真实存在,并得到了多少个确认(交易对应区块所在的最长区块链,该区块后面还有多少个区块已经生成),它的验证过程如下:
1、SPV节点保存着最长工作量证明的链条上的区块头的拷贝,并且它可以不断地向网络发起询问,直到它确信自己拥有最长的链条。
2、当SPV节点需要验证某一笔支付时,它通过向相邻节点发送“Merkleblock消息”,向比特币网络索要一个哈希序列,这个哈希序是被验证交易所在的区块的Merkle树的一个分支:即从交易所在节点通往Merkle根HASH的所有HASH序列。通过将计算出来的Merkle根HASH与SPV节点上区块头上记录的根HASH比较,就可以确认这笔支付是否存在于最长链上,同时通过计算这笔支付所在区块之后还有多少个区块,可以验证这笔支付得到过多少个确认。
SPV节点通常作为验证一笔支付的存在性以及它得到多少个确认,但中本聪在论文里同时也提到,当网络被攻击者控制时(坏节点居多),SPV节点会变得更脆弱。 一个经常作为支付的接收方的节点最好还是运行全节点,既能更好保证支付验证的安全性,同时可以得到更快的验证。
PS:真正能让比特币这个网络变更加可信的,是这个网络上诚实的全节点数量,诚实的全节点数量越多,被攻击的可能性越小。https://bitnodes.earn.com/ 这个网站上实时地分析比特币网络上在各个国家运行的全节点数量。
4 、交易记录不可篡改和抵赖
一但交易所在的区块被加入到主链(最长链)并得到确认(6次确认),得益于HASH值的链式设计,如果想篡改和抵赖交易,坏节点需要偷偷地计算该交易所在的区块所有的后续区块的工作量证明,并且需要掌握51%的全网算力才能将新的分叉追赶上主链的长度并广播出去才行。
5、基于区块链的P2P网络,交易产生后谁负责记账并确保各节点的一致性?
即如何解决拜占庭将军问题。
比特币通过工作量证明(挖矿),只有找到矿(一个满足条件的随机数)的节点所产生的区块才能被网络中的各个节点承认的,相应的这个块里的所有的交易才有可能被承认。
6、这样的一个货币系统,没有央行,货币如何发行?如何控制通货膨胀?
中本聪借鉴了前人的思想,采用了工作量证明的方式来进行激励。对于一个新区块,谁先完成了工作量证明,谁就拥有这个区块里交易的记账权,作为激励,能够获得系统发行的比特币(协议约定的)以及区块里所有交易的手续费。
为了控制通货膨胀,中本聪设定了每个10分钟记一次账(添加一个区块),第一个区块发行50个比特币,以后约每隔4年每个区块发行的比特币减半,总计约2100万枚。在论文中也有提到,这和黄金开采的模式很像。
至于为什么被设定为每10分钟产生一个区块,而不是20分钟、100分钟?这是因为:
如果时间太长,会影响交易达成和确认的时效性; 如果时间太短,则由于挖矿成本低,会在这一较短时间内找挖到矿的节点会太多,加上网络的延时性,导致过多的孤立区块(孤块)和分叉。
7、基于上述设计,是怎么解决“双花”的问题的?
根据区块链的设计思想,如果网络中发生了双花的行为,双花对应的2个交易必定不在同一个区块里,且不这个区块必须不在同一个链上,也就是说双花交易肯定会导致分叉的产生,而根据区块链的约定,当分叉产生时,各节点)始终遵循“长度最长、工作量最大的”的链为主链。即最终只能有一个是有效的。
8、交易如何验证
这分为2个小问题来讲:
(1). UTXO价值转移
中本聪开创性地提出的UTXO(Unspent Transaction Output)的概念替代了传统的账户余额概念。UTXO始终以交易为中心,将任何的交易分为“输入”和“输出”,每一笔交易产生的输出都是“未花费过的输出”,即UTXO,交易的输入则来自于付款方地址上的UTXO,并且每次将UTXO作为输入时都需要用尽,多余部分作为手续费及支付给自己,从而保证了每个交易输出产生的UTXO,要么没有被使用过,要么全部被用完。
UTXO这种方式在验证交易时,不需要验证客户的余额具体是多少,只需要验证交易对应的输入UTXO足够即可,即输入UTXO 之和大于输出+手续费,多出来的再支付给自己。
比特币采用脚本来完成交易的验证。
(2). SPV简单支付验证
具体见(5)。中本聪论文里提到了简单支付验证SPV(Simplified Payment Verification),SPV节点是相对于全节点来说的,它只存储区块头信息,验证交易时,只需要从其他节点获取该交易在merkle树中从交易的叶子节点到根节点的所有HASH值(Merkle树有专门算法找到这一路径),最后比对根HASH的一致性即可。
SPV节点的目标是验证某个支付是否真实存在,并得到了多少个确认(交易对应区块所在的最长区块链,该区块后面还有多少个区块已经生成)。
总结
综上所述,比特币具有的特点为:
(1)匿名性
(2)交易可追溯、防篡改、防抵赖
(3)去中心化、高度自治