libra白皮书技术解读-1

简介

libra目前是一个联盟链的组织形式,他的去中心化体现在,由多个validator来共同处理交易以及区块链中的状态,但是随着时间的推移,libra也计划朝着公有链的方向发展。

对于libra,我们可以将其看做是一个通过libra协议管理的带加密认证的数据库,通过libraBFT共识算法,可以保证每个诚实节点中数据库的数据是一致的。与ethereum相似的,libra也有智能合约和账户的概念,但是不同的是,libra将合约和资源是分开存储的,这个会在后续详细展开。

下面这个图是libra协议中两种角色:client,validator。validators就像是元老会,会轮流着产生提议者,用来将当前的交易定序、打包形成区块,并且共同维护着数据库的一致性。client就是负责发起提交交易,查询信息等,比如钱包就是一个典型的client。

v2-798f029ffb8f1d93adfa16c99d92c11b_b.jpg

这里简单介绍上图的流程,当用户通过钱包(client)发起了一笔转账交易后,钱包就会将这笔经过用户签名的交易通过grpc发送给validator(过程1)。节点在收到client提交的交易后,首先会对交易进行预检验,只有有效的交易才会被validator节点转发给当前轮次下的leader,leader是validator集合中在某个轮次下有提议权利的节点,leader从本地的交易池中获取若干条有效的交易,对其定序打包后,转发给其他validator(过程2)。validator(包括leader)可以理解为是一个状态机,每个validator在收到leader广播的block后,会执行其中的所有交易(过程3)。由于validator存在作恶的可能性,因此每个validator在执行完交易后不能直接将结果写入storage中,libra的共识要求他们对执行完的结果进行投票,只有达成共识的结果才能写入到storage中(过程4)。在交易被提交成功后,validator不仅会将交易,以及结果写入到storage,还会生成一个当前交易版本下整个数据状态的签名(其实就是Merkle Accumulator),client在进行一些只读的查询时可以从这个数据结构里进行查询(过程5)。


2 数据的逻辑结构

相比于ethereum,libra弱化了block的概念,只是把它当做是transaction的载体,实际的最小执行单位是交易。对于libra,我们可以看做是一个带版本号的数据库,这里的版本其实就是交易 的序号 ,这个序号是严格递增的。在版本号为 时,数据库会保存 元组数据,这里的 表示序号为 的交易, 表示执行完 交易后的输出结果, 表示账本状态。当我们执行某个程序,过程的大致可以表述为,在某个状态下,程序代码按照给定的参数执行。例如validator收到了一笔序号为 的交易 ,当validator执行时交易时,他的状态是基于上一个版本 ,输入参数则是接收到的交易 ,而需要执行的代码,其实在 中指定了需要执行的合约。所以,按照数学归纳法的推导,如果validator的最初状态都是一致,并且是诚实的节点(即诚实的执行),那么只要他们的输入是一致的,这些validator的账本状态也将是一致的。

通过这种带版本号的数据库,可以方便的查询在各个版本下的账本数据。例如,我们需要查询在版本号为10下某个账户的余额信息。

但是随之而来的问题是,我们如何判断上述的交易、状态数据等是有效和没有被篡改的?libra针对上述情况,设计了Ledger History数据结构。

2.1 账本状态

libra和ethereum一样,采用了账户模型,这里之所以没有采用utxo,主要是因为utxo模型不适合用于复杂的合约。

ethereum的账户地址是由公钥衍生出来的,libra也是一样,不过libra在创建用户的时候会生成两对公私钥:验证、签名(vk,sk)公私钥对。其中libra的账户地址是由vk的公钥经过哈希后生成的。之所以要区分vk和sk是为了安全起见,libra用户可以在不更换地址的情况下,更换新的签名公私钥对。

关于账户状态,libra和ethereum的区别比较大。在ethereum中,账户下面会存放余额、合约、nonce等信息。libra的账户状态主要包含了两部分:module、resource。module类似于ethereum中的合约,resource则是module中定义好的资源。module和resource的归属权是分开来的,如下图所示。方框表示的是module,椭圆表示的是resource。例如对于账户0x56来说,他发布了一个Currency的module(合约),那么这个module是存储在其0x56的目录下的,如果另外一个账户0x12也拥有了Currency.T这个资源,那么该资源是存储在0x12的目录下的,相当于是将代码段和数据段分开来了。

v2-96a7e7fab4773f05dd540576357721fd_b.jpg

而ethereum的合约并不是这样的,例如我们发布了一个ERC20的合约,我们会定义一个map结构mapping (address => uint256) public balanceOf; 该结构会存储某个账户在这个合约中包含有多少ERC20的token。也就是说,ethereum中的合约是将数据段和代码段混合在一起的。

libra之所以这样做,主要是为了保证资源的所属权,从而保证其安全性。

2.2 交易

交易中有个program字段,包含了需要执行的脚本以及参数,或者需要部署的module字节码。由于libra采用libraBFT的共识,当validator接收到block,并不意味着这轮的共识结束了,所以validator在执行完接收到的交易后,并不会马上将执行后的状态写入到Ledger state中,只有当大部分的节点关于该交易执行的结果投票达成共识后才会更改Ledger state。

交易 执行完后,除了会生成新的状态 外,还会额外产生一个交易输出 。交易输出可以类比于ethereum的交易收据,包括了gas使用、执行状态、event等。这里的执行状态是指虚拟机的执行状态,并不是具体合约的业务执行状态。例如,执行状态是成功,表示虚拟机在执行过程中没有出现gas不足或者导致执行异常的触发条件。

为了能够清晰的了解合约执行的执行过程,libra参考了ethereum,加入了event事件。event就像是我们在开发中采用print方法打印某些日志数据以此判断代码的执行逻辑。事实上,在ethereum的erc20中,开发者为了判断token转账是否成功,会在transfer函数执行成功后,加上一个Transfer event,一旦交易执行完成后,抛出了Transfer类型的event,那么开发者就可以认为此次合约转账是成功的(除去分叉的概率外)。

v2-30aff7b1eae700de5753a370755457a5_b.jpg

2.3 账本历史

账本历史(Ledger History)存储了已经执行并提交(达成共识)的交易,以及event信息等。这些信息对于validator执行交易来说是不需要的,之所以存储了上述信息,主要的目的是为了保证validator的可信度。client通过查询validator的数据,以此监督validator在正确的执行交易。

发布了1万+ 篇原创文章 · 获赞 109 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/cpongo4/article/details/98179366