2017年12月14日OKEx上线DAT币。该币的官方网站是datum.org。通过阅读其白皮书,发现该币的技术实现依赖一个叫做BigchainDB的技术,号称可以大容量、低延迟、高吞吐量的实现区块链技术。比特币的可扩展性不好是众所周知的,这样一种神器当然会引起人的好奇心。搜了一下,找到了BigchainDB的论文,是2016年6月的技术。决定好好读一读。
废话不多说,我们直接看具体技术,下面会沿用原文章的章节编号。
~~以下大部分是翻译稿~~
4. BigchainDB描述
4.1原理
BigchainDB不是从区块链技术出发来解决扩展性问题,而是从适用于大数据的分布式数据库的角度出发,增加一些区块链特性,希望以此避免传统区块链技术全备份的缺陷。(译者:这也不一定是缺陷,比特币的全备份和共识相关)。
我们在企业级分布式数据库的基础上建设BigchainDB,希望这样的BigchainDB具有高吞吐量、高容量、全功能NoSQL查询语言、有效查询和授权管理。特别的,增加的节点可以增加吞吐量和容量。(最后这句是针对比特币说的)。
鉴于大数据数据库具有内在的共识算法,能容忍一些故障型错误,我们的方案直接使用了这一技术。我们增加了一些算法来决定写什么样的交易,按照什么顺序写入区块。我们不鼓励使用私有的,节点间点到点通信的方式,鼓励使用数据库的内在通信机制。我们认为这样可以减少系统的复杂性,降低安全风险。这一假设意味着攻击节点不能向网络的一部分发送一条消息,同时向网络的另外一部分发送另外一条消息。简单讲,在这个模型中,每次一个节点“说话”,所有其它节点都可以收到。
4.2 概览
我们主要增加了以下区块链特性到数据库中。
1. 分布式控制:“没有人”拥有或者控制一个网络;
2.不可修改:写入(区块)的数据是(永久)防篡改的;
3.(有价值):可以不依赖中心实体通过网络生成和转移资产。
分布式控制通过具有投票权限的联盟节点实现。其它节点可以读取和提交交易。投票是在数据库内在的共识机制之上完成的。多数人的投票意见作为仲裁依据。(区块生成与投票操作是分开的),每一个区块都可以在投票和验证之前生成并写入数据库。但是区块链的实际形成却是通过投票完成的。每一个区块的id是该区块的交易,时间戳,投票人,生成节点公钥的哈希值(特别注意不包括前一个区块的哈希)。每一个区块还附有一个签名和一系列的投票。这一系列的投票由投票人在区块生成之后生成。投票中包含该区块的前一个区块的哈希值!不可修改性涉及以下机制:分区、复制、恢复不允许的更新和删除,常规的数据库备份,交易的数字签名,区块和投票。(关于有价值),任意有资产发行权限的实体都可以发行资产。资产转移的时候必须满足交易的密码条件。这意味这攻击者或者恶意的系统管理员不能任意修改数据,不存在单点失败的风险。
4.3 体系结构
图3展示了BigChainDB的体系结构。尽管该系统向客户提供API时类似一个单独的数据库,但实际上有两个数据库(表):交易集合S库和区块链C库。这两个库通过BigchainDB共识算法(BCA)连接。BCA运行在每一个投票节点中。非投票客户端根据权限的不同,可以读取,生成资产,转移资产等。
S 库和C库本身是两个单独的商业数据库,例如ReThinkDB数据库。我们不改动数据库内部的工作机制。好处是提升了数据库的可扩展性,还有例如版本控制和良好测试的代码等。每一个数据库运行其内部的类似Paxos的一种共识算法来达到数据的一致性。
S库存放未排序的交易。当一个交易到达某个节点之后,如果该节点认为该交易是有效的,就把该交易放到S库。同时把该交易随机的分配给一个其它节点。(注意S库会在多个节点之间同步数据,所以这里的随机分配给一个节点是为了让该随机节点打包交易,以图3为例,S库中是有所有7个交易的,但是S1节点只负责其中的三个,其它两个节点各负责两个)。
假设有N个签名节点。S_k=,t_,...}是分配给节点k的交易。
节点k运行BCA处理S_k中的交易:该节点把未排序的S_k中的交易进行排序,生成一个区块,把区块放在C库中。
签名节点可以投票决定区块是否有效。签名节点检查区块中每一个交易的的有效性,如果存在无效交易,则投出区块无效的选票;否则,给出有效的选票。
每一个区块一开始都是不确定的状态,没有选票。当多数选票认为区块有效后,进入确定有效状态;多数选票认为区块无效后,进入确定无效状态。进入确定状态后,区块及其交易不可再修改。
完整的一个区块包含区块id,时间戳,交易,投票信息等。
4.4 行为描述
本节描述一个客户端生成一个交易发给一个服务器节点的过程。每个服务器节点都有关于S库和C库的视图。
图4中每个卡片代表一个物理设备。客户端设备在左侧。客户端连接到右侧的BigchainDB服务器节点(即投票节点,也就是说客户端需要连接投票节点)。任意客户端可以向任意服务器节点发送交易。
图4左侧,客户端生成了一个有载荷的交易,ID是#A。BigchainDB数据库的S库是空的,C库只有一个创世区块。其它客户端类似操作。
当客户端发出交易以后,接收节点(译者:注意是投票节点)把该交易分配给联盟节点中的某个投票节点,并存入S库(译者:这里存入S库之后,由底层数据库确保所有投票节点都可以看到)。图4右侧展示了一个示例状态。我们看到节点1被分配了三个交易,节点2两个交易,节点1一个交易。C库还是空的。
图5左侧显示了节点1处理完分配给它的交易的状态。节点1把分给它的3个交易从S库中取出,生成一个区块,写入C库(注意区块的结构中不包含前一个区块的ID)。新的区块排在C库的末尾。
图5右侧显示节点3也处理完了分配给它的交易,写入了新的区块到C库。
当一个区块首次写入C库时,其状态是未确定的(译者:注意到底层数据库同步了写入C库的数据,所以所有投票节点都可以见到新区块)。每个投票节点投出支持或者反对的票。如果一个区块之前的所有区块都是确定的(包括判定无效),并且该区块内所有的交易是有效的,该区块才可以投票为有效。当有效或者无效投票达到多数之后,该区块进入确定有效或无效的状态。
在这个例子中,节点1的区块经过投票成为确定有效状态。节点3的区块在后续投票中判为无效。在图5中有阴影的区块表示确定为无效的区块。
当出现无效区块的时候,区块内的一些交易可能依旧是有效的,BigchainDB数据库给这些交易第二次机会。图6展示了这个过程:无效区块中的交易#B和#E重新写入了S库,以等待写入区块的下一次机会(译者:下一次,交易会由不同的节点验证,打包)。图6还展示了BigchainDB是如何处理无效区块的。无效区块并没有从C中移除,而只是标记为无效,这样不管它整个系统会更简单些,存储空间在BigchainDB中并不是一个问题。类似的,投票也是流水操作的,并不会在一个区块确定之后就停止一下(译者:意思是有区块就一直投)。
图7强调了上述过程是多个设备并行操作的。左侧显示一个节点可能与多个客户端有连接。右侧显示节点数量不止一个,尽管这些节点关于S和C库有一致的视图(由底层数据库技术保证)。
(译者:通过这一节可以明确BigchainDB库是由多个联盟节点形成的,通过投票和区块操作在数据库中形成区块链,其共识算法就是简单的多数投票,所以在诚实节点占多数的情况下,可以确认C库的数据是达成了共识的区块链数据)
4.5 数据模型
4.5.1交易
交易是一个JSON文档,具有以下结构
{
“id”:除了签名字段之外的所有内容的哈希值
“version”:交易模型的版本
"transaction":{
“fulfillments”:前一个交易的哈希值和签名值,类似比特币输入脚本
“conditions”:类似比特币的输出脚本,指定本资产转移的条件
“operations”:决定交易如何被验证,目前包括“创建”和“转移”
“timestamp”:客户端生成该交易的时间
“data”:{
"hash":载荷的哈希
"payload":任意JSON文档
}
}
}
4.5.2区块模型
区块是一个JSON文档,具有以下结构:
{
“id”:区块的哈希值
"block":{
“timestamp”:区块生成的时间
“transactions”:交易列表
“node_pubkey”:生成该区块的节点的公钥
“voters”:联盟节点的公钥列表
}
“signature”:区块的签名(生成区块节点的签名)
"votes":投票节点的投票列表
}
(译者:可以看到每一个区块明确包含了所有投票节点的公钥,投票节点不宜过多)
4.5.3投票模型
投票节点的投票具有以下结构:
{
“node_pubkey”:投票节点的公钥
“vote”:{
“voting_for_block”:被投票区块的id
“previous_block”:该区块的前驱区块
“is_block_valid”:投票
“invalid_reason”:包括无,双花,交易哈希不匹配,节点公钥不匹配等(译者:后面两个应该是签名验证错误)
“timestamp”:投票的时间
}
“signature”:投票的签名
}
4.6区块验证和区块链管道化
图8展示了一个区块链C。区块B_1是创世块。
区块按照底层数据库决定的顺序持续写入C库中。这意味着当一个签名节点插入一个区块到C库时,它不能同时完成投票。因为投票包含前一个区块字段,但是写入C库时并不能确定前一个区块。只有在写入区块的操作由底层数据库完全确认之后才有可能确定区块顺序。
(译者随感:一个分布式数据库,装备上Raft等共识,可以确保数据库中数据一致,例如超级账本。但是这些一致的数据没有经过投票检验,所以可以修改。而一旦投票之后,区块成链,哈希打包,再修改数据就可以检验了。这应该是BigchainDB比一般数据库好一点的地方。另外,一般数据库有管理员密码就可以随便读写,这个BigchainDB数据库C库的内容却不能随便写,而是要符合投票检验的规则)
在区块顺序确定之后,节点才可以投票。区块生成后,是不确定状态。投票完成后,转为确定有效或者无效状态。
与一般的区块链不同,这里的区块结构中并没有前一个区块的指针。相反的,一个区块中包含一些投票,每一个投票中包含一个前一个区块的指针,所以说这里是投票时才链化。
正常情况下,投票节点所指向的前一个区块的指针应当是相同的。但也有异常的情况发生。例如,一个节点宕机了,可能会导致异常。
在一个节点宕机之后,不会有大量新区块需要这个节点完成投票。因为区块中包含投票节点列表,而当区块宕机之后,区块中不会包含这个宕机节点的公钥。
区块B_2受到了5个投票中的3个.这3个投票都是确定有效的投票,并且达到了半数以上,因此区块进入确定有效状态。
区块B_3接收到了5个投票中。半数以上是确定无效,,区块进入无效确定状态。该无效区块留在C库中,但是当验证新区块时会把该区块忽略掉。
区块B_4是未确定状态,还没有获得半数以上的投票。
注意到尽管B_4是未确定状态,它也有后续的B_5区块(前面讲到C库的底层机制决定区块的顺序,其实应该是节点的处理速度确定的)。逻辑上,该系统把投票和生成区块分开了。分叉就不是这个系统可能具有的功能(任意区块只有有效无效的区别,只有一个列表,不存在分叉!)这里的原因在于所有节点是在相同的区块链(数据集)上工作的,而不是每个节点在自己的本地数据集的基础上工作的。节点间通信是通过数据库内在的机制完成的,可以看成一个广播信道。(译者:如果攻击的是底层数据库的数据一致性,成功的造成投票节点有不同的视图,就可能会出问题。所以这个假设也决定了该技术适用于联盟链的场景)。鉴于此,每个节点都可以增加新的区块,但是只会变成B_4的区块。后续区块按照底层数据库技术继续增加。可以把整个区块链想象成一个单向铁轨,下一个区块就挨着前一个区块放。在一个不确定状态的区块后面,当然可以继续增加新的区块,例如B_5和B_6区块。
把未确定的区块作为父区块确实会带来一些问题。特别的,我们需要对双花问题多做一些操作。我们要求放到新区块中的交易不能依赖任意非确定区块中的交易。这一策略通过两个方面来实现,一个是在生成新区块时检查这样的交易是否存在,一个是在投票时检查,如果一个区块包含这样的交易,这个区块投票为无效区块。
4.7BigchainDB共识算法(BCA)
BCA是在每个签名节点运行的一个分布式算法。这一节使用类Python的伪代码来给出BCA算法
4.7.1 主循环
def mainLoop()
global S,C #就是那两个全局库
while True:
S = assignTransactions(S, k) #k是运行该算法的节点编号
Sk, C =addBlock(Sk, C, k) #Sk是分配给k节点的交易集合
C = voteOnBlocks(C, k)
后面还给出了一个并行的主循环伪代码,如下:
(译者:这个并行版本充分表明每个投票节点可以独立的运行三个进程,一个负责接收交易到S库,并分配给特定节点;一个负责把自己负责的交易(在Sk集合中)打包成区块;一个负责对区块(流)投票。)
4.7.2 assignTransactions函数
def assignTransactions(S, k):#这个函数包括两个子函数
S = assignNewTransactions(S, k)
S =reassignOldTransactions(S. k)
return S
def assignNewTransactions(S, k):
for each new tx, t from outside: #对于每个接收的新交易t
if t is valid: #如果t是有效的
i ~ U() #随机选择一个其它节点i
t.assign_time=time()
Si = Si U t #再次注意到S库是分布式数据库,所以i知道
else: #通知发送方出错?伪代码没有处理
return S
defreassignOldTransactions(S, k):
for Sj in :
for each tx, t, in Sj:
if(time() - t.asign_time) > old_age_thr)#超时过了门限
i ~ U() #随机选择一个其它节点i
t.assign_time=time()
Si = Si U t
Sj = Sj - t
return S
交易可能会变Old的原因在于分配给某个节点后,这个节点宕机了,处理满,或者故意不作为等等。所以这个函数对S库中所有的子集扫描,扫描每个子集中的每个超市交易,重新对该交易分配节点。
4.7.3 增加新区块和对区块投票
(译者:增加新区块的操作就是把Sk的交易逐一判断是否所依赖交易不对,是否合法性不对,都是好的,就放到T_new中。否则,就放到T_postpone中。之后对T_new的交易打包,其中votes是投票集合,明确为空,其它在4.5.2节有定义。打包后写到C中,由C库自动同步排序。Sk更新存放推迟的交易(T_postpone)。需要注意的是在该函数中使用到了一个本地的B_tail区块来判断交易好不好,所以一个宕机重启的节点在C库同步完成前B_tail这里也许跟别人不一致。C库一边同步,一边写入新的,可能会使得部分节点关于B_tail的视图与其它节点不一致。该数据库的解决方法是不一致就等等,应该还是行之有效的)
(译者:区块投票函数就是找到自己该投的最早的区块(区块是C库单独排序的一个链),验证区块的有效性,然后在区块的第k个位置写上自己的选票,如果这个投票的区块是确定无效的,就把B的数据重写回S中(注意到S库会自动过滤相同的交易)。之后处理下一个区块。)
4.7.4验证交易
(译者:前面的函数中所用到的交易验证函数定义在这里。第一个是区块内交易验证函数,与投票所调用的稍有不同,其实可以理解为T和B_i一致。这个函数做的就是逐一验证区块内每一个交易。第二个函数验证每一个交易,可以看到并没有明确使用区块的信息;第三个需要用到区块信息以区分当前区块,以前的区块等。)
4.8 共识算法检查点列表
当我们设计BCA时,考虑了以下内容:
区块顺序。区块生成后不可修改(译者:有生成区块的节点签名)。这样区块之间的排序才有意义。
投票哈希。(本设计中区块的id并没有包含投票字段,毕竟生成区块时还没有投票。这意味着区块的投票是可以删除的。)
丢失交易。有些节点在分配到交易后宕机,所以设计了重新分配函数。
拒绝服务。构造恶意的交易干扰网络运行。(译者:设计者认为这和Web服务的拒绝服务类似,无法避免。所以,BigchainDB自身不是抗拒绝服务的。需要增加新的机制,例如名誉系统,积分赏罚,押金系统等)
客户交易顺序。(译者:这个需求是要求客户的交易顺序在服务节点应该保持。但是BigchainDB做不到!采用类似比特币的序列号的方法?然后服务节点检查交易时检查内存中的未打包交易的顺序?这个看起来有点难。比特币的序列号方法引起了拒绝服务攻击)
底层数据库内在通信机制的脆弱性。(译者:作者认为这不应该是一个问题。否则,当今的很多分布式数据库都会出现问题)。
双花攻击。(译者:作者认为已经充分考虑了该问题,一个新的交易是否双花需要检查所有的已知交易。)
恶意表现。(译者:如何解决节点的拜占庭表现?作者认为在联盟环境下,这种表现很容易检查出来,并受到惩罚。)
“上帝化”的管理员。这个系统的管理员具有像“上帝”一样的能力,进而导致单点失败吗?我们仔细的限制了系统管理员的权限,其权限还不如投票节点。根据我们目前的知识,系统管理员没有超级权限,因为所有的交易写入都需要投票完成。
离线节点。如果一个或者多个节点离线会怎样?(译者:少数几个离线没问题;离线节点过多会造成区块堵塞,诚实节点和攻击节点占比发生变化)
为什么以区块为单位,而不是以交易为单位。这里有几个原因:第一,数据库操作中,写1000个含有1000个交易的区块比写100万个交易要容易;第二,减小了投票节点所需要投票的数量;注意到投票是需要签名的。
4.9 交易的有效性,激励措施和原生资产
检查交易的有效性涉及许多方面。签名必须是有效的。有一些字段是必须存在的。各种值的表示必须正确。如果是生成交易或者注册新资产,那么同样的资产不能已经存在。如果交易是转移资产,那么资产必须存在。资产的转移操作必须由资产的所有人作出。
每一个投票节点会检查每一个交易的有效性。注意BigchainDB共识算法是基于联盟的。一个节点能否对交易(区块)投票取决于该节点是否有投票权限。这与POW模型和POS模型不同。(译者:言外之意是没有激励措施)
(传统上,数字资产要么像比特币一样,是系统的原生资产,要么像SPOOL一样,是依赖原生资产存活的,这两种方式各有缺点,作者给了一个表来比较)
4.10 激励措施和安全性
POW和POS模式下,激励措施和安全性是合在一起考虑的。但是这些方法带来了扩展性问题。
而在像BigchainDB这样的联盟中,每个节点自身的安全性以及整个网络的安全性不在系统本身,而是依赖外部。例如每个节点都不安全,整个系统必然是可攻击的。(译者:作者后面说外部激励的方式在公开部署中也是合理的,例如投票节点具有自己的需求去维护一个公开的数据库,例如非营利组织等)。
~~~~~~~~以上大部分是翻译稿~~~~~~~~~
关于BigchainDB的总结:
该技术适用于联盟链,联盟节点共同维护一个分布式数据库,各自为该数据库增设当前常规的安全措施以保证其安全性。在此基础上,这些节点可以采用该技术来对写入数据库中的数据进行分布式的控制,按照共识的原则向数据库中写数据!
该技术可能存在的问题:
1)单个投票问题:一个恶意的联盟节点生成区块时设置所需投票的数量为1,然后写入区块,并马上对该区块作出确认有效的投票。该攻击的有效性在于C库同步之后是不是攻击者能第一个投票。解决问题的方法在于每个区块应该包含的选票总数应该有下限。
2)删除问题。管理员如果参与交易的话,可以先生成一个交易,发给节点后,由节点包含在某个区块中。之后管理员使用其权限删除包含其交易区块的所有区块及其后续区块,是的原来的交易无效。解决方法是限制管理员的删除操作。下表是该文给出的限制管理员权限的一个示例表。
3)顺序问题。恶意联盟节点同时是交易节点。故意把交易的顺序打乱写入区块链,有可能造成双发。解决方法是交易双方等待区块链最终确认。
4)假冒节点问题。这是一般性的认证问题。客户端如何识别区块链节点,在工程实现中需要考虑。
5)拒绝服务攻击。这个问题BigchainDB没有解决。但是基于该系统的数字货币可以用类似比特币的方法解决。
最后,给出该技术的性能表,包括数据库系统的容量和延迟。
~~结束~~
领取专属 10元无门槛券
私享最新 技术干货