本文是 Aleo synthesizer 的代码审计报告的概述部分,Aleo synthesizer 是在 Aleo 区块链上部署和执行用户程序的核心协议。
该代码被发现经过了彻底的文档记录、严格的测试和良好的规范。报告了许多发现。
该报告受到了 Aleo 团队的好评:
以下是报告的概述部分的复制/粘贴
Aleo 合成器是在 Aleo 区块链上部署和执行用户程序的核心协议。它包装了 Varuna(Aleo 基于 Marlin 的零知识证明系统),并为用户提供了一个高级接口来部署和执行程序,并为网络提供验证正确部署和执行的接口。
理论上,合成器支持第三种流程,即费用收集流程,该流程的复杂性要低得多,我们将在概述中省略它。
本节从用户和网络的角度概述了合成器的部署和执行流程。
Aleo 提供了两种为其区块链编写程序的方法:使用 Leo 编程语言 或使用称为 Aleo 指令语言 的较低级别 VM 指令集。
Leo 程序最终会被编译成 Aleo 指令,后者是部署和执行程序的形式。因此,这是我们最后一次提到 Leo。
从高层次上讲,Aleo 程序包括许多与以太坊智能合约类似的结构:
finalize
函数,请参见后面的解释)。到目前为止,这与以太坊的智能合约设计没有太大区别。唯一的例外是函数仅在用户的机器上本地执行一次,然后通过使用零知识证明由网络验证。
由于用户交易在可以被网络排序之前执行函数,因此它们会在其消耗的资源上引入争用问题。想象一下:如果两个交易依赖于程序的状态为 A
,然后都尝试将状态更改为 B
和 C
,则只有一个交易可以成功。由于它们是冲突的交易,因此网络处理的第一个交易将使另一个交易无效。
因此,Aleo 程序中的函数实际上分为两个部分。
第一部分简称为“函数”,包含高度可并行化的逻辑,该逻辑应仅作用于单用户对象。这些单用户对象称为“记录”,类似于比特币中的 UTXO,但存储在类似于 Zcash 的屏蔽池中。如前所述,用户可以执行一个函数并向网络提供正确执行的证明。
因此,Aleo 程序定义了自己的自定义记录,这些记录始终具有一个 owner
字段(强制谁可以消费它们),并且可以包含特定于应用程序的数据。
第二部分是一些逻辑,其执行委托给网络(如以太坊中)。它的执行被推迟到它的包装交易被 Aleo 的共识排序和排序之后。一个函数可以通过创建一个同名的 finalize
函数来编码这种逻辑。
Finalize 函数的运行需要付费,具体取决于它包含的指令(类似于以太坊的“gas”概念)。finalize 函数由网络以明文形式运行,并且可以执行公共状态转换(特别是,更改程序中定义的任何映射)。这是更改程序公共状态的唯一方法。
为了简化这种拆分逻辑的概念,可以将在 Aleo 上开发视为与在以太坊上开发类似的体验,即如果一个人坚持将大部分逻辑托管在 finalize
函数中。但是,为了降低执行成本或提供隐私功能,开发人员可以选择将部分逻辑移至非 finalize 部分。
SnarkVM 合成器的主要目标是生成零知识证明电路,该电路对 Aleo 程序的函数进行编码。实际上,合成器通过将 Aleo 程序解析为用 Aleo 指令编写的函数,然后将每个 Aleo 指令转换为其匹配的电路 gadget 来实现此目的。
此外,在程序函数的开头和结尾添加了许多子电路:
请求验证。由于 Aleo 程序提供用户隐私,因此函数的调用者不能泄露。因此,每个电路都强制函数的调用者拥有他们的私钥。虽然这可以通过简单地见证私钥并强制其正确派生到调用者的地址来完成,但改为使用“请求”上的签名。
这些签名请求(如下所示)授权使用特定参数(或输入)执行某些程序的函数。用户可以使用它们将证明的创建委托给第三方证明者。
pub struct Request<N: Network> {
/// The request caller.
caller: Address<N>,
/// The network ID.
network_id: U16<N>,
/// The program ID.
program_id: ProgramID<N>,
/// The function name.
function_name: Identifier<N>,
/// The input ID for the transition.
input_ids: Vec<InputID<N>>,
/// The function inputs.
inputs: Vec<Value<N>>,
/// The signature for the transition.
signature: Signature<N>,
/// The tag secret key.
sk_tag: Field<N>,
/// The transition view key.
tvk: Field<N>,
/// The transition secret key.
tsk: Scalar<N>,
/// The transition commitment.
tcm: Field<N>,
}
输入和输出作为公共输入。函数的每个输入都被提交并作为公共输入公开。函数创建的任何输出也执行相同的操作。
调用 finalize。最后,如果函数调用 finalize 函数,则还会生成 finalize 函数的所有输入的哈希值。这些值也将在下面的 Transition
对象中以明文形式发送(因为网络需要它们以明文形式运行 finalize 函数)。
合成器的大部分复杂性来自于允许函数调用其他程序的函数。这类似于以太坊中智能合约调用其他智能合约。
在 Aleo 中,函数被转换为电路,因此函数调用意味着创建了两个电路:一个用于调用者,一个用于被调用者。为了突出这一点,如果一个函数最终产生 n 个函数调用,那么将运行 n+1 个电路(并且在执行该函数时将创建 n+1 个证明)。
实际上,“根”函数的执行被编码为“转换”的列表,其中每个转换表示单个函数调用的执行。转换的顺序从最嵌套的调用到最不嵌套的调用。这意味着最后一个转换是用户调用的主(或根)函数。
pub struct Transition<N: Network> {
/// The transition ID.
id: N::TransitionID,
/// The program ID.
program_id: ProgramID<N>,
/// The function name.
function_name: Identifier<N>,
/// The transition inputs.
inputs: Vec<Input<N>>,
/// The transition outputs.
outputs: Vec<Output<N>>,
/// The inputs for finalize.
finalize: Option<Vec<Value<N>>>,
/// The transition public key.
tpk: Group<N>,
/// The transition commitment.
tcm: Field<N>,
}
在函数的合成电路中,对外部函数的调用被替换为(公开地)见证函数调用的参数,然后(公开地)见证结果调用的输出。
因此,验证者的作用是“粘合”不同的函数调用(或转换),方法是确保公开见证的参数用于验证被调用者的电路,并且公开见证的输出确实是被调用者的电路输出的值。
请注意,我们也不想泄漏调用之间的输入和输出,因此输入和输出在作为公共输入公开之前会进行提交。在 Aleo 中,隐藏承诺被称为输入 ID 和输出 ID。
用户可以部署自己的 Aleo 程序,这些程序将全部上传到 Aleo 区块链。这意味着程序的代码(由 Aleo 指令组成)将存储在链上。
此外,部署还要求用户(希望部署其程序)生成与函数数量一样多的验证者密钥。然后,验证者密钥将部署在链上。
pub struct Deployment<N: Network> {
/// The edition.
edition: u16,
/// The program.
program: Program<N>,
/// The mapping of function names to their verifying key and certificate.
verifying_keys: Vec<(Identifier<N>, (VerifyingKey<N>, Certificate<N>))>,
}
由于验证者密钥的生成成本很高(它们由许多大型 MSM 组成,这些 MSM 承诺与 R1CS 相关的结构),因此用户生成它们,然后生成正确性证明(上面的 Certificate
)。
该证明基本上是一个 Sigma 协议,用于证明这些承诺编码了与 R1CS 相关的向量的低次扩展,方法是在一个随机点评估低次扩展。
要执行一个函数,用户使用合成器的方式与部署过程类似。因此,如果用户希望执行触发 n 个嵌套调用的函数调用,则用户将生成 n+1 个转换证明。合成器在运行时使用输入的实际值(而不是随机值)以及电路中的不同寄存器。
除了生成这些证明之外,用户还会生成 n+1 个“包含证明”。这些包含证明用于证明在转换或函数调用中用作输入的任何记录确实存在。包含证明证明记录存在于已包含在区块链中的某个先前区块中,或存在于先前的转换输出之一中。
包含证明还会公开输出序列号(在类似 Zcash 的系统中也称为 nullifier),这些序列号唯一地标识记录,而不会泄漏有关它们的任何信息。这样,记录就不能被多次消费。(此外,网络强制规定在同一交易中不能看到两次序列号。)
请注意,所有这些不同的证明最终都会使用 Varuna 的批处理功能聚合到一个证明中。
- 原文链接: blog.zksecurity.xyz/post...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!