mirror of
https://github.com/privacy-scaling-explorations/snark-verifier.git
synced 2026-01-10 06:47:54 -05:00
feat: update for multi-phase ConstraintSystem and implement shuffle and plookup with extra challenges
This commit is contained in:
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
cache-on-failure: true
|
||||
|
||||
- name: Run test
|
||||
run: cargo test --all -- --nocapture
|
||||
run: cargo test --all --features test -- --nocapture
|
||||
|
||||
|
||||
lint:
|
||||
|
||||
@@ -6,6 +6,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
ff = "0.12.0"
|
||||
group = "0.12.0"
|
||||
itertools = "0.10.3"
|
||||
lazy_static = "1.4.0"
|
||||
num-bigint = "0.4"
|
||||
num-traits = "0.2"
|
||||
@@ -34,8 +35,11 @@ paste = "1.0.7"
|
||||
|
||||
[features]
|
||||
default = ["halo2", "evm"]
|
||||
test = ["halo2", "evm"]
|
||||
|
||||
halo2 = ["dep:blake2b_simd", "dep:halo2_proofs", "dep:halo2_wrong", "dep:halo2_wrong_ecc", "dep:halo2_wrong_maingate", "dep:halo2_wrong_transcript", "dep:poseidon"]
|
||||
evm = ["dep:foundry_evm", "dep:crossterm", "dep:tui", "dep:ethereum_types", "dep:sha3"]
|
||||
sanity-check = []
|
||||
|
||||
[patch.crates-io]
|
||||
halo2_proofs = { git = "https://github.com/han0110/halo2", branch = "experiment", package = "halo2_proofs" }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::loader::evm::test::tui::Tui;
|
||||
use foundry_evm::{
|
||||
executor::{builder::Backend, ExecutorBuilder},
|
||||
executor::{backend::Backend, fork::MultiFork, ExecutorBuilder},
|
||||
revm::AccountInfo,
|
||||
utils::h256_to_u256_be,
|
||||
Address,
|
||||
@@ -27,14 +27,13 @@ pub fn execute(code: Vec<u8>, calldata: Vec<u8>) -> (bool, u64, Vec<u64>) {
|
||||
let caller = small_address(0xfe);
|
||||
let callee = small_address(0xff);
|
||||
|
||||
let builder = ExecutorBuilder::default()
|
||||
let mut evm = ExecutorBuilder::default()
|
||||
.with_gas_limit(u64::MAX.into())
|
||||
.set_tracing(debug)
|
||||
.set_debugger(debug);
|
||||
.set_debugger(debug)
|
||||
.build(Backend::new(MultiFork::new().0, None));
|
||||
|
||||
let mut evm = builder.build(Backend::simple());
|
||||
|
||||
evm.db
|
||||
evm.backend_mut()
|
||||
.insert_account_info(callee, AccountInfo::new(0.into(), 1, code.into()));
|
||||
|
||||
let result = evm
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::util::{Curve, Domain, Expression, Query};
|
||||
use crate::util::{Curve, Domain, Expression, Group, Query};
|
||||
|
||||
#[cfg(feature = "halo2")]
|
||||
pub mod halo2;
|
||||
@@ -23,3 +23,23 @@ impl<C: Curve> Protocol<C> {
|
||||
self.preprocessed.len() + self.num_statement + self.num_auxiliary.iter().sum::<usize>()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Snark<C: Curve> {
|
||||
pub protocol: Protocol<C>,
|
||||
pub statements: Vec<Vec<<C as Group>::Scalar>>,
|
||||
pub proof: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<C: Curve> Snark<C> {
|
||||
pub fn new(
|
||||
protocol: Protocol<C>,
|
||||
statements: Vec<Vec<<C as Group>::Scalar>>,
|
||||
proof: Vec<u8>,
|
||||
) -> Self {
|
||||
Snark {
|
||||
protocol,
|
||||
statements,
|
||||
proof,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
};
|
||||
use halo2_proofs::{
|
||||
arithmetic::{CurveAffine, CurveExt, FieldExt},
|
||||
plonk::{self, Advice, Any, ConstraintSystem, Fixed, Instance, VerifyingKey},
|
||||
plonk::{self, Any, ConstraintSystem, FirstPhase, SecondPhase, ThirdPhase, VerifyingKey},
|
||||
poly,
|
||||
transcript::{EncodedChallenge, Transcript},
|
||||
};
|
||||
@@ -111,7 +111,10 @@ struct Polynomials<'a, F: FieldExt> {
|
||||
num_fixed: usize,
|
||||
num_permutation_fixed: usize,
|
||||
num_instance: usize,
|
||||
num_advice: usize,
|
||||
num_advice: Vec<usize>,
|
||||
num_challenge: Vec<usize>,
|
||||
advice_index: Vec<usize>,
|
||||
challenge_index: Vec<usize>,
|
||||
num_lookup_permuted: usize,
|
||||
permutation_chunk_size: usize,
|
||||
num_permutation_z: usize,
|
||||
@@ -130,6 +133,29 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
} else {
|
||||
degree - 1
|
||||
};
|
||||
|
||||
let num_phase = *cs.advice_column_phase().iter().max().unwrap() as usize + 1;
|
||||
let remapping = |phase: Vec<u8>| {
|
||||
let num = phase.iter().fold(vec![0; num_phase], |mut num, phase| {
|
||||
num[*phase as usize] += 1;
|
||||
num
|
||||
});
|
||||
let index = phase
|
||||
.iter()
|
||||
.scan(vec![0; num_phase], |state, phase| {
|
||||
let index = state[*phase as usize];
|
||||
state[*phase as usize] += 1;
|
||||
Some(index)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
(num, index)
|
||||
};
|
||||
|
||||
let (num_advice, advice_index) = remapping(cs.advice_column_phase());
|
||||
let (num_challenge, challenge_index) = remapping(cs.challenge_phase());
|
||||
assert_eq!(num_advice.iter().sum::<usize>(), cs.num_advice_columns());
|
||||
assert_eq!(num_challenge.iter().sum::<usize>(), cs.num_challenges());
|
||||
|
||||
Self {
|
||||
cs,
|
||||
zk,
|
||||
@@ -138,7 +164,10 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
num_fixed: cs.num_fixed_columns(),
|
||||
num_permutation_fixed: cs.permutation().get_columns().len(),
|
||||
num_instance: cs.num_instance_columns(),
|
||||
num_advice: cs.num_advice_columns(),
|
||||
num_advice,
|
||||
num_challenge,
|
||||
advice_index,
|
||||
challenge_index,
|
||||
num_lookup_permuted: 2 * cs.lookups().len(),
|
||||
permutation_chunk_size,
|
||||
num_permutation_z: cs
|
||||
@@ -159,19 +188,30 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
}
|
||||
|
||||
fn num_auxiliary(&self) -> Vec<usize> {
|
||||
vec![
|
||||
self.num_proof * self.num_advice,
|
||||
self.num_proof * self.num_lookup_permuted,
|
||||
self.num_proof * (self.num_permutation_z + self.num_lookup_z) + self.zk as usize,
|
||||
]
|
||||
iter::empty()
|
||||
.chain(
|
||||
self.num_advice
|
||||
.clone()
|
||||
.iter()
|
||||
.map(|num| self.num_proof * num),
|
||||
)
|
||||
.chain([
|
||||
self.num_proof * self.num_lookup_permuted,
|
||||
self.num_proof * (self.num_permutation_z + self.num_lookup_z) + self.zk as usize,
|
||||
])
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn num_challenge(&self) -> Vec<usize> {
|
||||
vec![
|
||||
1, // theta
|
||||
2, // beta, gamma
|
||||
0,
|
||||
]
|
||||
let mut num_challenge = self.num_challenge.clone();
|
||||
*num_challenge.last_mut().unwrap() += 1; // theta
|
||||
iter::empty()
|
||||
.chain(num_challenge)
|
||||
.chain([
|
||||
2, // beta, gamma
|
||||
0,
|
||||
])
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn instance_offset(&self) -> usize {
|
||||
@@ -182,17 +222,35 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
self.instance_offset() + self.num_statement()
|
||||
}
|
||||
|
||||
fn cs_auxiliary_offset(&self) -> usize {
|
||||
self.auxiliary_offset()
|
||||
+ self
|
||||
.num_auxiliary()
|
||||
.iter()
|
||||
.take(self.num_advice.len())
|
||||
.sum::<usize>()
|
||||
}
|
||||
|
||||
fn query<C: Into<Any> + Copy, R: Into<Rotation>>(
|
||||
&self,
|
||||
column_type: C,
|
||||
column_index: usize,
|
||||
mut column_index: usize,
|
||||
rotation: R,
|
||||
t: usize,
|
||||
) -> Query {
|
||||
let offset = match column_type.into() {
|
||||
Any::Fixed => 0,
|
||||
Any::Instance => self.instance_offset() + t * self.num_instance,
|
||||
Any::Advice => self.auxiliary_offset() + t * self.num_advice,
|
||||
Any::Advice(advice) => {
|
||||
column_index = self.advice_index[column_index];
|
||||
let phase_offset = self.num_proof
|
||||
* self.num_advice[..advice.phase() as usize]
|
||||
.iter()
|
||||
.sum::<usize>();
|
||||
self.auxiliary_offset()
|
||||
+ phase_offset
|
||||
+ t * self.num_advice[advice.phase() as usize]
|
||||
}
|
||||
};
|
||||
Query::new(offset + column_index, rotation.into())
|
||||
}
|
||||
@@ -234,7 +292,7 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
}
|
||||
|
||||
fn permutation_poly(&'a self, t: usize, i: usize) -> usize {
|
||||
let z_offset = self.auxiliary_offset() + self.num_auxiliary().iter().take(2).sum::<usize>();
|
||||
let z_offset = self.cs_auxiliary_offset() + self.num_auxiliary()[self.num_advice.len()];
|
||||
z_offset + t * self.num_permutation_z + i
|
||||
}
|
||||
|
||||
@@ -275,9 +333,10 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
}
|
||||
|
||||
fn lookup_poly(&'a self, t: usize, i: usize) -> (usize, usize, usize) {
|
||||
let permuted_offset = self.auxiliary_offset() + self.num_auxiliary()[0];
|
||||
let z_offset =
|
||||
permuted_offset + self.num_auxiliary()[1] + self.num_proof * self.num_permutation_z;
|
||||
let permuted_offset = self.cs_auxiliary_offset();
|
||||
let z_offset = permuted_offset
|
||||
+ self.num_auxiliary()[self.num_advice.len()]
|
||||
+ self.num_proof * self.num_permutation_z;
|
||||
let z = z_offset + t * self.num_lookup_z + i;
|
||||
let permuted_input = permuted_offset + 2 * (t * self.num_lookup_z + i);
|
||||
let permuted_table = permuted_input + 1;
|
||||
@@ -328,9 +387,34 @@ impl<'a, F: FieldExt> Polynomials<'a, F> {
|
||||
expression.evaluate(
|
||||
&|scalar| Expression::Constant(scalar),
|
||||
&|_| unreachable!(),
|
||||
&|_, index, rotation| self.query(Fixed, index, rotation, t).into(),
|
||||
&|_, index, rotation| self.query(Advice, index, rotation, t).into(),
|
||||
&|_, index, rotation| self.query(Instance, index, rotation, t).into(),
|
||||
&|query| {
|
||||
self.query(Any::Fixed, query.column_index(), query.rotation(), t)
|
||||
.into()
|
||||
},
|
||||
&|query| {
|
||||
self.query(
|
||||
match query.phase() {
|
||||
0 => Any::advice_in(FirstPhase),
|
||||
1 => Any::advice_in(SecondPhase),
|
||||
2 => Any::advice_in(ThirdPhase),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
query.column_index(),
|
||||
query.rotation(),
|
||||
t,
|
||||
)
|
||||
.into()
|
||||
},
|
||||
&|query| {
|
||||
self.query(Any::Instance, query.column_index(), query.rotation(), t)
|
||||
.into()
|
||||
},
|
||||
&|challenge| {
|
||||
let phase_offset = self.num_challenge[..challenge.phase() as usize]
|
||||
.iter()
|
||||
.sum::<usize>();
|
||||
Expression::Challenge(phase_offset + self.challenge_index[challenge.index()])
|
||||
},
|
||||
&|a| -a,
|
||||
&|a, b| a + b,
|
||||
&|a, b| a * b,
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
use crate::{
|
||||
protocol::{
|
||||
halo2::{compile, Config},
|
||||
Protocol,
|
||||
},
|
||||
util::{CommonPolynomial, Curve, Expression, Group, Query},
|
||||
protocol::halo2::{compile, Config},
|
||||
util::{CommonPolynomial, Expression, Query},
|
||||
};
|
||||
use halo2_curves::bn256::{Bn256, Fr, G1};
|
||||
use halo2_proofs::{
|
||||
arithmetic::FieldExt,
|
||||
circuit::{floor_planner::V1, Layouter, Value},
|
||||
dev::MockProver,
|
||||
plonk::{
|
||||
create_proof, keygen_pk, keygen_vk, verify_proof, Advice, Any, Circuit, Column,
|
||||
ConstraintSystem, Error, Fixed, Instance, ProvingKey,
|
||||
},
|
||||
plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey},
|
||||
poly::{
|
||||
commitment::{CommitmentScheme, Params, ParamsProver, Prover, Verifier},
|
||||
kzg::commitment::KZGCommitmentScheme,
|
||||
@@ -21,254 +14,19 @@ use halo2_proofs::{
|
||||
},
|
||||
transcript::{EncodedChallenge, TranscriptReadBuffer, TranscriptWriterBuffer},
|
||||
};
|
||||
use halo2_wrong_ecc::EccConfig;
|
||||
use halo2_wrong_maingate::{
|
||||
MainGate, MainGateConfig, MainGateInstructions, RangeChip, RangeConfig, RangeInstructions,
|
||||
RegionCtx,
|
||||
};
|
||||
use rand_chacha::{
|
||||
rand_core::{RngCore, SeedableRng},
|
||||
ChaCha20Rng,
|
||||
};
|
||||
|
||||
mod circuit;
|
||||
mod kzg;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone)]
|
||||
pub struct StandardPlonkConfig {
|
||||
a: Column<Advice>,
|
||||
b: Column<Advice>,
|
||||
c: Column<Advice>,
|
||||
q_a: Column<Fixed>,
|
||||
q_b: Column<Fixed>,
|
||||
q_c: Column<Fixed>,
|
||||
q_ab: Column<Fixed>,
|
||||
constant: Column<Fixed>,
|
||||
instance: Column<Instance>,
|
||||
}
|
||||
|
||||
impl StandardPlonkConfig {
|
||||
pub fn configure<F: FieldExt>(meta: &mut ConstraintSystem<F>) -> Self {
|
||||
let a = meta.advice_column();
|
||||
let b = meta.advice_column();
|
||||
let c = meta.advice_column();
|
||||
|
||||
let q_a = meta.fixed_column();
|
||||
let q_b = meta.fixed_column();
|
||||
let q_c = meta.fixed_column();
|
||||
|
||||
let q_ab = meta.fixed_column();
|
||||
|
||||
let constant = meta.fixed_column();
|
||||
let instance = meta.instance_column();
|
||||
|
||||
meta.enable_equality(a);
|
||||
meta.enable_equality(b);
|
||||
meta.enable_equality(c);
|
||||
|
||||
meta.create_gate("", |meta| {
|
||||
let [a, b, c, q_a, q_b, q_c, q_ab, constant, instance] = [
|
||||
a.into(),
|
||||
b.into(),
|
||||
c.into(),
|
||||
q_a.into(),
|
||||
q_b.into(),
|
||||
q_c.into(),
|
||||
q_ab.into(),
|
||||
constant.into(),
|
||||
instance.into(),
|
||||
]
|
||||
.map(|column: Column<Any>| meta.query_any(column, Rotation::cur()));
|
||||
|
||||
vec![q_a * a.clone() + q_b * b.clone() + q_c * c + q_ab * a * b + constant + instance]
|
||||
});
|
||||
|
||||
StandardPlonkConfig {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
q_a,
|
||||
q_b,
|
||||
q_c,
|
||||
q_ab,
|
||||
constant,
|
||||
instance,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct StandardPlonk<F>(F);
|
||||
|
||||
impl<F: FieldExt> StandardPlonk<F> {
|
||||
pub fn rand<R: RngCore>(mut rng: R) -> Self {
|
||||
Self(F::from(rng.next_u32() as u64))
|
||||
}
|
||||
|
||||
pub fn instances(&self) -> Vec<Vec<F>> {
|
||||
vec![vec![self.0]]
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FieldExt> Circuit<F> for StandardPlonk<F> {
|
||||
type Config = StandardPlonkConfig;
|
||||
type FloorPlanner = V1;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
||||
meta.set_minimum_degree(4);
|
||||
StandardPlonkConfig::configure(meta)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<F>,
|
||||
) -> Result<(), Error> {
|
||||
layouter.assign_region(
|
||||
|| "",
|
||||
|mut region| {
|
||||
region.assign_advice(|| "", config.a, 0, || Value::known(self.0))?;
|
||||
region.assign_fixed(|| "", config.q_a, 0, || Value::known(-F::one()))?;
|
||||
|
||||
region.assign_advice(|| "", config.a, 1, || Value::known(-F::from(5)))?;
|
||||
for (column, idx) in [
|
||||
config.q_a,
|
||||
config.q_b,
|
||||
config.q_c,
|
||||
config.q_ab,
|
||||
config.constant,
|
||||
]
|
||||
.iter()
|
||||
.zip(1..)
|
||||
{
|
||||
region.assign_fixed(|| "", *column, 1, || Value::known(F::from(idx)))?;
|
||||
}
|
||||
|
||||
let a = region.assign_advice(|| "", config.a, 2, || Value::known(F::one()))?;
|
||||
a.copy_advice(|| "", &mut region, config.b, 3)?;
|
||||
a.copy_advice(|| "", &mut region, config.c, 4)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MainGateWithRangeConfig {
|
||||
main_gate_config: MainGateConfig,
|
||||
range_config: RangeConfig,
|
||||
}
|
||||
|
||||
impl MainGateWithRangeConfig {
|
||||
fn ecc_config(&self) -> EccConfig {
|
||||
EccConfig::new(self.range_config.clone(), self.main_gate_config.clone())
|
||||
}
|
||||
|
||||
fn configure<F: FieldExt>(
|
||||
meta: &mut ConstraintSystem<F>,
|
||||
composition_bits: Vec<usize>,
|
||||
overflow_bits: Vec<usize>,
|
||||
) -> Self {
|
||||
let main_gate_config = MainGate::<F>::configure(meta);
|
||||
let range_config =
|
||||
RangeChip::<F>::configure(meta, &main_gate_config, composition_bits, overflow_bits);
|
||||
MainGateWithRangeConfig {
|
||||
main_gate_config,
|
||||
range_config,
|
||||
}
|
||||
}
|
||||
|
||||
fn load_table<F: FieldExt>(&self, layouter: &mut impl Layouter<F>) -> Result<(), Error> {
|
||||
let range_chip = RangeChip::<F>::new(self.range_config.clone());
|
||||
range_chip.load_table(layouter)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct MainGateWithRange<F>(Vec<F>);
|
||||
|
||||
impl<F: FieldExt> MainGateWithRange<F> {
|
||||
pub fn new(inner: Vec<F>) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
|
||||
pub fn rand<R: RngCore>(mut rng: R) -> Self {
|
||||
Self::new(vec![F::from(rng.next_u32() as u64)])
|
||||
}
|
||||
|
||||
pub fn instances(&self) -> Vec<Vec<F>> {
|
||||
vec![self.0.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FieldExt> Circuit<F> for MainGateWithRange<F> {
|
||||
type Config = MainGateWithRangeConfig;
|
||||
type FloorPlanner = V1;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self(vec![F::zero()])
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
||||
MainGateWithRangeConfig::configure(meta, vec![8], vec![1, 7])
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<F>,
|
||||
) -> Result<(), Error> {
|
||||
let main_gate = MainGate::new(config.main_gate_config);
|
||||
let range_chip = RangeChip::new(config.range_config);
|
||||
range_chip.load_table(&mut layouter)?;
|
||||
|
||||
let a = layouter.assign_region(
|
||||
|| "",
|
||||
|mut region| {
|
||||
let mut offset = 0;
|
||||
let mut ctx = RegionCtx::new(&mut region, &mut offset);
|
||||
range_chip.decompose(&mut ctx, Value::known(F::from(u64::MAX)), 8, 64)?;
|
||||
range_chip.decompose(&mut ctx, Value::known(self.0[0]), 8, 33)?;
|
||||
let (a, _) = range_chip.decompose(&mut ctx, Value::known(self.0[0]), 8, 39)?;
|
||||
let b = main_gate.sub_sub_with_constant(&mut ctx, &a, &a, &a, F::from(2))?;
|
||||
let cond = main_gate.assign_bit(&mut ctx, Value::known(F::one()))?;
|
||||
main_gate.select(&mut ctx, &a, &b, &cond)?;
|
||||
|
||||
Ok(a)
|
||||
},
|
||||
)?;
|
||||
|
||||
main_gate.expose_public(layouter, a, 0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Snark<C: Curve> {
|
||||
protocol: Protocol<C>,
|
||||
statements: Vec<Vec<<C as Group>::Scalar>>,
|
||||
proof: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<C: Curve> Snark<C> {
|
||||
pub fn new(
|
||||
protocol: Protocol<C>,
|
||||
statements: Vec<Vec<<C as Group>::Scalar>>,
|
||||
proof: Vec<u8>,
|
||||
) -> Self {
|
||||
Snark {
|
||||
protocol,
|
||||
statements,
|
||||
proof,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use circuit::{
|
||||
maingate::{MainGateWithRange, MainGateWithRangeConfig},
|
||||
plookup::Plookuper,
|
||||
standard::StandardPlonk,
|
||||
};
|
||||
|
||||
pub fn create_proof_checked<'a, S, C, P, V, VS, TW, TR, EC, R, const ZK: bool>(
|
||||
params: &'a S::ParamsProver,
|
||||
|
||||
3
src/protocol/halo2/test/circuit.rs
Normal file
3
src/protocol/halo2/test/circuit.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod maingate;
|
||||
pub mod plookup;
|
||||
pub mod standard;
|
||||
103
src/protocol/halo2/test/circuit/maingate.rs
Normal file
103
src/protocol/halo2/test/circuit/maingate.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use halo2_proofs::{
|
||||
arithmetic::FieldExt,
|
||||
circuit::{floor_planner::V1, Layouter, Value},
|
||||
plonk::{Circuit, ConstraintSystem, Error},
|
||||
};
|
||||
use halo2_wrong_ecc::EccConfig;
|
||||
use halo2_wrong_maingate::{
|
||||
MainGate, MainGateConfig, MainGateInstructions, RangeChip, RangeConfig, RangeInstructions,
|
||||
RegionCtx,
|
||||
};
|
||||
use rand::RngCore;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MainGateWithRangeConfig {
|
||||
main_gate_config: MainGateConfig,
|
||||
range_config: RangeConfig,
|
||||
}
|
||||
|
||||
impl MainGateWithRangeConfig {
|
||||
pub fn ecc_config(&self) -> EccConfig {
|
||||
EccConfig::new(self.range_config.clone(), self.main_gate_config.clone())
|
||||
}
|
||||
|
||||
pub fn configure<F: FieldExt>(
|
||||
meta: &mut ConstraintSystem<F>,
|
||||
composition_bits: Vec<usize>,
|
||||
overflow_bits: Vec<usize>,
|
||||
) -> Self {
|
||||
let main_gate_config = MainGate::<F>::configure(meta);
|
||||
let range_config =
|
||||
RangeChip::<F>::configure(meta, &main_gate_config, composition_bits, overflow_bits);
|
||||
MainGateWithRangeConfig {
|
||||
main_gate_config,
|
||||
range_config,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_table<F: FieldExt>(&self, layouter: &mut impl Layouter<F>) -> Result<(), Error> {
|
||||
let range_chip = RangeChip::<F>::new(self.range_config.clone());
|
||||
range_chip.load_table(layouter)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct MainGateWithRange<F>(Vec<F>);
|
||||
|
||||
impl<F: FieldExt> MainGateWithRange<F> {
|
||||
pub fn new(inner: Vec<F>) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
|
||||
pub fn rand<R: RngCore>(mut rng: R) -> Self {
|
||||
Self::new(vec![F::from(rng.next_u32() as u64)])
|
||||
}
|
||||
|
||||
pub fn instances(&self) -> Vec<Vec<F>> {
|
||||
vec![self.0.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FieldExt> Circuit<F> for MainGateWithRange<F> {
|
||||
type Config = MainGateWithRangeConfig;
|
||||
type FloorPlanner = V1;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self(vec![F::zero()])
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
||||
MainGateWithRangeConfig::configure(meta, vec![8], vec![1, 7])
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<F>,
|
||||
) -> Result<(), Error> {
|
||||
let main_gate = MainGate::new(config.main_gate_config);
|
||||
let range_chip = RangeChip::new(config.range_config);
|
||||
range_chip.load_table(&mut layouter)?;
|
||||
|
||||
let a = layouter.assign_region(
|
||||
|| "",
|
||||
|mut region| {
|
||||
let mut offset = 0;
|
||||
let mut ctx = RegionCtx::new(&mut region, &mut offset);
|
||||
range_chip.decompose(&mut ctx, Value::known(F::from(u64::MAX)), 8, 64)?;
|
||||
range_chip.decompose(&mut ctx, Value::known(self.0[0]), 8, 33)?;
|
||||
let (a, _) = range_chip.decompose(&mut ctx, Value::known(self.0[0]), 8, 39)?;
|
||||
let b = main_gate.sub_sub_with_constant(&mut ctx, &a, &a, &a, F::from(2))?;
|
||||
let cond = main_gate.assign_bit(&mut ctx, Value::known(F::one()))?;
|
||||
main_gate.select(&mut ctx, &a, &b, &cond)?;
|
||||
|
||||
Ok(a)
|
||||
},
|
||||
)?;
|
||||
|
||||
main_gate.expose_public(layouter, a, 0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
1067
src/protocol/halo2/test/circuit/plookup.rs
Normal file
1067
src/protocol/halo2/test/circuit/plookup.rs
Normal file
File diff suppressed because it is too large
Load Diff
132
src/protocol/halo2/test/circuit/standard.rs
Normal file
132
src/protocol/halo2/test/circuit/standard.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
use halo2_proofs::{
|
||||
arithmetic::FieldExt,
|
||||
circuit::{floor_planner::V1, Layouter, Value},
|
||||
plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Error, Fixed, Instance},
|
||||
poly::Rotation,
|
||||
};
|
||||
use rand::RngCore;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone)]
|
||||
pub struct StandardPlonkConfig {
|
||||
a: Column<Advice>,
|
||||
b: Column<Advice>,
|
||||
c: Column<Advice>,
|
||||
q_a: Column<Fixed>,
|
||||
q_b: Column<Fixed>,
|
||||
q_c: Column<Fixed>,
|
||||
q_ab: Column<Fixed>,
|
||||
constant: Column<Fixed>,
|
||||
instance: Column<Instance>,
|
||||
}
|
||||
|
||||
impl StandardPlonkConfig {
|
||||
pub fn configure<F: FieldExt>(meta: &mut ConstraintSystem<F>) -> Self {
|
||||
let a = meta.advice_column();
|
||||
let b = meta.advice_column();
|
||||
let c = meta.advice_column();
|
||||
|
||||
let q_a = meta.fixed_column();
|
||||
let q_b = meta.fixed_column();
|
||||
let q_c = meta.fixed_column();
|
||||
|
||||
let q_ab = meta.fixed_column();
|
||||
|
||||
let constant = meta.fixed_column();
|
||||
let instance = meta.instance_column();
|
||||
|
||||
meta.enable_equality(a);
|
||||
meta.enable_equality(b);
|
||||
meta.enable_equality(c);
|
||||
|
||||
meta.create_gate("", |meta| {
|
||||
let [a, b, c, q_a, q_b, q_c, q_ab, constant, instance] = [
|
||||
a.into(),
|
||||
b.into(),
|
||||
c.into(),
|
||||
q_a.into(),
|
||||
q_b.into(),
|
||||
q_c.into(),
|
||||
q_ab.into(),
|
||||
constant.into(),
|
||||
instance.into(),
|
||||
]
|
||||
.map(|column: Column<Any>| meta.query_any(column, Rotation::cur()));
|
||||
|
||||
vec![q_a * a.clone() + q_b * b.clone() + q_c * c + q_ab * a * b + constant + instance]
|
||||
});
|
||||
|
||||
StandardPlonkConfig {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
q_a,
|
||||
q_b,
|
||||
q_c,
|
||||
q_ab,
|
||||
constant,
|
||||
instance,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct StandardPlonk<F>(F);
|
||||
|
||||
impl<F: FieldExt> StandardPlonk<F> {
|
||||
pub fn rand<R: RngCore>(mut rng: R) -> Self {
|
||||
Self(F::from(rng.next_u32() as u64))
|
||||
}
|
||||
|
||||
pub fn instances(&self) -> Vec<Vec<F>> {
|
||||
vec![vec![self.0]]
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FieldExt> Circuit<F> for StandardPlonk<F> {
|
||||
type Config = StandardPlonkConfig;
|
||||
type FloorPlanner = V1;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
||||
meta.set_minimum_degree(4);
|
||||
StandardPlonkConfig::configure(meta)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<F>,
|
||||
) -> Result<(), Error> {
|
||||
layouter.assign_region(
|
||||
|| "",
|
||||
|mut region| {
|
||||
region.assign_advice(|| "", config.a, 0, || Value::known(self.0))?;
|
||||
region.assign_fixed(|| "", config.q_a, 0, || Value::known(-F::one()))?;
|
||||
|
||||
region.assign_advice(|| "", config.a, 1, || Value::known(-F::from(5)))?;
|
||||
for (column, idx) in [
|
||||
config.q_a,
|
||||
config.q_b,
|
||||
config.q_c,
|
||||
config.q_ab,
|
||||
config.constant,
|
||||
]
|
||||
.iter()
|
||||
.zip(1..)
|
||||
{
|
||||
region.assign_fixed(|| "", *column, 1, || Value::known(F::from(idx)))?;
|
||||
}
|
||||
|
||||
let a = region.assign_advice(|| "", config.a, 2, || Value::known(F::one()))?;
|
||||
a.copy_advice(|| "", &mut region, config.b, 3)?;
|
||||
a.copy_advice(|| "", &mut region, config.c, 4)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ macro_rules! halo2_kzg_create_snark {
|
||||
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
|
||||
use $crate::{
|
||||
collect_slice,
|
||||
protocol::halo2::test::{create_proof_checked, Snark},
|
||||
protocol::{halo2::test::create_proof_checked, Snark},
|
||||
};
|
||||
|
||||
let instances = $circuits
|
||||
|
||||
@@ -6,11 +6,11 @@ use crate::{
|
||||
halo2::{
|
||||
test::{
|
||||
kzg::{BITS, LIMBS},
|
||||
MainGateWithRange, MainGateWithRangeConfig, Snark, StandardPlonk,
|
||||
MainGateWithRange, MainGateWithRangeConfig, StandardPlonk,
|
||||
},
|
||||
util::halo2::ChallengeScalar,
|
||||
},
|
||||
Protocol,
|
||||
Protocol, Snark,
|
||||
},
|
||||
scheme::kzg::{self, AccumulationScheme, ShplonkAccumulationScheme},
|
||||
util::{fe_to_limbs, Curve, Group, PrimeCurveAffine},
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
halo2_kzg_prepare,
|
||||
protocol::halo2::test::{
|
||||
kzg::{main_gate_with_range_with_mock_kzg_accumulator, LIMBS},
|
||||
MainGateWithRange,
|
||||
Plookuper, StandardPlonk,
|
||||
},
|
||||
scheme::kzg::{PlonkAccumulationScheme, ShplonkAccumulationScheme},
|
||||
};
|
||||
@@ -57,10 +57,10 @@ macro_rules! test {
|
||||
}
|
||||
|
||||
test!(
|
||||
zk_main_gate_with_range_rand,
|
||||
zk_standard_plonk_rand,
|
||||
9,
|
||||
halo2_kzg_config!(true, 2),
|
||||
MainGateWithRange::<_>::rand(ChaCha20Rng::from_seed(Default::default()))
|
||||
StandardPlonk::<_>::rand(ChaCha20Rng::from_seed(Default::default()))
|
||||
);
|
||||
test!(
|
||||
zk_main_gate_with_range_with_mock_kzg_accumulator,
|
||||
@@ -69,10 +69,10 @@ test!(
|
||||
main_gate_with_range_with_mock_kzg_accumulator::<Bn256>()
|
||||
);
|
||||
test!(
|
||||
main_gate_with_range_rand,
|
||||
standard_plonk_rand,
|
||||
9,
|
||||
halo2_kzg_config!(false, 2),
|
||||
MainGateWithRange::<_>::rand(ChaCha20Rng::from_seed(Default::default()))
|
||||
StandardPlonk::<_>::rand(ChaCha20Rng::from_seed(Default::default()))
|
||||
);
|
||||
test!(
|
||||
main_gate_with_range_with_mock_kzg_accumulator,
|
||||
@@ -80,3 +80,9 @@ test!(
|
||||
halo2_kzg_config!(false, 2, (0..4 * LIMBS).map(|idx| (0, idx + 1)).collect()),
|
||||
main_gate_with_range_with_mock_kzg_accumulator::<Bn256>()
|
||||
);
|
||||
test!(
|
||||
plookup_rand,
|
||||
9,
|
||||
halo2_kzg_config!(false, 2),
|
||||
Plookuper::<_, 2, 5, false>::rand(ChaCha20Rng::from_seed(Default::default()), 1 << 9)
|
||||
);
|
||||
|
||||
@@ -3,9 +3,9 @@ mod expression;
|
||||
mod transcript;
|
||||
|
||||
pub use arithmetic::{
|
||||
batch_invert, batch_invert_and_mul, fe_from_limbs, fe_to_limbs, Curve, Domain, Field, FieldOps,
|
||||
Fraction, Group, GroupEncoding, GroupOps, PrimeCurveAffine, PrimeField, Rotation,
|
||||
UncompressedEncoding,
|
||||
batch_invert, batch_invert_and_mul, fe_from_limbs, fe_to_limbs, BatchInvert, Curve, Domain,
|
||||
Field, FieldOps, Fraction, Group, GroupEncoding, GroupOps, PrimeCurveAffine, PrimeField,
|
||||
Rotation, UncompressedEncoding,
|
||||
};
|
||||
pub use expression::{CommonPolynomial, CommonPolynomialEvaluation, Expression, Query};
|
||||
pub use transcript::{Transcript, TranscriptRead};
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
};
|
||||
|
||||
pub use ff::{Field, PrimeField};
|
||||
pub use ff::{BatchInvert, Field, PrimeField};
|
||||
pub use group::{prime::PrimeCurveAffine, Curve, Group, GroupEncoding};
|
||||
|
||||
pub trait GroupOps:
|
||||
|
||||
Reference in New Issue
Block a user