4个版本
0.4.3 | 2024年4月30日 |
---|---|
0.4.2 | 2024年3月18日 |
0.4.1 | 2024年3月12日 |
0.4.0 | 2024年1月21日 |
在#fixed-length类别中排名第22
每月下载量68次
被5个crate(3个直接)使用
780KB
16K SLoC
axiom-eth
此crate是构建证明有关以太坊虚拟机(EVM)数据的ZK电路的主要库。
模块
原语
此crate的其余部分大量使用以下原语
halo2-base
特别是BaseCircuitBuilder
和LookupAnyManager
。rlc
:在此crate中,我们引入了一种新的自定义门,这是一种垂直门(1个建议列,1个选择列),使用3次旋转。这在PureRlcConfig
中。我们将BaseCircuitBuilder
扩展到支持此门,在RlcCircuitBuilder
中。RlcCircuitBuilder
是此crate中其余部分使用的核心电路构建器。keccak
:keccak哈希在EVM中扮演着非常重要的角色,因此在此crate的芯片中得到了大量使用。keccak
模块包含一个 适配器KeccakChip
,用于收集固定长度或可变长度字节数组的keccak哈希请求。需要注意的是,KeccakChip
不 显式约束这些keccak哈希的计算。哈希摘要以 未约束 的证据形式返回。这些哈希的验证取决于使用KeccakChip
的具体Circuit
实现。为此,我们现在讨论此crate中的Circuit
实现。
Circuit
实现方法
此crate有三个主要的Halo2 Circuit
trait实现方法
RlcKeccakCircuitImpl
:这是最直接的电路实现。它创建了一个独立的电路,其中包含由RlcCircuitBuilder
管理的子电路以及一个普通的zkEVM keccak子电路。由KeccakChip
收集的keccak调用直接与zkEVM keccak子电路的输出表进行约束。通过实现EthCircuitInstructions
来创建这样的电路。EthCircuitImpl
:这创建了一个包含RlcCircuitBuilder
管理的子电路的电路。此外,它加载一个keccak散列(及其输入)表作为私有证人,并以公输出形式输出表的一个Poseidon散列。由KeccakChip
收集的keccak调用在keccak散列表中动态查找。通过实现EthCircuitInstructions
来创建这样的电路。需要注意的是,由该电路生成的证明尚未完全验证:加载的keccak表必须通过约束表 Poseidon 散列等于KeccakComponentShardCircuit
的公输出来验证,该电路实际上证明表的正确性。这必须通过聚合电路来完成。ComponentCircuitImpl
:这是组件框架的一部分。更多详情请参阅那里。请注意,EthCircuitImpl
的实现实际上是ComponentCircuitImpl
的一个专用版本,因为它使用相同的PromiseLoader,
PromiseCollector
模式。
数据结构
rlp
:此模块定义了RlpChip
,它大量使用RLC来证明RLP(递归长度前缀)序列化的正确编码/解码。mpt
:此模块定义了MPTChip
,它使用rlp
和keccak
来证明Merkle Patricia Trie(MPT)中节点的包含和排除证明。
Ethereum执行层(EL)芯片
block_header
:证明将RLP编码的块头部(作为字节)分解为块头部字段。还通过keccak散列块头部来计算块哈希。storage
:证明账户证明进入状态trie和存储证明进入存储trie。transaction
:证明将RLP编码的交易包含在交易trie中。还提供了从交易中提取特定字段的功能。receipt
:证明将RLP编码的收据包含在收据trie中。还提供了从收据中提取特定字段的功能。solidity
:证明与一系列Solidity映射键对应的原始存储槽。
电路构建器
这是一个抽象概念,我们不会将其编码为顶级特质。这个crate在halo2-base
的基础上构建,特别是使用虚拟区域管理器。在这个框架中,电路使用电路构建器编写,这是一个虚拟区域管理器的集合。电路构建器拥有一组原始Halo2列和自定义门,但将电路本身的逻辑存储在某些虚拟状态中。然后,电路构建器可以根据这个虚拟状态进行自动配置或优化,然后将原始列和门选择器分配给原始Halo2电路。
因此,对于Halo2 Challenge API的每个阶段,编写电路有两个步骤
- 指定电路构建器内部虚拟区域的分配
- 将原始列和门选择器分配给原始Halo2电路
在这个包中,我们大量使用了随机线性组合(RLC),它需要两个阶段:阶段0和阶段1。阶段0对应于原始Halo2中的FirstPhase
结构体,阶段1对应于SecondPhase
结构体。由于阶段1中虚拟分配的正确计算需要挑战值,阶段1的虚拟分配必须在阶段0之后进行。具体来说,这意味着不能提前完全预填充电路构建器中所有虚拟区域。相反,必须在收到挑战值后指定一个函数来完成虚拟分配。
上述内容推动了本模块中核心特质的定义,例如CoreBuilder和PromiseBuilder。这些特质指定了函数变体的接口
virtual_assign_phase0
raw_synthesize_phase0
virtual_assign_phase1
raw_synthesize_phase1
这四个函数都在原始Halo2的Circuit::synthesize
特质实现中依次调用,阶段0列在raw_synthesize_phase0
和virtual_assign_phase1
之间提交,以便从virtual_assign_phase1
开始可用挑战值。(另一个技术区别是,virtual_assign_*
可以在没有Layouter
的情况下调用,用于任何预计算目的。)
大多数情况下,一个电路构建器可以用于不同的电路实现:raw_synthesize_*
逻辑保持不变,只需指定virtual_assign_*
指令,就可以快速编写新的电路。
阶段0有效载荷
阶段0的结果/数据也需要传递到阶段1以“继续计算”。理想情况下,会使用Rust闭包来自动推断这些数据在阶段之间传递。然而,由于一些编译器限制/可能的不可稳定性,我们选择要求从阶段0到阶段1传递的所有数据都显式地声明在某种Payload
结构体中。这些应始终视为闭包的显式实现。
组件框架
请参阅README。
依赖关系
~18–38MB
~640K SLoC