Facebook Libra 存储(Storage)简介

存储

存储模块为 Libra 区块链上的整个数据集提供了可靠且高效的持久化存储,以及 Libra Core 内部核心所必要的数据。

概观

存储模块旨在实现两个主要目的:

  • 持久化区块链数据,特别是通过验证器的共识协议完成的交易,还有持久化交易的输出数据。
  • 为区块链数据的查询提供 Merkle 凭证(Merkle proofs)的响应。如果客户端已获得正确的根哈希(Root Hash),则客户端可以轻松校验响应的完整性。

Libra 区块链可以被视为 Merkle 树(译注:Merkle Tree,通常也被称作 Hash Tree,顾名思义,就是存储 hash 值的一棵树,
参考),它包含以下组件:
在这里插入图片描述

账本历史 Ledger History

账本历史指的就是 Merkle 累加器。每笔交易添加到区块链的时候都包含 TransactionInfo 结构,在执行交易之后 Merkle 树会修改状态,根哈希也会修改,同时被添加到累加器上,显然这个根哈希是由交易生成的。

账本状态 Ledger State

一个稀疏 Merkle 树(Sparse Merkle Tree,默克尔树)就保存了账本所有的版本,该树也反映了全部帐户的状态。密钥是那个地址的 256 位散列,地址反映了整个帐户的状态,它被序列化为二进制 blob。虽然大小为 2^256 的树难以处理,但全部都是空节点的子树替换为占位符值,而包含一个叶子的子树将替换为单个节点。

当每个 TransactionInfo 结构指向不同的状态树,新树可以重用前一树的未改变部分,形成持久数据结构。

事件

每个交易都会发出一个事件列表,这些事件形成一个 Merkle 累加器。类似于状态 Merkle 树,交易的事件累加器的根哈希记录在相应的 TransactionInfo 结构中。

账本信息和签名

LedgerInfo 结构在某个版本和其他元数据中具有账本历史记录累加器的根哈希值,是对此版本之前的账本历史记录的绑定承诺。验证器在每次就一组交易及其执行结果达成一致时签署相应的 LedgerInfo 结构。对于被存储的每个 LedgerInfo 结构,还会存储来自验证器的此结构上的一组签名,因此客户端可以验证结构是否已获取每个验证器的公钥。

实施细节

存储模块使用 RocksDB 作为物理存储引擎。由于存储模块需要存储多种类型的数据,而 RocksDB 中的键值对却是字节数组的,于是我们在 RocksDB 上提供一个包装器来处理键和值的序列化。数据库中所有进进出出的数据结构都是根据预设定的模式(schemas)来定义的,并且是强制执行的。

LibraDB 是实现核心功能的主要模块。尽管我们使用单个 RocksDB 实例来存储整个数据集,但相关数据被分组到不同的逻辑存储中 - 例如,分类帐存储,状态存储和交易存储等。

对于管理分类帐状态的稀疏 Merkle 树,我们使用具有16个子节点的分支节点来优化磁盘布局,这些子节点表示4级子树,而扩展节点表示没有分支的路径。但是在计算根哈希和凭证时,我们仍会模拟二叉树。这样的做法使得凭证比以太坊的 Merkle Patricia 树生成的凭证短。

模块组织

storage
        └── accumulator      # Merkle 累加器的实现
        └── libradb          # LibraDB 的实现
        └── schemadb         # RocksDB 之上的模式包装器
        └── scratchpad       # Libra 核心数据结构,执行在内存的
        └── sparse_merkle    # 稀疏 Merkle 树的实现
        └── state_view       #  状态快照的抽象层,用于 Move VM 读取数据
        └── storage_client   #  gRPC 客户端的 Rust 包装器
        └── storage_proto    # 存储模块提供的所有接口
        └── storage_service  # gRPC 服务的存储模块.

译自 https://developers.libra.org/docs/crates/storage

发布了293 篇原创文章 · 获赞 260 · 访问量 232万+

猜你喜欢

转载自blog.csdn.net/zhangxin09/article/details/94212166