Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable instance query #96

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
89 changes: 49 additions & 40 deletions halo2_proofs/src/plonk/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,32 @@ pub fn create_proof<
return Err(Error::InstanceTooLarge);
}
for (poly, value) in poly.iter_mut().zip(values.iter()) {
if !P::QUERY_INSTANCE {
transcript.common_scalar(*value)?;
}
*poly = *value;
}
Ok(poly)
})
.collect::<Result<Vec<_>, _>>()?;
let instance_commitments_projective: Vec<_> = instance_values
.iter()
.map(|poly| params.commit_lagrange(poly, Blind::default()))
.collect();
let mut instance_commitments =
vec![Scheme::Curve::identity(); instance_commitments_projective.len()];
<Scheme::Curve as CurveAffine>::CurveExt::batch_normalize(
&instance_commitments_projective,
&mut instance_commitments,
);
let instance_commitments = instance_commitments;
drop(instance_commitments_projective);

for commitment in &instance_commitments {
transcript.common_point(*commitment)?;

if P::QUERY_INSTANCE {
let instance_commitments_projective: Vec<_> = instance_values
.iter()
.map(|poly| params.commit_lagrange(poly, Blind::default()))
.collect();
let mut instance_commitments =
vec![Scheme::Curve::identity(); instance_commitments_projective.len()];
<Scheme::Curve as CurveAffine>::CurveExt::batch_normalize(
&instance_commitments_projective,
&mut instance_commitments,
);
let instance_commitments = instance_commitments;
drop(instance_commitments_projective);

for commitment in &instance_commitments {
transcript.common_point(*commitment)?;
}
}

let instance_polys: Vec<_> = instance_values
Expand Down Expand Up @@ -504,23 +510,25 @@ pub fn create_proof<
let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
let xn = x.pow(&[params.n() as u64, 0, 0, 0]);

// Compute and hash instance evals for each circuit instance
for instance in instance.iter() {
// Evaluate polynomials at omega^i x
let instance_evals: Vec<_> = meta
.instance_queries
.iter()
.map(|&(column, at)| {
eval_polynomial(
&instance.instance_polys[column.index()],
domain.rotate_omega(*x, at),
)
})
.collect();
if P::QUERY_INSTANCE {
// Compute and hash instance evals for each circuit instance
for instance in instance.iter() {
// Evaluate polynomials at omega^i x
let instance_evals: Vec<_> = meta
.instance_queries
.iter()
.map(|&(column, at)| {
eval_polynomial(
&instance.instance_polys[column.index()],
domain.rotate_omega(*x, at),
)
})
.collect();

// Hash each instance column evaluation
for eval in instance_evals.iter() {
transcript.write_scalar(*eval)?;
// Hash each instance column evaluation
for eval in instance_evals.iter() {
transcript.write_scalar(*eval)?;
}
}
}

Expand Down Expand Up @@ -588,15 +596,16 @@ pub fn create_proof<
.flat_map(|(((instance, advice), permutation), lookups)| {
iter::empty()
.chain(
pk.vk
.cs
.instance_queries
.iter()
.map(move |&(column, at)| ProverQuery {
point: domain.rotate_omega(*x, at),
poly: &instance.instance_polys[column.index()],
blind: Blind::default(),
}),
P::QUERY_INSTANCE
.then_some(pk.vk.cs.instance_queries.iter().map(move |&(column, at)| {
ProverQuery {
point: domain.rotate_omega(*x, at),
poly: &instance.instance_polys[column.index()],
blind: Blind::default(),
}
}))
.into_iter()
.flatten(),
)
.chain(
pk.vk
Expand Down
132 changes: 97 additions & 35 deletions halo2_proofs/src/plonk/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{
vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, ChallengeY, Error,
VerifyingKey,
};
use crate::arithmetic::{CurveAffine, FieldExt};
use crate::arithmetic::{compute_inner_product, CurveAffine, FieldExt};
use crate::poly::commitment::{CommitmentScheme, Verifier};
use crate::poly::VerificationStrategy;
use crate::poly::{
Expand Down Expand Up @@ -45,34 +45,48 @@ pub fn verify_proof<
}
}

let instance_commitments = instances
.iter()
.map(|instance| {
instance
.iter()
.map(|instance| {
if instance.len() > params.n() as usize - (vk.cs.blinding_factors() + 1) {
return Err(Error::InstanceTooLarge);
}
let mut poly = instance.to_vec();
poly.resize(params.n() as usize, Scheme::Scalar::zero());
let poly = vk.domain.lagrange_from_vec(poly);

Ok(params.commit_lagrange(&poly, Blind::default()).to_affine())
})
.collect::<Result<Vec<_>, _>>()
})
.collect::<Result<Vec<_>, _>>()?;
let instance_commitments = if V::QUERY_INSTANCE {
instances
.iter()
.map(|instance| {
instance
.iter()
.map(|instance| {
if instance.len() > params.n() as usize - (vk.cs.blinding_factors() + 1) {
return Err(Error::InstanceTooLarge);
}
let mut poly = instance.to_vec();
poly.resize(params.n() as usize, Scheme::Scalar::zero());
let poly = vk.domain.lagrange_from_vec(poly);

Ok(params.commit_lagrange(&poly, Blind::default()).to_affine())
})
.collect::<Result<Vec<_>, _>>()
})
.collect::<Result<Vec<_>, _>>()?
} else {
vec![vec![]; instances.len()]
};

let num_proofs = instance_commitments.len();

// Hash verification key into transcript
vk.hash_into(transcript)?;

for instance_commitments in instance_commitments.iter() {
// Hash the instance (external) commitments into the transcript
for commitment in instance_commitments {
transcript.common_point(*commitment)?
if V::QUERY_INSTANCE {
for instance_commitments in instance_commitments.iter() {
// Hash the instance (external) commitments into the transcript
for commitment in instance_commitments {
transcript.common_point(*commitment)?
}
}
} else {
for instance in instances.iter() {
for instance in instance.iter() {
for value in instance.iter() {
transcript.common_scalar(*value)?;
}
}
}
}

Expand Down Expand Up @@ -153,9 +167,52 @@ pub fn verify_proof<
// Sample x challenge, which is used to ensure the circuit is
// satisfied with high probability.
let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
let instance_evals = (0..num_proofs)
.map(|_| -> Result<Vec<_>, _> { read_n_scalars(transcript, vk.cs.instance_queries.len()) })
.collect::<Result<Vec<_>, _>>()?;
let instance_evals = if V::QUERY_INSTANCE {
(0..num_proofs)
.map(|_| -> Result<Vec<_>, _> {
read_n_scalars(transcript, vk.cs.instance_queries.len())
})
.collect::<Result<Vec<_>, _>>()?
} else {
let xn = x.pow(&[params.n() as u64, 0, 0, 0]);
let (min_rotation, max_rotation) =
vk.cs
.instance_queries
.iter()
.fold((0, 0), |(min, max), (_, rotation)| {
if rotation.0 < min {
(rotation.0, max)
} else if rotation.0 > max {
(min, rotation.0)
} else {
(min, max)
}
});
let max_instance_len = instances
.iter()
.flat_map(|instance| instance.iter().map(|instance| instance.len()))
.max_by(Ord::cmp)
.unwrap_or_default();
let l_i_s = &vk.domain.l_i_range(
*x,
xn,
-max_rotation..max_instance_len as i32 + min_rotation.abs(),
);
instances
.iter()
.map(|instances| {
vk.cs
.instance_queries
.iter()
.map(|(column, rotation)| {
let instances = instances[column.index()];
let offset = (max_rotation - rotation.0) as usize;
compute_inner_product(instances, &l_i_s[offset..offset + instances.len()])
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
};

let advice_evals = (0..num_proofs)
.map(|_| -> Result<Vec<_>, _> { read_n_scalars(transcript, vk.cs.advice_queries.len()) })
Expand Down Expand Up @@ -282,15 +339,20 @@ pub fn verify_proof<
lookups,
)| {
iter::empty()
.chain(vk.cs.instance_queries.iter().enumerate().map(
move |(query_index, &(column, at))| {
VerifierQuery::new_commitment(
&instance_commitments[column.index()],
vk.domain.rotate_omega(*x, at),
instance_evals[query_index],
)
},
))
.chain(
V::QUERY_INSTANCE
.then_some(vk.cs.instance_queries.iter().enumerate().map(
move |(query_index, &(column, at))| {
VerifierQuery::new_commitment(
&instance_commitments[column.index()],
vk.domain.rotate_omega(*x, at),
instance_evals[query_index],
)
},
))
.into_iter()
.flatten(),
)
.chain(vk.cs.advice_queries.iter().enumerate().map(
move |(query_index, &(column, at))| {
VerifierQuery::new_commitment(
Expand Down
6 changes: 6 additions & 0 deletions halo2_proofs/src/poly/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ pub trait MSM<C: CurveAffine>: Clone + Debug {

/// Common multi-open prover interface for various commitment schemes
pub trait Prover<'params, Scheme: CommitmentScheme> {
/// Query instance or not
const QUERY_INSTANCE: bool;

/// Creates new prover instance
fn new(params: &'params Scheme::ParamsProver) -> Self;

Expand Down Expand Up @@ -156,6 +159,9 @@ pub trait Verifier<'params, Scheme: CommitmentScheme> {
/// Accumulator fot comressed verification
type MSMAccumulator;

/// Query instance or not
const QUERY_INSTANCE: bool;

/// Creates new verifier instance
fn new(params: &'params Scheme::ParamsVerifier) -> Self;

Expand Down
2 changes: 2 additions & 0 deletions halo2_proofs/src/poly/ipa/multiopen/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub struct ProverIPA<'params, C: CurveAffine> {
}

impl<'params, C: CurveAffine> Prover<'params, IPACommitmentScheme<C>> for ProverIPA<'params, C> {
const QUERY_INSTANCE: bool = true;

fn new(params: &'params ParamsIPA<C>) -> Self {
Self { params }
}
Expand Down
2 changes: 2 additions & 0 deletions halo2_proofs/src/poly/ipa/multiopen/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ impl<'params, C: CurveAffine> Verifier<'params, IPACommitmentScheme<C>>
type Guard = GuardIPA<'params, C>;
type MSMAccumulator = MSMIPA<'params, C>;

const QUERY_INSTANCE: bool = true;

fn new(params: &'params ParamsVerifierIPA<C>) -> Self {
Self { params }
}
Expand Down
2 changes: 2 additions & 0 deletions halo2_proofs/src/poly/kzg/multiopen/gwc/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub struct ProverGWC<'params, E: Engine> {

/// Create a multi-opening proof
impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme<E>> for ProverGWC<'params, E> {
const QUERY_INSTANCE: bool = false;

fn new(params: &'params ParamsKZG<E>) -> Self {
Self { params }
}
Expand Down
2 changes: 2 additions & 0 deletions halo2_proofs/src/poly/kzg/multiopen/gwc/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ impl<'params, E: MultiMillerLoop + Debug> Verifier<'params, KZGCommitmentScheme<
type Guard = GuardKZG<'params, E>;
type MSMAccumulator = DualMSM<'params, E>;

const QUERY_INSTANCE: bool = false;

fn new(params: &'params ParamsKZG<E>) -> Self {
Self { params }
}
Expand Down
2 changes: 2 additions & 0 deletions halo2_proofs/src/poly/kzg/multiopen/shplonk/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ impl<'a, E: Engine> ProverSHPLONK<'a, E> {
impl<'params, E: Engine + Debug> Prover<'params, KZGCommitmentScheme<E>>
for ProverSHPLONK<'params, E>
{
const QUERY_INSTANCE: bool = false;

fn new(params: &'params ParamsKZG<E>) -> Self {
Self { params }
}
Expand Down
2 changes: 2 additions & 0 deletions halo2_proofs/src/poly/kzg/multiopen/shplonk/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ impl<'params, E: MultiMillerLoop + Debug> Verifier<'params, KZGCommitmentScheme<
type Guard = GuardKZG<'params, E>;
type MSMAccumulator = DualMSM<'params, E>;

const QUERY_INSTANCE: bool = false;

fn new(params: &'params ParamsKZG<E>) -> Self {
Self { params }
}
Expand Down