mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 22:33:06 +00:00
Block circuit
This commit is contained in:
parent
3a6d693f3f
commit
b6f6c21018
@ -3,6 +3,7 @@ use std::ops::Range;
|
||||
|
||||
use itertools::Itertools;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2::fri::FriParams;
|
||||
use plonky2::gates::noop::NoopGate;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::hash::hashing::SPONGE_WIDTH;
|
||||
@ -10,7 +11,9 @@ use plonky2::iop::challenger::RecursiveChallenger;
|
||||
use plonky2::iop::target::{BoolTarget, Target};
|
||||
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, VerifierCircuitTarget};
|
||||
use plonky2::plonk::circuit_data::{
|
||||
CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget,
|
||||
};
|
||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
|
||||
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||
use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data;
|
||||
@ -50,6 +53,8 @@ where
|
||||
/// The EVM root circuit, which aggregates the (shrunk) per-table recursive proofs.
|
||||
pub root: RootCircuitData<F, C, D>,
|
||||
pub aggregation: AggregationCircuitData<F, C, D>,
|
||||
/// The block circuit, which verifies an aggregation root proof and a previous block proof.
|
||||
pub block: BlockCircuitData<F, C, D>,
|
||||
/// Holds chains of circuits for each table and for each initial `degree_bits`.
|
||||
by_table: [RecursiveCircuitsForTable<F, C, D>; NUM_TABLES],
|
||||
}
|
||||
@ -90,10 +95,22 @@ pub struct AggregationChildTarget<const D: usize> {
|
||||
evm_proof: ProofWithPublicInputsTarget<D>,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> AllRecursiveCircuits<F, C, D>
|
||||
pub struct BlockCircuitData<F, C, const D: usize>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F>,
|
||||
{
|
||||
circuit: CircuitData<F, C, D>,
|
||||
has_parent_block: BoolTarget,
|
||||
parent_block_proof: ProofWithPublicInputsTarget<D>,
|
||||
agg_root_proof: ProofWithPublicInputsTarget<D>,
|
||||
cyclic_vk: VerifierCircuitTarget,
|
||||
}
|
||||
|
||||
impl<F, C, const D: usize> AllRecursiveCircuits<F, C, D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
C: GenericConfig<D, F = F> + 'static,
|
||||
C::Hasher: AlgebraicHasher<F>,
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
[(); CpuStark::<F, D>::COLUMNS]:,
|
||||
@ -147,9 +164,11 @@ where
|
||||
let by_table = [cpu, keccak, keccak_sponge, logic, memory];
|
||||
let root = Self::create_root_circuit(&by_table, stark_config);
|
||||
let aggregation = Self::create_aggregation_circuit(&root);
|
||||
let block = Self::create_block_circuit(&aggregation);
|
||||
Self {
|
||||
root,
|
||||
aggregation,
|
||||
block,
|
||||
by_table,
|
||||
}
|
||||
}
|
||||
@ -298,6 +317,44 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn create_block_circuit(agg: &AggregationCircuitData<F, C, D>) -> BlockCircuitData<F, C, D> {
|
||||
// The block circuit is similar to the agg circuit; both verify two inner proofs.
|
||||
// We need to adjust a few things, but it's easier than making a new CommonCircuitData.
|
||||
let expected_common_data = CommonCircuitData {
|
||||
fri_params: FriParams {
|
||||
degree_bits: 14,
|
||||
..agg.circuit.common.fri_params.clone()
|
||||
},
|
||||
..agg.circuit.common.clone()
|
||||
};
|
||||
|
||||
let mut builder = CircuitBuilder::<F, D>::new(CircuitConfig::standard_recursion_config());
|
||||
let has_parent_block = builder.add_virtual_bool_target_safe();
|
||||
let parent_block_proof = builder.add_virtual_proof_with_pis::<C>(&expected_common_data);
|
||||
let agg_root_proof = builder.add_virtual_proof_with_pis::<C>(&agg.circuit.common);
|
||||
|
||||
let cyclic_vk = builder.add_verifier_data_public_inputs();
|
||||
builder
|
||||
.conditionally_verify_cyclic_proof_or_dummy::<C>(
|
||||
has_parent_block,
|
||||
&parent_block_proof,
|
||||
&expected_common_data,
|
||||
)
|
||||
.expect("Failed to build cyclic recursion circuit");
|
||||
|
||||
let agg_verifier_data = builder.constant_verifier_data(&agg.circuit.verifier_only);
|
||||
builder.verify_proof::<C>(&agg_root_proof, &agg_verifier_data, &agg.circuit.common);
|
||||
|
||||
let circuit = builder.build::<C>();
|
||||
BlockCircuitData {
|
||||
circuit,
|
||||
has_parent_block,
|
||||
parent_block_proof,
|
||||
agg_root_proof,
|
||||
cyclic_vk,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a proof for each STARK, then combine them, eventually culminating in a root proof.
|
||||
pub fn prove_root(
|
||||
&self,
|
||||
@ -375,6 +432,39 @@ where
|
||||
&self.aggregation.circuit.common,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn prove_block(
|
||||
&self,
|
||||
opt_parent_block_proof: Option<&ProofWithPublicInputs<F, C, D>>,
|
||||
agg_root_proof: &ProofWithPublicInputs<F, C, D>,
|
||||
) -> anyhow::Result<ProofWithPublicInputs<F, C, D>> {
|
||||
let mut block_inputs = PartialWitness::new();
|
||||
|
||||
block_inputs.set_bool_target(
|
||||
self.block.has_parent_block,
|
||||
opt_parent_block_proof.is_some(),
|
||||
);
|
||||
if let Some(parent_block_proof) = opt_parent_block_proof {
|
||||
block_inputs
|
||||
.set_proof_with_pis_target(&self.block.parent_block_proof, parent_block_proof);
|
||||
}
|
||||
|
||||
block_inputs.set_proof_with_pis_target(&self.block.agg_root_proof, agg_root_proof);
|
||||
|
||||
block_inputs
|
||||
.set_verifier_data_target(&self.block.cyclic_vk, &self.block.circuit.verifier_only);
|
||||
|
||||
self.block.circuit.prove(block_inputs)
|
||||
}
|
||||
|
||||
pub fn verify_block(&self, block_proof: &ProofWithPublicInputs<F, C, D>) -> anyhow::Result<()> {
|
||||
self.block.circuit.verify(block_proof.clone())?;
|
||||
check_cyclic_proof_verifier_data(
|
||||
block_proof,
|
||||
&self.block.circuit.verifier_only,
|
||||
&self.block.circuit.common,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct RecursiveCircuitsForTable<F, C, const D: usize>
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::hash::hash_types::RichField;
|
||||
pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub(crate) struct SelectorsInfo {
|
||||
pub struct SelectorsInfo {
|
||||
pub(crate) selector_indices: Vec<usize>,
|
||||
pub(crate) groups: Vec<Range<usize>>,
|
||||
}
|
||||
|
||||
@ -272,30 +272,30 @@ pub struct VerifierOnlyCircuitData<C: GenericConfig<D>, const D: usize> {
|
||||
pub struct CommonCircuitData<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub config: CircuitConfig,
|
||||
|
||||
pub(crate) fri_params: FriParams,
|
||||
pub fri_params: FriParams,
|
||||
|
||||
/// The types of gates used in this circuit, along with their prefixes.
|
||||
pub(crate) gates: Vec<GateRef<F, D>>,
|
||||
pub gates: Vec<GateRef<F, D>>,
|
||||
|
||||
/// Information on the circuit's selector polynomials.
|
||||
pub(crate) selectors_info: SelectorsInfo,
|
||||
pub selectors_info: SelectorsInfo,
|
||||
|
||||
/// The degree of the PLONK quotient polynomial.
|
||||
pub(crate) quotient_degree_factor: usize,
|
||||
pub quotient_degree_factor: usize,
|
||||
|
||||
/// The largest number of constraints imposed by any gate.
|
||||
pub(crate) num_gate_constraints: usize,
|
||||
pub num_gate_constraints: usize,
|
||||
|
||||
/// The number of constant wires.
|
||||
pub(crate) num_constants: usize,
|
||||
pub num_constants: usize,
|
||||
|
||||
pub num_public_inputs: usize,
|
||||
|
||||
/// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument.
|
||||
pub(crate) k_is: Vec<F>,
|
||||
pub k_is: Vec<F>,
|
||||
|
||||
/// The number of partial products needed to compute the `Z` polynomials.
|
||||
pub(crate) num_partial_products: usize,
|
||||
pub num_partial_products: usize,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CommonCircuitData<F, D> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user