Skip to content

Commit

Permalink
plonk: proof-system: proof-linking: Impl serialization for LinkingProof
Browse files Browse the repository at this point in the history
  • Loading branch information
joeykraut committed Jan 26, 2024
1 parent 0ce6a9c commit 8fd52e2
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 5 deletions.
1 change: 1 addition & 0 deletions plonk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ ark-ed-on-bn254 = "0.4.0"
criterion = { version = "0.5", features = ["async", "async_tokio"] }
hex = "^0.4.3"
lazy_static = "1.4"
serde_json = "1.0"
tokio = "1.33"

# Benchmarks
Expand Down
59 changes: 55 additions & 4 deletions plonk/src/proof_system/proof_linking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use ark_ec::{
};
use ark_ff::{Field, One, Zero};
use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use jf_primitives::{
pcs::{
prelude::{Commitment, UnivariateKzgPCS, UnivariateKzgProof},
Expand All @@ -19,6 +20,7 @@ use mpc_relation::{
gadgets::ecc::SWToTEConParam,
proof_linking::{GroupLayout, PROOF_LINK_WIRE_IDX},
};
use serde::{ser::SerializeSeq, Deserialize, Serialize};

use crate::{errors::PlonkError, transcript::PlonkTranscript};

Expand All @@ -28,14 +30,42 @@ use super::{
};

/// A proof that two circuits are linked on a given domain
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)]
pub struct LinkingProof<E: Pairing> {
/// The commitment to the linking quotient polynomial
pub quotient_commitment: Commitment<E>,
/// The proof of opening of the linking identity polynomial
pub opening_proof: UnivariateKzgProof<E>,
}

impl<E: Pairing> Serialize for LinkingProof<E> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut bytes = Vec::new();
self.serialize_compressed(&mut bytes).map_err(serde::ser::Error::custom)?;

// Serialize explicitly as a sequence to avoid issues with certain serde
// formats, e.g. flexbuffers
let mut seq = serializer.serialize_seq(Some(bytes.len()))?;
for byte in bytes.iter() {
seq.serialize_element(byte)?;
}
seq.end()
}
}

impl<'de, E: Pairing> Deserialize<'de> for LinkingProof<E> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bytes = <Vec<u8>>::deserialize(deserializer)?;
Self::deserialize_compressed(bytes.as_slice()).map_err(serde::de::Error::custom)
}
}

// ----------
// | Prover |
// ----------
Expand Down Expand Up @@ -407,8 +437,10 @@ pub mod test_helpers {
#[cfg(test)]
mod test {
use ark_bn254::{Bn254, Fr as FrBn254};
use ark_ec::pairing::Pairing;
use ark_std::UniformRand;
use itertools::Itertools;
use jf_primitives::pcs::prelude::UnivariateKzgProof;
use mpc_relation::{
proof_linking::{GroupLayout, LinkableCircuit},
PlonkCircuit,
Expand All @@ -424,9 +456,12 @@ mod test {
transcript::SolidityTranscript,
};

use super::test_helpers::{
gen_commit_keys, gen_proving_keys, gen_test_circuit1, gen_test_circuit2, CircuitSelector,
GROUP_NAME,
use super::{
test_helpers::{
gen_commit_keys, gen_proving_keys, gen_test_circuit1, gen_test_circuit2,
CircuitSelector, GROUP_NAME,
},
LinkingProof,
};

// -----------
Expand Down Expand Up @@ -493,6 +528,22 @@ mod test {
// | Test Cases |
// --------------

/// Tests serialization and deserialization of a linking proof
#[test]
fn test_serde() {
let mut rng = thread_rng();
let commitment = <Bn254 as Pairing>::G1Affine::rand(&mut rng).into();
let opening = UnivariateKzgProof { proof: <Bn254 as Pairing>::G1Affine::rand(&mut rng) };

let proof =
LinkingProof::<Bn254> { quotient_commitment: commitment, opening_proof: opening };

let bytes = serde_json::to_vec(&proof).unwrap();
let recovered = serde_json::from_slice(&bytes).unwrap();

assert_eq!(proof, recovered);
}

/// Tests a linking proof between two circuits that correctly use the same
/// values in the linking domain
#[test]
Expand Down
54 changes: 53 additions & 1 deletion plonk/src/proof_system/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use mpc_relation::{
},
PlonkCircuit,
};
use serde::{ser::SerializeSeq, Deserialize, Serialize};
use tagged_base64::tagged;

/// Universal StructuredReferenceString
Expand Down Expand Up @@ -87,14 +88,42 @@ pub struct Proof<E: Pairing> {
///
/// The linking hint contains information about the prover's witness needed to
/// link the proof to another proof of a different circuit
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
pub struct LinkingHint<E: Pairing> {
/// The wire polynomial that encodes the proof-linking gates for the circuit
pub linking_wire_poly: DensePolynomial<E::ScalarField>,
/// The commitment to the linking wire poly generated while proving
pub linking_wire_comm: Commitment<E>,
}

impl<E: Pairing> Serialize for LinkingHint<E> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut bytes = Vec::new();
self.serialize_compressed(&mut bytes).map_err(serde::ser::Error::custom)?;

// Serialize explicitly as a sequence to avoid issues with certain serde
// formats, e.g. flexbuffers
let mut seq = serializer.serialize_seq(Some(bytes.len()))?;
for byte in bytes.iter() {
seq.serialize_element(byte)?;
}
seq.end()
}
}

impl<'de, E: Pairing> Deserialize<'de> for LinkingHint<E> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bytes = <Vec<u8>>::deserialize(deserializer)?;
Self::deserialize_compressed(bytes.as_slice()).map_err(serde::de::Error::custom)
}
}

impl<E, P> TryFrom<Vec<E::BaseField>> for Proof<E>
where
E: Pairing<G1Affine = Affine<P>>,
Expand Down Expand Up @@ -931,6 +960,29 @@ mod test {
use super::*;
use ark_bn254::{g1::Config, Bn254, Fq};
use ark_ec::AffineRepr;
use ark_poly::DenseUVPolynomial;
use ark_std::UniformRand;
use itertools::Itertools;
use rand::thread_rng;

/// Test `LinkingHint` serde
#[test]
fn test_link_hint_serde() {
const N_COEFFS: usize = 10;
let mut rng = thread_rng();

let coeffs =
(0..N_COEFFS).map(|_| <Bn254 as Pairing>::ScalarField::rand(&mut rng)).collect_vec();
let poly = DensePolynomial::from_coefficients_vec(coeffs);
let comm = Commitment(<Bn254 as Pairing>::G1Affine::rand(&mut rng));

let hint = LinkingHint::<Bn254> { linking_wire_poly: poly, linking_wire_comm: comm };

let bytes = serde_json::to_vec(&hint).unwrap();
let recovered = serde_json::from_slice(&bytes).unwrap();

assert_eq!(hint, recovered);
}

#[test]
fn test_group_to_field() {
Expand Down

0 comments on commit 8fd52e2

Please sign in to comment.