1 个不稳定版本
0.1.0 | 2024年7月12日 |
---|
#8 在 #l2
195 每月下载
在 37 个crate(32个直接)中使用
1.5MB
33K SLoC
DAL(数据访问层)
此crate提供对主数据库(Postgres)的读写访问,它是真实来源的主数据库。
当前模式由 sqlx
管理。模式更改存储在 migrations
目录中。
模式概述
此概述跳过了与验证器相关的和以太坊发送者相关的表,这些表是主节点特有的。
L2 区块和L1 批次
-
miniblocks
. 存储L2 区块头。命名是由于历史原因。 -
miniblocks_consensus
. 存储与去中心化序列器使用的共识算法相关的L2 区块数据。与L2 区块一对一相关(关系的一端是可选的)。 -
l1_batches
. 存储L1 批次头。 -
commitments
. 存储L1 批次提交数据的一部分(事件队列和引导程序内存提交)。将来,其他与提交相关的列将从l1_batches
移动到这里。
交易
transactions
. 存储节点接收的所有交易,包括L2和L1交易。此表中的交易不一定包含在L2 区块中;即,此表还用作持久化内存池。
VM 存储
有关更多上下文,请参阅 zksync_state
crate。
-
storage_logs
。存储所有事务的VM存储写入日志,以及引导加载程序生成的非事务写入。这是VM存储的真相来源;所有其他VM存储实现(见zksync_state
crate)都基于它(例如,通过添加持久或内存缓存)。由多个组件使用,包括元数据计算器、提交生成器、API服务器(用于读取一次性值,如账户余额,以及作为VM沙箱的一部分)等。 -
initial_writes
。存储每个L1批次的初始写入信息,即每个键分配的枚举索引。在元数据计算器和提交生成器组件中生成L1批次元数据时使用,以及在API服务器中的VM沙箱中用于费用估算。 -
protective_reads
。存储每个L1批次的保护读取信息,即未修改的、影响批次的VM执行的关键。在提交生成器中生成L1批次元数据时使用。 -
factory_deps
。存储所有部署的L2合同的字节码。 -
storage
。**已过时,将予以删除;不得在新的代码中使用。**
其他VM工件
-
events
。存储在VM执行期间由智能合约发出的所有事件(又称日志)。 -
l2_to_l1_logs
。存储在VM执行期间由智能合约发出的L2到L1日志。 -
call_traces
。存储在VM执行期间发出的交易调用跟踪。(与L1节点实现不同,在Era中,当前所有交易都主动生成调用跟踪。) -
tokens
。存储在L1-L2桥中注册的所有ERC-20代币。 -
transaction_traces
。**已过时,将予以删除;不得在新的代码中使用。**
快照生成和恢复
有关应用级节点快照的概述,请参阅snapshots_creator
和snapshots_applier
crate。
-
snapshots
。存储由snapshots_creator
生成的所有快照的元数据,例如快照的L1批次。 -
snapshot_recovery
。存储在节点恢复期间使用的快照的元数据(如果有)。目前,预期此表不会有超过一行。
逻辑不变性
除了直接在数据库模式中体现的外键约束和其他约束外,以下不变性预期将被维持
- 如果在
miniblocks
表中存在一个标题,则预期数据库包含所有与L2块执行相关的工件,如events
、l2_to_l1_logs
、call_traces
、tokens
等。(有关这些工件的精确定义,请参阅状态管理员I/O逻辑。) - 同样,如果在
l1_batches
表中存在一个标题,则预期数据库中也包含所有与L1批次执行相关的工件,例如initial_writes
和protective_reads
。(有关这些工件的精确定义,请参阅状态管理员I/O逻辑。) - 数据库中存在的L2块和L1批次形成一个连续的数字范围。如果从节点快照恢复数据库,则第一个L2块/L1批次是
snapshot_recovery
表中提到的快照L2块/L1批次之后的下一个(即下一个)。 address
和key
字段在storage_logs
表中对于节点上执行的所有区块都不是空(即,其头信息存在于miniblocks
中)。另一方面,address
和key
字段在快照存储日志中可能是空的。这些字段对于某些组件的后处理 L1 批次是必要的,例如 Merkle 树和承诺生成器。它们都使用(address, key)
元组来对批次中的日志进行排序,以获得规范顺序。由于快照不会以这种方式进行后处理,因此对于快照日志可以接受跳过它们(仅限于快照日志)。
为 DAL 贡献
一些使贡献给 DAL 更容易的小技巧
- 如果您想添加新的 DB 查询,请搜索 DAL 代码或
.sqlx
目录中的相同或等效查询。重用几乎总是比复制更好。 - 通常使用
instrument
工具对您的查询进行检测是有意义的。有关详细信息,请参阅instrument
模块文档。 - 最好为添加的查询编写单元测试,以确保它们工作且未来不会出问题。虽然
sqlx
具有编译时模式检查,但这并不是万能的。 - 如果对查询性能有疑问,请在生产规模数据库上运行带有
EXPLAIN
/EXPLAIN ANALYZE
前缀的查询。
向后兼容性
预计所有 DB 模式更改都应该是向后兼容的。也就是说,旧 代码必须能够与 新 模式一起工作。例如,不允许删除/重命名列。相反,应使用两阶段迁移
- 应将列标记为已弃用,并在所有查询中替换其提及。如果应重命名列,则应创建新列并将数据(如果有的话)从旧列复制(另请参阅:程序性迁移)。
- 在经过显著的延迟(大约数月)后,旧列可以在单独的迁移中删除。
程序性迁移
我们不能承受由数据迁移引起的非平凡停机时间。也就是说,如果迁移可能引起此类停机时间(例如,它复制大量数据),则必须将其组织为程序性迁移,并在节点后台运行(可能将工作分割成多个部分,并在它们之间设置延迟,以便迁移不会占用所有数据库资源)。
依赖关系
~85MB
~1.5M SLoC