mirror of https://github.com/zcash/halo2.git
Refactor PLONK verifier
This commit is contained in:
parent
02b5b8442b
commit
def65609b1
|
@ -17,28 +17,40 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
params: &'a Params<C>,
|
params: &'a Params<C>,
|
||||||
vk: &VerifyingKey<C>,
|
vk: &VerifyingKey<C>,
|
||||||
msm: MSM<'a, C>,
|
msm: MSM<'a, C>,
|
||||||
aux_commitments: &[C],
|
aux_commitments_vec: &[&[C]],
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<Guard<'a, C>, Error> {
|
) -> Result<Guard<'a, C>, Error> {
|
||||||
// Check that aux_commitments matches the expected number of aux columns
|
// Check that aux_commitments matches the expected number of aux columns
|
||||||
|
for aux_commitments in aux_commitments_vec.iter() {
|
||||||
if aux_commitments.len() != vk.cs.num_aux_columns {
|
if aux_commitments.len() != vk.cs.num_aux_columns {
|
||||||
return Err(Error::IncompatibleParams);
|
return Err(Error::IncompatibleParams);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let num_proofs = aux_commitments_vec.len();
|
||||||
|
|
||||||
|
for aux_commitments in aux_commitments_vec.iter() {
|
||||||
// Hash the aux (external) commitments into the transcript
|
// Hash the aux (external) commitments into the transcript
|
||||||
for commitment in aux_commitments {
|
for commitment in *aux_commitments {
|
||||||
transcript
|
transcript
|
||||||
.common_point(*commitment)
|
.common_point(*commitment)
|
||||||
.map_err(|_| Error::TranscriptError)?
|
.map_err(|_| Error::TranscriptError)?
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut advice_commitments_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for _ in 0..num_proofs {
|
||||||
// Hash the prover's advice commitments into the transcript
|
// Hash the prover's advice commitments into the transcript
|
||||||
let advice_commitments =
|
let advice_commitments = read_n_points(transcript, vk.cs.num_advice_columns)
|
||||||
read_n_points(transcript, vk.cs.num_advice_columns).map_err(|_| Error::TranscriptError)?;
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
advice_commitments_vec.push(advice_commitments);
|
||||||
|
}
|
||||||
|
|
||||||
// Sample theta challenge for keeping lookup columns linearly independent
|
// Sample theta challenge for keeping lookup columns linearly independent
|
||||||
let theta = ChallengeTheta::get(transcript);
|
let theta = ChallengeTheta::get(transcript);
|
||||||
|
|
||||||
|
let mut lookups_permuted_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for _ in 0..num_proofs {
|
||||||
// Hash each lookup permuted commitment
|
// Hash each lookup permuted commitment
|
||||||
let lookups = vk
|
let lookups = vk
|
||||||
.cs
|
.cs
|
||||||
|
@ -46,6 +58,8 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|argument| argument.read_permuted_commitments(transcript))
|
.map(|argument| argument.read_permuted_commitments(transcript))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
lookups_permuted_vec.push(lookups);
|
||||||
|
}
|
||||||
|
|
||||||
// Sample beta challenge
|
// Sample beta challenge
|
||||||
let beta = ChallengeBeta::get(transcript);
|
let beta = ChallengeBeta::get(transcript);
|
||||||
|
@ -53,6 +67,8 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
// Sample gamma challenge
|
// Sample gamma challenge
|
||||||
let gamma = ChallengeGamma::get(transcript);
|
let gamma = ChallengeGamma::get(transcript);
|
||||||
|
|
||||||
|
let mut permutations_committed_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for _ in 0..num_proofs {
|
||||||
// Hash each permutation product commitment
|
// Hash each permutation product commitment
|
||||||
let permutations = vk
|
let permutations = vk
|
||||||
.cs
|
.cs
|
||||||
|
@ -60,12 +76,18 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|argument| argument.read_product_commitment(transcript))
|
.map(|argument| argument.read_product_commitment(transcript))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
permutations_committed_vec.push(permutations);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lookups_committed_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for lookups in lookups_permuted_vec.into_iter() {
|
||||||
// Hash each lookup product commitment
|
// Hash each lookup product commitment
|
||||||
let lookups = lookups
|
let lookups = lookups
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|lookup| lookup.read_product_commitment(transcript))
|
.map(|lookup| lookup.read_product_commitment(transcript))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
lookups_committed_vec.push(lookups);
|
||||||
|
}
|
||||||
|
|
||||||
// Sample y challenge, which keeps the gates linearly independent.
|
// Sample y challenge, which keeps the gates linearly independent.
|
||||||
let y = ChallengeY::get(transcript);
|
let y = ChallengeY::get(transcript);
|
||||||
|
@ -76,25 +98,43 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
// satisfied with high probability.
|
// satisfied with high probability.
|
||||||
let x = ChallengeX::get(transcript);
|
let x = ChallengeX::get(transcript);
|
||||||
|
|
||||||
|
let mut aux_evals_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for _ in 0..num_proofs {
|
||||||
|
let aux_evals = read_n_scalars(transcript, vk.cs.aux_queries.len())
|
||||||
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
aux_evals_vec.push(aux_evals);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut advice_evals_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for _ in 0..num_proofs {
|
||||||
let advice_evals = read_n_scalars(transcript, vk.cs.advice_queries.len())
|
let advice_evals = read_n_scalars(transcript, vk.cs.advice_queries.len())
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
let aux_evals =
|
advice_evals_vec.push(advice_evals);
|
||||||
read_n_scalars(transcript, vk.cs.aux_queries.len()).map_err(|_| Error::TranscriptError)?;
|
}
|
||||||
|
|
||||||
let fixed_evals = read_n_scalars(transcript, vk.cs.fixed_queries.len())
|
let fixed_evals = read_n_scalars(transcript, vk.cs.fixed_queries.len())
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
.map_err(|_| Error::TranscriptError)?;
|
||||||
|
|
||||||
let vanishing = vanishing.evaluate(transcript)?;
|
let vanishing = vanishing.evaluate(transcript)?;
|
||||||
|
|
||||||
|
let mut permutations_evaluated_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for permutations in permutations_committed_vec.into_iter() {
|
||||||
let permutations = permutations
|
let permutations = permutations
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(vk.permutations.iter())
|
.zip(vk.permutations.iter())
|
||||||
.map(|(permutation, vkey)| permutation.evaluate(vkey, transcript))
|
.map(|(permutation, vkey)| permutation.evaluate(vkey, transcript))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
permutations_evaluated_vec.push(permutations);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lookups_evaluated_vec = Vec::with_capacity(num_proofs);
|
||||||
|
for lookups in lookups_committed_vec.into_iter() {
|
||||||
let lookups = lookups
|
let lookups = lookups
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|lookup| lookup.evaluate(transcript))
|
.map(|lookup| lookup.evaluate(transcript))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
lookups_evaluated_vec.push(lookups);
|
||||||
|
}
|
||||||
|
|
||||||
// This check ensures the circuit is satisfied so long as the polynomial
|
// This check ensures the circuit is satisfied so long as the polynomial
|
||||||
// commitments open to the correct values.
|
// commitments open to the correct values.
|
||||||
|
@ -109,9 +149,18 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
* &vk.domain.get_barycentric_weight(); // l_0(x)
|
* &vk.domain.get_barycentric_weight(); // l_0(x)
|
||||||
|
|
||||||
// Compute the expected value of h(x)
|
// Compute the expected value of h(x)
|
||||||
let expressions = std::iter::empty()
|
let expressions = advice_evals_vec
|
||||||
|
.iter()
|
||||||
|
.zip(aux_evals_vec.iter())
|
||||||
|
.zip(permutations_evaluated_vec.iter())
|
||||||
|
.zip(lookups_evaluated_vec.iter())
|
||||||
|
.flat_map(|(((advice_evals, aux_evals), permutations), lookups)| {
|
||||||
|
let fixed_evals = fixed_evals.clone();
|
||||||
|
let fixed_evals_copy = fixed_evals.clone();
|
||||||
|
|
||||||
|
std::iter::empty()
|
||||||
// Evaluate the circuit using the custom gates provided
|
// Evaluate the circuit using the custom gates provided
|
||||||
.chain(vk.cs.gates.iter().map(|poly| {
|
.chain(vk.cs.gates.iter().map(move |poly| {
|
||||||
poly.evaluate(
|
poly.evaluate(
|
||||||
&|index| fixed_evals[index],
|
&|index| fixed_evals[index],
|
||||||
&|index| advice_evals[index],
|
&|index| advice_evals[index],
|
||||||
|
@ -125,7 +174,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
permutations
|
permutations
|
||||||
.iter()
|
.iter()
|
||||||
.zip(vk.cs.permutations.iter())
|
.zip(vk.cs.permutations.iter())
|
||||||
.map(|(p, argument)| {
|
.map(move |(p, argument)| {
|
||||||
p.expressions(vk, argument, &advice_evals, l_0, beta, gamma, x)
|
p.expressions(vk, argument, &advice_evals, l_0, beta, gamma, x)
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -135,7 +184,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
lookups
|
lookups
|
||||||
.iter()
|
.iter()
|
||||||
.zip(vk.cs.lookups.iter())
|
.zip(vk.cs.lookups.iter())
|
||||||
.map(|(p, argument)| {
|
.map(move |(p, argument)| {
|
||||||
p.expressions(
|
p.expressions(
|
||||||
vk,
|
vk,
|
||||||
l_0,
|
l_0,
|
||||||
|
@ -144,67 +193,78 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
||||||
beta,
|
beta,
|
||||||
gamma,
|
gamma,
|
||||||
&advice_evals,
|
&advice_evals,
|
||||||
&fixed_evals,
|
&fixed_evals_copy,
|
||||||
&aux_evals,
|
&aux_evals,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
);
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter();
|
||||||
|
|
||||||
vanishing.verify(expressions, y, xn)?;
|
vanishing.verify(expressions, y, xn)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let queries = iter::empty()
|
let queries = aux_commitments_vec
|
||||||
.chain(
|
|
||||||
vk.cs
|
|
||||||
.advice_queries
|
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.zip(aux_evals_vec.iter())
|
||||||
.map(|(query_index, &(column, at))| VerifierQuery {
|
.zip(advice_commitments_vec.iter())
|
||||||
point: vk.domain.rotate_omega(*x, at),
|
.zip(advice_evals_vec.iter())
|
||||||
commitment: &advice_commitments[column.index()],
|
.zip(permutations_evaluated_vec.iter())
|
||||||
eval: advice_evals[query_index],
|
.zip(lookups_evaluated_vec.iter())
|
||||||
}),
|
.flat_map(
|
||||||
)
|
|(
|
||||||
.chain(
|
((((aux_commitments, aux_evals), advice_commitments), advice_evals), permutations),
|
||||||
vk.cs
|
lookups,
|
||||||
.aux_queries
|
)| {
|
||||||
.iter()
|
iter::empty()
|
||||||
.enumerate()
|
.chain(vk.cs.aux_queries.iter().enumerate().map(
|
||||||
.map(|(query_index, &(column, at))| VerifierQuery {
|
move |(query_index, &(column, at))| VerifierQuery {
|
||||||
point: vk.domain.rotate_omega(*x, at),
|
point: vk.domain.rotate_omega(*x, at),
|
||||||
commitment: &aux_commitments[column.index()],
|
commitment: &aux_commitments[column.index()],
|
||||||
eval: aux_evals[query_index],
|
eval: aux_evals[query_index],
|
||||||
}),
|
},
|
||||||
)
|
))
|
||||||
.chain(
|
.chain(vk.cs.advice_queries.iter().enumerate().map(
|
||||||
vk.cs
|
move |(query_index, &(column, at))| VerifierQuery {
|
||||||
.fixed_queries
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(query_index, &(column, at))| VerifierQuery {
|
|
||||||
point: vk.domain.rotate_omega(*x, at),
|
point: vk.domain.rotate_omega(*x, at),
|
||||||
commitment: &vk.fixed_commitments[column.index()],
|
commitment: &advice_commitments[column.index()],
|
||||||
eval: fixed_evals[query_index],
|
eval: advice_evals[query_index],
|
||||||
}),
|
},
|
||||||
)
|
))
|
||||||
.chain(vanishing.queries(x))
|
|
||||||
.chain(
|
.chain(
|
||||||
permutations
|
permutations
|
||||||
.iter()
|
.iter()
|
||||||
.zip(vk.permutations.iter())
|
.zip(vk.permutations.iter())
|
||||||
.map(|(p, vkey)| p.queries(vk, vkey, x))
|
.map(move |(p, vkey)| p.queries(vk, vkey, x))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
lookups
|
lookups
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.queries(vk, x))
|
.map(move |p| p.queries(vk, x))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
);
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter()
|
||||||
|
.chain(
|
||||||
|
vk.cs
|
||||||
|
.fixed_queries
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(move |(query_index, &(column, at))| VerifierQuery {
|
||||||
|
point: vk.domain.rotate_omega(*x, at),
|
||||||
|
commitment: &vk.fixed_commitments[column.index()],
|
||||||
|
eval: fixed_evals.clone()[query_index],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.chain(vanishing.queries(x));
|
||||||
|
|
||||||
// We are now convinced the circuit is satisfied so long as the
|
// We are now convinced the circuit is satisfied so long as the
|
||||||
// polynomial commitments open to the correct values.
|
// polynomial commitments open to the correct values.
|
||||||
|
|
Loading…
Reference in New Issue