Skip to content

Commit

Permalink
Working recursive test (#27)
Browse files Browse the repository at this point in the history
* Working recursive test

* Nits

* Minimla

* Address review comments

* Downsize parameters to match size of the circuit

* Remove mutable ref from params

* Address (simple) review comments

* Remove SerdeObject and add read/write functions to hashable
  • Loading branch information
iquerejeta authored Jan 22, 2025
1 parent da31397 commit c5e0ba8
Show file tree
Hide file tree
Showing 29 changed files with 734 additions and 248 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ backtrace = { version = "0.3", optional = true }
ff = "0.13"
group = "0.13"
halo2curves = { version = "0.7.0", default-features = false }
blstrs = { git = "https://github.com/davidnevadoc/blstrs", rev = "8ca6da7" }
blstrs = { git = "https://github.com/davidnevadoc/blstrs", rev = "3dfe5bf" }
rand_core = { version = "0.6", default-features = false }
tracing = "0.1"
blake2b_simd = "1" # MSRV 1.66.0
Expand All @@ -59,6 +59,7 @@ tabbycat = { version = "0.1", features = ["attributes"], optional = true }

# Legacy circuit compatibility
halo2_legacy_pdqsort = { version = "0.1.0", optional = true }
num-bigint = "0.4.6"

[dev-dependencies]
assert_matches = "1.5"
Expand Down Expand Up @@ -86,6 +87,7 @@ sanity-checks = []
circuit-params = []
cost-estimator = ["serde", "serde_derive"]
derive_serde = ["halo2curves/derive_serde"]
truncated-challenges = [] # This feature truncates challenges to half the size of the scalar field.

[lib]
bench = false
Expand Down
2 changes: 1 addition & 1 deletion benches/plonk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ fn criterion_benchmark(c: &mut Criterion) {
a: Value::unknown(),
k,
};
let vk = keygen_vk(&params, &empty_circuit).expect("keygen_vk should not fail");
let vk = keygen_vk_with_k(&params, &empty_circuit, k).expect("keygen_vk should not fail");
let pk = keygen_pk(vk, &empty_circuit).expect("keygen_pk should not fail");
(params, pk)
}
Expand Down
6 changes: 3 additions & 3 deletions examples/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use halo2_proofs::transcript::{CircuitTranscript, Transcript};
use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
plonk::{
create_proof, keygen_pk, keygen_vk, prepare, Advice, Circuit, Column, ConstraintSystem,
Error, Fixed, Instance, ProvingKey,
create_proof, keygen_pk, keygen_vk_with_k, prepare, Advice, Circuit, Column,
ConstraintSystem, Error, Fixed, Instance, ProvingKey,
},
poly::{
kzg::{params::ParamsKZG, KZGCommitmentScheme},
Expand Down Expand Up @@ -128,7 +128,7 @@ fn main() {
let k = 4;
let circuit = StandardPlonk(Fr::random(OsRng));
let params = ParamsKZG::<Bn256>::unsafe_setup(k, OsRng);
let vk = keygen_vk::<_, KZGCommitmentScheme<Bn256>, _>(&params, &circuit)
let vk = keygen_vk_with_k::<_, KZGCommitmentScheme<Bn256>, _>(&params, &circuit, k)
.expect("vk should not fail");
let pk = keygen_pk(vk, &circuit).expect("pk should not fail");

Expand Down
3 changes: 1 addition & 2 deletions examples/vector-ops-unblinded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,13 +473,12 @@ where
Default + SerdeObject + Hashable<State> + CurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
E::Fr: WithSmallOrderMulGroup<3>
+ FromUniformBytes<64>
+ SerdeObject
+ Sampleable<State>
+ Hashable<State>
+ Ord,
{
let params: ParamsKZG<E> = ParamsKZG::unsafe_setup(k, OsRng);
let vk = keygen_vk(&params, &circuit).unwrap();
let vk = keygen_vk_with_k(&params, &circuit, k).unwrap();
let pk = keygen_pk(vk, &circuit).unwrap();

let proof = {
Expand Down
22 changes: 4 additions & 18 deletions src/dev/cost_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
//! verification cost, as well as resulting proof size.
use std::collections::HashSet;
use std::panic::AssertUnwindSafe;
use std::{iter, num::ParseIntError, panic, str::FromStr};
use std::{iter, num::ParseIntError, str::FromStr};

use crate::plonk::Any::Fixed;
use crate::plonk::Circuit;
use crate::plonk::{k_from_circuit, Circuit};
use ff::{Field, FromUniformBytes};
use serde::Deserialize;
use serde_derive::Serialize;
Expand Down Expand Up @@ -264,20 +263,6 @@ pub fn from_circuit_to_model_circuit<
options.into_model_circuit::<COMM, SCALAR>(comm_scheme)
}

fn run_mock_prover_with_fallback<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(
circuit: &C,
instances: Vec<Vec<F>>,
) -> MockProver<F> {
(1..25)
.find_map(|k| {
panic::catch_unwind(AssertUnwindSafe(|| {
MockProver::run(k, circuit, instances.clone()).unwrap()
}))
.ok()
})
.expect("A circuit which can be implemented with at most 2^24 rows.")
}

/// Given a circuit, this function returns [CostOptions]. If no upper bound for `k` is
/// provided, we iterate until a valid `k` is found (this might delay the computation).
pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(
Expand All @@ -289,7 +274,8 @@ pub fn from_circuit_to_cost_model_options<F: Ord + Field + FromUniformBytes<64>,
let prover = if let Some(k) = k_upper_bound {
MockProver::run(k, circuit, instances).unwrap()
} else {
run_mock_prover_with_fallback(circuit, instances.clone())
let k = k_from_circuit(circuit);
MockProver::run(k, circuit, instances).unwrap()
};

let cs = prover.cs;
Expand Down
16 changes: 8 additions & 8 deletions src/plonk/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,10 @@ pub struct FixedQuery {
}

impl FixedQuery {
/// Return the query index
pub fn index(&self) -> Option<usize> {
self.index
}
/// Column index
pub fn column_index(&self) -> usize {
self.column_index
Expand All @@ -504,7 +508,7 @@ impl FixedQuery {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct AdviceQuery {
/// Query index
pub(crate) index: Option<usize>,
pub index: Option<usize>,
/// Column index
pub(crate) column_index: usize,
/// Rotation of this query
Expand Down Expand Up @@ -534,7 +538,7 @@ impl AdviceQuery {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct InstanceQuery {
/// Query index
pub(crate) index: Option<usize>,
pub index: Option<usize>,
/// Column index
pub(crate) column_index: usize,
/// Rotation of this query
Expand Down Expand Up @@ -1338,11 +1342,6 @@ impl<F: Field> Product<Self> for Expression<F> {
}
}

// /// Represents an index into a vector where each entry corresponds to a distinct
// /// point that polynomials are queried at.
// #[derive(Copy, Clone, Debug)]
// pub(crate) struct PointIndex(pub usize);

/// A "virtual cell" is a PLONK cell that has been queried at a particular relative offset
/// within a custom gate.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -2140,7 +2139,8 @@ impl<F: Field> ConstraintSystem<F> {
});
}

pub(crate) fn phases(&self) -> impl Iterator<Item = sealed::Phase> {
/// Return an iterator over the phases of the constraint system.
pub fn phases(&self) -> impl Iterator<Item = sealed::Phase> {
let max_phase = self
.advice_column_phase
.iter()
Expand Down
5 changes: 4 additions & 1 deletion src/plonk/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub enum Error {
ColumnNotInPermutation(Column<Any>),
/// An error relating to a lookup table.
TableError(TableError),
/// The SRS provided does not have the correct size for the Circuit
SrsError,
}

impl From<io::Error> for Error {
Expand Down Expand Up @@ -79,7 +81,8 @@ impl fmt::Display for Error {
f,
"Column {column:?} must be included in the permutation. Help: try applying `meta.enable_equalty` on the column",
),
Error::TableError(error) => write!(f, "{error}")
Error::TableError(error) => write!(f, "{error}"),
Error::SrsError => write!(f, "The SRS provided for the given circuit does not match its size")
}
}
}
Expand Down
32 changes: 26 additions & 6 deletions src/plonk/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,8 @@ impl<F: Field> Assignment<F> for Assembly<F> {
}
}

// This code also appears in `keygen`. We duplicate it here for simplicity of the
// function body.
fn k_from_circuit<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(circuit: &C) -> u32 {
// TODO: We could optimize the order here.
/// Compute the minimal `k` to compute a circuit.
pub fn k_from_circuit<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(circuit: &C) -> u32 {
(1..25)
.find(|k| {
let n = 2usize.pow(*k);
Expand Down Expand Up @@ -244,8 +242,11 @@ fn k_from_circuit<F: Ord + Field + FromUniformBytes<64>, C: Circuit<F>>(circuit:
.expect("A circuit which can be implemented with at most 2^24 rows.")
}

/// Generate a `VerifyingKey` from an instance of `Circuit`.
/// By default, selector compression is turned **off**.
/// Generates a `VerifyingKey` from a `Circuit` instance.
///
/// Automatically determines the smallest `k` required for the given circuit
/// and adjusts the received parameters to match the circuit's size.
/// Use `keygen_vk_with_k` to specify a custom `k` value.
pub fn keygen_vk<F, CS, ConcreteCircuit>(
params: &CS::Parameters,
circuit: &ConcreteCircuit,
Expand All @@ -256,6 +257,25 @@ where
ConcreteCircuit: Circuit<F>,
{
let k = k_from_circuit(circuit);

if params.max_k() != k {
return Err(Error::SrsError);
}

keygen_vk_with_k(params, circuit, k)
}

/// Generate a `VerifyingKey` from an instance of `Circuit`.
pub fn keygen_vk_with_k<F, CS, ConcreteCircuit>(
params: &CS::Parameters,
circuit: &ConcreteCircuit,
k: u32,
) -> Result<VerifyingKey<F, CS>, Error>
where
F: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + Ord,
CS: PolynomialCommitmentScheme<F>,
ConcreteCircuit: Circuit<F>,
{
if params.max_k() < k {
return Err(Error::NotEnoughRowsAvailable {
current_k: params.max_k(),
Expand Down
9 changes: 4 additions & 5 deletions src/plonk/lookup/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
};
use ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
use group::ff::BatchInvert;
use halo2curves::serde::SerdeObject;
use rand_core::{CryptoRng, RngCore};
use std::{collections::BTreeMap, iter};

Expand Down Expand Up @@ -66,7 +65,7 @@ impl<F: WithSmallOrderMulGroup<3> + Ord> Argument<F> {
transcript: &mut T,
) -> Result<Permuted<F>, Error>
where
F: FromUniformBytes<64> + SerdeObject,
F: FromUniformBytes<64>,
CS::Commitment: Hashable<T::Hash>,
{
// Closure to get values of expressions and compress them
Expand Down Expand Up @@ -153,7 +152,7 @@ impl<F: WithSmallOrderMulGroup<3>> Permuted<F> {
transcript: &mut T,
) -> Result<Committed<F>, Error>
where
F: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + SerdeObject,
F: WithSmallOrderMulGroup<3> + FromUniformBytes<64>,
CS::Commitment: Hashable<T::Hash>,
{
let blinding_factors = pk.vk.cs.blinding_factors();
Expand Down Expand Up @@ -286,7 +285,7 @@ impl<F: WithSmallOrderMulGroup<3>> Committed<F> {
transcript: &mut T,
) -> Result<Evaluated<F>, Error>
where
F: Hashable<T::Hash> + SerdeObject,
F: Hashable<T::Hash>,
{
let domain = &pk.vk.domain;
let x_inv = domain.rotate_omega(x, Rotation::prev());
Expand Down Expand Up @@ -368,7 +367,7 @@ fn permute_expression_pair<F, CS: PolynomialCommitmentScheme<F>, R: RngCore>(
table_expression: &Polynomial<F, LagrangeCoeff>,
) -> Result<ExpressionPair<F>, Error>
where
F: WithSmallOrderMulGroup<3> + Ord + FromUniformBytes<64> + SerdeObject,
F: WithSmallOrderMulGroup<3> + Ord + FromUniformBytes<64>,
{
let blinding_factors = pk.vk.cs.blinding_factors();
let usable_rows = pk.vk.n() as usize - (blinding_factors + 1);
Expand Down
5 changes: 2 additions & 3 deletions src/plonk/lookup/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
poly::{Rotation, VerifierQuery},
};
use ff::{PrimeField, WithSmallOrderMulGroup};
use halo2curves::serde::SerdeObject;

pub struct PermutationCommitments<F: PrimeField, CS: PolynomialCommitmentScheme<F>> {
permuted_input_commitment: CS::Commitment,
Expand Down Expand Up @@ -57,7 +56,7 @@ impl<F: PrimeField, CS: PolynomialCommitmentScheme<F>> PermutationCommitments<F,
transcript: &mut T,
) -> Result<Committed<F, CS>, Error>
where
CS::Commitment: Hashable<T::Hash> + SerdeObject,
CS::Commitment: Hashable<T::Hash>,
{
let product_commitment = transcript.read()?;

Expand All @@ -74,7 +73,7 @@ impl<F: PrimeField, CS: PolynomialCommitmentScheme<F>> Committed<F, CS> {
transcript: &mut T,
) -> Result<Evaluated<F, CS>, Error>
where
F: Hashable<T::Hash> + SerdeObject,
F: Hashable<T::Hash>,
{
let product_eval = transcript.read()?;
let product_next_eval = transcript.read()?;
Expand Down
3 changes: 1 addition & 2 deletions src/plonk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ const VERSION: u8 = 0x03;

impl<F, CS> VerifyingKey<F, CS>
where
F: WithSmallOrderMulGroup<3> + SerdeObject + FromUniformBytes<64>,
F: WithSmallOrderMulGroup<3> + FromUniformBytes<64>,
CS: PolynomialCommitmentScheme<F>,
CS::Commitment: SerdeObject,
{
/// Returns `n`
pub fn n(&self) -> u64 {
Expand Down
10 changes: 5 additions & 5 deletions src/plonk/permutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use std::io;
#[derive(Debug, Clone)]
pub struct Argument {
/// A sequence of columns involved in the argument.
pub(super) columns: Vec<Column<Any>>,
pub columns: Vec<Column<Any>>,
}

impl Argument {
Expand Down Expand Up @@ -88,14 +88,14 @@ pub struct VerifyingKey<F: PrimeField, CS: PolynomialCommitmentScheme<F>> {
}

impl<F: PrimeField, CS: PolynomialCommitmentScheme<F>> VerifyingKey<F, CS> {
/// Returns commitments of sigma polynomials
/// Returns the (permutation argument) commitments of the verifying key.
pub fn commitments(&self) -> &Vec<CS::Commitment> {
&self.commitments
}

pub(crate) fn write<W: io::Write>(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()>
where
CS::Commitment: SerdeObject,
CS::Commitment: ProcessedSerdeObject,
{
for commitment in &self.commitments {
commitment.write(writer, format)?;
Expand All @@ -109,7 +109,7 @@ impl<F: PrimeField, CS: PolynomialCommitmentScheme<F>> VerifyingKey<F, CS> {
format: SerdeFormat,
) -> io::Result<Self>
where
CS::Commitment: SerdeObject,
CS::Commitment: ProcessedSerdeObject,
{
let commitments = (0..argument.columns.len())
.map(|_| CS::Commitment::read(reader, format))
Expand All @@ -119,7 +119,7 @@ impl<F: PrimeField, CS: PolynomialCommitmentScheme<F>> VerifyingKey<F, CS> {

pub(crate) fn bytes_length(&self, format: SerdeFormat) -> usize
where
CS::Commitment: SerdeObject,
CS::Commitment: ProcessedSerdeObject,
{
self.commitments.len() * byte_length::<CS::Commitment>(format)
}
Expand Down
5 changes: 2 additions & 3 deletions src/plonk/permutation/prover.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use ff::{PrimeField, WithSmallOrderMulGroup};
use group::ff::BatchInvert;
use halo2curves::serde::SerdeObject;
use rand_core::RngCore;
use std::iter::{self, ExactSizeIterator};

Expand Down Expand Up @@ -180,7 +179,7 @@ impl<F: PrimeField> super::ProvingKey<F> {
transcript: &mut T,
) -> Result<(), Error>
where
F: Hashable<T::Hash> + SerdeObject,
F: Hashable<T::Hash>,
{
// Hash permutation evals
for eval in self.polys.iter().map(|poly| eval_polynomial(poly, x)) {
Expand All @@ -199,7 +198,7 @@ impl<F: WithSmallOrderMulGroup<3>> Committed<F> {
transcript: &mut T,
) -> Result<Evaluated<F>, Error>
where
F: Hashable<T::Hash> + SerdeObject,
F: Hashable<T::Hash>,
{
let domain = &pk.vk.domain;
let blinding_factors = pk.vk.cs.blinding_factors();
Expand Down
Loading

0 comments on commit c5e0ba8

Please sign in to comment.