Skip to content

Commit

Permalink
Fix the TODOs.
Browse files Browse the repository at this point in the history
This commit breaks things up a bit: we now use one big
challenge (which is subdivided) to allow for proofs to be
conducted in parallel.
  • Loading branch information
joerowell committed Sep 8, 2023
1 parent 995c207 commit 7a676e4
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 104 deletions.
105 changes: 75 additions & 30 deletions pedersen/src/ec_point_add_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rand::{CryptoRng, RngCore};
use crate::{
mul_protocol::MulProof, opening_protocol::OpeningProof, pedersen_config::PedersenComm,
pedersen_config::PedersenConfig, transcript::ECPointAdditionTranscript,
transcript::EC_POINT_CHALLENGE_SIZE,
};

pub struct ECPointAddProof<P: PedersenConfig> {
Expand Down Expand Up @@ -45,7 +46,12 @@ pub struct ECPointAddProof<P: PedersenConfig> {
pub op: OpeningProof<P>,
}

impl<P: PedersenConfig> ECPointAddProof<P> {
impl<P: PedersenConfig> ECPointAddProof<P> {
/// This is just to circumvent an annoying issue with Rust's current generics system.
const MPSIZE: usize = MulProof::<P>::CHAL_SIZE;
const OPSIZE: usize = OpeningProof::<P>::CHAL_SIZE;
pub const CHAL_SIZE: usize = 3*Self::MPSIZE + Self::OPSIZE;

fn make_transcript(
transcript: &mut Transcript,
c1: &PedersenComm<P>,
Expand Down Expand Up @@ -115,32 +121,58 @@ impl<P: PedersenConfig> ECPointAddProof<P> {
let taua = <P as PedersenConfig>::from_ob_to_sf(tau);
let c7 = PedersenComm::new(taua, rng);

// Now commit to all of them.
// Now we begin the stage of incorporating everything into the
// transcript. We do this by creating the intermediates for each
// proof (which adds to the transcript in turn), before generating a long
// challenge (with enough space for each sub-proof). We then, finally,
// split up this challenge into smaller slices that can be used by each
// individual proof.
Self::make_transcript(transcript, &c1, &c2, &c3, &c4, &c5, &c6, &c7);

// And now we simply invoke each of the sub-protocols.
// TODO: shouldn't all of these proofs be done in parallel? Meaning using one long challenge..
let z1 = &c3 - &c1;
let z2 = &c4 - &c2;
let x1 = <P as PedersenConfig>::from_ob_to_sf(b_x - a_x);
let mp1 = MulProof::create(transcript, rng, &x1, &taua, &z1, &c7, &z2);

let z4 = &c1 + &c3 + &c5;
let mp2 = MulProof::create(transcript, rng, &taua, &taua, &c7, &c7, &z4);
assert!(mp2.alpha.is_on_curve());
assert!(mp2.beta.is_on_curve());
assert!(mp2.delta.is_on_curve());
// These are the temporaries for the first multiplication proof, which
// verifies that (b_x - a_x)*tau = b_y - a_y.
let z1 = &c3 - &c1; // This is the commitment for b_x - a_x.
let z2 = &c4 - &c2; // This is the commitment for b_y - a_y.

let x3 = <P as PedersenConfig>::from_ob_to_sf(a_x - t_x);

let z5 = &c1 - &c5;
let z6 = &c2 + &c6;
let mp3 = MulProof::create(transcript, rng, &taua, &x3, &c7, &z5, &z6);
let x1 = <P as PedersenConfig>::from_ob_to_sf(b_x - a_x);
let mpi1 = MulProof::create_intermediates(transcript, rng, &z1, &c7, &z2);

// These are the temporaries for the second multiplication proof, which verifies that
// tau^2 = a_x + b_x + t_x.
let z4 = &c1 + &c3 + &c5; // This is the commitment to a_x + b_x + t_x.
let mpi2 = MulProof::create_intermediates(transcript, rng, &c7, &c7, &z4);

// These are the temporaries for the third multiplication proof, which verifies that
// tau*(a_x - t_x) = a_y + t_y.
let x3 = <P as PedersenConfig>::from_ob_to_sf(a_x - t_x); // Value of a_x - t_x
let z5 = &c1 - &c5; // The commitment to a_x - t_x
let z6 = &c2 + &c6; // The commitment to a_y + t_y.
let mpi3 = MulProof::create_intermediates(transcript, rng, &c7, &z5, &z6);

// And, finally, the intermediates for the Opening proof.
// This proves that C2 opens to a_y.
let ay_sf = <P as PedersenConfig>::from_ob_to_sf(a_y);
let op = OpeningProof::create(transcript, rng, &ay_sf, &c2);

let opi = OpeningProof::create_intermediates(transcript, rng, &c2);

// Now we make a very large challenge and create the various proofs from the
// intermediates.
let chal_buf = ECPointAdditionTranscript::challenge_scalar(transcript, b"c");

// Make sure it all lines up.
assert!(Self::CHAL_SIZE == EC_POINT_CHALLENGE_SIZE);

// Make the sub-challenges.
let mp1chal = &chal_buf[0..Self::MPSIZE];
let mp2chal = &chal_buf[Self::MPSIZE..2*Self::MPSIZE];
let mp3chal = &chal_buf[2*Self::MPSIZE..3*Self::MPSIZE];
let opchal = &chal_buf[3*Self::MPSIZE..];

// And now we build the sub-proofs before returning.
let mp1 = MulProof::create_proof(&x1, &taua, &mpi1, &z1, &c7, &z2, mp1chal);
let mp2 = MulProof::create_proof(&taua, &taua, &mpi2, &c7, &c7, &z4, mp2chal);
let mp3 = MulProof::create_proof(&taua, &x3, &mpi3, &c7, &z5, &z6, mp3chal);
let op = OpeningProof::create_proof(&ay_sf, &opi, &c2, opchal);

// And now we just return.
Self {
c1: c1,
Expand All @@ -150,28 +182,41 @@ impl<P: PedersenConfig> ECPointAddProof<P> {
c5: c5,
c6: c6,
c7: c7,
mp1: mp1,
mp2: mp2,
mp3: mp3,
op: op,
mp1: mp1,
mp2: mp2,
mp3: mp3,
op: op,
}
}

pub fn verify(&self, transcript: &mut Transcript) -> bool {
Self::make_transcript(
transcript, &self.c1, &self.c2, &self.c3, &self.c4, &self.c5, &self.c6, &self.c7,
);

let z1 = &self.c3 - &self.c1;
let z2 = &self.c7;
let z3 = &self.c4 - &self.c2;
let z4 = &self.c1 + &self.c3 + &self.c5;
let z5 = &self.c1 - &self.c5;
let z6 = &self.c2 + &self.c6;

self.mp1.verify(transcript, &z1, &z2, &z3)
&& self.mp2.verify(transcript, &self.c7, &self.c7, &z4)
&& self.mp3.verify(transcript, &z2, &z5, &z6)
&& self.op.verify(transcript, &self.c2)
// Rebuild the rest of the transcript.
self.mp1.add_to_transcript(transcript, &z1, &z2, &z3);
self.mp2.add_to_transcript(transcript, &self.c7, &self.c7, &z4);
self.mp3.add_to_transcript(transcript, &z2, &z5, &z6);
self.op.add_to_transcript(transcript, &self.c2);

// Make the challenges and sub-challenges.
let chal_buf = ECPointAdditionTranscript::challenge_scalar(transcript, b"c");
let mp1chal = &chal_buf[0..Self::MPSIZE];
let mp2chal = &chal_buf[Self::MPSIZE..2*Self::MPSIZE];
let mp3chal = &chal_buf[2*Self::MPSIZE..3*Self::MPSIZE];
let opchal = &chal_buf[3*Self::MPSIZE..];

self.mp1.verify_with_challenge(&z1, &z2, &z3, mp1chal)
&& self.mp2.verify_with_challenge(&self.c7, &self.c7, &z4, mp2chal)
&& self.mp3.verify_with_challenge(&z2, &z5, &z6, mp3chal)
&& self.op.verify_with_challenge(&self.c2, opchal)
}
}
58 changes: 38 additions & 20 deletions pedersen/src/equality_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,30 @@ use ark_ec::{
short_weierstrass::{self as sw},
};

use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};

use ark_serialize::CanonicalSerialize;
use ark_std::{UniformRand, ops::Mul};
use rand::{RngCore, CryptoRng};

use crate::{transcript::EqualityTranscript, pedersen_config::PedersenConfig, pedersen_config::PedersenComm};
use crate::{transcript::EqualityTranscript, pedersen_config::PedersenConfig, pedersen_config::PedersenComm, transcript::CHALLENGE_SIZE};

pub struct EqualityProof<P: PedersenConfig> {
pub alpha: sw::Affine<P>,
pub z : <P as CurveConfig>::ScalarField,
}

pub struct EqualityProofIntermediate<P: PedersenConfig> {
pub r: <P as CurveConfig>::ScalarField,
pub alpha : sw::Affine<P>,
}

impl<P: PedersenConfig> EqualityProof<P> {
/// This is just to circumvent an annoying issue with Rust's current generics system.
pub const CHAL_SIZE: usize = CHALLENGE_SIZE;

pub fn add_to_transcript(&self, transcript: &mut Transcript, c1: &PedersenComm<P>, c2: &PedersenComm<P>) {
Self::make_transcript(transcript, c1, c2, &self.alpha)
}

fn make_transcript(transcript: &mut Transcript,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>,
Expand All @@ -40,38 +50,46 @@ impl<P: PedersenConfig> EqualityProof<P> {
transcript.append_point(b"alpha", &compressed_bytes[..]);
}

fn make_challenge(transcript: &mut Transcript) -> <P as CurveConfig>::ScalarField {
<P as CurveConfig>::ScalarField::deserialize_compressed(&transcript.challenge_scalar(b"c")[..]).unwrap()
}


pub fn create<T: RngCore + CryptoRng>(transcript: &mut Transcript,
pub fn create_intermediates<T: RngCore + CryptoRng>(transcript: &mut Transcript,
rng: &mut T,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>) -> EqualityProof<P> {
c2: &PedersenComm<P>) -> EqualityProofIntermediate<P> {

let r = <P as CurveConfig>::ScalarField::rand(rng);
let alpha = P::GENERATOR2.mul(r).into_affine();
Self::make_transcript(transcript, c1, c2, &alpha);
EqualityProofIntermediate {
r: r,
alpha: alpha
}
}

pub fn create<T: RngCore + CryptoRng>(transcript: &mut Transcript,
rng: &mut T,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>) -> Self {
Self::create_proof(&Self::create_intermediates(transcript, rng, c1, c2), c1, c2, &transcript.challenge_scalar(b"c")[..])
}

// Now make the challenge.
let chal = Self::make_challenge(transcript);
pub fn create_proof(inter: &EqualityProofIntermediate<P>, c1: &PedersenComm<P>, c2: &PedersenComm<P>, chal_buf: &[u8]) -> Self {

let z = chal * (c1.r - c2.r) + r;
let chal = <P as PedersenConfig>::make_challenge_from_buffer(chal_buf);
let z = chal * (c1.r - c2.r) + inter.r;
EqualityProof {
alpha: alpha,
alpha: inter.alpha,
z: z
}
}

pub fn verify(&self, transcript: &mut Transcript, c1: &PedersenComm<P>, c2: &PedersenComm<P>) -> bool {
// Make the transcript.
Self::make_transcript(transcript, c1, c2, &self.alpha);

// Now make the challenge and check.
let chal = Self::make_challenge(transcript);
self.add_to_transcript(transcript, c1, c2);
self.verify_with_challenge(c1, c2, &transcript.challenge_scalar(b"c")[..])
}

P::GENERATOR2.mul(self.z) == (c1.comm - c2.comm).mul(chal) + self.alpha
pub fn verify_with_challenge(&self, c1: &PedersenComm<P>, c2: &PedersenComm<P>, chal_buf: &[u8]) -> bool {
let chal = <P as PedersenConfig>::make_challenge_from_buffer(chal_buf);
P::GENERATOR2.mul(self.z) == (c1.comm - c2.comm).mul(chal) + self.alpha
}
}

78 changes: 57 additions & 21 deletions pedersen/src/mul_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use ark_ec::{
short_weierstrass::{self as sw},
};

use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
use ark_serialize::CanonicalSerialize;
use ark_std::{UniformRand, ops::Mul};
use rand::{RngCore, CryptoRng};

use crate::{transcript::MulTranscript, pedersen_config::PedersenConfig, pedersen_config::PedersenComm};
use crate::{transcript::MulTranscript, pedersen_config::PedersenConfig, pedersen_config::PedersenComm, transcript::CHALLENGE_SIZE};

pub struct MulProof<P: PedersenConfig> {
pub alpha: sw::Affine<P>,
Expand All @@ -27,8 +27,28 @@ pub struct MulProof<P: PedersenConfig> {
pub z5: <P as CurveConfig>::ScalarField,
}

pub struct MulProofIntermediate<P: PedersenConfig> {
pub alpha: sw::Affine<P>,
pub beta: sw::Affine<P>,
pub delta: sw::Affine<P>,

pub b1: <P as CurveConfig>::ScalarField,
pub b2: <P as CurveConfig>::ScalarField,
pub b3: <P as CurveConfig>::ScalarField,
pub b4: <P as CurveConfig>::ScalarField,
pub b5: <P as CurveConfig>::ScalarField,
}

impl <P: PedersenConfig> MulProof<P> {
/// This is just to circumvent an annoying issue with Rust's current generics system.
pub const CHAL_SIZE: usize = CHALLENGE_SIZE;

pub fn add_to_transcript(&self, transcript: &mut Transcript, c1: &PedersenComm<P>,
c2: &PedersenComm<P>,
c3: &PedersenComm<P>) {
Self::make_transcript(transcript, c1, c2, c3, &self.alpha, &self.beta, &self.delta)
}

fn make_transcript(transcript: &mut Transcript,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>,
Expand Down Expand Up @@ -60,20 +80,22 @@ impl <P: PedersenConfig> MulProof<P> {
delta.serialize_compressed(&mut compressed_bytes).unwrap();
transcript.append_point(b"delta", &compressed_bytes[..]);
}


fn make_challenge(transcript: &mut Transcript) -> <P as CurveConfig>::ScalarField {
<P as CurveConfig>::ScalarField::deserialize_compressed(&transcript.challenge_scalar(b"c")[..]).unwrap()
}

pub fn create<T: RngCore + CryptoRng>(transcript: &mut Transcript,
rng: &mut T,
x: &<P as CurveConfig>::ScalarField,
y: &<P as CurveConfig>::ScalarField,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>,
c3: &PedersenComm<P>) -> Self {
c3: &PedersenComm<P>) -> Self {
Self::create_proof(x, y, &Self::create_intermediates(transcript, rng, c1, c2, c3), c1, c2, c3, &transcript.challenge_scalar(b"c")[..])
}

pub fn create_intermediates<T: RngCore + CryptoRng>(transcript: &mut Transcript,
rng: &mut T,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>,
c3: &PedersenComm<P>) -> MulProofIntermediate<P> {
// Generate the random values.
let b1 = <P as CurveConfig>::ScalarField::rand(rng);
let b2 = <P as CurveConfig>::ScalarField::rand(rng);
Expand All @@ -87,25 +109,39 @@ impl <P: PedersenConfig> MulProof<P> {

Self::make_transcript(transcript, c1, c2, c3, &alpha, &beta, &delta);

// Now make the challenge.
let chal = Self::make_challenge(transcript);

MulProofIntermediate { b1: b1, b2: b2, b3: b3, b4: b4, b5: b5, alpha: alpha, beta: beta, delta: delta }
}

pub fn create_proof(x: &<P as CurveConfig>::ScalarField, y: &<P as CurveConfig>::ScalarField,
inter: &MulProofIntermediate<P>,
c1: &PedersenComm<P>,
c2: &PedersenComm<P>,
c3: &PedersenComm<P>,
chal_buf: &[u8]) -> Self {

// Make the challenge itself.
let chal = <P as PedersenConfig>::make_challenge_from_buffer(chal_buf);

Self {
alpha: alpha,
beta: beta,
delta: delta,
z1: b1 + (chal * (x)),
z2: b2 + (chal * c1.r),
z3: b3 + (chal * (y)),
z4: b4 + (chal * c2.r),
z5: b5 + chal * (c3.r - (c1.r*(y)))
alpha: inter.alpha,
beta: inter.beta,
delta: inter.delta,
z1: inter.b1 + (chal * (x)),
z2: inter.b2 + (chal * c1.r),
z3: inter.b3 + (chal * (y)),
z4: inter.b4 + (chal * c2.r),
z5: inter.b5 + chal * (c3.r - (c1.r*(y)))
}
}

pub fn verify(&self, transcript: &mut Transcript, c1: &PedersenComm<P>, c2: &PedersenComm<P>, c3: &PedersenComm<P>) -> bool {
Self::make_transcript(transcript, c1, c2, c3, &self.alpha, &self.beta, &self.delta);
let chal = Self::make_challenge(transcript);

self.verify_with_challenge(c1, c2, c3, &transcript.challenge_scalar(b"c")[..])
}


pub fn verify_with_challenge(&self, c1: &PedersenComm<P>, c2: &PedersenComm<P>, c3: &PedersenComm<P>, chal_buf: &[u8]) -> bool {
let chal = <P as PedersenConfig>::make_challenge_from_buffer(chal_buf);
(self.alpha + c1.comm.mul(chal) == P::GENERATOR.mul(self.z1) + P::GENERATOR2.mul(self.z2)) &&
(self.beta + c2.comm.mul(chal) == P::GENERATOR.mul(self.z3) + P::GENERATOR2.mul(self.z4)) &&
(self.delta + c3.comm.mul(chal) == c1.comm.mul(self.z3) + P::GENERATOR2.mul(self.z5))
Expand Down
Loading

0 comments on commit 7a676e4

Please sign in to comment.