声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表火星财经官方立场。
边肖:记得要集中注意力。
来源:了解于闯
作者:0x7F@了解于闯404实验室时间:2020年1月9日
原文:https://paper.seebug.org/1110/
0x00前言随着技术的激增和国家政策的推动,区块链慢慢进入了我们的视野。在2020年初的这个时刻,我们不妨回顾一下区块链的发展,谈谈区块链的几个技术要点,为新的一年打好基础。
2017年是数据货币爆炸的一年。其标志性事件是2017年12月比特币价格创历史新高,区块链被引入大众视野;所以2018年被称为区块链元年,各种与区块链相关的数字货币和技术在互联网上如雨后春笋般出现;后来,随着区块链监管力度的加大,2019年对区块链来说是寒冷的一年,终于所有有价值的区块链项目都接受了考验。
那么,在本文中,我们将撇开数字货币,仅从区块链方面来谈;本文使用比特币v0.19.x的源代码(commit:0655 C7 a 94 cc 9 BF 54d 43 seed 805 e 83 f1 b 59 e 2409)来帮助理解。
0x01区块链简介区块链随着比特币的诞生而诞生,最早出现在《比特币(https://bitcoin.org/bitcoin.pdf)白皮书》中,用于存储比特币的交易记录;在比特币中,多个交易记录按照时间顺序集中排序存储形成一个块,块之间通过哈希值连接形成链式结构,我们称之为区块链。
在比特币中,多个节点通过P2P网络共同维护一个区块链,使得这种链状结构去中心化、防篡改、可追溯。后续的以太坊、超级账本等项目也是基于这种链式结构。
这里,我们抛开数字货币,以区块链为主角。我们可以更容易理解区块链:区块链是基于P2P的分布式数据库,多个节点共同维护一个数据;从这个角度来说,比特币区块链中存储的“交易记录”也是数据,只是数据比较特殊。
0x02区块链vs分布式数据库我们可以认为区块链是基于P2P的分布式数据库,因为区块链和分布式数据库有相似的目标:使用多个节点共同维护一个数据。
但我们只通过“存储”的操作来理解,而忽略了自身的应用场景,所有节点都是可信的,可靠的,默认无延迟的通信,等等。在实际环境中,我们需要考虑上述因素,因此区块链不能等同于分布式存储数据库。
我们使用表格来比较区块链和分布式数据库:
区块链分布式数据库
分布式体系结构
价值主张数字信任系统的高性能存储和访问
用于网络通信的对等客户端-服务器
管理模式:集中管理和分散管理。
数据结构的链接索引等。
对节点关系的怀疑制约了信任与合作。
一致一致性算法的主从复制
数据持久性数据不可变可修改非持久性。
低性能和高性能
了解了区块链和分布式存储数据库的异同后,可以知道分布式存储数据库和区块链都需要解决分布中的问题;区块链仍然需要解决其独特的问题。因此,我们基于分布式存储数据库来帮助我们理解区块链中涉及的技术要点。
0x03分布式系统1中的挑战。FLP不可能原理对于分布式系统中的不确定性,Fischer、Lynch和Patterson三位科学家在1985年发表论文,提出了FLP不可能原理:在网络可靠性最小化的异步模型系统中,即使只有一个节点失效,也不存在能够解决一致性问题的确定性算法。
所以理论上一致性问题没有完美的解决方案,但是在工程应用中,我们可以选择牺牲一些特性来换取一个可行的方案。
2.CAP原则那么我们应该如何选择代价来换取这个可行的方案呢?2000年在ACM由Eric Brewer教授组织的一次研讨会上,提出了CAP原则:分布式系统不可能同时保证以下三个特性:一致性、可用性和分区性,在设计上往往需要削弱对某一特性的保证。
根据CAP原理,我们可以根据不同的需求选择三个特性。如果访问分布式网站的静态内容,可以接受数据的延迟更新,削弱了一致性;在区块链中,即使牺牲性能,也需要确保只有一个被认可的数据,这削弱了可用性。
3.拜占庭容错在分布式数据库中,节点相互信任,彼此忠诚。他们可能会离线或停机,但他们永远不会发送错误的消息。所以我们可以信任任何一个节点,分布式数据库往往采用“主从复制”来实现一致性,即选择一个节点作为主节点,其他节点从该节点复制数据。如果该节点出现故障,将选择一个新的主节点。
在区块链中,节点可以自由加入和退出,可能会出现恶意节点:节点可能会离线、宕机,发送错误消息扰乱数据的一致性;这通常被称为拜占庭一般问题。
这是上世纪80年代提出的假设性问题。其中描述道:“一群拜占庭将军率领一支军队联合围攻一座城市。因为每支军队都在城市的不同方向,他们只能通过信使沟通;军队的行动策略仅限于进攻或撤退,军队的一些进攻和一些撤退可能会产生灾难性的后果,因此将军们必须通过投票达成一致的策略;每个将军都通过信使将自己的投票信息通知其他将军,这样每个将军都可以知道投票结果,并根据自己的投票和所有其他将军发送的信息决定行动策略。”
上图中,叛军发送的错误投票信息导致的不一致问题称为“拜占庭错误”,处理拜占庭错误的方式称为“拜占庭容错”。那么在区块链是如何解决的呢?
0x04一致性算法PBFT算法PBFT(实用拜占庭容错)算法主要是为了解决拜占庭错误而提出的。算法的核心是三个阶段:预准备阶段(pre-preparation stage)、准备阶段(preparation stage)和提交阶段。让我们来理解下图中的算法。
其中c代表请求客户端,0123代表服务节点,3个节点出现故障,F代表故障节点的数量。
c向节点0发起请求。节点0向其他服务节点广播请求。在接收到预准备消息后,节点可以选择接受和拒绝该消息。收到消息后,它将准备消息广播给其他服务节点。当节点处于准备阶段并接收到2f准备消息时,它进入提交阶段。向其他服务节点广播提交消息。当一个节点处于提交阶段并接收到2f 1提交消息(包括其自身)时,它向C客户端发送一条消息。当C客户端收到回复消息时,表示共识已经完成。
PBFT的节点数必须满足N=3f 1的关系。只要节点中故障节点的数量不超过1/3,就可以确定一致性。由于其特点和性能问题,PBFT算法经常被用于小规模的联盟链。
PoW算法PoW(工作证明)算法用在比特币中,就是工作量证明算法。算法的核心是利用复杂的数学计算来竞争一次加块的机会,结合“不利原则”和只承认最长的链是合法链的规则来完成节点共识。
在比特币中,PoW的工作方式如下:
用户发起一个事务,节点广播该事务,直到所有节点都收到事务包并将其放入一个块中。节点计算散列结果并获得添加块的机会。2中的块被添加到区块链的末尾,并且该块被广播到所有节点。收到新的方块信息后,验证方块的合法性,合法后加到区块链的末尾,进入下一轮比赛。通过PoW算法,即使全网出现50%的节点错误,比特币依然可以完成共识。
PoW算法的实现PoW算法位于块生成模块(挖掘)。我们来看看比特币的启动过程。比特币程序入口位于bitcoind.cpp下,比特币中的各种服务都是通过这样一个调用链来启动的:
main-AppInit-AppInitMain
包括RPC服务。在比特币中,我们需要使用bitcoin-cli通过RPC服务开始挖坑,最后在rpc/mining.cpp/generateBlocks中生成主逻辑:
其中,pow.cpp/CheckProofOfWork函数通过PoW算法进行验证,主要是判断当前nonce值下,块hash值是否小于难度值:
而另一些,因为PoW算法的低性能和大量计算能力的浪费,人们又提出了新的共识算法,比如PoS(权益证明),DPoS(委托人权益证明机制),等等。然而,从比特币占区块链项目一半的事实来看,PoW仍然是最常用的共识算法。
0x05存储结构在了解了共识算法之后,我们就可以保证数据的一致性,那么这些数据在区块链中是如何存储的呢?
Merkle Tree在比特币中,Merkle Tree用于将交易信息组织存储在一个块中。它是基于hash的二叉树(或多分支树),其结构如下:
叶节点存储数据。非叶节点存储其子节点内容的哈希值。使用Merkle树的优点是:
快速对比大量数据,对比根节点的哈希值,就知道两组数据是否相同。快速定位修改,子节点的任何修改都会传递到根节点,从根节点向下搜索就能找到修改的节点。
Merkle树在比特币中实现,Merkle树的生成是挖掘步骤中的一个子步骤。它遵循上述块生成过程中的miner.cpp/IncrementExtraNonce函数,并在该函数中调用consensus/merkle . CPP/blockmerkerroot函数来构建Merkle树:
在一个块中,哈希链不仅包括打包成Merkle树的事务信息,还包括块高、随机数、时间等信息,其中父块的哈希值将所有块连接起来形成一个链结构,如下:
哈希链在比特币中实现,块由块头和Merkle事务树组成。块头的数据结构在primitives/block.h中定义如下:
0x06网络通信那么,区块链中的节点是如何传输数据的呢?相对于分布式数据库的服务器-客户端网络结构,采用主从复制来同步数据,区块链是一种对等网络结构。当节点获取数据时,也需要向其他节点提供数据。
我们直接来看p2p协议在比特币中的实现。
P2p协议是用比特币实现的。默认情况下,tcp侦听建立在端口8333,以启动p2p服务。在bitcoind的init.cpp/AppInitMain启动过程中,网络被初始化并启动:
[init.cpp/AppInitMain()]
node.connman-Start
开始节点入口,网络初始化和建立。
[net.cpp/Start()]
2.初始化绑定
建立网络监控
3.AddOneShot
添加种子节点
4.跟踪线程.
启动五个网络处理线程
这五个线程负责p2p网络处理流程:
其中,负责p2p协议处理的线程是ThreadMessageHandler线程。让我们来看看这部分流程。在这个线程中,尝试从每个节点接收数据,接收到数据后会进行如下调用流程:
[net_processing.cpp]
进程消息-进程消息
判断进程消息中的协议格式。比特币中的p2p协议格式如下:
然后输入实际消息处理流的ProcessMessage。在这个函数中,主要逻辑是多个if-else语句根据commmand进入不同的消息处理流程。支持的消息有:
每个命令都有不同的消息格式和处理逻辑。这样比特币就打通了节点之间的通道。
0x07总结通过这篇文章,我们从分布式数据库的角度讲了区块链的一些技术点,了解了区块链和传统分布式的异同,也了解了区块链的基本概念和原理。
区块链的去中心化和不可篡改的特性给我们提供了无限的遐想,但目前还没有公开完善的区块链项目,我们希望这一天早日到来。
参考资料:
1.《区块链技术指南》
2.《白话区块链》
3.《区块链原理、设计与应用》
4.https://bitcoin.org/bitcoin.pdf
5.https://101 block chains . com/区块链对比数据库差异/
6.https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf
7.https://medium . com/ultrain-chain/区块链和分布式数据库之间的差异-556f8361e6b3
8.http://pmg.csail.mit.edu/papers/osdi99.pdf
9.https://github.com/bitcoin/bitcoin
10.https://zh.wikipedia.org/wiki/.的拜占庭将军
11.https://www.zhihu.com/question/264717547
请注明出处。