Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d8f1bbf
build(evm): update generated verifier pragma to Solidity 0.8.30
jtcoolen Jan 10, 2026
bcd1f54
test(evm): raise local limits for large-verifier gas estimation
jtcoolen Jan 19, 2026
6ceb111
chore(vendor): vendor halo2-lib snapshot and route halo2-base/ecc loc…
jtcoolen Feb 17, 2026
5fc6269
chore(vendor): apply halo2-base blsFr scalar-field patch (360a9d3)
jtcoolen Feb 17, 2026
52272a3
chore(vendor): apply halo2-base blsFq 6-limb patch set (f56347d)
jtcoolen Feb 17, 2026
3521425
fix(vendor): make from_u64_digits width-agnostic
jtcoolen Feb 17, 2026
7c2e1b9
chore(lockfile): resolve dependency graph for pinned halo2 stack
jtcoolen Feb 17, 2026
c5a590e
chore(vendor): import halo2-base snapshot from f56347d
jtcoolen Feb 17, 2026
37ddb9b
fix(vendor): make from_u64_digits width-agnostic
jtcoolen Feb 17, 2026
37c0669
refactor(sdk): switch bn256 generics to bls12_381
jtcoolen Feb 17, 2026
86c7d76
feat(evm-loader): support BLS byte widths for proof/ec-point IO
jtcoolen Feb 17, 2026
63d9de6
feat(evm-decider): move G2 serialization to 8-word pairing inputs
jtcoolen Feb 17, 2026
0acb7c4
feat(evm-codegen): adopt BLS precompile call shapes in generated runtime
jtcoolen Feb 17, 2026
de04db8
fix(evm): correct EIP-2537 precompile addresses
jtcoolen Feb 17, 2026
594f95c
fix(decider): serialize G2 in EIP-2537 c0,c1 order
jtcoolen Feb 17, 2026
6e50139
fix(field-arith): set LIMBS=3 and BITS=128 for BLS constraints
jtcoolen Feb 17, 2026
a089d14
chore(toolchain): bump rust-toolchain to 1.88.0
jtcoolen Feb 17, 2026
7c3dd7f
fix(revm): harden Prague config and revert diagnostics
jtcoolen Feb 17, 2026
79bfb0a
chore(lockfile): refresh lockfile after revm/runtime wiring
jtcoolen Feb 17, 2026
42c1649
chore(evm): improve solc error surfacing
jtcoolen Feb 17, 2026
728397d
fix(transcript/evm): handle identity encoding and disjoint transcript…
jtcoolen Feb 25, 2026
f4e4942
perf(loader_evm): batch MSM precompile path and harden inversion sema…
jtcoolen Feb 25, 2026
0004143
chore(example): port standard_plonk to BLS12-381
jtcoolen Feb 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,238 changes: 753 additions & 485 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,17 @@ incremental = false
[profile.flamegraph]
inherits = "release"
debug = true
#[patch.crates-io]
#halo2curves-axiom = { git = "https://github.com/jtcoolen/halo2curves.git" }
#halo2-base = { git = "https://github.com/jtcoolen/halo2-lib.git", branch = "main" }

[patch."https://github.com/axiom-crypto/halo2-lib.git"]
halo2-base = { path = "vendor/halo2-lib/halo2-base" }
halo2-ecc = { path = "vendor/halo2-lib/halo2-ecc" }

[patch."https://github.com/jtcoolen/halo2-lib.git"]
halo2-base = { path = "vendor/halo2-lib/halo2-base" }
halo2-ecc = { path = "vendor/halo2-lib/halo2-ecc" }

[patch.crates-io]
halo2curves-axiom = { git = "https://github.com/jtcoolen/halo2curves.git", rev = "edeb29e7964f1d24bb3bc0d2a5f9417de92a572a" }
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.85.1
1.88.0
Copy link
Copy Markdown
Author

@jtcoolen jtcoolen Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to bump the rust version to gain access to BLS precompiles with revm?

100 changes: 44 additions & 56 deletions snark-verifier-sdk/examples/standard_plonk.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
use std::path::Path;

use halo2_base::gates::circuit::CircuitBuilderStage;
use halo2_base::halo2_proofs;
use halo2_base::utils::fs::gen_srs;
use halo2_proofs::halo2curves as halo2_curves;
use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG};
use halo2_proofs::{halo2curves::bls12_381::Bls12, poly::kzg::commitment::ParamsKZG};
use rand::rngs::OsRng;
#[cfg(feature = "revm")]
use snark_verifier_sdk::evm::evm_verify;
use snark_verifier_sdk::evm::{gen_evm_proof_shplonk, gen_evm_verifier_shplonk};
use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality};
use snark_verifier_sdk::{
gen_pk,
halo2::{aggregation::AggregationCircuit, gen_snark_shplonk},
Snark,
};
use snark_verifier_sdk::{CircuitExt, SHPLONK};
use snark_verifier_sdk::evm::{gen_evm_proof_gwc, gen_evm_verifier_gwc, write_calldata};
use snark_verifier_sdk::{gen_pk, CircuitExt};

mod application {
use super::halo2_curves::bn256::Fr;
use super::halo2_curves::bls12_381::Fr;
use super::halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance},
Expand Down Expand Up @@ -46,7 +38,6 @@ mod application {
let [a, b, c] = [(); 3].map(|_| meta.advice_column());
let [q_a, q_b, q_c, q_ab, constant] = [(); 5].map(|_| meta.fixed_column());
let instance = meta.instance_column();

[a, b, c].map(|column| meta.enable_equality(column));

meta.create_gate(
Expand All @@ -56,7 +47,7 @@ mod application {
[a, b, c].map(|column| meta.query_advice(column, Rotation::cur()));
let [q_a, q_b, q_c, q_ab, constant] = [q_a, q_b, q_c, q_ab, constant]
.map(|column| meta.query_fixed(column, Rotation::cur()));
let instance = meta.query_instance(instance, Rotation::cur());
let instance = meta.query_instance(instance, Rotation::cur());
Some(
q_a * a.clone()
+ q_b * b.clone()
Expand Down Expand Up @@ -141,6 +132,7 @@ mod application {
region.assign_advice(|| "", config.a, 2, || Value::known(Fr::one()))?;
a.copy_advice(|| "", &mut region, config.b, 3)?;
a.copy_advice(|| "", &mut region, config.c, 4)?;
Ok(())
}
#[cfg(feature = "halo2-axiom")]
{
Expand All @@ -160,61 +152,57 @@ mod application {
let a = region.assign_advice(config.a, 2, Value::known(Fr::one()));
a.copy_advice(&mut region, config.b, 3);
a.copy_advice(&mut region, config.c, 4);
Ok(())
}

Ok(())
},
)
}
}
}

fn gen_application_snark(params: &ParamsKZG<Bn256>) -> Snark {
let circuit = application::StandardPlonk::rand(OsRng);

let pk = gen_pk(params, &circuit, None);
gen_snark_shplonk(params, &pk, circuit, None::<&str>)
}

fn main() {
let params_app = gen_srs(8);

let k = 21u32;
let lookup_bits = k as usize - 1;
let params = gen_srs(k);
let snarks = [(); 1].map(|_| gen_application_snark(&params_app));

let mut agg_circuit = AggregationCircuit::new::<SHPLONK>(
CircuitBuilderStage::Keygen,
AggregationConfigParams { degree: k, lookup_bits, ..Default::default() },
&params,
snarks.clone(),
VerifierUniversality::Full,
);
let agg_config = agg_circuit.calculate_params(Some(10));
let k = 12;
let params = ParamsKZG::<Bls12>::setup(k, OsRng);
let circuit = application::StandardPlonk::rand(OsRng);
let num_instance = circuit.num_instance();
let instances = circuit.instances();

let pk = gen_pk(&params, &agg_circuit, None);
let break_points = agg_circuit.break_points();
drop(agg_circuit);
let pk = gen_pk(&params, &circuit, None);
let proof = gen_evm_proof_gwc(&params, &pk, circuit, instances.clone());

let agg_circuit = AggregationCircuit::new::<SHPLONK>(
CircuitBuilderStage::Prover,
agg_config,
&params,
snarks.clone(),
VerifierUniversality::Full,
)
.use_break_points(break_points);
let num_instances = agg_circuit.num_instance();
let instances = agg_circuit.instances();
let _proof = gen_evm_proof_shplonk(&params, &pk, agg_circuit, instances.clone());

let _deployment_code = gen_evm_verifier_shplonk::<AggregationCircuit>(
let deployment_code = gen_evm_verifier_gwc::<application::StandardPlonk>(
&params,
pk.get_vk(),
num_instances,
num_instance,
Some(Path::new("examples/StandardPlonkVerifier.sol")),
);

let deployment_bytecode = format!("0x{}", hex::encode(&deployment_code));
std::fs::write("examples/standard_plonk.bytecode", &deployment_bytecode).unwrap();
let calldata =
write_calldata(&instances, &proof, Path::new("examples/standard_plonk.calldata")).unwrap();

println!("proof size: {}", proof.len());
println!("deployment code len: {}", deployment_code.len());
println!("wrote examples/standard_plonk.bytecode");
println!("wrote examples/standard_plonk.calldata ({} hex chars)", calldata.len());

#[cfg(feature = "revm")]
evm_verify(_deployment_code, instances, _proof).expect("evm_verify should succeed");
{
if std::env::var("RUN_REVM").ok().as_deref() == Some("1") {
match evm_verify(deployment_code, instances, proof) {
Ok(gas_cost) => println!("gas cost: {}", gas_cost),
Err(err) => {
println!("revm verification failed: {}", err);
println!(
"note: local revm simulation still reverted; validate against a known BLS-enabled client/node for authoritative verification"
);
}
}
} else {
println!(
"revm verification skipped (set RUN_REVM=1 to run local revm simulation)"
);
}
}
}
28 changes: 14 additions & 14 deletions snark-verifier-sdk/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{CircuitExt, PlonkVerifier};
#[cfg(feature = "display")]
use ark_std::{end_timer, start_timer};
use halo2_base::halo2_proofs::{
halo2curves::bn256::{Bn256, Fq, Fr, G1Affine},
halo2curves::bls12_381::{Bls12, Fq, Fr, G1Affine},
plonk::{create_proof, verify_proof, Circuit, ProvingKey, VerifyingKey},
poly::{
commitment::{ParamsProver, Prover, Verifier},
Expand Down Expand Up @@ -34,19 +34,19 @@ use std::{fs, io, path::Path, rc::Rc};

/// Generates a proof for evm verification using either SHPLONK or GWC proving method. Uses Keccak for Fiat-Shamir.
pub fn gen_evm_proof<'params, C, P, V>(
params: &'params ParamsKZG<Bn256>,
params: &'params ParamsKZG<Bls12>,
pk: &'params ProvingKey<G1Affine>,
circuit: C,
instances: Vec<Vec<Fr>>,
) -> Vec<u8>
where
C: Circuit<Fr>,
P: Prover<'params, KZGCommitmentScheme<Bn256>>,
P: Prover<'params, KZGCommitmentScheme<Bls12>>,
V: Verifier<
'params,
KZGCommitmentScheme<Bn256>,
Guard = GuardKZG<'params, Bn256>,
MSMAccumulator = DualMSM<'params, Bn256>,
KZGCommitmentScheme<Bls12>,
Guard = GuardKZG<'params, Bls12>,
MSMAccumulator = DualMSM<'params, Bls12>,
>,
{
let instances = instances.iter().map(|instances| instances.as_slice()).collect_vec();
Expand All @@ -56,7 +56,7 @@ where
let rng = StdRng::from_entropy();
let proof = {
let mut transcript = TranscriptWriterBuffer::<_, G1Affine, _>::init(Vec::new());
create_proof::<KZGCommitmentScheme<Bn256>, P, _, _, EvmTranscript<_, _, _, _>, _>(
create_proof::<KZGCommitmentScheme<Bls12>, P, _, _, EvmTranscript<_, _, _, _>, _>(
params,
pk,
&[circuit],
Expand Down Expand Up @@ -89,7 +89,7 @@ where
}

pub fn gen_evm_proof_gwc<'params, C: Circuit<Fr>>(
params: &'params ParamsKZG<Bn256>,
params: &'params ParamsKZG<Bls12>,
pk: &'params ProvingKey<G1Affine>,
circuit: C,
instances: Vec<Vec<Fr>>,
Expand All @@ -98,7 +98,7 @@ pub fn gen_evm_proof_gwc<'params, C: Circuit<Fr>>(
}

pub fn gen_evm_proof_shplonk<'params, C: Circuit<Fr>>(
params: &'params ParamsKZG<Bn256>,
params: &'params ParamsKZG<Bls12>,
pk: &'params ProvingKey<G1Affine>,
circuit: C,
instances: Vec<Vec<Fr>>,
Expand All @@ -117,15 +117,15 @@ pub trait EvmKzgAccumulationScheme:
Rc<EvmLoader>,
VerifyingKey = KzgAsVerifyingKey,
Accumulator = KzgAccumulator<G1Affine, Rc<EvmLoader>>,
> + AccumulationDecider<G1Affine, Rc<EvmLoader>, DecidingKey = KzgDecidingKey<Bn256>>
> + AccumulationDecider<G1Affine, Rc<EvmLoader>, DecidingKey = KzgDecidingKey<Bls12>>
{
}

impl EvmKzgAccumulationScheme for crate::GWC {}
impl EvmKzgAccumulationScheme for crate::SHPLONK {}

pub fn gen_evm_verifier_sol_code<C, AS>(
params: &ParamsKZG<Bn256>,
params: &ParamsKZG<Bls12>,
vk: &VerifyingKey<G1Affine>,
num_instance: Vec<usize>,
) -> String
Expand Down Expand Up @@ -155,7 +155,7 @@ where
}

pub fn gen_evm_verifier<C, AS>(
params: &ParamsKZG<Bn256>,
params: &ParamsKZG<Bls12>,
vk: &VerifyingKey<G1Affine>,
num_instance: Vec<usize>,
path: Option<&Path>,
Expand All @@ -174,7 +174,7 @@ where
}

pub fn gen_evm_verifier_gwc<C: CircuitExt<Fr>>(
params: &ParamsKZG<Bn256>,
params: &ParamsKZG<Bls12>,
vk: &VerifyingKey<G1Affine>,
num_instance: Vec<usize>,
path: Option<&Path>,
Expand All @@ -183,7 +183,7 @@ pub fn gen_evm_verifier_gwc<C: CircuitExt<Fr>>(
}

pub fn gen_evm_verifier_shplonk<C: CircuitExt<Fr>>(
params: &ParamsKZG<Bn256>,
params: &ParamsKZG<Bls12>,
vk: &VerifyingKey<G1Affine>,
num_instance: Vec<usize>,
path: Option<&Path>,
Expand Down
Loading