mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-06 07:43:10 +00:00
Start recursive verifier test
This commit is contained in:
parent
7ab21a4f13
commit
b50a9809db
@ -1,4 +1,5 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::convert::TryInto;
|
||||
use std::time::Instant;
|
||||
|
||||
use log::info;
|
||||
@ -20,6 +21,7 @@ use crate::permutation_argument::TargetPartition;
|
||||
use crate::plonk_common::PlonkPolynomials;
|
||||
use crate::polynomial::commitment::ListPolynomialCommitment;
|
||||
use crate::polynomial::polynomial::PolynomialValues;
|
||||
use crate::proof::HashTarget;
|
||||
use crate::target::Target;
|
||||
use crate::util::partial_products::num_partial_products;
|
||||
use crate::util::{log2_ceil, log2_strict, transpose, transpose_poly_values};
|
||||
@ -38,7 +40,7 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
|
||||
public_input_index: usize,
|
||||
|
||||
/// The next available index for a `VirtualTarget`.
|
||||
virtual_target_index: usize,
|
||||
pub virtual_target_index: usize,
|
||||
|
||||
copy_constraints: Vec<(Target, Target)>,
|
||||
|
||||
@ -92,6 +94,24 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
(0..n).map(|_i| self.add_virtual_target()).collect()
|
||||
}
|
||||
|
||||
pub fn add_virtual_hash(&mut self) -> HashTarget {
|
||||
HashTarget::from_vec(self.add_virtual_targets(4))
|
||||
}
|
||||
|
||||
pub fn add_virtual_hashes(&mut self, n: usize) -> Vec<HashTarget> {
|
||||
(0..n).map(|_i| self.add_virtual_hash()).collect()
|
||||
}
|
||||
|
||||
pub fn add_virtual_extension_target(&mut self) -> ExtensionTarget<D> {
|
||||
ExtensionTarget(self.add_virtual_targets(D).try_into().unwrap())
|
||||
}
|
||||
|
||||
pub fn add_virtual_extension_targets(&mut self, n: usize) -> Vec<ExtensionTarget<D>> {
|
||||
(0..n)
|
||||
.map(|_i| self.add_virtual_extension_target())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn add_gate_no_constants(&mut self, gate_type: GateRef<F, D>) -> usize {
|
||||
self.add_gate(gate_type, Vec::new())
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ pub struct MerkleProof<F: Field> {
|
||||
pub siblings: Vec<Hash<F>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MerkleProofTarget {
|
||||
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
|
||||
pub siblings: Vec<HashTarget>,
|
||||
|
||||
@ -246,7 +246,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
}
|
||||
|
||||
pub struct OpeningProof<F: Field + Extendable<D>, const D: usize> {
|
||||
fri_proof: FriProof<F, D>,
|
||||
pub fri_proof: FriProof<F, D>,
|
||||
// TODO: Get the degree from `CommonCircuitData` instead.
|
||||
quotient_degree: usize,
|
||||
}
|
||||
@ -278,7 +278,7 @@ impl<F: Field + Extendable<D>, const D: usize> OpeningProof<F, D> {
|
||||
}
|
||||
|
||||
pub struct OpeningProofTarget<const D: usize> {
|
||||
fri_proof: FriProofTarget<D>,
|
||||
pub fri_proof: FriProofTarget<D>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
10
src/proof.rs
10
src/proof.rs
@ -61,7 +61,7 @@ impl HashTarget {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Proof<F: Field + Extendable<D>, const D: usize> {
|
||||
pub struct Proof<F: Extendable<D>, const D: usize> {
|
||||
/// Merkle root of LDEs of wire values.
|
||||
pub wires_root: Hash<F>,
|
||||
/// Merkle root of LDEs of Z, in the context of Plonk's permutation argument.
|
||||
@ -78,8 +78,8 @@ pub struct ProofTarget<const D: usize> {
|
||||
pub wires_root: HashTarget,
|
||||
pub plonk_zs_root: HashTarget,
|
||||
pub quotient_polys_root: HashTarget,
|
||||
pub openings: Vec<OpeningSetTarget<D>>,
|
||||
pub opening_proof: Vec<OpeningProofTarget<D>>,
|
||||
pub openings: OpeningSetTarget<D>,
|
||||
pub opening_proof: OpeningProofTarget<D>,
|
||||
}
|
||||
|
||||
/// Evaluations and Merkle proof produced by the prover in a FRI query step.
|
||||
@ -88,6 +88,7 @@ pub struct FriQueryStep<F: Field + Extendable<D>, const D: usize> {
|
||||
pub merkle_proof: MerkleProof<F>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FriQueryStepTarget<const D: usize> {
|
||||
pub evals: Vec<ExtensionTarget<D>>,
|
||||
pub merkle_proof: MerkleProofTarget,
|
||||
@ -106,6 +107,7 @@ impl<F: Field> FriInitialTreeProof<F> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FriInitialTreeProofTarget {
|
||||
pub evals_proofs: Vec<(Vec<Target>, MerkleProofTarget)>,
|
||||
}
|
||||
@ -123,6 +125,7 @@ pub struct FriQueryRound<F: Field + Extendable<D>, const D: usize> {
|
||||
pub steps: Vec<FriQueryStep<F, D>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FriQueryRoundTarget<const D: usize> {
|
||||
pub initial_trees_proof: FriInitialTreeProofTarget,
|
||||
pub steps: Vec<FriQueryStepTarget<D>>,
|
||||
@ -198,5 +201,6 @@ pub struct OpeningSetTarget<const D: usize> {
|
||||
pub wires: Vec<ExtensionTarget<D>>,
|
||||
pub plonk_zs: Vec<ExtensionTarget<D>>,
|
||||
pub plonk_zs_right: Vec<ExtensionTarget<D>>,
|
||||
pub partial_products: Vec<ExtensionTarget<D>>,
|
||||
pub quotient_polys: Vec<ExtensionTarget<D>>,
|
||||
}
|
||||
|
||||
@ -7,16 +7,234 @@ use crate::proof::ProofTarget;
|
||||
const MIN_WIRES: usize = 120; // TODO: Double check.
|
||||
const MIN_ROUTED_WIRES: usize = 28; // TODO: Double check.
|
||||
|
||||
/// Recursively verifies an inner proof.
|
||||
pub fn add_recursive_verifier<F: Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
inner_config: CircuitConfig,
|
||||
inner_circuit: VerifierCircuitTarget,
|
||||
inner_gates: Vec<GateRef<F, D>>,
|
||||
inner_proof: ProofTarget<D>,
|
||||
) {
|
||||
assert!(builder.config.num_wires >= MIN_WIRES);
|
||||
assert!(builder.config.num_wires >= MIN_ROUTED_WIRES);
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Recursively verifies an inner proof.
|
||||
pub fn add_recursive_verifier(
|
||||
&mut self,
|
||||
inner_config: CircuitConfig,
|
||||
inner_circuit: VerifierCircuitTarget,
|
||||
inner_gates: Vec<GateRef<F, D>>,
|
||||
inner_proof: ProofTarget<D>,
|
||||
) {
|
||||
assert!(self.config.num_wires >= MIN_WIRES);
|
||||
assert!(self.config.num_wires >= MIN_ROUTED_WIRES);
|
||||
|
||||
todo!()
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
||||
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
|
||||
use crate::merkle_proofs::MerkleProofTarget;
|
||||
use crate::polynomial::commitment::OpeningProofTarget;
|
||||
use crate::proof::{
|
||||
FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget,
|
||||
HashTarget, OpeningSetTarget, Proof,
|
||||
};
|
||||
use crate::witness::PartialWitness;
|
||||
|
||||
fn proof_to_proof_target<F: Extendable<D>, const D: usize>(
|
||||
proof: &Proof<F, D>,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> ProofTarget<D> {
|
||||
let wires_root = builder.add_virtual_hash();
|
||||
let plonk_zs_root = builder.add_virtual_hash();
|
||||
let quotient_polys_root = builder.add_virtual_hash();
|
||||
|
||||
let openings = OpeningSetTarget {
|
||||
constants: builder.add_virtual_extension_targets(proof.openings.constants.len()),
|
||||
plonk_sigmas: builder
|
||||
.add_virtual_extension_targets(proof.openings.plonk_s_sigmas.len()),
|
||||
wires: builder.add_virtual_extension_targets(proof.openings.wires.len()),
|
||||
plonk_zs: builder.add_virtual_extension_targets(proof.openings.plonk_zs.len()),
|
||||
plonk_zs_right: builder
|
||||
.add_virtual_extension_targets(proof.openings.plonk_zs_right.len()),
|
||||
partial_products: builder
|
||||
.add_virtual_extension_targets(proof.openings.partial_products.len()),
|
||||
quotient_polys: builder
|
||||
.add_virtual_extension_targets(proof.openings.quotient_polys.len()),
|
||||
};
|
||||
|
||||
let mut query_round = FriQueryRoundTarget {
|
||||
initial_trees_proof: FriInitialTreeProofTarget {
|
||||
evals_proofs: vec![],
|
||||
},
|
||||
steps: vec![],
|
||||
};
|
||||
for (v, merkle_proof) in &proof.opening_proof.fri_proof.query_round_proofs[0]
|
||||
.initial_trees_proof
|
||||
.evals_proofs
|
||||
{
|
||||
query_round.initial_trees_proof.evals_proofs.push((
|
||||
builder.add_virtual_targets(v.len()),
|
||||
MerkleProofTarget {
|
||||
siblings: builder.add_virtual_hashes(merkle_proof.siblings.len()),
|
||||
},
|
||||
));
|
||||
}
|
||||
for step in &proof.opening_proof.fri_proof.query_round_proofs[0].steps {
|
||||
query_round.steps.push(FriQueryStepTarget {
|
||||
evals: builder.add_virtual_extension_targets(step.evals.len()),
|
||||
merkle_proof: MerkleProofTarget {
|
||||
siblings: builder.add_virtual_hashes(step.merkle_proof.siblings.len()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let opening_proof =
|
||||
OpeningProofTarget {
|
||||
fri_proof: FriProofTarget {
|
||||
commit_phase_merkle_roots: vec![
|
||||
builder.add_virtual_hash();
|
||||
proof
|
||||
.opening_proof
|
||||
.fri_proof
|
||||
.commit_phase_merkle_roots
|
||||
.len()
|
||||
],
|
||||
query_round_proofs: vec![
|
||||
query_round.clone();
|
||||
proof.opening_proof.fri_proof.query_round_proofs.len()
|
||||
],
|
||||
final_poly: PolynomialCoeffsExtTarget(builder.add_virtual_extension_targets(
|
||||
proof.opening_proof.fri_proof.final_poly.len(),
|
||||
)),
|
||||
pow_witness: builder.add_virtual_target(),
|
||||
},
|
||||
};
|
||||
|
||||
ProofTarget {
|
||||
wires_root,
|
||||
plonk_zs_root,
|
||||
quotient_polys_root,
|
||||
openings,
|
||||
opening_proof,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_proof_target<F: Extendable<D>, const D: usize>(
|
||||
proof: &Proof<F, D>,
|
||||
pt: &ProofTarget<D>,
|
||||
pw: &mut PartialWitness<F>,
|
||||
) {
|
||||
pw.set_hash_target(pt.wires_root, proof.wires_root);
|
||||
pw.set_hash_target(pt.plonk_zs_root, proof.plonk_zs_root);
|
||||
pw.set_hash_target(pt.quotient_polys_root, proof.quotient_polys_root);
|
||||
|
||||
for (&t, &x) in pt.openings.wires.iter().zip(&proof.openings.wires) {
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in pt.openings.constants.iter().zip(&proof.openings.constants) {
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in pt
|
||||
.openings
|
||||
.plonk_sigmas
|
||||
.iter()
|
||||
.zip(&proof.openings.plonk_s_sigmas)
|
||||
{
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in pt.openings.plonk_zs.iter().zip(&proof.openings.plonk_zs) {
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in pt
|
||||
.openings
|
||||
.plonk_zs_right
|
||||
.iter()
|
||||
.zip(&proof.openings.plonk_zs_right)
|
||||
{
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in pt
|
||||
.openings
|
||||
.partial_products
|
||||
.iter()
|
||||
.zip(&proof.openings.partial_products)
|
||||
{
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in pt
|
||||
.openings
|
||||
.quotient_polys
|
||||
.iter()
|
||||
.zip(&proof.openings.quotient_polys)
|
||||
{
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
|
||||
let fri_proof = &proof.opening_proof.fri_proof;
|
||||
let fpt = &pt.opening_proof.fri_proof;
|
||||
|
||||
pw.set_target(fpt.pow_witness, fri_proof.pow_witness);
|
||||
|
||||
for (&t, &x) in fpt.final_poly.0.iter().zip(&fri_proof.final_poly.coeffs) {
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
|
||||
for (&t, &x) in fpt
|
||||
.commit_phase_merkle_roots
|
||||
.iter()
|
||||
.zip(&fri_proof.commit_phase_merkle_roots)
|
||||
{
|
||||
pw.set_hash_target(t, x);
|
||||
}
|
||||
|
||||
for (qt, q) in fpt
|
||||
.query_round_proofs
|
||||
.iter()
|
||||
.zip(&fri_proof.query_round_proofs)
|
||||
{
|
||||
for (at, a) in qt
|
||||
.initial_trees_proof
|
||||
.evals_proofs
|
||||
.iter()
|
||||
.zip(&q.initial_trees_proof.evals_proofs)
|
||||
{
|
||||
for (&t, &x) in at.0.iter().zip(&a.0) {
|
||||
pw.set_target(t, x);
|
||||
}
|
||||
for (&t, &x) in at.1.siblings.iter().zip(&a.1.siblings) {
|
||||
pw.set_hash_target(t, x);
|
||||
}
|
||||
}
|
||||
|
||||
for (st, s) in qt.steps.iter().zip(&q.steps) {
|
||||
for (&t, &x) in st.evals.iter().zip(&s.evals) {
|
||||
pw.set_extension_target(t, x);
|
||||
}
|
||||
for (&t, &x) in st
|
||||
.merkle_proof
|
||||
.siblings
|
||||
.iter()
|
||||
.zip(&s.merkle_proof.siblings)
|
||||
{
|
||||
pw.set_hash_target(t, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recursive_verifier() {
|
||||
type F = CrandallField;
|
||||
type FF = QuarticCrandallField;
|
||||
let proof = {
|
||||
let config = CircuitConfig::large_config();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let zero = builder.zero();
|
||||
let data = builder.build();
|
||||
data.prove(PartialWitness::new())
|
||||
};
|
||||
|
||||
let config = CircuitConfig::large_config();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut pw = PartialWitness::new();
|
||||
let pt = proof_to_proof_target(&proof, &mut builder);
|
||||
set_proof_target(&proof, &pt, &mut pw);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field::Field;
|
||||
use crate::gates::gate::GateInstance;
|
||||
use crate::proof::{Hash, HashTarget};
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
|
||||
@ -142,6 +143,13 @@ impl<F: Field> PartialWitness<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_hash_target(&mut self, ht: HashTarget, value: Hash<F>) {
|
||||
ht.elements
|
||||
.into_iter()
|
||||
.zip(value.elements)
|
||||
.for_each(|(&t, x)| self.set_target(t, x));
|
||||
}
|
||||
|
||||
pub fn set_extension_target<const D: usize>(
|
||||
&mut self,
|
||||
et: ExtensionTarget<D>,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user