译自 halo2 book:https://zcash.github.io/halo2/design/gadgets/ecc/fixed-base-scalar-mul.html
Orchard 协议中有 6 个定基(fixed base):
K Orchard ,用于推导 nullifier;
G Orchard ,用于 spend authorization(花费授权);
R 基,用于 NoteCommit Orchard ;
V 和 R 基,用于 ValueCommit Orchard ;以及
R 基,用于 Commit ivk 。
我们支持三种类型标量(scalar)的定基标量乘:
一个来自 F q 的 255 位标量。我们把一个全宽标量 α 分解为 85 个 3 位窗口(window):
α = k 0 + k 1 ⋅ ( 2 3 ) 1 + ⋯ + k 84 ⋅ ( 2 3 ) 84 , k i ∈ [ 0.. 2 3 ) .
对于表示 [ 0 , 2 255 ) 范围内任意整数的 k 0..84 ,标量乘都将被正确计算——也就是说,允许标量是非规范(non-canonical)的。
我们使用一个多项式范围检查约束(polynomial range-check constraint)对标量分解的每个 3 位字(word)进行范围约束:
Degree 9 Constraint q mul_fixed_full ⋅ range_check ( word , 2 3 ) = 0
其中 range_check ( word , range ) = word ⋅ ( 1 − word ) ⋯ ( range − 1 − word ) .
我们支持使用一个基域元素(base field element)作为定基乘法中的标量。例如,这出现在 Action 电路 nullifier 计算的标量乘中:DeriveNullifie r nk = Extract P ( [ ( PR F nk nfOrchard ( ρ ) + ψ ) mod q P ] K Orchard + cm ) :这里,标量 [ ( PR F nk nfOrchard ( ρ ) + ψ ) mod q P ] 是一次基域加法的结果。
把基域元素 α 分解为三位窗口,并对每个窗口进行范围约束,使用严格模式(strict mode)下的短范围分解(short range decomposition) gadget,其中 W = 85 , K = 3.
如果 k 0..84 是直接见证的,那么不会出现规范性(canonicity)问题。然而,因为这里标量是作为一个基域元素给出的,必须谨慎确保规范表示,因为 2 255 > p 。也就是说,我们必须检查 0 ≤ α < p , 其中 p 是 Pallas 基域模数 p = 2 254 + t p = 2 254 + 45560315531419706090280762371685220353. 注意 t p < 2 130 .
为此,我们把 α 分解为三段:α = α 0 (252 bits) ∣∣ α 1 (2 bits) ∣∣ α 2 (1 bit) .
我们通过以下方式检查此分解的正确性:
Degree 5 3 2 Constraint q canon-base-field ⋅ range_check ( α 1 , 2 2 ) = 0 q canon-base-field ⋅ bool_check ( α 2 ) = 0 q canon-base-field ⋅ ( z 84 − ( α 1 + α 2 ⋅ 2 2 ) ) = 0
如果最高有效位(MSB)α 2 = 0 未被置位,那么 α < 2 254 < p . 然而,在 α 2 = 1 的情况下,我们必须检查:
α 2 = 1 ⟹ α 1 = 0 ;
α 2 = 1 ⟹ α 0 < t p :
α 2 = 1 ⟹ 0 ≤ α 0 < 2 130 ,
α 2 = 1 ⟹ 0 ≤ α 0 + 2 130 − t p < 2 130
为了检查 0 ≤ α 0 < 2 130 , 我们利用三位移动求和(running sum)分解:
首先,我们通过强制 α 0 的高 120 位全为零,把 α 0 约束为一个 132 位值。我们可以从分解中得到 alpha_0_hi_120 :
z 44 ⟹ alpha_0_hi_120 = k 44 + 2 3 k 45 + ⋯ + 2 3 ⋅ ( 84 − 44 ) k 84 = z 44 − 2 3 ⋅ ( 84 − 44 ) k 84 = z 44 − 2 3 ⋅ ( 40 ) z 84 .
然后,我们约束 α 0 的第 130.. = 131 位为零;换句话说,我们约束三位字 k 43 = α [ 129.. = 131 ] = α 0 [ 129.. = 131 ] ∈ { 0 , 1 } . 我们利用移动求和分解来得到 k 43 = z 43 − z 44 ⋅ 2 3 .
定义 α 0 ′ = α 0 + 2 130 − t p 。为了检查 0 ≤ α 0 ′ < 2 130 , 我们使用 13 个十位查找(lookups) ,在其中我们约束查找的 z 13 移动求和输出在 α 2 = 1 时为 0.
Degree 2 3 3 4 3 Constraint q canon-base-field ⋅ ( α 0 ′ − ( α 0 + 2 130 − t P )) = 0 q canon-base-field ⋅ α 2 ⋅ α 1 = 0 q canon-base-field ⋅ α 2 ⋅ alpha_0_hi_120 = 0 q canon-base-field ⋅ α 2 ⋅ bool_check ( k 43 ) = 0 q canon-base-field ⋅ α 2 ⋅ z 13 ( lookup ( α 0 ′ , 13 )) = 0 Comment α 2 = 1 ⟹ α 1 = 0 Constrain α 0 to be a 132-bit value Constrain α 0 [ 130.. = 131 ] to 0 α 2 = 1 ⟹ 0 ≤ α 0 ′ < 2 130
一个短有符号标量被见证为一个幅值(magnitude)m 和一个符号(sign)s ,使得
s ∈ { − 1 , 1 } m ∈ [ 0 , 2 64 ) v old − v new = s ⋅ m .
这用于 ValueCommi t Orchard 。我们想要计算 ValueCommi t rcv Orchard ( v old − v new ) = [ v old − v new ] V + [ rcv ] R ,其中
− ( 2 64 − 1 ) ≤ v old − v new ≤ 2 64 − 1
v old 和 v new 各自已经被约束到 64 位(由于它们被用作 NoteCommi t Orchard 的输入)。
把幅值 m 分解为三位窗口,并对每个窗口进行范围约束,使用严格模式下的短范围分解(short range decomposition) gadget,其中 W = 22 , K = 3.
我们有两个额外的约束:
Degree 3 3 Constraint q mul_fixed_short ⋅ bool_check ( k 21 ) = 0 q mul_fixed_short ⋅ ( s 2 − 1 ) = 0 Comment The last window must be a single bit. The sign must be 1 or − 1.
其中 bool_check ( x ) = x ⋅ ( 1 − x ) 。
然后,我们为每个窗口预计算定基 B 的若干倍数。这采取窗口表(window table)的形式:M [ 0.. W ) [ 0..8 ) ,使得:
对于前 (W-1) 行 M [ 0.. ( W − 1 )) [ 0..8 ) :M [ w ] [ k ] = [( k + 2 ) ⋅ ( 2 3 ) w ] B
在最后一行 M [ W − 1 ] [ 0..8 ) :M [ w ] [ k ] = [ k ⋅ ( 2 3 ) w − j = 0 ∑ 83 2 3 j + 1 ] B
额外的 ( k + 2 ) 项让我们在 k = 0 的情况下避免加上无穷远点(point at infinity)。我们通过在最后一个窗口中减去这些累加项来抵消它们,即我们减去 j = 0 ∑ W − 2 2 3 j + 1 。
注:虽然 ( k + 1 ) 的偏移量朴素地看似乎就足够了,但它会在 k 0 = 7 , k 1 = 0 时引入一个边界情形(edge case)。
在这种情况下,窗口表项求值为同一个点:
M [ 0 ] [ k 0 ] = [( 7 + 1 ) ∗ ( 2 3 ) 0 ] B = [ 8 ] B ,
M [ 1 ] [ k 1 ] = [( 0 + 1 ) ∗ ( 2 3 ) 1 ] B = [ 8 ] B .
在定基标量乘中,我们使用不完全加法(incomplete addition)对每个窗口(除最后一个之外)的 B 的倍数求和。
由于倍点(point doubling)情形不被不完全加法处理,我们通过使用 ( k + 2 ) 的偏移量来避免它。
对于每个定基倍数窗口 M [ w ] = ( M [ w ] [ 0 ] , ⋯ , M [ w ] [ 7 ]) , w ∈ [ 0.. ( W − 1 )) :
定义一个 Lagrange 插值多项式(interpolation polynomial)L x ( k ) ,它把 k ∈ [ 0..8 ) 映射到倍数 M [ w ] [ k ] 的 x 坐标,即
L x ( k ) = ⎩ ⎨ ⎧ ([( k + 2 ) ⋅ ( 2 3 ) w ] B ) x ([ k ⋅ ( 2 3 ) w − j = 0 ∑ 83 2 3 j + 1 ] B ) x for w ∈ [ 0.. ( W − 1 )) ; for w = 84 ; and
找到一个值 z w ,使得 z w + ( M [ w ] [ k ] ) y 在域中是一个平方数 u 2 ,但错误符号的 y 坐标 z w − ( M [ w ] [ k ] ) y 不产生平方数。
对全部 W 个窗口重复此操作,我们最终得到:
一个 W × 8 的表 L x ,为每个窗口存储 8 个对 x 坐标进行插值的系数。每个 x 坐标插值多项式将具有如下形式
L x [ w ] ( k ) = c 0 + c 1 ⋅ k + c 2 ⋅ k 2 + ⋯ + c 7 ⋅ k 7 ,
其中 k ∈ [ 0..8 ) , w ∈ [ 0..85 ) ,且 c k 是 k 各次幂的系数;以及
一个长度为 W 的数组 Z ,存储各个 z w 。
每当我们在电路中进行定基标量乘时,就把这些预计算值加载到固定列(fixed columns)中。
给定一个分解后的标量 α 和一个定基 B ,我们如下计算 [ α ] B :
对于标量分解中的每个 k w , w ∈ [ 0..85 ) , k w ∈ [ 0..8 ) ,见证 x 坐标和 y 坐标 ( x w , y w ) = M [ w ] [ k w ] .
检查 ( x w , y w ) 在曲线上:y w 2 = x w 3 + b 。
见证 u w ,使得 y w + z w = u w 2 。
对于除最后一个之外的所有窗口,使用不完全加法(incomplete addition) 对各个 M [ w ] [ k w ] 求和,得到 [ α − k 84 ⋅ ( 2 3 ) 84 + j = 0 ∑ 83 2 3 j + 1 ] B 。
对于最后一个窗口,使用完全加法(complete addition)M [ 83 ] [ k 83 ] + M [ 84 ] [ k 84 ] 并返回最终结果。
注:最后一步需要完全加法,以便正确地把 [ 0 ] B 映射到无穷远点的表示 ( 0 , 0 ) ;并且也用于处理最后一步是倍点的一个极端情形(corner case)。
约束(Constraints):
Degree 8 4 3 Constraint q mul-fixed ⋅ ( L x [ w ] ( k w ) − x w ) = 0 q mul-fixed ⋅ ( y w 2 − x w 3 − b ) = 0 q mul-fixed ⋅ ( u w 2 − y w − Z [ w ] ) = 0
其中 b = 5 (来自 Pallas 曲线方程)。
回想一下,有符号短指数被见证为一个 64 位幅值 m 和一个符号 s ∈ 1 , − 1 . 使用上述算法,我们计算 P = [ m ] B 。然后,为了得到最终结果 P ′ , 我们使用 ( x , y ) ↦ ( x , s ⋅ y ) 对 P 进行条件取负(conditionally negate)。
约束(Constraints):
Degree 3 3 Constraint q mul_fixed_short ⋅ ( P y ′ − P y ) ⋅ ( P y ′ + P y ) = 0 q mul_fixed_short ⋅ ( s ⋅ P y ′ − P y ) = 0
x P x P , 0 x P , 1 x P , 2 ⋮ y P y P , 0 y P , 1 y P , 2 ⋮ x QR x Q , 1 = x P , 0 x Q , 2 = x R , 1 ⋮ y QR y Q , 1 = y P , 0 y Q , 2 = y R , 1 ⋮ u u 0 u 1 u 2 ⋮ window window 0 window 1 window 2 ⋮ L 0.. = 7 L 0.. = 7 , 0 L 0.. = 7 , 1 L 0.. = 7 , 1 ⋮ fixed_z fixed_z 0 fixed_z 1 fixed_z 2 ⋮
注:这不包括使用完全加法(complete addition) 的最后一行。在实现中这是在一个不同的 region 中分配的。