Our zk-SNARKs currently rely on BN254, a pairing-friendly Barreto-Naehrig curve construction over a 254-bit base field. After some recent optimizations to the NFS algorithm, our team did an analysis to understand the concrete security level of BN254.
@zooko's conclusion:
Okay, done! We've understood the concrete security level BN_128. Answer: everyone agrees that it is at least 110 bits, and either everyone or almost-everyone agrees that if you counted all of the costs it would be at least 128 bits.
Pairing-friendly curves are inherently more susceptible to advances in crypto research due to their small embedding degrees, so although the BN curve is currently good enough there is wisdom in adopting current academic recommendations wherever possible.
Sapling is a great opportunity to switch to a more secure pairing curve, since our protocol currently doesn't depend on the underlying curve, and we're considering many changes to the protocol which will. Switching later will be irritating, as it will require re-implementing everything again: new embedded curves, new hash functions, etc. We can buy more time by switching now when it's not as painful.
I've designed a new curve construction called BLS12-381 which targets 128-bit security given current recommendations.
Performance of BLS12-381
Currently, Zcash uses the BN254 implementation inside of libsnark, with USE_ASM disabled. I have recently implemented BLS12-381 in Rust.
Here are some preliminary benchmarks run on my i7-3770S:

As you can see, my implementation of BLS12-381 (which doesn't use any unsafe{} code or any hand-optimized assembly) is faster than the implementation of BN254 that we currently use in Zcash.
In fact, due to the small Hamming weight of its parameterization and its more efficient extension field tower, its G2 and pairing performance are on par with libsnark's assembly-optimized code that we don't use. This makes adopting BLS12-381 a strict performance improvement in all areas, without the auditing cost of assembly optimization.
Here are my current benchmarks:
BLS12-381 (Rust):
G1 addition: 1,249 ns/iter
G2 addition: 4,141 ns/iter
Full pairing: 2,557,330 ns/iter
G1 precomputation: 12,894 ns/iter
G2 precomputation: 223,809 ns/iter
Miller loop: 606,379 ns/iter
Final exponentiation: 1,696,878 ns/iter
libsnark USE_ASM off:
G1 addition: 1,366 ns/iter.
G2 addition: 6,509 ns/iter.
Full pairing: 4,199,397 ns/iter.
G1 precomputation: 3,102 ns/iter.
G2 precomputation: 540,984 ns/iter.
Miller loop: 1,339,208 ns/iter.
Final exponentiation: 2,332,928 ns/iter.
libsnark USE_ASM on:
G1 addition: 900 ns/iter.
G2 addition: 3,990 ns/iter.
Full pairing: 2,627,332 ns/iter.
G1 precomputation: 3,002 ns/iter.
G2 precomputation: 338,027 ns/iter.
Miller loop: 838,821 ns/iter.
Final exponentiation: 1,437,695 ns/iter.
ate-pairing:
G1 addition: 735 ns/iter.
G2 addition: 1,897 ns/iter.
Full pairing: 659,231 ns/iter.
G1 precomputation: 2,615 ns/iter.
G2 precomputation: 91,191 ns/iter.
Miller loop: 216,609 ns/iter.
Final exponentiation: 346,264 ns/iter.
Obviously, ate-pairing is way faster, but it relies on dynamic code compilation and tons of tricky optimizations. Hence, we don't use it in Zcash.
Security of BLS12-381
BLS12-381 follows the recommendations of several papers that pairing-friendly curves with embedding degree 12 should be instantiated over approximately 384-bit fields. (BN curves are thus unacceptable for us, because they will have exceedingly large scalar fields.)
BLS12-381 is also a far more rigid construction; it is part of a subfamily of BLS curves that have optimal extension field towers, simple twisting isomorphisms, and immediately determined curve parameters. It is the largest curve that meets our requirements for zk-SNARK efficiency, and so it's likely that others would arrive to the same curve as well.
The same cannot be said of BN254, which was chosen without respect to pairing and G2 performance.
Matthew Green and Ian Miers had Paulo Barreto and Diego Aranha, both experts in these curves, take a look at the BLS12-381 construction. Diego even implemented it in his RELIC library. It is also slated to appear in an upcoming academic paper.
Implementation of BLS12-381
As I previously mentioned, I have an implementation of BLS12-381 in Rust. This implementation follows over a year of refinement, testing, and auditing in which I uncovered several bugs in libsnark, one of which was a subgroup attack vulnerability (now fixed) and others that could have manifested as remote DoS. I carefully avoid some of the mistakes made in libsnark's BN254 implementation.
I'm also automatically testing my implementation on 64-bit and 32-bit Linux/Windows.
I'm not entirely finished with this implementation, but when I'm finished it should have strong guarantees against memory safety problems and API misuse, without the portability problems of libsnark's curve implementations. It already has and will continue to accrue extensive test coverage.
Our zk-SNARKs currently rely on BN254, a pairing-friendly Barreto-Naehrig curve construction over a 254-bit base field. After some recent optimizations to the NFS algorithm, our team did an analysis to understand the concrete security level of BN254.
@zooko's conclusion:
Pairing-friendly curves are inherently more susceptible to advances in crypto research due to their small embedding degrees, so although the BN curve is currently good enough there is wisdom in adopting current academic recommendations wherever possible.
Sapling is a great opportunity to switch to a more secure pairing curve, since our protocol currently doesn't depend on the underlying curve, and we're considering many changes to the protocol which will. Switching later will be irritating, as it will require re-implementing everything again: new embedded curves, new hash functions, etc. We can buy more time by switching now when it's not as painful.
I've designed a new curve construction called BLS12-381 which targets 128-bit security given current recommendations.
Performance of BLS12-381
Currently, Zcash uses the BN254 implementation inside of libsnark, with
USE_ASMdisabled. I have recently implemented BLS12-381 in Rust.Here are some preliminary benchmarks run on my i7-3770S:
As you can see, my implementation of BLS12-381 (which doesn't use any
unsafe{}code or any hand-optimized assembly) is faster than the implementation of BN254 that we currently use in Zcash.In fact, due to the small Hamming weight of its parameterization and its more efficient extension field tower, its G2 and pairing performance are on par with libsnark's assembly-optimized code that we don't use. This makes adopting BLS12-381 a strict performance improvement in all areas, without the auditing cost of assembly optimization.
Here are my current benchmarks:
Obviously,
ate-pairingis way faster, but it relies on dynamic code compilation and tons of tricky optimizations. Hence, we don't use it in Zcash.Security of BLS12-381
BLS12-381 follows the recommendations of several papers that pairing-friendly curves with embedding degree 12 should be instantiated over approximately 384-bit fields. (BN curves are thus unacceptable for us, because they will have exceedingly large scalar fields.)
BLS12-381 is also a far more rigid construction; it is part of a subfamily of BLS curves that have optimal extension field towers, simple twisting isomorphisms, and immediately determined curve parameters. It is the largest curve that meets our requirements for zk-SNARK efficiency, and so it's likely that others would arrive to the same curve as well.
The same cannot be said of BN254, which was chosen without respect to pairing and G2 performance.
Matthew Green and Ian Miers had Paulo Barreto and Diego Aranha, both experts in these curves, take a look at the BLS12-381 construction. Diego even implemented it in his RELIC library. It is also slated to appear in an upcoming academic paper.
Implementation of BLS12-381
As I previously mentioned, I have an implementation of BLS12-381 in Rust. This implementation follows over a year of refinement, testing, and auditing in which I uncovered several bugs in libsnark, one of which was a subgroup attack vulnerability (now fixed) and others that could have manifested as remote DoS. I carefully avoid some of the mistakes made in libsnark's BN254 implementation.
I'm also automatically testing my implementation on 64-bit and 32-bit Linux/Windows.
I'm not entirely finished with this implementation, but when I'm finished it should have strong guarantees against memory safety problems and API misuse, without the portability problems of libsnark's curve implementations. It already has and will continue to accrue extensive test coverage.