1. 引言
前序博客有:
- Nova: Recursive Zero-Knowledge Arguments from Folding Schemes学习笔记
- 基于cycle of curves的Nova证明系统(1)
- 基于cycle of curves的Nova证明系统(2)
微软团队2021年论文 《Nova: Recursive Zero-Knowledge Arguments from Folding Schemes》。
本文主要解析代码见:
- https://github.com/Microsoft/Nova(Rust)
其主要依赖的库有:
- bellperson(bellman)库:https://github.com/filecoin-project/bellperson
- ff 有限域库:https://github.com/zkcrypto/ff
- (Sha2)digest库:https://github.com/RustCrypto/traits
- SHA-3 (Keccak) 哈希函数库:https://github.com/RustCrypto/hashes
- rayon并行库:https://github.com/rayon-rs/rayon
- rand_core库(基础随机数生成器):https://github.com/rust-random/rand
- rand_chacha库(使用ChaCha算法的密码学安全的随机数生成器):https://github.com/rust-random/rand
- itertools库(批量数据遍历工具库):https://github.com/rust-itertools/itertools
- subtle库(constant-time密码学库):https://github.com/dalek-cryptography/subtle,可参看博客:
- Rust crate subtle:用于实现常量时间执行密码学操作的库
- rust Trait subtle::ConditionallySelectable常量时间执行及应用举例
- dudect_bencher test for constant-time函数
- subtle:constant-time密码学库
- pasta库(Pasta曲线对——Pallas和Vesta库):https://github.com/zcash/pasta_curves,可参看博客:Mina中的Pasta(Pallas和Vesta)曲线。
- neptune Poseidon哈希函数库(由Filecoin开发、已审计,支持BLS12-381/Pallas/Vesta曲线的scalar域的Poseidon哈希。 ):https://github.com/lurk-lab/neptune
- generic-array(通用数组类型库):https://github.com/fizyk20/generic-array
- num-bigint(大整数库):https://github.com/rust-num/num-bigint
- num-traits(通用数学numeric traits):https://github.com/rust-num/num-traits
- num-integer(整数trait和函数库):https://github.com/rust-num/num-integer
- serde(通用序列化、反序列化框架):https://github.com/serde-rs/serde
- bincode(结构体与字节之间相互转换的二进制序列化反序列化工具):https://github.com/bincode-org/bincode
- flate2(基于DEFLATE stream的streaming压缩解压缩库):https://github.com/rust-lang/flate2-rs
- bitvec(以bits来对内存寻址,即逐bit管理内存):https://github.com/ferrilab/bitvec
- byteorder(按big-endian或little-endian对数字进行编解码):https://github.com/BurntSushi/byteorder
- thiserror(derive(Error) 派生宏):https://github.com/dtolnay/thiserror
2. 基本类型定义
基本类型定义见traits/mod.rs
:
- Base:某group的base域内元素。
- Scalar:某group的scalar域内元素。
- CompressedGroupElement:某group元素的压缩表示。
- GroupElement:对压缩group元素的解压缩表示。
- PreprocessedGroupElement:表示preprocessed group元素。
- RO:表示某电路友好的sponge类型:其消耗base域元素,挤出scalar域元素。【实际采用了Poseidon哈希函数】
- ROCircuit:将RO表示为电路模式。
- TE:外化proof时所使用的通用Fiat-Shamir transcript。【实际采用了SHA-3(Keccak)哈希函数】
- CE:基于group scalar值的承诺机制。【实际采用了Pedersen承诺机制】
- ROConstants:与RO相关的哈希函数常量值。
- ROConstantsCircuit:与ROCircuit相关的哈希函数常量值。
相关结构定义见:src/r1cs.rs
中:
- 1)标准R1CS结构定义:
- 矩阵A、B、C的列数为:num_vars + num_io + 1,与向量 Z = ( W , u , x ) Z=(W,u,x) Z=(W,u,x)的长度一致,即列号的取值范围为0~(num_vars + num_io)。
- 矩阵A、B、C的行数num_cons:即对应为总约束数。
/// A type that holds the shape of the R1CS matrices #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct R1CSShape<G: Group> { pub(crate) num_cons: usize, // 矩阵A、B、C的行数,即行号取值范围为0~num_cons-1 pub(crate) num_vars: usize, // witness $W$ 向量长度 pub(crate) num_io: usize, // public input/output $x$ 向量长度 pub(crate) A: Vec<(usize, usize, G::Scalar)>, // 矩阵A以一维向量表示,其中每个元素的格式为(行号,列号,值) pub(crate) B: Vec<(usize, usize, G::Scalar)>, pub(crate) C: Vec<(usize, usize, G::Scalar)>, }
- 2)R1CS instance-witness定义为:【对应Az * Bz = Cz】
/// A type that holds a witness for a given R1CS instance #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct R1CSWitness<G: Group> { W: Vec<G::Scalar>, } /// A type that holds an R1CS instance #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(bound = "")] pub struct R1CSInstance<G: Group> { pub(crate) comm_W: Commitment<G>, pub(crate) X: Vec<G::Scalar>, }
- 3)relaxed R1CS instance-witness定义为:【对应Az * Bz = u*Cz + E】
/// A type that holds a witness for a given Relaxed R1CS instance #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct RelaxedR1CSWitness<G: Group> { pub(crate) W: Vec<G::Scalar>, pub(crate) E: Vec<G::Scalar>, } /// A type that holds a Relaxed R1CS instance #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(bound = "")] pub struct RelaxedR1CSInstance<G: Group> { pub(crate) comm_W: Commitment<G>, pub(crate) comm_E: Commitment<G>, pub(crate) X: Vec<G::Scalar>, pub(crate) u: G::Scalar, }
当采用Spartan来压缩最终的IVC proof时,需将 ( u , x ) ~ \widetilde{(u,x)} (u,x) 以multilinear多项式表示,则要求 ( u , x ) (u,x) (u,x)填充后的长度为power of two,同时要求未填充的 x x x向量的长度为偶数:
// We require the number of public inputs/outputs to be even
if num_io % 2 != 0 {
return Err(NovaError::OddInputLength);
}
2.1 R1CSShape中关键函数
R1CSShape中关键函数有:
- 1)new():明确创建特定的R1CS矩阵,会对矩阵向量的行列号做是否越界判断。
- 2)multiply_vec():计算AZ、BZ、CZ矩阵与向量乘积,结果为三个向量值。
- 3)is_sat_relaxed(ck, U, W):判断一组relaxed R1CS instance-witness是否satisfiable,即需同时满足以下条件:
- 3.1)witness 中的W.W、W.E向量长度应分别为num_vars和num_cons,instance中的U.X向量长度应为num_io。
- 3.2)满足Az * Bz = u*Cz + E,其中z=(W.W, U.u, U.X)
- 3.3)承诺值匹配,即U.comm_W== commit(ck, W.W) 且 U.comm_E== commit(ck, W.E)。
- 4)is_sat(ck, U, W):判断一组标准 R1CS instance-witness是否satisfiable,即需同时满足以下条件:
- 4.1)witness 中的W.W向量长度应为num_vars,instance中的U.X向量长度应为num_io。
- 4.2)满足Az * Bz = Cz,其中z=(W.W, 1, U.X)
- 4.3)承诺值匹配,即U.comm_W== commit(ck, W.W)。
- 5)commit_T(ck, U1, W1, U2, W2):计算committed relaxed R1CS folding scheme中的交叉项T的承诺值。其中(U1, W1)为relaxed R1CS instance-witness,(U2, W2)为标准R1CS instance-witness,即有U2.u=1且W2.E为零向量。
- 5.1)计算: T = A Z 1 ∘ B Z 2 + A Z 2 ∘ B Z 1 − u 1 ⋅ C Z 2 − u 2 ⋅ C Z 1 T=AZ_1\circ BZ_2+AZ_2\circ BZ_1-u_1\cdot CZ_2-u_2\cdot CZ_1 T=AZ1∘BZ2+AZ2∘BZ1−u1⋅CZ2−u2⋅CZ1
- 5.2)计算T的承诺值commit(ck, T)。
- 6)pad():当采用Spartan来压缩最终的IVC proof时,需将
W
~
(
⋅
)
、
A
~
(
⋅
,
⋅
)
、
B
~
(
⋅
,
⋅
)
、
C
~
(
⋅
,
⋅
)
、
(
u
,
x
)
~
\widetilde{W}(\cdot)、\widetilde{A}(\cdot,\cdot)、\widetilde{B}(\cdot,\cdot)、\widetilde{C}(\cdot,\cdot)、\widetilde{(u,x)}
W
(⋅)、A
(⋅,⋅)、B
(⋅,⋅)、C
(⋅,⋅)、(u,x)
以multilinear多项式表示,要求将A、B、C矩阵的行列数均填充为power of two;要求将W向量的长度填充为power of two;要求将
(
u
,
x
)
(u,x)
(u,x)的长度填充为power of two。为便于表示,实际填充时,取 A、B、C矩阵行数 与 W向量长度 的最大值的next_power_of_two() 为m。
本pad()函数仅对R1CSShape即A、B、C矩阵的行列进行填充。若只需做行填充,则直接改变num_cons参数值即可;若需做列填充,则将A、B、C 第 “c > (num_vars-1)” 列之后的值的列号调整为"c + m - num_vars"。
2.2 RelaxedR1CSWitness中关键函数
RelaxedR1CSWitness中关键函数有:
- 1)default():设置RelaxedR1CSWitness中W和E均为零向量。
- 2)from_r1cs_witness():根据R1CSWitness设置RelaxedR1CSWitness,其中E为零向量。
- 3)commit():分别对W和E向量进行承诺。
- 4)fold(W2, T, r):
Nova系列博客
- Nova: Recursive Zero-Knowledge Arguments from Folding Schemes学习笔记
- Nova 和 SuperNova:无需通用电路的通用机器执行证明系统
- Sangria:类似Nova folding scheme的relaxed PLONK for PLONK
- 基于Nova/SuperNova的zkVM
- SuperNova:为多指令虚拟机执行提供递归证明
- Lurk——Recursive zk-SNARKs编程语言
- Research Day 2023:Succinct ZKP最新进展
- 2023年 ZK Hack以及ZK Summit 亮点记
- 基于cycle of curves的Nova证明系统(1)
- 基于cycle of curves的Nova证明系统(2)