#[cfg(not(feature = "std"))]
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
use anyhow::Result;
use hashbrown::HashMap;
use plonky2_field::extension::Extendable;
use plonky2_field::polynomial::PolynomialCoeffs;
use crate::fri::proof::{FriFinalPolys, FriFinalPolysTarget, FriProof, FriProofTarget};
use crate::fri::{FriConfig, FriFinalPolyLayout, FriParams, FriReductionStrategy};
use crate::gates::noop::NoopGate;
use crate::gates::selectors::SelectorsInfo;
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
use crate::hash::merkle_tree::MerkleCap;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::Target;
use crate::iop::witness::{PartialWitness, PartitionWitness, WitnessWrite};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::{
CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierCircuitTarget,
VerifierOnlyCircuitData,
};
use crate::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher};
use crate::plonk::proof::{
OpeningSet, OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs,
ProofWithPublicInputsTarget,
};
use crate::util::serialization::{Buffer, DefaultGateSerializer, IoResult, Read, Write};
pub fn cyclic_base_proof<F, C, const D: usize>(
common_data: &CommonCircuitData<F, D>,
verifier_data: &VerifierOnlyCircuitData<C, D>,
mut nonzero_public_inputs: HashMap<usize, F>,
) -> ProofWithPublicInputs<F, C, D>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
C::Hasher: AlgebraicHasher<C::F>,
C::InnerHasher: AlgebraicHasher<F>,
{
let pis_len = common_data.num_public_inputs;
let cap_elements = common_data.config.fri_config.num_cap_elements();
let start_vk_pis = pis_len - 4 - 4 * cap_elements;
nonzero_public_inputs.extend((start_vk_pis..).zip(verifier_data.circuit_digest.elements));
for i in 0..cap_elements {
let start = start_vk_pis + 4 + 4 * i;
nonzero_public_inputs
.extend((start..).zip(verifier_data.constants_sigmas_cap.0[i].elements));
}
dummy_proof::<F, C, D>(
&dummy_circuit::<F, C, D>(common_data),
nonzero_public_inputs,
)
.unwrap()
}
pub fn dummy_proof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
circuit: &CircuitData<F, C, D>,
nonzero_public_inputs: HashMap<usize, F>,
) -> anyhow::Result<ProofWithPublicInputs<F, C, D>>
where
{
let mut pw = PartialWitness::new();
for i in 0..circuit.common.num_public_inputs {
let pi = nonzero_public_inputs.get(&i).copied().unwrap_or_default();
pw.set_target(circuit.prover_only.public_inputs[i], pi)?;
}
circuit.prove(pw)
}
pub fn dummy_circuit<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
) -> CircuitData<F, C, D>
where
C::InnerHasher: crate::plonk::config::AlgebraicHasher<F>,
{
let config = common_data.config.clone();
let degree = common_data.degree();
let num_noop_gate = degree - common_data.num_public_inputs.div_ceil(8) - 2;
let mut builder = CircuitBuilder::<F, D>::new(config);
for _ in 0..num_noop_gate {
builder.add_gate(NoopGate, vec![]);
}
for gate in &common_data.gates {
builder.add_gate_to_gate_set(gate.clone());
}
for _ in 0..common_data.num_public_inputs {
builder.add_virtual_public_input();
}
let circuit = builder.build::<C>();
assert_eq!(&circuit.common, common_data);
circuit
}
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub(crate) fn dummy_proof_and_vk<C: GenericConfig<D, F = F> + 'static>(
&mut self,
common_data: &CommonCircuitData<F, D>,
) -> anyhow::Result<(ProofWithPublicInputsTarget<D>, VerifierCircuitTarget)>
where
C::Hasher: AlgebraicHasher<F>,
C::InnerHasher: AlgebraicHasher<F>,
{
let dummy_circuit = dummy_circuit::<F, C, D>(common_data);
let dummy_proof_with_pis = dummy_proof::<F, C, D>(&dummy_circuit, HashMap::new())?;
let dummy_proof_with_pis_target = self.add_virtual_proof_with_pis(common_data);
let dummy_verifier_data_target =
self.add_virtual_verifier_data(self.config.fri_config.cap_height);
self.add_simple_generator(DummyProofGenerator {
proof_with_pis_target: dummy_proof_with_pis_target.clone(),
proof_with_pis: dummy_proof_with_pis,
verifier_data_target: dummy_verifier_data_target.clone(),
verifier_data: dummy_circuit.verifier_data(),
});
Ok((dummy_proof_with_pis_target, dummy_verifier_data_target))
}
pub fn dummy_proof_and_constant_vk_no_generator<C: GenericConfig<D, F = F> + 'static>(
&mut self,
common_data: &CommonCircuitData<F, D>,
) -> anyhow::Result<(ProofWithPublicInputsTarget<D>, VerifierCircuitTarget)>
where
C::Hasher: AlgebraicHasher<F>,
C::InnerHasher: AlgebraicHasher<F>,
{
let dummy_circuit = dummy_circuit::<F, C, D>(common_data);
let dummy_proof_with_pis_target = self.add_virtual_proof_with_pis(common_data);
let dummy_verifier_data_target = self.constant_verifier_data(&dummy_circuit.verifier_only);
Ok((dummy_proof_with_pis_target, dummy_verifier_data_target))
}
}
#[derive(Debug)]
pub struct DummyProofGenerator<F, C, const D: usize>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
{
pub(crate) proof_with_pis_target: ProofWithPublicInputsTarget<D>,
pub(crate) proof_with_pis: ProofWithPublicInputs<F, C, D>,
pub(crate) verifier_data_target: VerifierCircuitTarget,
pub(crate) verifier_data: VerifierCircuitData<F, C, D>,
}
impl<F, C, const D: usize> Default for DummyProofGenerator<F, C, D>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
{
fn default() -> Self {
let proof_with_pis_target = ProofWithPublicInputsTarget {
proof: ProofTarget {
wires_cap: MerkleCapTarget(vec![]),
plonk_zs_partial_products_cap: MerkleCapTarget(vec![]),
quotient_polys_cap: MerkleCapTarget(vec![]),
openings: OpeningSetTarget::default(),
opening_proof: FriProofTarget {
commit_phase_merkle_caps: vec![],
batch_mask_proof: None,
query_round_proofs: vec![],
final_polys: FriFinalPolysTarget { chunks: vec![] },
pow_witness: Target::default(),
},
},
public_inputs: vec![],
};
let proof_with_pis = ProofWithPublicInputs {
proof: Proof {
wires_cap: MerkleCap(vec![]),
plonk_zs_partial_products_cap: MerkleCap(vec![]),
quotient_polys_cap: MerkleCap(vec![]),
openings: OpeningSet::default(),
opening_proof: FriProof {
commit_phase_merkle_caps: vec![],
batch_mask_proof: None,
query_round_proofs: vec![],
final_polys: FriFinalPolys::from_single(PolynomialCoeffs { coeffs: vec![] }),
pow_witness: F::ZERO,
},
},
public_inputs: vec![],
};
let verifier_data_target = VerifierCircuitTarget {
constants_sigmas_cap: MerkleCapTarget(vec![]),
circuit_digest: HashOutTarget {
elements: [Target::default(); 4],
},
};
let verifier_data = VerifierCircuitData {
common: CommonCircuitData {
config: CircuitConfig::default(),
trace_degree_bits: 0,
fri_params: FriParams {
config: FriConfig {
rate_bits: 0,
cap_height: 0,
proof_of_work_bits: 0,
reduction_strategy: FriReductionStrategy::MinSize(None),
num_query_rounds: 0,
},
leaf_hiding: false,
batch_masking: None,
degree_bits: 0,
reduction_arity_bits: vec![],
final_poly_layout: FriFinalPolyLayout::Single,
},
public_initial_degree_bits: 0,
fri_oracle_layouts: vec![],
gates: vec![],
selectors_info: SelectorsInfo {
selector_indices: vec![],
groups: vec![],
},
quotient_degree_factor: 0,
num_gate_constraints: 0,
num_constants: 0,
num_public_inputs: 0,
k_is: vec![],
num_partial_products: 0,
num_lookup_polys: 0,
num_lookup_selectors: 0,
luts: vec![],
},
verifier_only: VerifierOnlyCircuitData {
constants_sigmas_cap: MerkleCap(vec![]),
circuit_digest: <<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::Hash::from_bytes(
&vec![0; <<C as GenericConfig<D>>::Hasher as Hasher<C::F>>::HASH_SIZE],
),
},
};
Self {
proof_with_pis_target,
proof_with_pis,
verifier_data_target,
verifier_data,
}
}
}
impl<F, C, const D: usize> SimpleGenerator<F, D> for DummyProofGenerator<F, C, D>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F> + 'static,
C::Hasher: AlgebraicHasher<F>,
{
fn id(&self) -> String {
"DummyProofGenerator".to_string()
}
fn dependencies(&self) -> Vec<Target> {
vec![]
}
fn run_once(
&self,
_witness: &PartitionWitness<F>,
out_buffer: &mut GeneratedValues<F>,
) -> Result<()> {
out_buffer.set_proof_with_pis_target(&self.proof_with_pis_target, &self.proof_with_pis)?;
out_buffer.set_verifier_data_target(
&self.verifier_data_target,
&self.verifier_data.verifier_only,
)
}
fn serialize(&self, dst: &mut Vec<u8>, _common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_target_verifier_circuit(&self.verifier_data_target)?;
dst.write_verifier_circuit_data(&self.verifier_data, &DefaultGateSerializer)?;
dst.write_target_proof_with_public_inputs(&self.proof_with_pis_target)?;
dst.write_proof_with_public_inputs(&self.proof_with_pis)
}
fn deserialize(src: &mut Buffer, _common_data: &CommonCircuitData<F, D>) -> IoResult<Self> {
let verifier_data_target = src.read_target_verifier_circuit()?;
let verifier_data = src.read_verifier_circuit_data(&DefaultGateSerializer)?;
let proof_with_pis_target = src.read_target_proof_with_public_inputs()?;
let proof_with_pis = src.read_proof_with_public_inputs(&verifier_data.common)?;
Ok(Self {
proof_with_pis_target,
proof_with_pis,
verifier_data_target,
verifier_data,
})
}
}