- 线约束的目的:证明不同门之间连线上的信号值相等
- 例如:
门A的输出 = 门B的输入
例如电路:
- 门1:
a + b = c
(加法门) - 门2:
c * d = e
(乘法门) 其中门1的输出c与门2的输入c必须相等
给每个信号位置分配唯一编号:
- left[i]: 第i个门的左输入 (编号范围: 0 ~ n-1)
- right[i]: 第i个门的右输入 (编号范围: n ~ 2n-1)
- out[i]: 第i个门的输出 (编号范围: 2n ~ 3n-1)
例如 n=4 的电路:
- left: [0,1,2,3]
- right: [4,5,6,7]
- out: [8,9,10,11]
对于第i个门:
- 左输入编号 = i
- 右输入编号 = i + 4
- 输出编号 = i + 8
如果门1的输出(编号8)连接到门2的左输入(编号1):
- 原始序列:
[0,1,2,3, 4,5,6,7, 8,9,10,11]
- 置换后:
[0,8,2,3, 4,5,6,7, 1,9,10,11]
# 1. 每个门的编号是固定的
门1 = {
"左输入": 0, # 第1个门的左输入固定为0
"右输入": 4, # 第1个门的右输入固定为4
"输出": 8 # 第1个门的输出固定为8
}
门2 = {
"左输入": 1, # 第2个门的左输入固定为1
"右输入": 5, # 第2个门的右输入固定为5
"输出": 9 # 第2个门的输出固定为9
}
# 2. 当我们说"8连接到1"时,实际上是在说:
# - 门1的输出值(编号8)
# - 要传递给门2的左输入位置(编号1)
- 置换σ表示了这种连接关系:
σ(8)=1, σ(1)=8
目标:证明不同位置的信号值相等,同时保持零知识性 方法:使用随机数构造累加器,使得相等的信号产生相等的累加值
- 选择随机数β,γ
- 为每个位置i计算: acc[i] = (index[i] + β * value[i] + γ)
- 构造累加器多项式: P(X) = ∏(acc[i])
- 如果两个位置的信号相等,则它们的acc值也相等
假设有两个相等的信号:
- 位置i: index=8, value=5
- 位置j: index=1, value=5
- acc[i] = 8 + β*5 + γ
- acc[j] = 1 + β*5 + γ
如果这两个信号确实相等,则:
P(X) = P'(X)
(P'是置换后的累加器多项式)
- 随机数
β
,γ
确保:
- 攻击者无法预测
acc值
- 不同位置的不相等信号几乎不可能产生相同的
acc值
- 位置编号
index
确保:
- 即使信号值相等,不同位置也会产生不同的
acc值
- 除非这确实是一个有效的连接
# 1. 原始序列的累加器多项式
P(X) = (index[0] + β*value[0] + γ) *
(index[1] + β*value[1] + γ) *
... *
(index[n] + β*value[n] + γ)
# 2. 置换后序列的累加器多项式
P'(X) = (index[σ(0)] + β*value[0] + γ) *
(index[σ(1)] + β*value[1] + γ) *
... *
(index[σ(n)] + β*value[n] + γ)
# 3. 验证
如果所有连接都正确,则 P(X) = P'(X)
- 零知识性:
- β,γ的随机性保护了具体的信号值
- 绑定性:
- 不同的信号值几乎不可能产生相同的acc值
- 完备性:
- 正确的连接一定会通过验证
- 可靠性:
- 错误的连接通过验证的概率可忽略
type PermutationArgument struct {
// 1. 置换映射
Sigma []int // σ(i) 表示位置i连接到的位置
// 2. 置换多项式
S1 *Polynomial // 左输入置换
S2 *Polynomial // 右输入置换
S3 *Polynomial // 输出置换
// 3. 累加器多项式
Z *Polynomial // 累积乘积多项式
}
// 4. 构造累加器
func BuildAccumulator(
indices []int,
values []Fr,
beta Fr,
gamma Fr,
) *Polynomial {
acc := make([]Fr, len(indices))
for i := 0; i < len(indices); i++ {
// acc[i] = index[i] + β*value[i] + γ
acc[i].Mul(&values[i], &beta)
acc[i].Add(&acc[i], &indices[i])
acc[i].Add(&acc[i], &gamma)
}
return NewPolynomial(acc)
}
- 计算原始累加器多项式
P(X)
- 计算置换后的累加器多项式
P'(X)
- 证明
P(X) = P'(X)
- 检查
累加器多项式承诺
- 验证评估点处
P(z) = P'(z)
- 验证
除法证明
公开输入的线约束需要特殊处理:
- 分配固定的编号
- 在累加器中使用特殊的系数
常量门的线约束:
- 不参与置换
- 使用特殊的累加器计算方式
某些门的输入/输出未连接:
- 自循环置换
(σ(i)=i)
- 使用
特殊值
填充