不说谎的源代码:Libra区块链是中心化的
关于Libra项目,市场上并不缺少深入的分析,包括长期和短期理论,媒体的报道也五花八门。然而,这些分析当中,很多都集中在项目的愿景(与Facebook的业绩相比),或者是针对Libra白皮书本身的研究。而对于Libra源代码中隐藏的内容,却鲜有人提起。本报告旨在通过窥视Libra项目的代码库,了解其代码是否反映了Facebook提出的逐步实现“去中心化”Libra项目的意图。
(注: 原文 作者是TD Research研究合伙人Raul Jordan,本文为译文)
基础知识
Libra项目是由一个大型团队以完全中心化的方式构建的,这个团队可能拥有“无限”的预算,使用Facebook最高的开发和项目管理标准。因此,Facebook的工程师们,从一张白纸开始,花了大量时间了解其他密码货币项目的发展前景,以及它们的权衡和设计决策。
他们的任务不是“我们如何构建Libra”,而是“什么是一流的技术,例如P2P网络包、编程语言和RPC通信库,Facebook应该使用这些技术构建Libra,即使是牺牲了去中心化”。
与以太坊最大处理400万个验证者不同,Libra不需要在这个约束下运行。因此,Libra的代码必须设计成更像一个性能良好的服务器,而不是一个完全去中心化、拜占庭式的容错系统。为了填补这些空白,Libra还可以自由地开发其名为"Move"的智能合约编程语言,并构建自己的内部软件和工具来完成这项工作。
为什么这些决定很重要?
这些决策很重要,它们与其他密码货币项目的软件治理思想形成了鲜明对比。Facebook不需要一个社区或一组核心开发人员的共识来决定将什么技术融入到Libra中。Facebook在构建Libra时不需要在不相关的团队之间构建多客户端网络或一致性测试来构建相同的协议。如果Libra 项目经理达成共识,即必须实施某项功能,必须使用某些技术,他们肯定会让自己的工程师来建造。
而其他的密码货币项目则是在不同的约束下运行的,新一代的密码货币需要进行ICO,或进行种子轮融资,又或者仅仅是让社区自愿为项目进行贡献,而后者正遭受着公地悲剧的困扰。如果一个项目确实成功地通过了融资挑战,那么它现在必须迎合公共/私人投资者的群体,通过其网络,获得挖矿者/验证者群体的一部分,并在短时间内发布一个产品。对于已被构建为无需许可模型的项目,它们在进行软件改进时,通常会遇到协调困难问题,通常这需要不相关团队之间的很多讨论和协调来实现变更请求(RFC)。诚然,这种协调困难受益于无许可创新,任何工程师都可通过正确的论点和理由建议对协议进行改进,然后获得支持,并通过社区的共识将其纳入未来的硬分叉。如果Facebook真的决定走这条路,而Libra项目背后有一个更大的社区,它可能会面临其他密码项目所遇到的同样的治理难题。
考虑到协议的无许可改进承诺,包含基于优点和共识的特性,那为何一些一流的技术并没有被那些密码货币项目所采用呢?主要原因在于去中心化的项目,想要实现共识是非常困难的。一旦很多团队实现了一个协议,就很难创建让每个人都满意的结果,从而导致更多的治理痛苦。例如,在Go语言中实现和标准化通用序列化库,可能要比在Rust等可访问通用类型的语言中要困难得多。
考虑到Facebook只需维护一个客户端,并且已研究了一段时间的协议,它可以根据自己的协议设计,结合任意多的实现决策。结论是,以有效的方式构建真正去中心化的项目是非常困难的。与其他密码货币相比,不受此约束的Facebook,在为产品发布强大的代码库方面可能会占据优势。
验证者 vs 公共节点运行者
Libra协会的网站上提到:
“协会的一项任务是与社区合作,随时间的推移,使网络逐渐过渡到无许可模式。”
尽管这绝对应该是Libra项目的目标,但我们还是花时间去深入了解它的代码库,看看它的基础是否是为这个转换而建立,或者这是否需要从当前的实现中大幅度地脱离出来。
而第二件事,也许也是让我们对第一件事有最深入了解的一件事,就是特权验证者对网络的能见度,是否与普通节点用户的能见度不同。其中最关键的一点是,任何用户(不仅仅是特权验证者)是否能够自由下载和复制账本的整个状态,以独立地验证交易(译者注:这也是去中心化区块链全节点的功能)。
关于源代码之外的主题,我们能找到的最全面的信息是Libra的 官方文档 ,它提供了该项目的鸟瞰图,以及关于如何运行和连接到运行中的测试网的说明。目前,Libra为用户提供了两个选项:
(1)运行连接至测试网验证者的本地客户端;
(2)运行一条本地链上的本地验证者节点;
对于选项(1),运行连接至验证者的本地客户端,Libra允许我们访问一个 CLI(命令行界面),它允许我们创建新账户、转移币,以及查看与测试网上帐户对应的状态/交易(或译为事务)信息。
也就是说,作为一名用户,我只能查询来自验证者的有限交易/状态信息,但是没有查看完整状态信息或新交易提交到账本的选项。
libra% query txn_acc_seq 0 0 true
>> Getting committed transaction by account and sequence number
Committed transaction: SignedTransaction {
{ raw_txn: RawTransaction {
sender: 3ed8e5fafae4147b2a105a0be2f81972883441cfaaadf93fc0868e7a0253c4a8,
sequence_number: 0,
payload: {,
transaction: peer_to_peer_transaction,
args: [
{ADDRESS: 8337aac709a41fe6be03cad8878a0d4209740b1608f8a81566c9a7d4b95a2ec7},
{U64: 10000000},
]
},
尽管上面的CLI 告诉我们,这可能只是软件故意模糊化了可能存在的常规用户的信息。也就是说,在网络中读取每笔交易(或事务)的功能可能存在,但可能是被CLI工具隐藏了。也许可通过分叉项目并修改其代码,以使我们能够读取账本本身?我的本地客户端是否可以和测试网完全同步?让我们看看:
libra% h
Connected to validator at: ac.testnet.libra.org:8000
usage: \<command\> \<args\>Use the following commands:
account | a
Account operations
query | q
Query operations
transfer | transferb | t | tb
Suffix 'b' is for blocking.
Transfer coins (in libra) from account to another.
submit | submitb | s | sb
\<signer\_account\_address\>|\<signer\_account\_ref\_id\> \<path\_to\_raw\_transaction\> Suffix 'b' is for blocking.
Load a RawTransaction from file and submit to the network
help | h
Prints this help
quit | q!
Exit this client
如果我们想从网络中查询事件,我们唯一能访问的信息是:
libra% q
usage: qUse the following args for this command:
balance | b <account_ref_id>|<account_address>
Get the current balance of an account
sequence | s <account_ref_id>|<account_address>
Get the current sequence number for an account
account_state | as <account_ref_id>|<account_address>
Get the latest state for an account
txn_acc_seq | ts <account_ref_id>|<account_address>
Get the committed transaction by account and sequence number.
txn_range | tr <start_version> Get the committed transactions by version range.
event | ev <account_ref_id>|<account_address>
Get events by account and event type (sent|received).
因此,在检查了可使用这个CLI工具执行的多个命令后,我们发现该工具只能执行帐户创建、传输和查询验证者节点以获取特定信息的功能。可执行的查询信息,如余额、状态、提交的交易(事务)和交易(事务)类型。
当我们连接到测试网时,我们的节点并没有同步。 相反,它将RPC请求发送到ac.testnet.libra.org上的一个远程节点,该节点会返回信息,其要求我们完全信任接收到的数据,而不需要进行独立验证 。目前,使用Libra CLI的用户只能查看这些内容。
运行一个本地验证器
Libra指定交易(事务)的生命周期,将其封装在验证器runtime,而客户端只是作为单个入口点工作。
来源:https://developers.libra.org/docs/life-of-a-transaction
Libra节点连接到一组可信共识对等节点,这些对等节点可依据公钥进行验证。目前,没有已知的方法可以生成一个可与其他在线测试网验证者对等的节点,这是因为
trusted_peers
配置选项当前为空。
Libra公开的唯一端点(endpoint)是facebook拥有的公共访问控制RPC url,它可能在某些云基础设施上运行负载均衡器。虽然在下载状态/区块信息方面似乎没有访问控制,但有一些机制可根据配置选项在网络层验证共识对等节点。目前还不清楚在Libra主网发布时,其是否会模糊化对等节点的ID和IP地址,并且经身份验证的验证者,可以很容易地阻止生产中未经身份验证的对等节点。目前也不清楚验证者是否会被激励分享他们的账本信息,因为他们为上面提到的特权支付了大量资源。
Libra的术语经常将网络对等节点称为“验证者”,这进一步推动了仅运行RPC客户端的用户概念。
pub fn gen_genesis_transaction>(
path: P,
faucet_account_keypair: &KeyPair,
trusted_peer_config: &TrustedPeersConfig,
) -> Result<()> {
let validator_set = trusted_peer_config
.peers
.iter()
.map(|(peer_id, peer)| {
ValidatorPublicKeys::new(
AccountAddress::try_from(peer_id.clone()).expect("[config] invalid peer_id"),
peer.get_consensus_public(),
peer.get_network_signing_public(),
peer.get_network_identity_public(),
)
})
Source: libra/config/config_builder/src/util.rs
以及
/// Returns the key that establishes a validator's identity in the p2p network
pub fn network_identity_public_key(&self) -> &X25519PublicKey {
&self.network_identity_public_key
}
来源:libra/types/src/validator_public_keys.rs
上面的
validator_set
是从可信的p2p对等节点列表中构建的,这意味着一个网络和身份签名公钥可用于网络级别的访问控制。这意味着只有经身份验证的验证者,才可能被网络中的其他验证者视为受信任的对等节点。
结论
综上所述,研究表明对于Libra区块链而言,普通用户和验证者拥有不同的读取权限,前者目前无法访问有关完整账本的信息。因此,普通用户不能完全复制Libra状态机,因为他们的客户端更多地是充当连接至实际运行网络的验证者节点的sidecar。我们不知道当Libra正式上线后是否还是这样的情况,或者这就是Libra项目仍在考虑的选择结果。此外,Libra的源代码经常将全节点命名为验证者,这添加了Facebook可能认定这种方向的进一步证据。一旦Libra网络以这种方式投入生产,对于每个支付了1000万美元的特权节点而言,他们也就没有什么动力允许未经身份验证的对等方,对账本和状态数据进行访问控制。
相关资料:
https://libra.org/en-US/
https://developers.libra.org/docs/move-paper