本文介绍了Circom中定义Rank 1约束系统(R1CS)的基本语法,包括模板参数的使用、循环和变量的声明与应用、以及如何在满足特定条件时生成约束。此外,还强调了在Circom中约束必须是静态的,不能依赖于信号动态改变,但变量可以作为常量参与R1CS运算,并解释了if
语句在Circom中的使用限制,着重介绍了 variables 的使用方法,以及 signals 的使用限制。
本章介绍基本的语法,你会在大多数 Circom 程序中见到这些语法。使用 Circom,我们可以使用代码定义 Rank 1 Constraint System (R1CS),而不是显式地定义每个约束。我们将在本章中探讨这些工具。
之前,我们看了一个电路 (IsBinary
),它验证提供的输入是否确实是二进制的。该电路被硬编码为仅接受 2 个输入。
template IsBinary() {
signal input in[2];
in[0] * (in[0] - 1) === 0;
in[1] * (in[1] - 1) === 0;
}
component main = IsBinary();
虽然上面的代码适用于两个输入,但修改它以支持大量的 n
输入将需要手动添加约束,这是一种糟糕的开发者体验。
因此,Circom 允许我们使用以下模式约束任意数量的信号,以自动生成约束:
template IsBinary(n) {
// n 个输入的数组
signal input in[n];
// n 个循环:n 个约束
for (var i = 0; i < n; i++) {
in[i] * (in[i] - 1) === 0;
}
}
// 使用 4 个输入和 4 个约束实例化
component main = IsBinary(4);
请注意,模板声明已更改为在括号中包含 n
。
n
被称为模板参数n
在电路中用于指定数组 in
的大小n
的值虽然约束可以通过编程方式生成,但约束的存在和配置不能有条件地依赖于信号。
虽然模板可以使用参数,但电路必须是静态的且定义明确。不支持“动态长度”的电路或约束 —— 一切都必须从一开始就固定且定义明确。
想象一下,如果一个 R1CS 约束系统的结构可以根据输入信号值而改变,会发生什么。证明者和验证者都无法操作,因为约束的数量没有确定。
n
的值必须在编译时设置。
for
、var
现在我们解释上面介绍的 for
循环。
template IsBinary(n) {
// n 个输入的数组
signal input in[n];
// n 个循环:n 个约束
for (var i = 0; i < n; i++) {
in[i] * (in[i] - 1) === 0;
}
}
// 使用 4 个输入和 4 个约束实例化
component main = IsBinary(4);
n
定义0
还是 1
我们在电路中引入了两个新的关键字:for
和 var
for
的工作方式与你习惯的方式相同。var
关键字声明一个 变量;在本例中,是 i
,如循环定义中所示。=
将右边的值赋给左边的变量。在这里,变量 i
用于以编程方式引用输入数组中的不同信号,同时为它们创建约束。能够以编程方式生成约束非常有用,因为当涉及到数百或数千个约束时,手动执行此操作将非常容易出错。
变量保存非信号数据并且是可变的。这是一个在循环之外声明变量的示例:
template VariableExample(n) {
var acc = 2;
signal s;
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!