mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-28 18:43:11 +00:00
change hashing of VerifierData to constants.
This commit is contained in:
parent
190c6063f5
commit
aa13ff3253
@ -1,8 +1,8 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::{HashOutTarget, RichField};
|
||||||
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::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
|
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, 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;
|
||||||
@ -20,7 +20,8 @@ pub struct CompressionCircuit<
|
|||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
inner_common_data: CommonCircuitData<F, D>,
|
inner_common_data: CommonCircuitData<F, D>,
|
||||||
phantom_data: PhantomData<(C,H)>
|
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
phantom_data: PhantomData<H>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -28,7 +29,6 @@ pub struct CompressionTargets<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
>{
|
>{
|
||||||
pub inner_proof: ProofWithPublicInputsTarget<D>,
|
pub inner_proof: ProofWithPublicInputsTarget<D>,
|
||||||
pub verifier_data: VerifierCircuitTarget,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
@ -39,9 +39,13 @@ impl<
|
|||||||
> CompressionCircuit<F,D,C,H> where
|
> CompressionCircuit<F,D,C,H> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
pub fn new(inner_common_data: CommonCircuitData<F,D>) -> Self {
|
pub fn new(
|
||||||
|
inner_common_data: CommonCircuitData<F,D>,
|
||||||
|
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
) -> Self {
|
||||||
Self{
|
Self{
|
||||||
inner_common_data,
|
inner_common_data,
|
||||||
|
inner_verifier_data,
|
||||||
phantom_data:PhantomData::default(),
|
phantom_data:PhantomData::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,29 +63,29 @@ impl<
|
|||||||
assert_eq!(inner_pub_input.len(), 8);
|
assert_eq!(inner_pub_input.len(), 8);
|
||||||
builder.register_public_inputs(&inner_pub_input[0..4]);
|
builder.register_public_inputs(&inner_pub_input[0..4]);
|
||||||
|
|
||||||
// virtual target for the verifier data
|
// constant target for the verifier data
|
||||||
let inner_verifier_data = builder.add_virtual_verifier_data(inner_common.config.fri_config.cap_height);
|
let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data);
|
||||||
|
|
||||||
// register verifier data hash as public input.
|
// register verifier data hash as public input.
|
||||||
let mut vd_pub_input = vec![];
|
let mut vd_pub_input = vec![];
|
||||||
vd_pub_input.extend_from_slice(&inner_verifier_data.circuit_digest.elements);
|
vd_pub_input.extend_from_slice(&const_verifier_data.circuit_digest.elements);
|
||||||
for i in 0..builder.config.fri_config.num_cap_elements() {
|
for i in 0..builder.config.fri_config.num_cap_elements() {
|
||||||
vd_pub_input.extend_from_slice(&inner_verifier_data.constants_sigmas_cap.0[i].elements);
|
vd_pub_input.extend_from_slice(&const_verifier_data.constants_sigmas_cap.0[i].elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
let hash_inner_vd_pub_input = builder.hash_n_to_hash_no_pad::<H>(vd_pub_input);
|
let hash_inner_vd_pub_input = builder.hash_n_to_hash_no_pad::<H>(vd_pub_input);
|
||||||
let mut vd_to_hash = vec![];
|
|
||||||
vd_to_hash.extend_from_slice(&inner_pub_input[4..8]);
|
// make sure the VerifierData we use is the same as the tree root hash of the VerifierData
|
||||||
vd_to_hash.extend_from_slice(&hash_inner_vd_pub_input.elements);
|
builder.connect_hashes(hash_inner_vd_pub_input,HashOutTarget::from_vec(inner_pub_input[4..8].to_vec()));
|
||||||
let vd_hash = builder.hash_n_to_hash_no_pad::<H>(vd_to_hash);
|
|
||||||
builder.register_public_inputs(&vd_hash.elements);
|
builder.register_public_inputs(&hash_inner_vd_pub_input.elements);
|
||||||
|
|
||||||
// verify the proofs in-circuit
|
// verify the proofs in-circuit
|
||||||
builder.verify_proof::<C>(&vir_proof, &inner_verifier_data, &inner_common);
|
builder.verify_proof::<C>(&vir_proof, &const_verifier_data, &inner_common);
|
||||||
|
|
||||||
// return targets
|
// return targets
|
||||||
let t = CompressionTargets {
|
let t = CompressionTargets {
|
||||||
inner_proof: vir_proof,
|
inner_proof: vir_proof,
|
||||||
verifier_data: inner_verifier_data,
|
|
||||||
};
|
};
|
||||||
Ok(t)
|
Ok(t)
|
||||||
|
|
||||||
@ -92,7 +96,6 @@ impl<
|
|||||||
&self, pw: &mut PartialWitness<F>,
|
&self, pw: &mut PartialWitness<F>,
|
||||||
targets: &CompressionTargets<D>,
|
targets: &CompressionTargets<D>,
|
||||||
inner_proof: ProofWithPublicInputs<F, C, D>,
|
inner_proof: ProofWithPublicInputs<F, C, D>,
|
||||||
verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// assign the proof
|
// assign the proof
|
||||||
pw.set_proof_with_pis_target(&targets.inner_proof, &inner_proof)
|
pw.set_proof_with_pis_target(&targets.inner_proof, &inner_proof)
|
||||||
@ -100,12 +103,6 @@ impl<
|
|||||||
CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string())
|
CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// assign the verifier data
|
|
||||||
pw.set_verifier_data_target(&targets.verifier_data, verifier_only_data)
|
|
||||||
.map_err(|e| {
|
|
||||||
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::{HashOut, RichField};
|
||||||
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::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
|
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, 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;
|
||||||
@ -21,7 +21,8 @@ pub struct LeafCircuit<
|
|||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
inner_common_data: CommonCircuitData<F, D>,
|
inner_common_data: CommonCircuitData<F, D>,
|
||||||
phantom_data: PhantomData<(C,H)>
|
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
phantom_data: PhantomData<H>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -29,7 +30,6 @@ pub struct LeafTargets <
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
>{
|
>{
|
||||||
pub inner_proof: Vec<ProofWithPublicInputsTarget<D>>,
|
pub inner_proof: Vec<ProofWithPublicInputsTarget<D>>,
|
||||||
pub verifier_data: VerifierCircuitTarget,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
@ -41,9 +41,13 @@ impl<
|
|||||||
> LeafCircuit<F,D,C,H,N> where
|
> LeafCircuit<F,D,C,H,N> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
pub fn new(inner_common_data: CommonCircuitData<F,D>) -> Self {
|
pub fn new(
|
||||||
|
inner_common_data: CommonCircuitData<F,D>,
|
||||||
|
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
) -> Self {
|
||||||
Self{
|
Self{
|
||||||
inner_common_data,
|
inner_common_data,
|
||||||
|
inner_verifier_data,
|
||||||
phantom_data:PhantomData::default(),
|
phantom_data:PhantomData::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,27 +71,21 @@ impl<
|
|||||||
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>(pub_input);
|
||||||
builder.register_public_inputs(&hash_inner_pub_input.elements);
|
builder.register_public_inputs(&hash_inner_pub_input.elements);
|
||||||
|
|
||||||
// virtual target for the verifier data
|
// pad the public input with constants so that it shares the same structure as the node
|
||||||
let inner_verifier_data = builder.add_virtual_verifier_data(inner_common.config.fri_config.cap_height);
|
let zero_hash = builder.constant_hash(HashOut::<F>::default());
|
||||||
|
builder.register_public_inputs(&zero_hash.elements);
|
||||||
|
|
||||||
// register verifier data hash as public input.
|
// virtual constant target for the verifier data
|
||||||
let mut vd_pub_input = vec![];
|
let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data);
|
||||||
vd_pub_input.extend_from_slice(&inner_verifier_data.circuit_digest.elements);
|
|
||||||
for i in 0..builder.config.fri_config.num_cap_elements() {
|
|
||||||
vd_pub_input.extend_from_slice(&inner_verifier_data.constants_sigmas_cap.0[i].elements);
|
|
||||||
}
|
|
||||||
let hash_inner_vd_pub_input = builder.hash_n_to_hash_no_pad::<H>(vd_pub_input);
|
|
||||||
builder.register_public_inputs(&hash_inner_vd_pub_input.elements);
|
|
||||||
|
|
||||||
// verify the proofs in-circuit
|
// verify the proofs in-circuit
|
||||||
for i in 0..N {
|
for i in 0..N {
|
||||||
builder.verify_proof::<C>(&vir_proofs[i], &inner_verifier_data, &inner_common);
|
builder.verify_proof::<C>(&vir_proofs[i], &const_verifier_data, &inner_common);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return targets
|
// return targets
|
||||||
let t = LeafTargets {
|
let t = LeafTargets {
|
||||||
inner_proof: vir_proofs,
|
inner_proof: vir_proofs,
|
||||||
verifier_data: inner_verifier_data,
|
|
||||||
};
|
};
|
||||||
Ok(t)
|
Ok(t)
|
||||||
|
|
||||||
@ -98,7 +96,6 @@ impl<
|
|||||||
&self, pw: &mut PartialWitness<F>,
|
&self, pw: &mut PartialWitness<F>,
|
||||||
targets: &LeafTargets<D>,
|
targets: &LeafTargets<D>,
|
||||||
inner_proof: &[ProofWithPublicInputs<F, C, D>],
|
inner_proof: &[ProofWithPublicInputs<F, C, D>],
|
||||||
verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
assert_eq!(inner_proof.len(), N);
|
assert_eq!(inner_proof.len(), N);
|
||||||
// assign the proofs
|
// assign the proofs
|
||||||
@ -109,12 +106,6 @@ impl<
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the verifier data
|
|
||||||
pw.set_verifier_data_target(&targets.verifier_data, verifier_only_data)
|
|
||||||
.map_err(|e| {
|
|
||||||
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::RichField;
|
||||||
|
use plonky2::iop::target::BoolTarget;
|
||||||
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::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
|
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData};
|
||||||
@ -8,7 +9,7 @@ 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::circuits::utils::vec_to_array;
|
// use crate::circuits::utils::vec_to_array;
|
||||||
|
|
||||||
/// recursion node circuit - verifies M leaf proofs
|
/// recursion node circuit - verifies M leaf proofs
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -21,8 +22,9 @@ pub struct NodeCircuit<
|
|||||||
> where
|
> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
leaf_common_data: CommonCircuitData<F, D>,
|
common_data: CommonCircuitData<F, D>,
|
||||||
phantom_data: PhantomData<(C,H)>
|
leaf_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
phantom_data: PhantomData<H>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -30,7 +32,8 @@ pub struct NodeTargets<
|
|||||||
const D: usize,
|
const D: usize,
|
||||||
>{
|
>{
|
||||||
pub leaf_proofs: Vec<ProofWithPublicInputsTarget<D>>,
|
pub leaf_proofs: Vec<ProofWithPublicInputsTarget<D>>,
|
||||||
pub verifier_data: VerifierCircuitTarget,
|
pub node_verifier_data: VerifierCircuitTarget,
|
||||||
|
pub condition: BoolTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
@ -43,9 +46,13 @@ impl<
|
|||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
|
|
||||||
pub fn new(inner_common_data: CommonCircuitData<F,D>) -> Self {
|
pub fn new(
|
||||||
|
common_data: CommonCircuitData<F,D>,
|
||||||
|
leaf_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
) -> Self {
|
||||||
Self{
|
Self{
|
||||||
leaf_common_data: inner_common_data,
|
common_data,
|
||||||
|
leaf_verifier_data,
|
||||||
phantom_data:PhantomData::default(),
|
phantom_data:PhantomData::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +60,7 @@ impl<
|
|||||||
/// build the leaf circuit
|
/// build the leaf circuit
|
||||||
pub fn build(&self, builder: &mut CircuitBuilder<F, D>) -> Result<NodeTargets<D>> {
|
pub fn build(&self, builder: &mut CircuitBuilder<F, D>) -> Result<NodeTargets<D>> {
|
||||||
|
|
||||||
let inner_common = self.leaf_common_data.clone();
|
let inner_common = self.common_data.clone();
|
||||||
|
|
||||||
// assert public input is of size 8 - 2 hashout
|
// assert public input is of size 8 - 2 hashout
|
||||||
assert_eq!(inner_common.num_public_inputs, 8);
|
assert_eq!(inner_common.num_public_inputs, 8);
|
||||||
@ -61,13 +68,11 @@ impl<
|
|||||||
// the proof virtual targets - M proofs
|
// the proof virtual targets - M proofs
|
||||||
let mut vir_proofs = vec![];
|
let mut vir_proofs = vec![];
|
||||||
let mut pub_input = vec![];
|
let mut pub_input = vec![];
|
||||||
let mut inner_vd_hashes = vec![];
|
|
||||||
for _i in 0..M {
|
for _i in 0..M {
|
||||||
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);
|
||||||
pub_input.extend_from_slice(&inner_pub_input[0..4]);
|
pub_input.extend_from_slice(&inner_pub_input[0..4]);
|
||||||
inner_vd_hashes.extend_from_slice(&inner_pub_input[4..8]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash the public input & make it public
|
// hash the public input & make it public
|
||||||
@ -75,22 +80,34 @@ impl<
|
|||||||
builder.register_public_inputs(&hash_inner_pub_input.elements);
|
builder.register_public_inputs(&hash_inner_pub_input.elements);
|
||||||
|
|
||||||
// virtual target for the verifier data
|
// virtual target for the verifier data
|
||||||
let inner_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);
|
||||||
|
|
||||||
// register verifier data hash as public input. H(H_l, H_l, H_n) -> public input
|
// virtual target for the verifier data
|
||||||
|
let const_leaf_verifier_data = builder.constant_verifier_data(&self.leaf_verifier_data);
|
||||||
|
|
||||||
|
// register only the node verifier data hash as public input.
|
||||||
let mut vd_pub_input = vec![];
|
let mut vd_pub_input = vec![];
|
||||||
vd_pub_input.extend_from_slice(&inner_verifier_data.circuit_digest.elements);
|
vd_pub_input.extend_from_slice(&node_verifier_data.circuit_digest.elements);
|
||||||
for i in 0..builder.config.fri_config.num_cap_elements() {
|
for i in 0..builder.config.fri_config.num_cap_elements() {
|
||||||
vd_pub_input.extend_from_slice(&inner_verifier_data.constants_sigmas_cap.0[i].elements);
|
vd_pub_input.extend_from_slice(&node_verifier_data.constants_sigmas_cap.0[i].elements);
|
||||||
}
|
}
|
||||||
let vd_hash = builder.hash_n_to_hash_no_pad::<H>(vd_pub_input);
|
let vd_hash = builder.hash_n_to_hash_no_pad::<H>(vd_pub_input);
|
||||||
inner_vd_hashes.extend_from_slice(&vd_hash.elements);
|
builder.register_public_inputs(&vd_hash.elements);
|
||||||
let vd_hash_all = builder.hash_n_to_hash_no_pad::<H>(inner_vd_hashes);
|
|
||||||
builder.register_public_inputs(&vd_hash_all.elements);
|
// condition for switching between node and leaf
|
||||||
|
let condition = builder.add_virtual_bool_target_safe();
|
||||||
|
|
||||||
|
// true -> node, false -> leaf
|
||||||
|
let selected_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..M {
|
||||||
builder.verify_proof::<C>(&vir_proofs[i], &inner_verifier_data, &inner_common);
|
builder.verify_proof::<C>(&vir_proofs[i], &selected_vd, &inner_common);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have every gate to match `common_data`.
|
||||||
|
for g in &inner_common.gates {
|
||||||
|
builder.add_gate_to_gate_set(g.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// let proofs = vec_to_array::<2, ProofWithPublicInputsTarget<D>>(vir_proofs)?;
|
// let proofs = vec_to_array::<2, ProofWithPublicInputsTarget<D>>(vir_proofs)?;
|
||||||
@ -98,7 +115,8 @@ impl<
|
|||||||
// return targets
|
// return targets
|
||||||
let t = NodeTargets {
|
let t = NodeTargets {
|
||||||
leaf_proofs: vir_proofs,
|
leaf_proofs: vir_proofs,
|
||||||
verifier_data: inner_verifier_data,
|
node_verifier_data,
|
||||||
|
condition,
|
||||||
};
|
};
|
||||||
Ok(t)
|
Ok(t)
|
||||||
|
|
||||||
@ -110,6 +128,7 @@ impl<
|
|||||||
targets: &NodeTargets<D>,
|
targets: &NodeTargets<D>,
|
||||||
node_proofs: &[ProofWithPublicInputs<F, C, D>],
|
node_proofs: &[ProofWithPublicInputs<F, C, D>],
|
||||||
verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
||||||
|
condition: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// assert size of proofs vec
|
// assert size of proofs vec
|
||||||
assert_eq!(node_proofs.len(), M);
|
assert_eq!(node_proofs.len(), M);
|
||||||
@ -123,11 +142,15 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assign the verifier data
|
// assign the verifier data
|
||||||
pw.set_verifier_data_target(&targets.verifier_data, &verifier_only_data)
|
pw.set_verifier_data_target(&targets.node_verifier_data, &verifier_only_data)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// assign the condition
|
||||||
|
pw.set_bool_target(targets.condition, condition)
|
||||||
|
.map_err(|e| CircuitError::BoolTargetAssignmentError("condition".to_string(), e.to_string()))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use plonky2::hash::hash_types::{HashOut, HashOutTarget, RichField};
|
use plonky2::hash::hash_types::{ HashOutTarget, RichField};
|
||||||
use plonky2::iop::target::Target;
|
use plonky2::iop::target::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, VerifierCircuitData, VerifierCircuitTarget};
|
use plonky2::plonk::circuit_data::{CommonCircuitData, 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;
|
||||||
@ -29,20 +29,15 @@ pub struct PublicInputVerificationCircuit<
|
|||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>,
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>,
|
||||||
{
|
{
|
||||||
pub node_common_data: CommonCircuitData<F, D>,
|
pub node_common_data: CommonCircuitData<F, D>,
|
||||||
phantom: PhantomData<(C, H)>,
|
pub node_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
phantom: PhantomData<H>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds the virtual targets for the circuit.
|
/// Holds the virtual targets for the circuit.
|
||||||
/// - `inner_proof`: the proof to be verified and contains the public input to be verified.
|
/// - `inner_proof`: the proof to be verified and contains the public input to be verified.
|
||||||
/// - `inner_pub_inputs`: A nested vector of targets with dimensions T×K.
|
/// - `inner_pub_inputs`: A nested vector of targets with dimensions T×K.
|
||||||
/// - `node_verifier_data`: Verifier data for the node circuit.
|
|
||||||
/// - `leaf_verifier_data`: Verifier data for the leaf circuit.
|
|
||||||
/// - `inner_verifier_data`: Verifier data for the inner circuit.
|
|
||||||
pub struct PublicInputVerificationTargets<const D: usize> {
|
pub struct PublicInputVerificationTargets<const D: usize> {
|
||||||
pub inner_proof: ProofWithPublicInputsTarget<D>,
|
pub inner_proof: ProofWithPublicInputsTarget<D>,
|
||||||
pub node_verifier_data: VerifierCircuitTarget,
|
|
||||||
pub leaf_verifier_data: HashOutTarget,
|
|
||||||
pub inner_verifier_data: HashOutTarget,
|
|
||||||
pub inner_pub_inputs: Vec<Vec<Target>>,
|
pub inner_pub_inputs: Vec<Vec<Target>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,13 +50,17 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>,
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>,
|
||||||
{
|
{
|
||||||
/// Create a new instance of the circuit.
|
/// Create a new instance of the circuit.
|
||||||
pub fn new(node_common_data: CommonCircuitData<F, D>) -> Self {
|
pub fn new(
|
||||||
|
node_common_data: CommonCircuitData<F, D>,
|
||||||
|
node_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
|
) -> Self {
|
||||||
// we expect exactly 8 public inputs from the tree root proof
|
// we expect exactly 8 public inputs from the tree root proof
|
||||||
// 4 for the final aggregated public-input hash, 4 for the final aggregated verifier-data hash
|
// 4 for the final aggregated public-input hash, 4 for the node verifier-data hash
|
||||||
assert_eq!(node_common_data.num_public_inputs, 8);
|
assert_eq!(node_common_data.num_public_inputs, 8);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
node_common_data,
|
node_common_data,
|
||||||
|
node_verifier_data,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,19 +68,17 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
/// Builds the circuit by:
|
/// Builds the circuit by:
|
||||||
/// 1. Verifies a proof target with 8 public inputs (the final [pi_hash, vd_hash]).
|
/// 1. Verifies a proof target with 8 public inputs (the final [pi_hash, vd_hash]).
|
||||||
/// 2. verifies correct tree hashing of all T×K targets to represent all inner public inputs.
|
/// 2. verifies correct tree hashing of all T×K targets to represent all inner public inputs.
|
||||||
/// 3. verifies correct tree hashing of node_verifier_date leaf_verifier_data and inner_verifier_data (each 4 field elements).
|
/// 3. verifies correct node_verifier_date used is the same as in public input (last 4 field elements).
|
||||||
pub fn build(&self, builder: &mut CircuitBuilder<F, D>) -> Result<PublicInputVerificationTargets<D>> {
|
pub fn build(&self, builder: &mut CircuitBuilder<F, D>) -> Result<PublicInputVerificationTargets<D>> {
|
||||||
// Add a virtual proof with 8 public inputs. This is the final root proof whose
|
// Add a virtual proof with 8 public inputs. This is the final root proof whose
|
||||||
// public inputs we want to check in-circuit.
|
// public inputs we want to check in-circuit.
|
||||||
let inner_proof = builder.add_virtual_proof_with_pis(&self.node_common_data);
|
let inner_proof = builder.add_virtual_proof_with_pis(&self.node_common_data);
|
||||||
|
|
||||||
// Create a VerifierCircuitTarget for the node's verifier data (unhashed).
|
// Create a constant VerifierCircuitTarget for the node's verifier data.
|
||||||
let node_verifier_data = builder.add_virtual_verifier_data(
|
let const_node_vd = builder.constant_verifier_data(&self.node_verifier_data);
|
||||||
self.node_common_data.config.fri_config.cap_height
|
|
||||||
);
|
|
||||||
|
|
||||||
// verify the proof
|
// verify the proof
|
||||||
builder.verify_proof::<C>(&inner_proof, &node_verifier_data, &self.node_common_data);
|
builder.verify_proof::<C>(&inner_proof, &const_node_vd, &self.node_common_data);
|
||||||
|
|
||||||
// create T×K targets for all inner public inputs from the base level.
|
// create T×K targets for all inner public inputs from the base level.
|
||||||
let mut inner_pub_inputs = Vec::with_capacity(T);
|
let mut inner_pub_inputs = Vec::with_capacity(T);
|
||||||
@ -97,34 +94,30 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
// Summary of the logic:
|
// Summary of the logic:
|
||||||
//
|
//
|
||||||
// let final_pi = proof.public_inputs[0..4];
|
// let final_pi = proof.public_inputs[0..4];
|
||||||
// let final_vd = proof.public_inputs[4..8];
|
// let node_vd = proof.public_inputs[4..8];
|
||||||
// ...
|
// ...
|
||||||
// leaf-level pub inputs tree hashing: chunks of N -> hash -> combine with inner_verifier_data
|
// leaf-level pub inputs tree hashing: chunks of N -> hash
|
||||||
// node-level pub inputs tree hashing: chunks of M -> hash -> combine with either leaf_hash (only level 0) or node_hash
|
// node-level pub inputs tree hashing: chunks of M -> hash
|
||||||
// ...
|
// ...
|
||||||
// check final result matches final_pi, final_vd
|
// check final result matches final_pi
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
// Extract the final 4 field elements for the public-input hash & next 4 for the verifier-data hash.
|
// Extract the final 4 field elements for the public-input hash & next 4 for the verifier-data hash.
|
||||||
let final_pi_hash_t = &inner_proof.public_inputs[0..4];
|
let final_pi_hash_t = &inner_proof.public_inputs[0..4];
|
||||||
let final_vd_hash_t = &inner_proof.public_inputs[4..8];
|
let node_vd_hash_t = &inner_proof.public_inputs[4..8];
|
||||||
|
|
||||||
// Compute node_hash in-circuit
|
// Compute node_hash in-circuit
|
||||||
let mut node_vd_input_t = Vec::new();
|
let mut node_vd_input_t = Vec::new();
|
||||||
node_vd_input_t.extend_from_slice(&node_verifier_data.circuit_digest.elements);
|
node_vd_input_t.extend_from_slice(&const_node_vd.circuit_digest.elements);
|
||||||
for cap_elem in node_verifier_data.constants_sigmas_cap.0.iter() {
|
for cap_elem in const_node_vd.constants_sigmas_cap.0.iter() {
|
||||||
node_vd_input_t.extend_from_slice(&cap_elem.elements);
|
node_vd_input_t.extend_from_slice(&cap_elem.elements);
|
||||||
}
|
}
|
||||||
let node_hash_t = builder.hash_n_to_hash_no_pad::<H>(node_vd_input_t);
|
let node_hash_t = builder.hash_n_to_hash_no_pad::<H>(node_vd_input_t);
|
||||||
|
// make sure the VerifierData we use is the same as the tree root hash of the VerifierData
|
||||||
|
builder.connect_hashes(node_hash_t,HashOutTarget::from_vec(node_vd_hash_t.to_vec()));
|
||||||
builder.register_public_inputs(&node_hash_t.elements); // public input
|
builder.register_public_inputs(&node_hash_t.elements); // public input
|
||||||
|
|
||||||
|
|
||||||
let mut pub_in_hashes_t = Vec::new();
|
let mut pub_in_hashes_t = Vec::new();
|
||||||
let mut vd_hashes_t = Vec::new();
|
|
||||||
|
|
||||||
// hash targets for the leaf and inner circuit's verifier data.
|
|
||||||
let leaf_hash_t = builder.add_virtual_hash_public_input(); // public input
|
|
||||||
let inner_hash_t = builder.add_virtual_hash_public_input(); // public input
|
|
||||||
|
|
||||||
// Leaf level hashing: chunks of N
|
// Leaf level hashing: chunks of N
|
||||||
let base_chunks = T / N; // T is assumed to be multiple of N
|
let base_chunks = T / N; // T is assumed to be multiple of N
|
||||||
@ -139,20 +132,15 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
|
|
||||||
// track these in vectors
|
// track these in vectors
|
||||||
pub_in_hashes_t.push(pi_hash_chunk);
|
pub_in_hashes_t.push(pi_hash_chunk);
|
||||||
vd_hashes_t.push(inner_hash_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now at the node level:
|
// Now at the node level:
|
||||||
|
|
||||||
let mut level = 0;
|
|
||||||
let mut current_len = base_chunks;
|
let mut current_len = base_chunks;
|
||||||
|
|
||||||
while current_len > 1 {
|
while current_len > 1 {
|
||||||
|
|
||||||
let next_len = (current_len + (M - 1)) / M;
|
let next_len = (current_len + (M - 1)) / M;
|
||||||
|
|
||||||
let mut next_pub_in_hashes_t = Vec::with_capacity(next_len);
|
let mut next_pub_in_hashes_t = Vec::with_capacity(next_len);
|
||||||
let mut next_vd_hashes_t = Vec::with_capacity(next_len);
|
|
||||||
|
|
||||||
for i in 0..next_len {
|
for i in 0..next_len {
|
||||||
let start_idx = i * M;
|
let start_idx = i * M;
|
||||||
@ -164,44 +152,24 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
pi_flat.extend_from_slice(&pub_in_hashes_t[j].elements);
|
pi_flat.extend_from_slice(&pub_in_hashes_t[j].elements);
|
||||||
}
|
}
|
||||||
let pi_hash = builder.hash_n_to_hash_no_pad::<H>(pi_flat);
|
let pi_hash = builder.hash_n_to_hash_no_pad::<H>(pi_flat);
|
||||||
|
|
||||||
// flatten all vd_hashes in [start_idx..end_idx]
|
|
||||||
let mut vd_flat = Vec::with_capacity((end_idx - start_idx) * 4);
|
|
||||||
for j in start_idx..end_idx {
|
|
||||||
vd_flat.extend_from_slice(&vd_hashes_t[j].elements);
|
|
||||||
}
|
|
||||||
// use leaf_hash if level == 0, else node_hash
|
|
||||||
let hash_n_t = if level == 0 { leaf_hash_t } else { node_hash_t };
|
|
||||||
vd_flat.extend_from_slice(&hash_n_t.elements);
|
|
||||||
|
|
||||||
let vd_hash = builder.hash_n_to_hash_no_pad::<H>(vd_flat);
|
|
||||||
|
|
||||||
next_pub_in_hashes_t.push(pi_hash);
|
next_pub_in_hashes_t.push(pi_hash);
|
||||||
next_vd_hashes_t.push(vd_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub_in_hashes_t = next_pub_in_hashes_t;
|
pub_in_hashes_t = next_pub_in_hashes_t;
|
||||||
vd_hashes_t = next_vd_hashes_t;
|
|
||||||
current_len = next_len;
|
current_len = next_len;
|
||||||
level += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now have exactly one pub_in_hash and one vd_hash
|
// now have exactly one pub_in_hash
|
||||||
let final_computed_pi_t = &pub_in_hashes_t[0];
|
let final_computed_pi_t = &pub_in_hashes_t[0];
|
||||||
let final_computed_vd_t = &vd_hashes_t[0];
|
|
||||||
|
|
||||||
// connect them to the final 8 public inputs of `inner_proof`.
|
// connect them to the final 4 public inputs of `inner_proof`.
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
builder.connect(final_pi_hash_t[i], final_computed_pi_t.elements[i]);
|
builder.connect(final_pi_hash_t[i], final_computed_pi_t.elements[i]);
|
||||||
builder.connect(final_vd_hash_t[i], final_computed_vd_t.elements[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return all the targets
|
// return all the targets
|
||||||
Ok(PublicInputVerificationTargets {
|
Ok(PublicInputVerificationTargets {
|
||||||
inner_proof,
|
inner_proof,
|
||||||
node_verifier_data,
|
|
||||||
leaf_verifier_data: leaf_hash_t,
|
|
||||||
inner_verifier_data: inner_hash_t,
|
|
||||||
inner_pub_inputs,
|
inner_pub_inputs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -209,18 +177,12 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
/// Assigns witness values to the targets.
|
/// Assigns witness values to the targets.
|
||||||
/// - `inner_proof`: The tree root proof with 8 public inputs [pi_hash, vd_hash].
|
/// - `inner_proof`: The tree root proof with 8 public inputs [pi_hash, vd_hash].
|
||||||
/// - `inner_pub_inputs_vals`: T×K public input values from inner proofs.
|
/// - `inner_pub_inputs_vals`: T×K public input values from inner proofs.
|
||||||
/// - `node_verifier_data`: node verifier data
|
|
||||||
/// - `leaf_verifier_data`: leaf circuit’s verifier data.
|
|
||||||
/// - `inner_verifier_data`:inner-circuit’s verifier data.
|
|
||||||
pub fn assign_targets(
|
pub fn assign_targets(
|
||||||
&self,
|
&self,
|
||||||
pw: &mut PartialWitness<F>,
|
pw: &mut PartialWitness<F>,
|
||||||
targets: &PublicInputVerificationTargets<D>,
|
targets: &PublicInputVerificationTargets<D>,
|
||||||
inner_proof: ProofWithPublicInputs<F, C, D>,
|
inner_proof: ProofWithPublicInputs<F, C, D>,
|
||||||
inner_pub_inputs_vals: Vec<Vec<F>>,
|
inner_pub_inputs_vals: Vec<Vec<F>>,
|
||||||
node_verifier_data: &VerifierCircuitData<F, C, D>,
|
|
||||||
leaf_verifier_data: &VerifierCircuitData<F, C, D>,
|
|
||||||
inner_verifier_data: &VerifierCircuitData<F, C, D>,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Assign the final proof - it should have 8 public inputs
|
// Assign the final proof - it should have 8 public inputs
|
||||||
pw.set_proof_with_pis_target(&targets.inner_proof, &inner_proof)
|
pw.set_proof_with_pis_target(&targets.inner_proof, &inner_proof)
|
||||||
@ -252,38 +214,6 @@ PublicInputVerificationCircuit<F, D, C, H, N, M, T, K>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign the node verifier data
|
|
||||||
pw.set_verifier_data_target(&targets.node_verifier_data, &node_verifier_data.verifier_only)
|
|
||||||
.map_err(|e| {
|
|
||||||
CircuitError::VerifierDataTargetAssignmentError(e.to_string())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Assign the leaf circuit’s verifier data
|
|
||||||
let leaf_hash = Self::get_hash_of_verifier_data(leaf_verifier_data);
|
|
||||||
pw.set_hash_target(targets.leaf_verifier_data, leaf_hash).map_err(|e| {
|
|
||||||
CircuitError::HashTargetAssignmentError("leaf verifier data hash".to_string(), e.to_string())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Assign the inner circuit’s verifier data
|
|
||||||
let inner_hash = Self::get_hash_of_verifier_data(inner_verifier_data);
|
|
||||||
pw.set_hash_target(targets.inner_verifier_data, inner_hash).map_err(|e| {
|
|
||||||
CircuitError::HashTargetAssignmentError("inner verifier data hash".to_string(), e.to_string())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper fn to generate hash of verifier data
|
|
||||||
fn get_hash_of_verifier_data(verifier_data: &VerifierCircuitData<F, C, D>) -> HashOut<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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,13 +46,14 @@ impl<
|
|||||||
{
|
{
|
||||||
|
|
||||||
pub fn build(
|
pub fn build(
|
||||||
inner_common_data: CommonCircuitData<F,D>
|
inner_common_data: CommonCircuitData<F,D>,
|
||||||
|
inner_verifier_data: VerifierOnlyCircuitData<C, D>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
// build leaf with standard recursion config
|
// build leaf with standard recursion config
|
||||||
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);
|
||||||
|
|
||||||
let leaf = LeafCircuit::<_,D,_,_,N>::new(inner_common_data.clone());
|
let leaf = LeafCircuit::<_,D,_,_,N>::new(inner_common_data.clone(), inner_verifier_data.clone());
|
||||||
let leaf_targets = leaf.build(&mut builder)?;
|
let leaf_targets = leaf.build(&mut builder)?;
|
||||||
let leaf_circ_data = builder.build::<C>();
|
let leaf_circ_data = builder.build::<C>();
|
||||||
// println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits());
|
// println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits());
|
||||||
@ -61,7 +62,7 @@ impl<
|
|||||||
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);
|
||||||
|
|
||||||
let node = NodeCircuit::<_,D,_,_,M>::new(leaf_circ_data.common.clone());
|
let node = NodeCircuit::<_,D,_,_,M>::new(leaf_circ_data.common.clone(), leaf_circ_data.verifier_only.clone());
|
||||||
let node_targets = node.build(&mut builder)?;
|
let node_targets = node.build(&mut builder)?;
|
||||||
let node_circ_data = builder.build::<C>();
|
let node_circ_data = builder.build::<C>();
|
||||||
// println!("node circuit size = {:?}", node_circ_data.common.degree_bits());
|
// println!("node circuit size = {:?}", node_circ_data.common.degree_bits());
|
||||||
@ -70,7 +71,7 @@ impl<
|
|||||||
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);
|
||||||
let node_common = node_circ_data.common.clone();
|
let node_common = node_circ_data.common.clone();
|
||||||
let compression_circ = CompressionCircuit::new(node_common);
|
let compression_circ = CompressionCircuit::new(node_common, node_circ_data.verifier_only.clone());
|
||||||
let compression_targets = compression_circ.build(&mut builder)?;
|
let compression_targets = compression_circ.build(&mut builder)?;
|
||||||
let compression_circ_data = builder.build::<C>();
|
let compression_circ_data = builder.build::<C>();
|
||||||
// println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits());
|
// println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits());
|
||||||
@ -108,13 +109,12 @@ impl<
|
|||||||
pub fn prove_tree_and_compress(
|
pub fn prove_tree_and_compress(
|
||||||
&mut self,
|
&mut self,
|
||||||
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
||||||
inner_verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Result<(ProofWithPublicInputs<F, C, D>)>
|
) -> Result<(ProofWithPublicInputs<F, C, D>)>
|
||||||
{
|
{
|
||||||
let proof =
|
let proof =
|
||||||
self.prove_tree(proofs_with_pi, inner_verifier_only_data)?;
|
self.prove_tree(proofs_with_pi)?;
|
||||||
let mut pw = PartialWitness::<F>::new();
|
let mut pw = PartialWitness::<F>::new();
|
||||||
self.compression.assign_targets(&mut pw, &self.compression_targets, proof, &self.node_circ_data.verifier_only)?;
|
self.compression.assign_targets(&mut pw, &self.compression_targets, proof)?;
|
||||||
|
|
||||||
self.compression_circ_data.prove(pw).map_err(
|
self.compression_circ_data.prove(pw).map_err(
|
||||||
|e| CircuitError::InvalidProofError(e.to_string())
|
|e| CircuitError::InvalidProofError(e.to_string())
|
||||||
@ -125,7 +125,6 @@ impl<
|
|||||||
(
|
(
|
||||||
&mut self,
|
&mut self,
|
||||||
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
||||||
inner_verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Result<(ProofWithPublicInputs<F, C, D>)>
|
) -> Result<(ProofWithPublicInputs<F, C, D>)>
|
||||||
{
|
{
|
||||||
if proofs_with_pi.len() % 2 != 0 {
|
if proofs_with_pi.len() % 2 != 0 {
|
||||||
@ -137,12 +136,11 @@ impl<
|
|||||||
// process leaves
|
// process leaves
|
||||||
let leaf_proofs = self.get_leaf_proofs(
|
let leaf_proofs = self.get_leaf_proofs(
|
||||||
proofs_with_pi,
|
proofs_with_pi,
|
||||||
inner_verifier_only_data,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// process nodes
|
// process nodes
|
||||||
let (root_proof, vd) =
|
let (root_proof, _vd) =
|
||||||
self.prove(&leaf_proofs,&self.leaf_circ_data.verifier_only)?;
|
self.prove(&leaf_proofs,&self.leaf_circ_data.verifier_only, 0)?;
|
||||||
|
|
||||||
Ok(root_proof)
|
Ok(root_proof)
|
||||||
}
|
}
|
||||||
@ -151,7 +149,6 @@ impl<
|
|||||||
(
|
(
|
||||||
&mut self,
|
&mut self,
|
||||||
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
||||||
inner_verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
|
||||||
) -> Result<(Vec<ProofWithPublicInputs<F, C, D>>)> {
|
) -> Result<(Vec<ProofWithPublicInputs<F, C, D>>)> {
|
||||||
|
|
||||||
let mut leaf_proofs = vec![];
|
let mut leaf_proofs = vec![];
|
||||||
@ -159,7 +156,7 @@ impl<
|
|||||||
for proof in proofs_with_pi.chunks(N){
|
for proof in proofs_with_pi.chunks(N){
|
||||||
let mut pw = PartialWitness::<F>::new();
|
let mut pw = PartialWitness::<F>::new();
|
||||||
|
|
||||||
self.leaf.assign_targets(&mut pw,&self.leaf_targets,proof,inner_verifier_only_data)?;
|
self.leaf.assign_targets(&mut pw,&self.leaf_targets,proof)?;
|
||||||
let proof = self.leaf_circ_data.prove(pw).unwrap();
|
let proof = self.leaf_circ_data.prove(pw).unwrap();
|
||||||
leaf_proofs.push(proof);
|
leaf_proofs.push(proof);
|
||||||
}
|
}
|
||||||
@ -172,6 +169,7 @@ impl<
|
|||||||
&self,
|
&self,
|
||||||
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
|
||||||
verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
verifier_only_data: &VerifierOnlyCircuitData<C, D>,
|
||||||
|
level: usize,
|
||||||
) -> Result<(ProofWithPublicInputs<F, C, D>, VerifierOnlyCircuitData<C, D>)> where
|
) -> Result<(ProofWithPublicInputs<F, C, D>, VerifierOnlyCircuitData<C, D>)> where
|
||||||
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
|
||||||
{
|
{
|
||||||
@ -182,6 +180,8 @@ impl<
|
|||||||
|
|
||||||
let mut new_proofs = vec![];
|
let mut new_proofs = vec![];
|
||||||
|
|
||||||
|
let condition = if level == 0 {false} else {true};
|
||||||
|
|
||||||
for chunk in proofs_with_pi.chunks(M) {
|
for chunk in proofs_with_pi.chunks(M) {
|
||||||
|
|
||||||
let mut inner_pw = PartialWitness::new();
|
let mut inner_pw = PartialWitness::new();
|
||||||
@ -191,6 +191,7 @@ impl<
|
|||||||
&self.node_targets,
|
&self.node_targets,
|
||||||
chunk,
|
chunk,
|
||||||
verifier_only_data,
|
verifier_only_data,
|
||||||
|
condition
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let proof = self.node_circ_data.prove(inner_pw)
|
let proof = self.node_circ_data.prove(inner_pw)
|
||||||
@ -198,7 +199,7 @@ impl<
|
|||||||
new_proofs.push(proof);
|
new_proofs.push(proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.prove(&new_proofs, &self.node_circ_data.verifier_only)
|
self.prove(&new_proofs, &self.node_circ_data.verifier_only, level+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_proof(
|
pub fn verify_proof(
|
||||||
@ -219,18 +220,17 @@ impl<
|
|||||||
&self,
|
&self,
|
||||||
proof: ProofWithPublicInputs<F, C, D>,
|
proof: ProofWithPublicInputs<F, C, D>,
|
||||||
inner_public_input: Vec<Vec<F>>,
|
inner_public_input: Vec<Vec<F>>,
|
||||||
inner_verifier_data: &VerifierCircuitData<F, C, D>,
|
|
||||||
is_compressed: bool,
|
is_compressed: bool,
|
||||||
) -> Result<()>{
|
) -> Result<()>{
|
||||||
let public_input = proof.public_inputs.clone();
|
let public_input = proof.public_inputs.clone();
|
||||||
if is_compressed{
|
if is_compressed{
|
||||||
self.compression_circ_data.verify(proof)
|
self.compression_circ_data.verify(proof)
|
||||||
.map_err(|e| CircuitError::InvalidProofError(e.to_string()))?;
|
.map_err(|e| CircuitError::InvalidProofError(e.to_string()))?;
|
||||||
self.verify_public_input(public_input, inner_public_input, inner_verifier_data, is_compressed)
|
self.verify_public_input(public_input, inner_public_input)
|
||||||
}else {
|
}else {
|
||||||
self.node_circ_data.verify(proof)
|
self.node_circ_data.verify(proof)
|
||||||
.map_err(|e| CircuitError::InvalidProofError(e.to_string()))?;
|
.map_err(|e| CircuitError::InvalidProofError(e.to_string()))?;
|
||||||
self.verify_public_input(public_input, inner_public_input, inner_verifier_data, is_compressed)
|
self.verify_public_input(public_input, inner_public_input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,23 +238,15 @@ impl<
|
|||||||
&self,
|
&self,
|
||||||
public_input: Vec<F>,
|
public_input: Vec<F>,
|
||||||
inner_public_input: Vec<Vec<F>>,
|
inner_public_input: Vec<Vec<F>>,
|
||||||
inner_verifier_data: &VerifierCircuitData<F, C, D>,
|
|
||||||
is_compressed: bool,
|
|
||||||
) -> Result<()>{
|
) -> Result<()>{
|
||||||
assert_eq!(public_input.len(), 8);
|
assert_eq!(public_input.len(), 8);
|
||||||
|
|
||||||
let given_input_hash = &public_input[0..4];
|
let given_input_hash = &public_input[0..4];
|
||||||
let given_vd_hash = &public_input[4..8];
|
let given_vd_hash = &public_input[4..8];
|
||||||
|
|
||||||
let inner_hash = Self::get_hash_of_verifier_data(&inner_verifier_data);
|
let node_hash = get_hash_of_verifier_data::<F,D,C,H>(&self.node_circ_data.verifier_data());
|
||||||
|
|
||||||
let leaf_hash = Self::get_hash_of_verifier_data(&self.leaf_circ_data.verifier_data());
|
|
||||||
|
|
||||||
let node_hash = Self::get_hash_of_verifier_data(&self.node_circ_data.verifier_data());
|
|
||||||
|
|
||||||
|
|
||||||
let mut pub_in_hashes = vec![];
|
let mut pub_in_hashes = vec![];
|
||||||
let mut inner_vd_hashes = vec![];
|
|
||||||
for pub_in in inner_public_input.chunks(N){
|
for pub_in in inner_public_input.chunks(N){
|
||||||
let pub_in_flat: Vec<F> = pub_in
|
let pub_in_flat: Vec<F> = pub_in
|
||||||
.iter()
|
.iter()
|
||||||
@ -262,64 +254,50 @@ impl<
|
|||||||
.collect();
|
.collect();
|
||||||
let hash = H::hash_no_pad(&pub_in_flat);
|
let hash = H::hash_no_pad(&pub_in_flat);
|
||||||
pub_in_hashes.push(hash);
|
pub_in_hashes.push(hash);
|
||||||
inner_vd_hashes.push(inner_hash.clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut level = 0;
|
let mut level = 0;
|
||||||
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();
|
||||||
let mut next_level_vd_hashes = Vec::new();
|
for pi_chunk in pub_in_hashes.chunks(M) {
|
||||||
for (pi_chunk, vd_chunk) in pub_in_hashes.chunks(M).zip(inner_vd_hashes.chunks(M)) {
|
|
||||||
// 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())
|
||||||
.collect();
|
.collect();
|
||||||
let mut vd_chunk_f: Vec<F> = vd_chunk.iter()
|
// Compute hash of the concatenated chunk
|
||||||
.flat_map(|h| h.elements.iter().cloned())
|
|
||||||
.collect();
|
|
||||||
let hash_n = if level == 0 {leaf_hash} else{node_hash};
|
|
||||||
vd_chunk_f.extend_from_slice(&hash_n.elements);
|
|
||||||
|
|
||||||
// Compute Poseidon2 hash of the concatenated chunk
|
|
||||||
let pi_hash = H::hash_no_pad(&pi_chunk_f);
|
let pi_hash = H::hash_no_pad(&pi_chunk_f);
|
||||||
let vd_hash = H::hash_no_pad(&vd_chunk_f);
|
|
||||||
next_level_pi_hashes.push(pi_hash);
|
next_level_pi_hashes.push(pi_hash);
|
||||||
next_level_vd_hashes.push(vd_hash);
|
|
||||||
}
|
}
|
||||||
pub_in_hashes = next_level_pi_hashes;
|
pub_in_hashes = next_level_pi_hashes;
|
||||||
inner_vd_hashes = next_level_vd_hashes;
|
|
||||||
level +=1;
|
level +=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check expected hash
|
//check expected hash
|
||||||
let expected_pi_hash = pub_in_hashes[0];
|
let expected_pi_hash = pub_in_hashes[0];
|
||||||
let mut expected_vd_hash = inner_vd_hashes[0];
|
|
||||||
|
|
||||||
if is_compressed {
|
|
||||||
let mut vd_to_hash = vec![];
|
|
||||||
vd_to_hash.extend_from_slice(&expected_vd_hash.elements);
|
|
||||||
vd_to_hash.extend_from_slice(&node_hash.elements);
|
|
||||||
expected_vd_hash = H::hash_no_pad(&vd_to_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(given_input_hash, expected_pi_hash.elements);
|
assert_eq!(given_input_hash, expected_pi_hash.elements);
|
||||||
assert_eq!(given_vd_hash, expected_vd_hash.elements);
|
assert_eq!(given_vd_hash, node_hash.elements);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper fn to generate hash of verifier data
|
|
||||||
fn get_hash_of_verifier_data(verifier_data: &VerifierCircuitData<F, C, D>) -> HashOut<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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ mod tests {
|
|||||||
use crate::params::Params;
|
use crate::params::Params;
|
||||||
use codex_plonky2_circuits::recursion::uniform::{tree::TreeRecursion};
|
use codex_plonky2_circuits::recursion::uniform::{tree::TreeRecursion};
|
||||||
use codex_plonky2_circuits::recursion::uniform::pi_verifier::PublicInputVerificationCircuit;
|
use codex_plonky2_circuits::recursion::uniform::pi_verifier::PublicInputVerificationCircuit;
|
||||||
|
use codex_plonky2_circuits::recursion::uniform::tree::get_hash_of_verifier_data;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uniform_recursion() -> anyhow::Result<()> {
|
fn test_uniform_recursion() -> anyhow::Result<()> {
|
||||||
@ -42,25 +43,25 @@ mod tests {
|
|||||||
const N: usize = 1;
|
const N: usize = 1;
|
||||||
const M: usize = 2;
|
const M: usize = 2;
|
||||||
|
|
||||||
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(inner_data.common.clone())?;
|
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(inner_data.common.clone(), inner_data.verifier_only.clone())?;
|
||||||
|
|
||||||
let root = tree.prove_tree(&proofs, &inner_data.verifier_only)?;
|
let root = tree.prove_tree(&proofs)?;
|
||||||
println!("pub input size = {}", root.public_inputs.len());
|
println!("pub input size = {}", root.public_inputs.len());
|
||||||
println!("proof size = {:?} bytes", root.to_bytes().len());
|
println!("proof size = {:?} bytes", root.to_bytes().len());
|
||||||
|
|
||||||
let root_compressed = tree.prove_tree_and_compress(&proofs, &inner_data.verifier_only)?;
|
let root_compressed = tree.prove_tree_and_compress(&proofs)?;
|
||||||
println!("pub input size (compressed) = {}", root_compressed.public_inputs.len());
|
println!("pub input size (compressed) = {}", root_compressed.public_inputs.len());
|
||||||
println!("proof size compressed = {:?} bytes", root_compressed.to_bytes().len());
|
println!("proof size compressed = {:?} bytes", root_compressed.to_bytes().len());
|
||||||
|
|
||||||
let inner_pi: Vec<Vec<F>> = proofs.iter().map(|p| p.public_inputs.clone()).collect();
|
let inner_pi: Vec<Vec<F>> = proofs.iter().map(|p| p.public_inputs.clone()).collect();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
tree.verify_proof_and_public_input(root,inner_pi.clone(),&inner_data.verifier_data(), false).is_ok(),
|
tree.verify_proof_and_public_input(root,inner_pi.clone(), false).is_ok(),
|
||||||
"proof verification failed"
|
"proof verification failed"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
tree.verify_proof_and_public_input(root_compressed,inner_pi,&inner_data.verifier_data(), true).is_ok(),
|
tree.verify_proof_and_public_input(root_compressed,inner_pi, true).is_ok(),
|
||||||
"compressed proof verification failed"
|
"compressed proof verification failed"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -99,22 +100,22 @@ mod tests {
|
|||||||
const N: usize = 1;
|
const N: usize = 1;
|
||||||
const M: usize = 2;
|
const M: usize = 2;
|
||||||
|
|
||||||
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(inner_data.common.clone())?;
|
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(inner_data.common.clone(), inner_data.verifier_only.clone())?;
|
||||||
|
|
||||||
let root = tree.prove_tree(&proofs, &inner_data.verifier_only)?;
|
let root = tree.prove_tree(&proofs)?;
|
||||||
println!("pub input size = {}", root.public_inputs.len());
|
println!("pub input size = {}", root.public_inputs.len());
|
||||||
println!("proof size = {:?} bytes", root.to_bytes().len());
|
println!("proof size = {:?} bytes", root.to_bytes().len());
|
||||||
|
|
||||||
let inner_pi: Vec<Vec<F>> = proofs.iter().map(|p| p.public_inputs.clone()).collect();
|
let inner_pi: Vec<Vec<F>> = proofs.iter().map(|p| p.public_inputs.clone()).collect();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
tree.verify_proof_and_public_input(root.clone(),inner_pi.clone(),&inner_data.verifier_data(), false).is_ok(),
|
tree.verify_proof_and_public_input(root.clone(),inner_pi.clone(), false).is_ok(),
|
||||||
"proof verification failed"
|
"proof verification failed"
|
||||||
);
|
);
|
||||||
|
|
||||||
// ------------------- Public input verifier Circuit --------------------
|
// ------------------- Public input verifier Circuit --------------------
|
||||||
|
|
||||||
let pi_verifier_circ = PublicInputVerificationCircuit::<F, D, C, HF, N, M, T, K>::new(tree.get_node_common_data());
|
let pi_verifier_circ = PublicInputVerificationCircuit::<F, D, C, HF, N, M, T, K>::new(tree.get_node_common_data(), tree.get_node_verifier_data().verifier_only);
|
||||||
|
|
||||||
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);
|
||||||
@ -125,7 +126,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut pw = PartialWitness::<F>::new();
|
let mut pw = PartialWitness::<F>::new();
|
||||||
|
|
||||||
pi_verifier_circ.assign_targets(&mut pw, &pi_tarq, root, inner_pi.clone(), &tree.get_node_verifier_data(), &tree.get_leaf_verifier_data(), &inner_data.verifier_data())?;
|
pi_verifier_circ.assign_targets(&mut pw, &pi_tarq, root, inner_pi.clone())?;
|
||||||
|
|
||||||
let proof = pi_circ_data.prove(pw)?;
|
let proof = pi_circ_data.prove(pw)?;
|
||||||
println!("pub input size = {}", proof.public_inputs.len());
|
println!("pub input size = {}", proof.public_inputs.len());
|
||||||
@ -134,13 +135,20 @@ mod tests {
|
|||||||
let pub_input_flat: Vec<F> = inner_pi.iter().cloned().flatten().collect();
|
let pub_input_flat: Vec<F> = inner_pi.iter().cloned().flatten().collect();
|
||||||
let num_pi = proof.public_inputs.len();
|
let num_pi = proof.public_inputs.len();
|
||||||
|
|
||||||
// sanity check
|
// sanity check on public input
|
||||||
for (i, e) in proof.public_inputs.iter().enumerate(){
|
for (i, e) in proof.public_inputs.iter().enumerate(){
|
||||||
if i < pub_input_flat.len() {
|
if i < pub_input_flat.len() {
|
||||||
assert_eq!(*e, pub_input_flat[i])
|
assert_eq!(*e, pub_input_flat[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanity check on the verifier data
|
||||||
|
let hashed_node_vd = get_hash_of_verifier_data::<F,D,C,HF>(&tree.get_node_verifier_data());
|
||||||
|
for (i, &e) in proof.public_inputs[proof.public_inputs.len()-4 ..].iter().enumerate(){
|
||||||
|
assert_eq!(e, hashed_node_vd.elements[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
pi_circ_data.verify(proof).is_ok(),
|
pi_circ_data.verify(proof).is_ok(),
|
||||||
"pi-verifier proof verification failed"
|
"pi-verifier proof verification failed"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user