Skip to content

Commit

Permalink
Block circuit
Browse files Browse the repository at this point in the history
  • Loading branch information
dlubarov committed Jan 15, 2023
1 parent 3a6d693 commit b6f6c21
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 11 deletions.
94 changes: 92 additions & 2 deletions evm/src/fixed_recursive_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ 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;
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;
Expand Down Expand Up @@ -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],
}
Expand Down Expand Up @@ -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]:,
Expand Down Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion plonky2/src/gates/selectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>,
}
Expand Down
16 changes: 8 additions & 8 deletions plonky2/src/plonk/circuit_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down

0 comments on commit b6f6c21

Please sign in to comment.