1. 引言
前序博客:
- Efficient ZK ECDSA
- ECDSA VS Schnorr signature VS BLS signature
- Spartan: zkSNARKS without trusted setup学习笔记
- Spartan: zkSNARKS without trusted setup 源代码解析
Personae Labs开源的:
- https://github.com/personaelabs/spartan-ecdsa(Rust+TypeScript)
为当前最快的ZK ECDSA(sep256k1)。
Spartan-ECDSA证明ECDSA group membership的速度 要比 之前Personae Labs开源Efficient ZK ECDSA 快10倍。
Proving membership to a group of ECDSA public keys的性能情况为:
Benchmark | # |
---|---|
Constraints | 8,076 |
Proving time in browser | 4s |
Proving time in Node.js | 2s |
Verification time in browser | 1s |
Verification time in Node.js | 300ms |
Proof size | 16kb |
- Measured on a M1 MacBook Pro with 80Mbps internet speed.
- Both proving and verification time in browser includes the time to download the circuit.
Spartan-ECDSA的核心技术为:
- 1)Secp256k1曲线+Secq256k1曲线(Secp256k1曲线的scalar域 为 Secq256k1曲线的基域):因ECDSA验签过程中不仅包含 F p \mathbb{F}_p Fp域内的运算,还包含 F q \mathbb{F}_q Fq域内的运算。
- 2)Spartan证明系统:使用了基于Secq256k1曲线的Spartan分支。
- 3)Circom:Circom用于定义arithmetic circuit。采用了基于Secp256k1基域(即Secq256k1 scalar域)的Circom分支来进行算术化。
- 4)Nova-Scotia:为Circom R1CS编译器。fork了一个分支来将Circom circuits编译为Spartan可处理的二进制格式,并对Nova-Scotia做了小调整以兼容Secq256k1。
Personae Labs团队未来将进一步:
- 1)对Keccak加速
- 2)使链上验证成为可能:如可利用递归证明,降低单个证明的验证开销。
参考资料
[1] Twitter Introducing spartan-ecdsa
[2] ebfull hackmd Wait, what are these isomorphic elliptic curves doing on the secp256k1/secq256k1 cycle?
[3] Personae Labs 2023年2月博客 Introducing Spartan-ecdsa
附录:Secp256k1/Secq256k1曲线cycle
Secp256k1椭圆曲线 y 2 = x 3 + 7 y^2=x^3+7 y2=x3+7 defined over F p \mathbb{F}_p Fp with order q q q,而Secq256k1椭圆曲线 y 2 = x 3 + 7 y^2=x^3+7 y2=x3+7 defined over F q \mathbb{F}_q Fq with order p p p,二者形成了2-cycle curve,相应的SageMath脚本验证为:
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
q = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
# Secp256k1
P = GF(p)
aP = P(0x0000000000000000000000000000000000000000000000000000000000000000)
bP = P(0x0000000000000000000000000000000000000000000000000000000000000007)
Secp256k1 = EllipticCurve(P, (aP, bP))
Secp256k1.set_order(q)
# Secq256k1
Q = GF(q)
aQ = P(0x0000000000000000000000000000000000000000000000000000000000000000)
bQ = P(0x0000000000000000000000000000000000000000000000000000000000000007)
Secq256k1 = EllipticCurve(Q, (aQ, bQ))
Secq256k1.set_order(p)
print(
"Secp256k1 group order == Secq256k1 base field order:",
Secp256k1.order() == Secq256k1.base_field().cardinality()
)
print(
"Secp256k1 base field order == Secq256k1 group order:",
Secp256k1.base_field().cardinality() == Secq256k1.order()
)