Why BN254, and when to switch off it
BN254 is the default curve for production ZK in 2026. The 128-bit security claim is no longer 128 bits, and BLS12-381 is gaining ground. Here is the math, the deployment reality, and the migration path.
- FROM
- Dax the Dev <[email protected]>
- SOURCE
- https://blog.skill-issue.dev/blog/why_bn254_and_when_to_switch/
- FILED
- 2026-04-15 17:00 UTC
- REVISED
- 2026-04-15 17:00 UTC
- TIME
- 10 min read
- SERIES
- ZK SNARKs in production
- TAGS
Every production ZK system you can name in 2026 — Zcash Sapling, Aleo, Mina, Filecoin’s PoRep, Solana’s alt_bn128_* syscalls, the Ethereum precompile at 0x06/0x07/0x08, zera-sdk — runs Groth16 over the same curve. BN254. A Barreto–Naehrig curve with a 254-bit base field, embedding degree 12, and a pairing that has been the default in pairing-based cryptography for nearly two decades.
It is also the curve that has lost the most bits of advertised security in the last ten years.
This post is the long answer to two questions that come up in every cryptography review I run with a serious team: why is BN254 still the default in 2026, and when do we get off it.
The minimum cryptography you need
A pairing is a bilinear map
with cyclic groups of prime order on an elliptic curve , and a multiplicative subgroup of an extension field . Bilinear means
for any and generators . That single equation is the entire reason pairing-based cryptography exists — it lets you “multiply in the exponent” across two different groups, which is exactly what Groth16’s verification equation needs.
Two parameters drive everything. The embedding degree is the smallest integer with ; it sets the size of the target field . The base field characteristic sets the cost of every operation in . The security of the pairing rests on:
- The discrete log problem (DLP) in and — protected by Pollard’s rho, cost , so we want for 128-bit security.
- The DLP in — protected by the number field sieve, cost subexponential in , so we want large enough that NFS is no easier than .
The trick of pairing-friendly curve design is to find where both DLPs are hard and is small enough that field operations don’t dominate. BN curves use the parameterisation
with defined over and embedding degree . Pick such that and are both prime, and you get a curve. BN254 is the choice — an integer carefully chosen so has 254 bits and has 254 bits, and so the resulting field arithmetic is reasonably efficient.
Where the 128 bits went
When BN254 was deployed in 2010-2015, the security argument was: , the NFS algorithm at the time required field operations to break the DLP in , and Pollard’s rho on required . Both legs landed at 128-bit security. Done.
Then Kim and Barbulescu (2016) introduced exTNFS, an extended Tower NFS variant that exploits the structure of when has a non-trivial factorisation (which does). The complexity of NFS dropped, and the Barbulescu-Duquesne (2019) update re-estimated the security of BN254 at roughly 100-110 bits — depending on which constant in the NFS asymptotic you trust.
That is the gap. The curve is not broken. The pairing still works. But “BN254 = 128-bit security” was the marketing line, and after 2016 it should have been “BN254 ≈ 100 bits.”
The honest table:
| Option | Cost | Latency | Blast radius | Notes |
|---|---|---|---|---|
| BN254 | ~254-bit base field; cheapest pairing in production | Best verifier perf; ~3ms Groth16 verify on Solana | ~100-110 bits actual security after exTNFS | Default in Ethereum precompile, Solana, Zcash Sprout, zera-sdk. Fine for 2026; not a forever choice. |
| BLS12-381 | ~381-bit base field; ~50% slower pairings | Verifier ~5-7ms typical | ~120-126 bits actual security | Ethereum 2.0 BLS signatures, Zcash Sapling, Filecoin. The realistic upgrade target. |
| BLS12-446 | ~446-bit base field; ~80% slower than BN254 | Verifier ~7-9ms | ~128 bits with margin | Theoretically clean 128-bit choice; minimal deployment as of 2026. |
| BLS24-509 | Larger base, embedding degree 24, very fast G_T arithmetic | Verifier ~6-8ms | ~128 bits, more conservative NFS margin | Niche; competes with BLS12-381 on perf, more on paper than in production. |
| Post-quantum (lattice / hash / code) | No pairings; structurally different | STARK-style verification, larger proofs | Quantum-secure (still active research) | When pairing-based cryptography retires, this is what replaces it. Not 2026, probably 2030+. |
The blast-radius column is the load-bearing one. BN254 is not broken in 2026. A 100-bit security level still costs an attacker field operations, which is not within the budget of any actor we model. But it is also not a curve you start a fresh decade-long deployment on.
The migration hierarchy
The pairing-friendly curve landscape, drawn as a hierarchy of “what would I deploy next”:
flowchart TD BN254[BN254 — current default, ~100-110 bit security after exTNFS] --> BLS381[BLS12-381 — ~120-126 bit, Ethereum/Filecoin/Sapling] BLS381 --> BLS446[BLS12-446 — clean ~128 bit with margin] BLS381 --> BLS24[BLS24-509 — embedding degree 24, niche] BLS446 --> PQ[Post-quantum candidates: lattice (Falcon/Dilithium), STARK-based] BLS24 --> PQ BN254 -.-> PQ classDef now fill:#1a1a1a,stroke:#4ade80,color:#4ade80 classDef next fill:#1a1a1a,stroke:#a3a3a3,color:#e8e8e8 classDef long fill:#1a1a1a,stroke:#737373,color:#a3a3a3 class BN254 now class BLS381,BLS446,BLS24 next class PQ long
The bottom row is what kills pairing-based cryptography eventually. Shor’s algorithm runs in polynomial time on a sufficiently large quantum computer, the discrete log breaks, and every curve in the diagram above goes to zero overnight. The realistic time horizon for that is not 2026 — the largest credible quantum factorisation as of last year is still toy-scale — but it is the reason you build a hash function migration story into your protocol from day one. We did this in zera-sdk by isolating the curve choice to a single crates/zera-sdk-core/src/curve.rs module. A future migration to BLS12-381 is one type alias and a regenerated .zkey. A migration to a lattice-based scheme is a bigger lift but the seam is clean.
Why the IETF still hasn’t picked one
The IETF CFRG has been running a pairing-friendly curves working group since 2018. As of draft 11, the recommendation lists BLS12-381 and BN462 as the two curves with 128-bit security after exTNFS. BN254 is explicitly not recommended for new deployments — the draft notes:
The BN curves with smaller parameters such as BN254 should not be used for applications requiring 128-bit security level due to the recent improvements of the number field sieve algorithm. Implementations targeting the 128-bit security level SHOULD use BLS12-381 or BN462.
The reason BN254 is still the production default in 2026 despite this is one part path-dependence (the Ethereum precompile is BN254 and rewriting that is a hard fork) and one part cost (BLS12-381 is roughly 50% slower per pairing and 50% larger per group element). For a privacy pool that is already paying tens of milliseconds per proof, the trade-off is real.
The clean argument: BN254 today, BLS12-381 next, lattice-based when the quantum threat becomes credible. That ordering is what every serious protocol designer I’ve talked to in the last year converges on.
Pairing arithmetic, by hand
The pairing itself is a Miller-loop algorithm followed by a final exponentiation. It is unreasonable to derive in a blog post — go read Barreto, Galbraith, Ó hÉigeartaigh, Scott (2007) for the optimal-Ate construction — but the bilinearity check is one line and worth seeing:
The toy below verifies this property over a tiny pairing-friendly toy curve. It uses a synthetic group and a synthetic pairing — not BN254, because computing a real BN254 pairing in 60 lines of TypeScript is not honest pedagogy. The shape of the relations is real. The numbers are not.
The Rust shape of a real pairing — using arkworks — is much closer to a one-liner once the curve is in scope:
The real implementation lives in arkworks-rs/algebra and supranational/blst. The latter is what production Ethereum and Solana ZK code links against — blst is the BLS12-381 pairing library written by Pierre-Yves Strub and Sergey Vasilyev, audited, and with constant-time multi-scalar multiplication that beats anything else in the open source.
What changes if we move to BLS12-381
The migration cost is not the curve. The migration cost is everything that touches the curve.
- Re-run the trusted setup. Groth16 needs a per-circuit setup. Migrating to BLS12-381 means a fresh ceremony for every circuit. That is non-trivial — a Powers-of-Tau ceremony runs for months — but it is also not blocked on cryptography.
- Regenerate the verifying keys. Every on-chain verifier ships a verifying key (a few KB of curve points). Those have to be regenerated and re-deployed. On Solana, that’s a program upgrade. On Ethereum, that’s a fresh contract deploy.
- Update every prover. snarkjs, rapidsnark, the Rust prover in zera-sdk-core — all of them. The
ffandpairingcrate ecosystem in Rust is curve-generic, so this is anark-bn254→ark-bls12-381swap and a recompile. The TypeScript side is harder because circomlibjs is BN254-pinned in places. - Eat the verifier-cost hit. A BLS12-381 pairing is roughly 50% more expensive than BN254. On Solana that’s 1500 extra compute units per pairing-based verification. Multiplied by the four pairings in a typical multi-input transfer proof, that’s 6000 CUs — meaningful but absorbable.
We’ve scoped this work for zera-sdk v2 but not yet committed to a date. The bet is: BN254 carries us through 2027 deployments comfortably, and the BLS12-381 migration is a clean lift the moment the broader Solana ecosystem standardises on it (the alt_bls12_381_* syscalls have been in cargo-audit feature flags since 2025).
Where this lands in the stack
In crates/zera-sdk-core/src/curve.rs the curve is a single type alias:
// Currently:
pub type Curve = ark_bn254::Bn254;
pub type Fr = ark_bn254::Fr;
pub type G1 = ark_bn254::G1Affine;
pub type G2 = ark_bn254::G2Affine;
// Future:
// pub type Curve = ark_bls12_381::Bls12_381;
// pub type Fr = ark_bls12_381::Fr;
// ...etc
The whole SDK reads from Curve, Fr, G1, G2. The migration is a four-line swap and a re-ceremony. The cleanliness is on purpose — see Building the Zera SDK: Day One for why we boxed the curve choice the way we did.
What I tell people who ask “should I deploy on BN254 or BLS12-381?”: deploy on BN254 if you need to compose with the Ethereum precompile or the Solana alt_bn128_* syscall today, deploy on BLS12-381 if you don’t and you want the security headroom. The math is the math. The deployment surface is what makes the call.
Further reading
- Updating Key Size Estimations for Pairings — Barbulescu, Duquesne (Journal of Cryptology 2019) — the post-exTNFS security recompute.
- Extended Tower Number Field Sieve: A New Complexity for the Medium Prime Case — Kim, Barbulescu (CRYPTO 2016) — the attack that dropped BN254’s security.
- Pairing-Friendly Curves (IETF CFRG draft) — the standardisation path.
- BLS12-381 For The Rest Of Us — Ben Edgington’s accessible explainer.
- arkworks-rs/algebra — the curve-generic Rust implementation we use.
- supranational/blst — the production BLS12-381 library.
- Pedersen commitments, in production — the sister piece on what we commit with.
- Poseidon, by hand and by code — the hash that lives inside circuits over the same curve.