译自 halo2 book:https://zcash.github.io/halo2/design/gadgets/sinsemilla/merkle-crh.html
SinsemillaHash 被用在 MerkleCR H Orchard 哈希函数 中。SinsemillaHash 的输入是:
l ⋆ ∣∣ left ⋆ ∣∣ right ⋆ ,
其中:
l ⋆ = I2LEBSP 10 ( l ) = I2LEBSP 10 ( MerkleDepth Orchard − 1 − layer ) ,
left ⋆ = I2LEBSP ℓ Merkle Orchard ( left ) ,
right ⋆ = I2LEBSP ℓ Merkle Orchard ( right ) ,
其中 ℓ Merkle Orchard = 255. left ⋆ 和
right ⋆ 允许是 left 和 right 的非规范(non-canonical)255 比特编码。
Sinsemilla 以 10 比特的整数倍进行操作,所以我们首先把消息分解(decomposing)成若干块(chunks):
l ⋆ left ⋆ right ⋆ = a 0 = a 1 ∣∣ b 0 ∣∣ b 1 = ( bits 0.. = 239 of left ) ∣∣ ( bits 240.. = 249 of left ) ∣∣ ( bits 250.. = 254 of left ) = b 2 ∣∣ c = ( bits 0.. = 4 of right ) ∣∣ ( bits 5.. = 254 of right )
然后我们把这些块重新组合(recompose)成若干 MessagePiece(消息片):
Length (bits) 250 20 250 Piece a = a 0 ∣∣ a 1 b = b 0 ∣∣ b 1 ∣∣ b 2 c
每个消息片都被 SinsemillaHash 约束到其所声明的长度。此外,
left 和 right 作为域元素(field elements)被见证(witnessed),所以我们知道它们
是规范的(canonical)。然而,我们还需要额外的约束来确保这些块具有正确的比特长度(否则它们可能在分解中相互重叠,从而允许证明者(prover)见证出任意的 SinsemillaHash 消息)。
其中一些约束可以用可复用的电路 gadget 来实现。我们定义一个由选择子(selector)q decompose 控制的自定义门(custom gate)来承载其余的约束。
块 c 由 Sinsemilla 直接约束。我们用以下约束来约束其余的块:
z 1 , a ,即 SinsemillaHash ( a ) 的下标为 1 的累加和(running sum)输出,被拷入门中。z 1 , a 已被 SinsemillaHash 约束为 240 比特,并且恰好就是 a 1 。我们利用 a , z 1 , a 来恢复块 a 0 :
z 1 , a ⟹ a 0 = 2 10 a − a 0 = a 1 = a − z 1 , a ⋅ 2 10 .
z 1 , b ,即 SinsemillaHash ( b ) 的下标为 1 的累加和输出,被拷入门中。z 1 , b 已被 SinsemillaHash 约束为 10 比特。我们在该门之外见证子片(subpieces)b 1 , b 2 ,并各自约束它们为 5 比特。在门内,我们检查 b 1 + 2 5 ⋅ b 2 = z 1 , b .
我们还利用 ( b , z 1 , b ) 恢复子片 b 0 :
z 1 , b ⟹ b 0 = 2 10 b − b 0.. = 10 = b − ( z 1 , b ⋅ 2 10 ) .
Degree 2 Constraint short_lookup_range_check ( b 1 , 5 ) short_lookup_range_check ( b 2 , 5 ) q decompose ⋅ ( z 1 , b − ( b 1 + b 2 ⋅ 2 5 )) = 0
其中 short_lookup_range_check ( ) 是一个
短查表范围检查(short lookup range check) 。
至此我们已经导出或见证了每个子片,并对每个子片做了范围约束:
a 0 (10 比特),导出为 a 0 = a − 2 10 ⋅ z 1 , a ;
a 1 (240 比特),等于 z 1 , a ;
b 0 (10 比特),导出为 b 0 = b − 2 10 ⋅ z 1 , b ;
b 1 (5 比特)在门外被见证并约束;
b 2 (5 比特)在门外被见证并约束;
c (250 比特)在门外被见证并约束。
b 1 + 2 5 ⋅ b 2 被约束为等于 z 1 , b 。
现在我们可以用它们来重建原始的域元素输入:
l left right = a 0 = a 1 + 2 240 ⋅ b 0 + 2 250 ⋅ b 1 = b 2 + 2 5 ⋅ c
Degree 2 2 2 Constraint q decompose ⋅ ( a 0 − l ) = 0 q decompose ⋅ ( a 1 + ( b 0 + b 1 ⋅ 2 10 ) ⋅ 2 240 − left ) = 0 q decompose ⋅ ( b 2 + c ⋅ 2 5 − right ) = 0
a z 1 , a b z 1 , b c b 1 left b 2 right l q decompose 1 0
Orchard 电路横跨 10 个建议列(advice columns),而 Sinsemilla 芯片(chip)只使用 5 个建议列。我们把路径哈希(path hashing)均匀地分摊到两个 Sinsemilla 芯片上,以便更好地利用可用的电路面积。由于上一层哈希的输出会被拷入下一层哈希,即使在从一个芯片转到另一个芯片时,我们也能保持连续性。