mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-07 16:23:11 +00:00
remove N from leaf. only N-to-1 is supported at node level
This commit is contained in:
parent
07bc66bac4
commit
5b7efc0e0c
4
codex-plonky2-circuits/.gitignore
vendored
4
codex-plonky2-circuits/.gitignore
vendored
@ -11,3 +11,7 @@ pgo-data.profdata
|
|||||||
|
|
||||||
# MacOS nuisances
|
# MacOS nuisances
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# circuit files
|
||||||
|
/prover_data
|
||||||
|
/verifier_data
|
||||||
|
|||||||
@ -30,7 +30,7 @@ impl<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
> Bundle<F, C, D, H> {
|
> Bundle<F, C, D, H> {
|
||||||
pub fn new(bundle_size: usize, circuit_params: CircuitParams) -> Result<(Self)>{
|
pub fn new(bundle_size: usize, circuit_params: CircuitParams) -> Result<Self>{
|
||||||
let samp_circ = SampleCircuit::<F, D, H>::new(circuit_params.clone());
|
let samp_circ = SampleCircuit::<F, D, H>::new(circuit_params.clone());
|
||||||
let (sample_targets, circuit_data) = samp_circ.build_with_standard_config()?;
|
let (sample_targets, circuit_data) = samp_circ.build_with_standard_config()?;
|
||||||
println!("sampling circuit built. Degree bits = {:?}", circuit_data.common.degree_bits());
|
println!("sampling circuit built. Degree bits = {:?}", circuit_data.common.degree_bits());
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use plonky2::hash::hash_types::{HashOut, RichField};
|
|||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
|
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
|
||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData};
|
use plonky2::plonk::circuit_data::VerifierCircuitData;
|
||||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||||
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||||
use plonky2_field::extension::Extendable;
|
use plonky2_field::extension::Extendable;
|
||||||
@ -15,8 +15,7 @@ use crate::recursion::utils::{bucket_count, compute_flag_buckets};
|
|||||||
|
|
||||||
pub const BUCKET_SIZE: usize = 32;
|
pub const BUCKET_SIZE: usize = 32;
|
||||||
|
|
||||||
/// recursion leaf circuit - verifies N inner proof
|
/// recursion leaf circuit - verifies 1 inner proof
|
||||||
/// N: number of inner proofs
|
|
||||||
/// T: total number of sampling proofs
|
/// T: total number of sampling proofs
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LeafCircuit<
|
pub struct LeafCircuit<
|
||||||
@ -24,13 +23,11 @@ pub struct LeafCircuit<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const N: usize,
|
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> where
|
> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
inner_common_data: CommonCircuitData<F, D>,
|
inner_verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
|
||||||
phantom_data: PhantomData<H>
|
phantom_data: PhantomData<H>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,9 +39,8 @@ pub struct LeafCircuit<
|
|||||||
pub struct LeafTargets <
|
pub struct LeafTargets <
|
||||||
const D: usize,
|
const D: usize,
|
||||||
>{
|
>{
|
||||||
pub inner_proof: Vec<ProofWithPublicInputsTarget<D>>,
|
pub inner_proof: ProofWithPublicInputsTarget<D>,
|
||||||
pub index: Target, // public input
|
pub index: Target, // public input
|
||||||
// TODO: change this to vec of size N so that one flag per inner-proof
|
|
||||||
pub flag: BoolTarget,
|
pub flag: BoolTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +50,7 @@ pub struct LeafInput<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
>{
|
>{
|
||||||
pub inner_proof: Vec<ProofWithPublicInputs<F, C, D>>,
|
pub inner_proof: ProofWithPublicInputs<F, C, D>,
|
||||||
pub flag: bool,
|
pub flag: bool,
|
||||||
pub index: usize
|
pub index: usize
|
||||||
}
|
}
|
||||||
@ -64,17 +60,14 @@ impl<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const N: usize,
|
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> LeafCircuit<F,D,C,H,N,T> where
|
> LeafCircuit<F,D,C,H,T> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
inner_common_data: CommonCircuitData<F, D>,
|
inner_verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner_common_data,
|
|
||||||
inner_verifier_data,
|
inner_verifier_data,
|
||||||
phantom_data: PhantomData::default(),
|
phantom_data: PhantomData::default(),
|
||||||
}
|
}
|
||||||
@ -87,9 +80,8 @@ impl<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const N: usize,
|
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> Plonky2Circuit<F, C, D> for LeafCircuit<F,D,C,H,N,T> where
|
> Plonky2Circuit<F, C, D> for LeafCircuit<F,D,C,H,T> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
type Targets = LeafTargets<D>;
|
type Targets = LeafTargets<D>;
|
||||||
@ -97,21 +89,15 @@ impl<
|
|||||||
|
|
||||||
fn add_targets(&self, builder: &mut CircuitBuilder<F, D>, register_pi: bool) -> Result<LeafTargets<D>> {
|
fn add_targets(&self, builder: &mut CircuitBuilder<F, D>, register_pi: bool) -> Result<LeafTargets<D>> {
|
||||||
|
|
||||||
let inner_common = self.inner_common_data.clone();
|
let inner_common = self.inner_verifier_data.common.clone();
|
||||||
let n_bucket: usize = bucket_count(T);
|
let n_bucket: usize = bucket_count(T);
|
||||||
|
|
||||||
// the proof virtual targets
|
// the proof virtual target
|
||||||
let mut pub_input = vec![];
|
let vir_proof = builder.add_virtual_proof_with_pis(&inner_common);
|
||||||
let mut vir_proofs = vec![];
|
let inner_pub_input = vir_proof.public_inputs.clone();
|
||||||
for _i in 0..N {
|
|
||||||
let vir_proof = builder.add_virtual_proof_with_pis(&inner_common);
|
|
||||||
let inner_pub_input = vir_proof.public_inputs.clone();
|
|
||||||
vir_proofs.push(vir_proof);
|
|
||||||
pub_input.extend_from_slice(&inner_pub_input);
|
|
||||||
}
|
|
||||||
|
|
||||||
// hash the public input & make it public
|
// hash the public input & make it public
|
||||||
let hash_inner_pub_input = builder.hash_n_to_hash_no_pad::<H>(pub_input);
|
let hash_inner_pub_input = builder.hash_n_to_hash_no_pad::<H>(inner_pub_input);
|
||||||
if register_pi {
|
if register_pi {
|
||||||
builder.register_public_inputs(&hash_inner_pub_input.elements);
|
builder.register_public_inputs(&hash_inner_pub_input.elements);
|
||||||
}
|
}
|
||||||
@ -123,11 +109,11 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// virtual constant target for the verifier data
|
// virtual constant target for the verifier data
|
||||||
let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data);
|
let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data.verifier_only);
|
||||||
|
|
||||||
// virtual constant target for dummy verifier data
|
// virtual constant target for dummy verifier data
|
||||||
let const_dummy_vd = builder.constant_verifier_data(
|
let const_dummy_vd = builder.constant_verifier_data(
|
||||||
&DummyProofGen::<F,D,C>::gen_dummy_verifier_data(&self.inner_common_data)
|
&DummyProofGen::<F,D,C>::gen_dummy_verifier_data(&inner_common)
|
||||||
);
|
);
|
||||||
|
|
||||||
// index: 0 <= index < T where T = total number of proofs
|
// index: 0 <= index < T where T = total number of proofs
|
||||||
@ -137,7 +123,7 @@ impl<
|
|||||||
// Instead of taking flag_buckets as external public inputs,
|
// Instead of taking flag_buckets as external public inputs,
|
||||||
// compute them internally from the index and flag.
|
// compute them internally from the index and flag.
|
||||||
let computed_flag_buckets = compute_flag_buckets(builder, index, flag, BUCKET_SIZE, n_bucket)?;
|
let computed_flag_buckets = compute_flag_buckets(builder, index, flag, BUCKET_SIZE, n_bucket)?;
|
||||||
// Then, for example, you could register these outputs as part of your public input vector:
|
// register these outputs as part of your public input vector:
|
||||||
if register_pi {
|
if register_pi {
|
||||||
builder.register_public_inputs(&computed_flag_buckets);
|
builder.register_public_inputs(&computed_flag_buckets);
|
||||||
}
|
}
|
||||||
@ -145,9 +131,7 @@ impl<
|
|||||||
// verify the proofs in-circuit based on the
|
// verify the proofs in-circuit based on the
|
||||||
// true -> real proof, false -> dummy proof
|
// true -> real proof, false -> dummy proof
|
||||||
let selected_vd = builder.select_verifier_data(flag.clone(), &const_verifier_data, &const_dummy_vd);
|
let selected_vd = builder.select_verifier_data(flag.clone(), &const_verifier_data, &const_dummy_vd);
|
||||||
for i in 0..N {
|
builder.verify_proof::<C>(&vir_proof, &selected_vd, &inner_common);
|
||||||
builder.verify_proof::<C>(&vir_proofs[i], &selected_vd, &inner_common);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have every gate to match `common_data`.
|
// Make sure we have every gate to match `common_data`.
|
||||||
for g in &inner_common.gates {
|
for g in &inner_common.gates {
|
||||||
@ -156,7 +140,7 @@ impl<
|
|||||||
|
|
||||||
// return targets
|
// return targets
|
||||||
let t = LeafTargets {
|
let t = LeafTargets {
|
||||||
inner_proof: vir_proofs,
|
inner_proof: vir_proof,
|
||||||
index,
|
index,
|
||||||
flag,
|
flag,
|
||||||
};
|
};
|
||||||
@ -169,15 +153,12 @@ impl<
|
|||||||
targets: &Self::Targets,
|
targets: &Self::Targets,
|
||||||
input: &Self::Input,
|
input: &Self::Input,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
assert_eq!(input.inner_proof.len(), N);
|
assert!(input.index <= T, "given index is not valid");
|
||||||
assert!(input.index <= T && input.index >= 0, "given index is not valid");
|
|
||||||
// assign the proofs
|
// assign the proofs
|
||||||
for i in 0..N {
|
pw.set_proof_with_pis_target(&targets.inner_proof, &input.inner_proof)
|
||||||
pw.set_proof_with_pis_target(&targets.inner_proof[i], &input.inner_proof[i])
|
.map_err(|e| {
|
||||||
.map_err(|e| {
|
CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string())
|
||||||
CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string())
|
})?;
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign the global index.
|
// Assign the global index.
|
||||||
pw.set_target(targets.index, F::from_canonical_u64(input.index as u64))
|
pw.set_target(targets.index, F::from_canonical_u64(input.index as u64))
|
||||||
@ -197,7 +178,7 @@ mod tests {
|
|||||||
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2::plonk::config::GenericConfig;
|
use plonky2::plonk::config::GenericConfig;
|
||||||
use plonky2_field::types::{Field, PrimeField64};
|
use plonky2_field::types::PrimeField64;
|
||||||
use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
|
use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
|
||||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
|
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
|
||||||
|
|
||||||
@ -221,17 +202,15 @@ mod tests {
|
|||||||
// End-to-End test for the entire leaf circuit.
|
// End-to-End test for the entire leaf circuit.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_full_leaf_circuit() -> anyhow::Result<()> {
|
fn test_full_leaf_circuit() -> anyhow::Result<()> {
|
||||||
const N: usize = 1;
|
|
||||||
|
|
||||||
// get inner common
|
// get inner common
|
||||||
let common_data = dummy_common_circuit_data();
|
let common_data = dummy_common_circuit_data();
|
||||||
|
|
||||||
// Generate a dummy inner proof for the leaf using DummyProofGen
|
// Generate a dummy inner proof for the leaf using DummyProofGen
|
||||||
let (dummy_inner_proof, vd) = DummyProofGen::<F, D, C>::gen_dummy_proof_and_vd_zero_pi(&common_data)?;
|
let (dummy_inner_proof, vd) = DummyProofGen::<F, D, C>::gen_dummy_proof_and_vd_zero_pi(&common_data)?;
|
||||||
let dummy_verifier_data = DummyProofGen::<F, D, C>::gen_dummy_verifier_data(&common_data);
|
// let dummy_verifier_data = DummyProofGen::<F, D, C>::gen_dummy_verifier_data(&common_data);
|
||||||
|
|
||||||
// the leaf circuit.
|
// the leaf circuit.
|
||||||
let leaf = LeafCircuit::<F, D, C, H, N, 4>::new(common_data.clone(), dummy_verifier_data);
|
let leaf = LeafCircuit::<F, D, C, H, 128>::new(vd.clone());
|
||||||
|
|
||||||
// Build the leaf circuit.
|
// Build the leaf circuit.
|
||||||
let (targets, circuit_data) = leaf.build_with_standard_config()?;
|
let (targets, circuit_data) = leaf.build_with_standard_config()?;
|
||||||
@ -240,7 +219,7 @@ mod tests {
|
|||||||
|
|
||||||
// test leaf input
|
// test leaf input
|
||||||
let input = LeafInput {
|
let input = LeafInput {
|
||||||
inner_proof: vec![dummy_inner_proof],
|
inner_proof: dummy_inner_proof,
|
||||||
flag: true,
|
flag: true,
|
||||||
index: 45,
|
index: 45,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,19 +3,18 @@ use plonky2::hash::hash_types::RichField;
|
|||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
|
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
|
||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2::plonk::circuit_data::{CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
|
use plonky2::plonk::circuit_data::{VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
|
||||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||||
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||||
use plonky2_field::extension::Extendable;
|
use plonky2_field::extension::Extendable;
|
||||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2;
|
||||||
use crate::{error::CircuitError,Result};
|
use crate::{error::CircuitError,Result};
|
||||||
use crate::circuit_helper::Plonky2Circuit;
|
use crate::circuit_helper::Plonky2Circuit;
|
||||||
use crate::recursion::leaf::BUCKET_SIZE;
|
|
||||||
use crate::recursion::dummy_gen::DummyProofGen;
|
use crate::recursion::dummy_gen::DummyProofGen;
|
||||||
use crate::recursion::utils::bucket_count;
|
use crate::recursion::utils::bucket_count;
|
||||||
|
|
||||||
/// recursion node circuit
|
/// recursion node circuit
|
||||||
/// M: number of leaf proofs
|
/// N: number of leaf proofs
|
||||||
/// T: total number of sampling proofs
|
/// T: total number of sampling proofs
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NodeCircuit<
|
pub struct NodeCircuit<
|
||||||
@ -23,13 +22,12 @@ pub struct NodeCircuit<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const M: usize,
|
const N: usize,
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> where
|
> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
common_data: CommonCircuitData<F, D>,
|
leaf_verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
leaf_verifier_data: VerifierOnlyCircuitData<C, D>,
|
|
||||||
phantom_data: PhantomData<H>
|
phantom_data: PhantomData<H>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,8 +41,8 @@ pub struct NodeCircuit<
|
|||||||
pub struct NodeTargets<
|
pub struct NodeTargets<
|
||||||
const D: usize,
|
const D: usize,
|
||||||
>{
|
>{
|
||||||
pub leaf_proofs: Vec<ProofWithPublicInputsTarget<D>>,
|
pub inner_proofs: Vec<ProofWithPublicInputsTarget<D>>,
|
||||||
pub node_verifier_data: VerifierCircuitTarget,
|
pub inner_verifier_data: VerifierCircuitTarget,
|
||||||
pub condition: BoolTarget,
|
pub condition: BoolTarget,
|
||||||
pub index: Target,
|
pub index: Target,
|
||||||
pub flags: Vec<BoolTarget>,
|
pub flags: Vec<BoolTarget>,
|
||||||
@ -56,7 +54,7 @@ pub struct NodeInput<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
>{
|
>{
|
||||||
pub node_proofs: Vec<ProofWithPublicInputs<F, C, D>>,
|
pub inner_proofs: Vec<ProofWithPublicInputs<F, C, D>>,
|
||||||
pub verifier_only_data: VerifierOnlyCircuitData<C, D>,
|
pub verifier_only_data: VerifierOnlyCircuitData<C, D>,
|
||||||
pub condition: bool,
|
pub condition: bool,
|
||||||
pub flags: Vec<bool>,
|
pub flags: Vec<bool>,
|
||||||
@ -68,19 +66,17 @@ impl<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const M: usize,
|
const N: usize,
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> NodeCircuit<F,D,C,H,M,T> where
|
> NodeCircuit<F,D,C,H, N,T> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
common_data: CommonCircuitData<F,D>,
|
leaf_verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
leaf_verifier_data: VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
assert!(M.is_power_of_two(), "M is NOT a power of two");
|
assert!(N.is_power_of_two(), "M is NOT a power of two");
|
||||||
Self{
|
Self{
|
||||||
common_data,
|
|
||||||
leaf_verifier_data,
|
leaf_verifier_data,
|
||||||
phantom_data:PhantomData::default(),
|
phantom_data:PhantomData::default(),
|
||||||
}
|
}
|
||||||
@ -93,16 +89,16 @@ impl<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const M: usize,
|
const N: usize,
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> Plonky2Circuit<F, C, D> for NodeCircuit<F, D, C, H, M, T> where
|
> Plonky2Circuit<F, C, D> for NodeCircuit<F, D, C, H, N, T> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
type Targets = NodeTargets<D>;
|
type Targets = NodeTargets<D>;
|
||||||
type Input = NodeInput<F, D, C>;
|
type Input = NodeInput<F, D, C>;
|
||||||
|
|
||||||
fn add_targets(&self, builder: &mut CircuitBuilder<F, D>, register_pi: bool) -> Result<Self::Targets> {
|
fn add_targets(&self, builder: &mut CircuitBuilder<F, D>, register_pi: bool) -> Result<Self::Targets> {
|
||||||
let inner_common = self.common_data.clone();
|
let inner_common = self.leaf_verifier_data.common.clone();
|
||||||
let zero_target = builder.zero();
|
let zero_target = builder.zero();
|
||||||
|
|
||||||
// assert public input is of size 8 + 1 (index) + B (flag buckets)
|
// assert public input is of size 8 + 1 (index) + B (flag buckets)
|
||||||
@ -114,7 +110,7 @@ impl<
|
|||||||
let mut pub_input = vec![];
|
let mut pub_input = vec![];
|
||||||
let mut inner_flag_buckets = vec![];
|
let mut inner_flag_buckets = vec![];
|
||||||
let mut inner_indexes = vec![];
|
let mut inner_indexes = vec![];
|
||||||
for _i in 0..M {
|
for _i in 0..N {
|
||||||
let vir_proof = builder.add_virtual_proof_with_pis(&inner_common);
|
let vir_proof = builder.add_virtual_proof_with_pis(&inner_common);
|
||||||
let inner_pub_input = vir_proof.public_inputs.clone();
|
let inner_pub_input = vir_proof.public_inputs.clone();
|
||||||
vir_proofs.push(vir_proof);
|
vir_proofs.push(vir_proof);
|
||||||
@ -133,11 +129,11 @@ impl<
|
|||||||
let node_verifier_data = builder.add_virtual_verifier_data(inner_common.config.fri_config.cap_height);
|
let node_verifier_data = builder.add_virtual_verifier_data(inner_common.config.fri_config.cap_height);
|
||||||
|
|
||||||
// virtual target for the verifier data
|
// virtual target for the verifier data
|
||||||
let const_leaf_verifier_data = builder.constant_verifier_data(&self.leaf_verifier_data);
|
let const_leaf_verifier_data = builder.constant_verifier_data(&self.leaf_verifier_data.verifier_only);
|
||||||
|
|
||||||
// virtual constant target for dummy verifier data
|
// virtual constant target for dummy verifier data
|
||||||
let const_dummy_vd = builder.constant_verifier_data(
|
let const_dummy_vd = builder.constant_verifier_data(
|
||||||
&DummyProofGen::<F,D,C>::gen_dummy_verifier_data(&self.common_data)
|
&DummyProofGen::<F,D,C>::gen_dummy_verifier_data(&inner_common)
|
||||||
);
|
);
|
||||||
|
|
||||||
// register only the node verifier data hash as public input.
|
// register only the node verifier data hash as public input.
|
||||||
@ -158,12 +154,12 @@ impl<
|
|||||||
let mut flag_buckets: Vec<Target> = (0..n_bucket).map(|_i| zero_target.clone()).collect();
|
let mut flag_buckets: Vec<Target> = (0..n_bucket).map(|_i| zero_target.clone()).collect();
|
||||||
// index: 0 <= index < T where T = total number of proofs
|
// index: 0 <= index < T where T = total number of proofs
|
||||||
let index = builder.add_virtual_public_input();
|
let index = builder.add_virtual_public_input();
|
||||||
let flags: Vec<BoolTarget> = (0..M).map(|_i| builder.add_virtual_bool_target_safe()).collect();
|
let flags: Vec<BoolTarget> = (0..N).map(|_i| builder.add_virtual_bool_target_safe()).collect();
|
||||||
|
|
||||||
// condition: true -> node, false -> leaf
|
// condition: true -> node, false -> leaf
|
||||||
let node_or_leaf_vd = builder.select_verifier_data(condition.clone(), &node_verifier_data, &const_leaf_verifier_data);
|
let node_or_leaf_vd = builder.select_verifier_data(condition.clone(), &node_verifier_data, &const_leaf_verifier_data);
|
||||||
// verify the proofs in-circuit - M proofs
|
// verify the proofs in-circuit - M proofs
|
||||||
for i in 0..M {
|
for i in 0..N {
|
||||||
// flag: true -> real, false -> dummy
|
// flag: true -> real, false -> dummy
|
||||||
let selected_vd = builder.select_verifier_data(flags[i].clone(), &node_or_leaf_vd, &const_dummy_vd);
|
let selected_vd = builder.select_verifier_data(flags[i].clone(), &node_or_leaf_vd, &const_dummy_vd);
|
||||||
builder.verify_proof::<C>(&vir_proofs[i], &selected_vd, &inner_common);
|
builder.verify_proof::<C>(&vir_proofs[i], &selected_vd, &inner_common);
|
||||||
@ -172,7 +168,7 @@ impl<
|
|||||||
// Check flag buckets for dummy inner proofs:
|
// Check flag buckets for dummy inner proofs:
|
||||||
// For each inner proof, if its corresponding flag `flags[i]` is false,
|
// For each inner proof, if its corresponding flag `flags[i]` is false,
|
||||||
// then enforce that every bucket in inner_flag_buckets[i] is zero.
|
// then enforce that every bucket in inner_flag_buckets[i] is zero.
|
||||||
for i in 0..M {
|
for i in 0..N {
|
||||||
let not_flag_i = builder.not(flags[i]);
|
let not_flag_i = builder.not(flags[i]);
|
||||||
let not_flag_val = not_flag_i.target;
|
let not_flag_val = not_flag_i.target;
|
||||||
for j in 0..n_bucket {
|
for j in 0..n_bucket {
|
||||||
@ -184,9 +180,9 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check inner proof indexes are correct
|
// check inner proof indexes are correct
|
||||||
let m_const = builder.constant(F::from_canonical_u64(M as u64));
|
let m_const = builder.constant(F::from_canonical_u64(N as u64));
|
||||||
let mut expected_inner_index = builder.mul(index, m_const);
|
let mut expected_inner_index = builder.mul(index, m_const);
|
||||||
for i in 0..M {
|
for i in 0..N {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
let i_const = builder.constant(F::from_canonical_u64(i as u64));
|
let i_const = builder.constant(F::from_canonical_u64(i as u64));
|
||||||
expected_inner_index = builder.add(expected_inner_index, i_const);
|
expected_inner_index = builder.add(expected_inner_index, i_const);
|
||||||
@ -210,8 +206,8 @@ impl<
|
|||||||
|
|
||||||
// return targets
|
// return targets
|
||||||
let t = NodeTargets {
|
let t = NodeTargets {
|
||||||
leaf_proofs: vir_proofs,
|
inner_proofs: vir_proofs,
|
||||||
node_verifier_data,
|
inner_verifier_data: node_verifier_data,
|
||||||
condition,
|
condition,
|
||||||
index,
|
index,
|
||||||
flags,
|
flags,
|
||||||
@ -222,20 +218,20 @@ impl<
|
|||||||
|
|
||||||
fn assign_targets(&self, pw: &mut PartialWitness<F>, targets: &Self::Targets, input: &Self::Input) -> Result<()> {
|
fn assign_targets(&self, pw: &mut PartialWitness<F>, targets: &Self::Targets, input: &Self::Input) -> Result<()> {
|
||||||
// assert size of proofs vec
|
// assert size of proofs vec
|
||||||
assert_eq!(input.node_proofs.len(), M);
|
assert_eq!(input.inner_proofs.len(), N);
|
||||||
assert_eq!(input.flags.len(), M);
|
assert_eq!(input.flags.len(), N);
|
||||||
assert!(input.index <= T && input.index >= 0, "given index is not valid");
|
assert!(input.index <= T, "given index is not valid");
|
||||||
|
|
||||||
// assign the proofs
|
// assign the proofs
|
||||||
for i in 0..M {
|
for i in 0..N {
|
||||||
pw.set_proof_with_pis_target(&targets.leaf_proofs[i], &input.node_proofs[i])
|
pw.set_proof_with_pis_target(&targets.inner_proofs[i], &input.inner_proofs[i])
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string())
|
CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string())
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the verifier data
|
// assign the verifier data
|
||||||
pw.set_verifier_data_target(&targets.node_verifier_data, &input.verifier_only_data)
|
pw.set_verifier_data_target(&targets.inner_verifier_data, &input.verifier_only_data)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
||||||
})?;
|
})?;
|
||||||
@ -248,7 +244,7 @@ impl<
|
|||||||
pw.set_target(targets.index, F::from_canonical_u64(input.index as u64))
|
pw.set_target(targets.index, F::from_canonical_u64(input.index as u64))
|
||||||
.map_err(|e| CircuitError::TargetAssignmentError(format!("index {}", input.index),e.to_string()))?;
|
.map_err(|e| CircuitError::TargetAssignmentError(format!("index {}", input.index),e.to_string()))?;
|
||||||
// Assign the flags - switch between real & fake proof
|
// Assign the flags - switch between real & fake proof
|
||||||
for i in 0..M {
|
for i in 0..N {
|
||||||
pw.set_bool_target(targets.flags[i], input.flags[i])
|
pw.set_bool_target(targets.flags[i], input.flags[i])
|
||||||
.map_err(|e| CircuitError::TargetAssignmentError(format!("flag {}", input.flags[i]), e.to_string()))?;
|
.map_err(|e| CircuitError::TargetAssignmentError(format!("flag {}", input.flags[i]), e.to_string()))?;
|
||||||
}
|
}
|
||||||
@ -263,10 +259,10 @@ mod tests {
|
|||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2::plonk::config::GenericConfig;
|
use plonky2::plonk::config::GenericConfig;
|
||||||
use plonky2_field::types::{Field, PrimeField64};
|
use plonky2_field::types::{Field, PrimeField64};
|
||||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData};
|
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
|
||||||
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
|
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
|
||||||
use crate::recursion::leaf::{LeafCircuit, LeafInput};
|
use crate::recursion::leaf::BUCKET_SIZE;
|
||||||
use crate::recursion::dummy_gen::DummyProofGen;
|
|
||||||
|
|
||||||
// For our tests, we define:
|
// For our tests, we define:
|
||||||
const D: usize = 2;
|
const D: usize = 2;
|
||||||
@ -322,9 +318,9 @@ mod tests {
|
|||||||
/// End-to-End test for the entire node circuit.
|
/// End-to-End test for the entire node circuit.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_full_node_circuit() -> anyhow::Result<()> {
|
fn test_full_node_circuit() -> anyhow::Result<()> {
|
||||||
const M: usize = 2;
|
const N: usize = 2;
|
||||||
const B: usize = 4; // bucket size
|
const B: usize = 4; // bucket size
|
||||||
const T: usize = 2;
|
const T: usize = 128;
|
||||||
|
|
||||||
let (leaf_data, leaf_pi) = dummy_leaf::<B>();
|
let (leaf_data, leaf_pi) = dummy_leaf::<B>();
|
||||||
let leaf_vd = leaf_data.verifier_data();
|
let leaf_vd = leaf_data.verifier_data();
|
||||||
@ -332,7 +328,7 @@ mod tests {
|
|||||||
let indices = vec![0,1];
|
let indices = vec![0,1];
|
||||||
let leaf_proofs = dummy_leaf_proofs::<B>(leaf_data,leaf_pi,indices);
|
let leaf_proofs = dummy_leaf_proofs::<B>(leaf_data,leaf_pi,indices);
|
||||||
|
|
||||||
let node = NodeCircuit::<F, D, C, H, M, T>::new(leaf_vd.common.clone(), leaf_vd.verifier_only.clone());
|
let node = NodeCircuit::<F, D, C, H, N, T>::new(leaf_vd.clone());
|
||||||
|
|
||||||
// Build the node circuit.
|
// Build the node circuit.
|
||||||
let (targets, circuit_data) = node.build_with_standard_config()?;
|
let (targets, circuit_data) = node.build_with_standard_config()?;
|
||||||
@ -341,7 +337,7 @@ mod tests {
|
|||||||
|
|
||||||
// node input
|
// node input
|
||||||
let input = NodeInput {
|
let input = NodeInput {
|
||||||
node_proofs: leaf_proofs,
|
inner_proofs: leaf_proofs,
|
||||||
verifier_only_data: leaf_vd.verifier_only.clone(),
|
verifier_only_data: leaf_vd.verifier_only.clone(),
|
||||||
condition: false,
|
condition: false,
|
||||||
flags: vec![true, true],
|
flags: vec![true, true],
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use plonky2::hash::hash_types::{HashOut, RichField};
|
use plonky2::hash::hash_types::RichField;
|
||||||
use plonky2::iop::witness::PartialWitness;
|
use plonky2::iop::witness::PartialWitness;
|
||||||
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierOnlyCircuitData};
|
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierOnlyCircuitData};
|
||||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||||
@ -13,23 +13,22 @@ use crate::recursion::{leaf::{LeafTargets, LeafCircuit}, node::{NodeTargets, Nod
|
|||||||
use crate::recursion::compress::{CompressionCircuit, CompressionInput, CompressionTargets};
|
use crate::recursion::compress::{CompressionCircuit, CompressionInput, CompressionTargets};
|
||||||
use crate::recursion::leaf::LeafInput;
|
use crate::recursion::leaf::LeafInput;
|
||||||
use crate::recursion::node::NodeInput;
|
use crate::recursion::node::NodeInput;
|
||||||
|
use crate::recursion::utils::get_hash_of_verifier_data;
|
||||||
|
|
||||||
/// tree recursion
|
/// tree recursion
|
||||||
/// - `N`: Number of inner-proofs aggregated at the leaf level.
|
/// - `N`: Number of leaf proofs aggregated at the node level. set to 2 for 2-to-1 tree
|
||||||
/// - `M`: Number of leaf proofs aggregated at the node level.
|
|
||||||
pub struct TreeRecursion<
|
pub struct TreeRecursion<
|
||||||
F: RichField + Extendable<D> + Poseidon2,
|
F: RichField + Extendable<D> + Poseidon2,
|
||||||
const D: usize,
|
const D: usize,
|
||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const N: usize,
|
const N: usize,
|
||||||
const M: usize,
|
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> where
|
> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
leaf: LeafCircuit<F, D, C, H, N, T>,
|
leaf: LeafCircuit<F, D, C, H, T>,
|
||||||
node: NodeCircuit<F, D, C, H, M, T>,
|
node: NodeCircuit<F, D, C, H, N, T>,
|
||||||
compression: CompressionCircuit<F, D, C>,
|
compression: CompressionCircuit<F, D, C>,
|
||||||
leaf_circ_data: CircuitData<F, C, D>,
|
leaf_circ_data: CircuitData<F, C, D>,
|
||||||
node_circ_data: CircuitData<F, C, D>,
|
node_circ_data: CircuitData<F, C, D>,
|
||||||
@ -46,18 +45,15 @@ impl<
|
|||||||
C: GenericConfig<D, F = F>,
|
C: GenericConfig<D, F = F>,
|
||||||
H: AlgebraicHasher<F>,
|
H: AlgebraicHasher<F>,
|
||||||
const N: usize,
|
const N: usize,
|
||||||
const M: usize,
|
|
||||||
const T: usize,
|
const T: usize,
|
||||||
> TreeRecursion<F, D, C, H, N, M, T> where
|
> TreeRecursion<F, D, C, H, N, T> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
/// build with standard recursion config
|
/// build with standard recursion config
|
||||||
pub fn build_with_standard_config(
|
pub fn build_with_standard_config(
|
||||||
inner_common_data: CommonCircuitData<F,D>,
|
inner_verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
Self::build(
|
Self::build(
|
||||||
inner_common_data,
|
|
||||||
inner_verifier_data,
|
inner_verifier_data,
|
||||||
CircuitConfig::standard_recursion_config()
|
CircuitConfig::standard_recursion_config()
|
||||||
)
|
)
|
||||||
@ -65,22 +61,20 @@ impl<
|
|||||||
|
|
||||||
/// build the tree with given config
|
/// build the tree with given config
|
||||||
pub fn build(
|
pub fn build(
|
||||||
inner_common_data: CommonCircuitData<F,D>,
|
inner_verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
|
||||||
config: CircuitConfig,
|
config: CircuitConfig,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
// build leaf with standard recursion config
|
// build leaf with standard recursion config
|
||||||
let leaf = LeafCircuit::<_,D,_,_,N, T>::new(inner_common_data, inner_verifier_data);
|
let leaf = LeafCircuit::<_,D,_,_,T>::new(inner_verifier_data);
|
||||||
let (leaf_targets, leaf_circ_data) = leaf.build(config.clone())?;
|
let (leaf_targets, leaf_circ_data) = leaf.build(config.clone())?;
|
||||||
println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits());
|
println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits());
|
||||||
|
|
||||||
// build node with standard recursion config
|
// build node with standard recursion config
|
||||||
let node = NodeCircuit::<_,D,_,_,M, T>::new(leaf_circ_data.common.clone(), leaf_circ_data.verifier_only.clone());
|
let node = NodeCircuit::<_,D,_,_,N, T>::new(leaf_circ_data.verifier_data());
|
||||||
let (node_targets, node_circ_data) = node.build(config.clone())?;
|
let (node_targets, node_circ_data) = node.build(config.clone())?;
|
||||||
println!("node circuit size = {:?}", node_circ_data.common.degree_bits());
|
println!("node circuit size = {:?}", node_circ_data.common.degree_bits());
|
||||||
|
|
||||||
// compression build
|
// compression build
|
||||||
// let node_common = node_circ_data.common.clone();
|
|
||||||
let compression_circ = CompressionCircuit::new(node_circ_data.verifier_data());
|
let compression_circ = CompressionCircuit::new(node_circ_data.verifier_data());
|
||||||
let (compression_targets, compression_circ_data) = compression_circ.build(config.clone())?;
|
let (compression_targets, compression_circ_data) = compression_circ.build(config.clone())?;
|
||||||
println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits());
|
println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits());
|
||||||
@ -115,8 +109,8 @@ impl<
|
|||||||
self.node_circ_data.verifier_data()
|
self.node_circ_data.verifier_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prove_bundle(bundle: Bundle<F, C, D, H>){
|
pub fn prove_bundle(_bundle: Bundle<F, C, D, H>){
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prove_tree_and_compress(
|
pub fn prove_tree_and_compress(
|
||||||
@ -170,9 +164,9 @@ impl<
|
|||||||
|
|
||||||
let mut leaf_proofs = vec![];
|
let mut leaf_proofs = vec![];
|
||||||
|
|
||||||
for (i, proofs) in proofs_with_pi.chunks(N).enumerate(){
|
for (i, proof) in proofs_with_pi.iter().enumerate(){
|
||||||
let leaf_input = LeafInput{
|
let leaf_input = LeafInput{
|
||||||
inner_proof: proofs.to_vec(),
|
inner_proof: proof.clone(),
|
||||||
flag: true,
|
flag: true,
|
||||||
index: i,
|
index: i,
|
||||||
};
|
};
|
||||||
@ -205,15 +199,15 @@ impl<
|
|||||||
|
|
||||||
let condition = if level == 0 {false} else {true};
|
let condition = if level == 0 {false} else {true};
|
||||||
|
|
||||||
for (i, chunk) in proofs_with_pi.chunks(M).enumerate() {
|
for (i, chunk) in proofs_with_pi.chunks(N).enumerate() {
|
||||||
|
|
||||||
let mut inner_pw = PartialWitness::new();
|
let mut inner_pw = PartialWitness::new();
|
||||||
|
|
||||||
let node_input = NodeInput{
|
let node_input = NodeInput{
|
||||||
node_proofs: chunk.to_vec().clone(),
|
inner_proofs: chunk.to_vec().clone(),
|
||||||
verifier_only_data: verifier_only_data.clone(),
|
verifier_only_data: verifier_only_data.clone(),
|
||||||
condition,
|
condition,
|
||||||
flags: [true; M].to_vec(),
|
flags: [true; N].to_vec(),
|
||||||
index: i,
|
index: i,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -276,18 +270,14 @@ impl<
|
|||||||
let node_hash = get_hash_of_verifier_data::<F,D,C,H>(&self.node_circ_data.verifier_data());
|
let node_hash = get_hash_of_verifier_data::<F,D,C,H>(&self.node_circ_data.verifier_data());
|
||||||
|
|
||||||
let mut pub_in_hashes = vec![];
|
let mut pub_in_hashes = vec![];
|
||||||
for pub_in in inner_public_input.chunks(N){
|
for pub_in in inner_public_input{
|
||||||
let pub_in_flat: Vec<F> = pub_in
|
let hash = H::hash_no_pad(&pub_in);
|
||||||
.iter()
|
|
||||||
.flat_map(|v| v.iter().cloned())
|
|
||||||
.collect();
|
|
||||||
let hash = H::hash_no_pad(&pub_in_flat);
|
|
||||||
pub_in_hashes.push(hash);
|
pub_in_hashes.push(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
while pub_in_hashes.len() > 1 {
|
while pub_in_hashes.len() > 1 {
|
||||||
let mut next_level_pi_hashes = Vec::new();
|
let mut next_level_pi_hashes = Vec::new();
|
||||||
for pi_chunk in pub_in_hashes.chunks(M) {
|
for pi_chunk in pub_in_hashes.chunks(N) {
|
||||||
// collect field elements
|
// collect field elements
|
||||||
let pi_chunk_f: Vec<F> = pi_chunk.iter()
|
let pi_chunk_f: Vec<F> = pi_chunk.iter()
|
||||||
.flat_map(|h| h.elements.iter().cloned())
|
.flat_map(|h| h.elements.iter().cloned())
|
||||||
@ -308,27 +298,6 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper fn to generate hash of verifier data
|
|
||||||
pub fn get_hash_of_verifier_data<
|
|
||||||
F: RichField + Extendable<D> + Poseidon2,
|
|
||||||
const D: usize,
|
|
||||||
C: GenericConfig<D, F = F>,
|
|
||||||
H: AlgebraicHasher<F>,
|
|
||||||
>(verifier_data: &VerifierCircuitData<F, C, D>) -> HashOut<F> where
|
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
|
||||||
{
|
|
||||||
let mut vd = vec![];
|
|
||||||
let digest: &HashOut<F> = &verifier_data.verifier_only.circuit_digest;
|
|
||||||
let caps = &verifier_data.verifier_only.constants_sigmas_cap;
|
|
||||||
vd.extend_from_slice(&digest.elements);
|
|
||||||
for i in 0..verifier_data.common.config.fri_config.num_cap_elements() {
|
|
||||||
let cap_hash = caps.0[i] as HashOut<F>;
|
|
||||||
vd.extend_from_slice(&cap_hash.elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
H::hash_no_pad(&vd)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use plonky2::gates::noop::NoopGate;
|
use plonky2::gates::noop::NoopGate;
|
||||||
@ -350,7 +319,7 @@ mod tests {
|
|||||||
fn dummy_proofs<const T: usize>() -> (CircuitData<F, C, D>, Vec<ProofWithPublicInputs<F, C, D>>) {
|
fn dummy_proofs<const T: usize>() -> (CircuitData<F, C, D>, Vec<ProofWithPublicInputs<F, C, D>>) {
|
||||||
let config = CircuitConfig::standard_recursion_config();
|
let config = CircuitConfig::standard_recursion_config();
|
||||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||||
for _ in 0..8192 {
|
for _ in 0..(4096+10) {
|
||||||
builder.add_gate(NoopGate, vec![]);
|
builder.add_gate(NoopGate, vec![]);
|
||||||
}
|
}
|
||||||
// Add one virtual public input so that the circuit has minimal structure.
|
// Add one virtual public input so that the circuit has minimal structure.
|
||||||
@ -367,13 +336,12 @@ mod tests {
|
|||||||
// End-to-End test for the entire Tree circuit.
|
// End-to-End test for the entire Tree circuit.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_full_tree_circuit() -> anyhow::Result<()> {
|
fn test_full_tree_circuit() -> anyhow::Result<()> {
|
||||||
const N: usize = 1;
|
const N: usize = 2;
|
||||||
const M: usize = 2;
|
const T: usize = 128;
|
||||||
const T: usize = 4;
|
|
||||||
|
|
||||||
let (data, proofs) = dummy_proofs::<T>();
|
let (data, proofs) = dummy_proofs::<T>();
|
||||||
|
|
||||||
let mut tree = TreeRecursion::<F,D,C,H, N, M, T>::build_with_standard_config(data.common.clone(), data.verifier_only.clone())?;
|
let mut tree = TreeRecursion::<F,D,C,H, N, T>::build_with_standard_config(data.verifier_data())?;
|
||||||
|
|
||||||
// aggregate - no compression
|
// aggregate - no compression
|
||||||
let root = tree.prove_tree(&proofs)?;
|
let root = tree.prove_tree(&proofs)?;
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::{HashOut, RichField};
|
||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
|
use plonky2::plonk::circuit_data::VerifierCircuitData;
|
||||||
|
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||||
use plonky2_field::extension::Extendable;
|
use plonky2_field::extension::Extendable;
|
||||||
use plonky2_poseidon2::Poseidon2;
|
use plonky2_poseidon2::Poseidon2;
|
||||||
use crate::recursion::leaf::{BUCKET_SIZE, LeafCircuit};
|
use crate::recursion::leaf::BUCKET_SIZE;
|
||||||
|
|
||||||
/// Splits a target `index` which is known to lie in the range [0, T)
|
/// Splits a target `index` which is known to lie in the range [0, T)
|
||||||
/// where T = bucket_size * num_buckets
|
/// where T = bucket_size * num_buckets
|
||||||
@ -135,6 +137,26 @@ pub fn bucket_count(t: usize) -> usize {
|
|||||||
(t + BUCKET_SIZE -1) / BUCKET_SIZE
|
(t + BUCKET_SIZE -1) / BUCKET_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// helper fn to generate hash of verifier data
|
||||||
|
pub fn get_hash_of_verifier_data<
|
||||||
|
F: RichField + Extendable<D> + Poseidon2,
|
||||||
|
const D: usize,
|
||||||
|
C: GenericConfig<D, F = F>,
|
||||||
|
H: AlgebraicHasher<F>,
|
||||||
|
>(verifier_data: &VerifierCircuitData<F, C, D>) -> HashOut<F> where
|
||||||
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
|
{
|
||||||
|
let mut vd = vec![];
|
||||||
|
let digest: &HashOut<F> = &verifier_data.verifier_only.circuit_digest;
|
||||||
|
let caps = &verifier_data.verifier_only.constants_sigmas_cap;
|
||||||
|
vd.extend_from_slice(&digest.elements);
|
||||||
|
for i in 0..verifier_data.common.config.fri_config.num_cap_elements() {
|
||||||
|
let cap_hash = caps.0[i] as HashOut<F>;
|
||||||
|
vd.extend_from_slice(&cap_hash.elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
H::hash_no_pad(&vd)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user