Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #10

Merged
merged 4 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ ark-serialize.workspace = true
fflonk.workspace = true
merlin.workspace = true
rayon = { workspace = true, optional = true }
rand_chacha = "0.3.1"

[dev-dependencies]
ark-ed-on-bls12-381-bandersnatch = { version = "0.4", default-features = false }
Expand Down
27 changes: 12 additions & 15 deletions common/src/gadgets/sw_cond_add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pub struct CondAdd<F: FftField, P: AffineRepr<BaseField=F>> {
points: AffineColumn<F, P>,
// The polynomial `X - w^{n-1}` in the Lagrange basis
not_last: FieldColumn<F>,
pub acc: AffineColumn<F, P>, // accumulates the (conditional) rolling sum of the points
// Accumulates the (conditional) rolling sum of the points
pub acc: AffineColumn<F, P>,
pub result: P,
}

Expand All @@ -60,29 +61,30 @@ impl<F, Curve> CondAdd<F, Affine<Curve>> where
F: FftField,
Curve: SWCurveConfig<BaseField=F>,
{
// Populates the acc column starting from the supplied initial point (as 0 doesn't have an affine representation).
// Populates the acc column starting from the supplied seed (as 0 doesn't have an affine SW representation).
// As the SW addition formula used is not complete, the seed must be selected in a way that would prevent
// exceptional cases (doublings or adding the opposite point).
// The last point of the input column is ignored, as adding it would made the acc column overflow due the initial point.
pub fn init(bitmask: BitColumn<F>,
points: AffineColumn<F, Affine<Curve>>,
seed: Affine<Curve>,
domain: &Domain<F>) -> Self {
assert_eq!(bitmask.bits.len(), domain.capacity - 1);
assert_eq!(points.points.len(), domain.capacity - 1);
let not_last = domain.not_last_row.clone();
let init = Self::point_in_g1_complement();
assert!(!init.is_zero());
let acc = bitmask.bits.iter()
.zip(points.points.iter())
.scan(init.clone(), |acc, (&b, point)| {
.scan(seed, |acc, (&b, point)| {
if b {
*acc = (*acc + point).into_affine();
}
Some(*acc)
});
let acc: Vec<_> = ark_std::iter::once(init)
let acc: Vec<_> = ark_std::iter::once(seed)
.chain(acc)
.collect();
let init_plus_result = acc.last().unwrap();
let result = init_plus_result.into_group() - init.into_group();
let result = init_plus_result.into_group() - seed.into_group();
let result = result.into_affine();
let acc = AffineColumn::init(acc, domain);

Expand All @@ -97,11 +99,6 @@ impl<F, Curve> CondAdd<F, Affine<Curve>> where
acc: self.acc.evaluate(z),
}
}

//TODO: find
pub fn point_in_g1_complement() -> Affine<Curve> {
Affine::<Curve>::generator()
}
}


Expand Down Expand Up @@ -261,15 +258,15 @@ mod tests {
let log_n = 10;
let n = 2usize.pow(log_n);
let domain = Domain::new(n, hiding);
let seed = SWAffine::generator();

let bitmask = random_bitvec(domain.capacity - 1, 0.5, rng);
let points = random_vec::<SWAffine, _>(domain.capacity - 1, rng);
let init = CondAdd::point_in_g1_complement();
let expected_res = init + cond_sum(&bitmask, &points);
let expected_res = seed + cond_sum(&bitmask, &points);

let bitmask_col = BitColumn::init(bitmask, &domain);
let points_col = AffineColumn::init(points, &domain);
let gadget = CondAdd::init(bitmask_col, points_col, &domain);
let gadget = CondAdd::init(bitmask_col, points_col, seed, &domain);
let res = gadget.acc.points.last().unwrap();
assert_eq!(res, &expected_res);

Expand Down
10 changes: 10 additions & 0 deletions common/src/transcript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use ark_ff::PrimeField;
use ark_poly::GeneralEvaluationDomain;
use ark_serialize::CanonicalSerialize;
use ark_std::{vec, vec::Vec};
use ark_std::rand::SeedableRng;
use fflonk::pcs::{PCS, PcsParams};
use rand_chacha::ChaCha20Rng;

use crate::{ColumnsCommited, ColumnsEvaluated};

Expand Down Expand Up @@ -60,6 +62,8 @@ pub trait Transcript<F: PrimeField, CS: PCS<F>>: Clone {
}

fn _add_serializable(&mut self, label: &'static [u8], message: &impl CanonicalSerialize);

fn to_rng(self) -> ChaCha20Rng;
}

impl<F: PrimeField, CS: PCS<F>> Transcript<F, CS> for merlin::Transcript {
Expand All @@ -74,4 +78,10 @@ impl<F: PrimeField, CS: PCS<F>> Transcript<F, CS> for merlin::Transcript {
message.serialize_uncompressed(&mut buf).unwrap();
self.append_message(label, &buf);
}

fn to_rng(mut self) -> ChaCha20Rng {
let mut buf = [0u8; 32];
self.challenge_bytes(b"transcript_rng", &mut buf);
ChaCha20Rng::from_seed(buf)
}
}
12 changes: 7 additions & 5 deletions common/src/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use ark_ff::{Field, PrimeField};
use ark_serialize::CanonicalSerialize;
use ark_std::test_rng;
use ark_std::{vec, vec::Vec};
use ark_std::rand::Rng;
use fflonk::pcs::{Commitment, PCS, PcsParams};
use rand_chacha::ChaCha20Rng;

use crate::{ColumnsCommited, ColumnsEvaluated, Proof};
use crate::piop::VerifierPiop;
Expand All @@ -29,11 +30,12 @@ impl<F: PrimeField, CS: PCS<F>, T: Transcript<F, CS>> PlonkVerifier<F, CS, T> {
}
}

pub fn verify<Piop, Commitments, Evaluations>(
pub fn verify<Piop, Commitments, Evaluations, R: Rng>(
&self,
piop: Piop,
proof: Proof<F, CS, Commitments, Evaluations>,
challenges: Challenges<F>,
rng: &mut R,
) -> bool
where
Piop: VerifierPiop<F, CS::C>,
Expand Down Expand Up @@ -63,7 +65,7 @@ impl<F: PrimeField, CS: PCS<F>, T: Transcript<F, CS>> PlonkVerifier<F, CS, T> {

let zeta_omega = zeta * domain_evaluated.omega();

CS::batch_verify(&self.pcs_vk, vec![cl, lin_comm], vec![challenges.zeta, zeta_omega], vec![agg_y, proof.lin_at_zeta_omega], vec![proof.agg_at_zeta_proof, proof.lin_at_zeta_omega_proof], &mut test_rng())
CS::batch_verify(&self.pcs_vk, vec![cl, lin_comm], vec![challenges.zeta, zeta_omega], vec![agg_y, proof.lin_at_zeta_omega], vec![proof.agg_at_zeta_proof, proof.lin_at_zeta_omega_proof], rng)
}

pub fn restore_challenges<Commitments, Evaluations>(
Expand All @@ -72,7 +74,7 @@ impl<F: PrimeField, CS: PCS<F>, T: Transcript<F, CS>> PlonkVerifier<F, CS, T> {
proof: &Proof<F, CS, Commitments, Evaluations>,
n_polys: usize,
n_constraints: usize,
) -> Challenges<F>//, TranscriptRng)
) -> (Challenges<F>, ChaCha20Rng)
where
Commitments: ColumnsCommited<F, CS::C>,
Evaluations: ColumnsEvaluated<F>,
Expand All @@ -92,7 +94,7 @@ impl<F: PrimeField, CS: PCS<F>, T: Transcript<F, CS>> PlonkVerifier<F, CS, T> {
zeta,
nus,
};
challenges //, fiat_shamir_rng(&mut transcript))
(challenges, transcript.to_rng())
}
}

Expand Down
1 change: 1 addition & 0 deletions ring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fflonk.workspace = true
merlin.workspace = true
rayon = { workspace = true, optional = true }
common = { path = "../common" }
blake2 = "0.10"

[dev-dependencies]
ark-bls12-381 = { version = "0.4", default-features = false, features = ["curve"] }
Expand Down
32 changes: 29 additions & 3 deletions ring/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![cfg_attr(not(feature = "std"), no_std)]

use ark_ec::short_weierstrass::{Affine, SWCurveConfig};
use ark_ff::{One, Zero};
use fflonk::pcs::PCS;

use common::Proof;
Expand All @@ -15,10 +17,23 @@ pub mod ring_verifier;

pub type RingProof<F, CS> = Proof<F, CS, RingCommitments<F, <CS as PCS<F>>::C>, RingEvaluations<F>>;

// Calling the method for a prime-order curve results in an infinite loop.
pub fn find_complement_point<Curve: SWCurveConfig>() -> Affine<Curve> {
let mut x = Curve::BaseField::zero();
loop {
let p = Affine::<Curve>::get_point_from_x_unchecked(x, false);
if p.is_some() && !p.unwrap().is_in_correct_subgroup_assuming_on_curve() {
return p.unwrap()
}
x = x + Curve::BaseField::one()
}
}

#[cfg(test)]
mod tests {
use ark_ec::CurveGroup;
use ark_ed_on_bls12_381_bandersnatch::{Fq, Fr, SWAffine};
use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, Fq, Fr, SWAffine};
use ark_ff::MontFp;
use ark_std::{end_timer, start_timer, test_rng, UniformRand};
use ark_std::rand::Rng;
use ark_std::ops::Mul;
Expand All @@ -27,6 +42,7 @@ mod tests {

use common::domain::Domain;
use common::test_helpers::*;
use crate::find_complement_point;

use crate::piop::params::PiopParams;
use crate::ring_prover::RingProver;
Expand All @@ -36,8 +52,10 @@ mod tests {
let rng = &mut test_rng();

// SETUP per curve and domain
let h = SWAffine::rand(rng);
let seed = find_complement_point::<BandersnatchConfig>();
let domain = Domain::new(domain_size, true);
let piop_params = PiopParams::setup(domain.clone(), &mut test_rng());
let piop_params = PiopParams::setup(domain.clone(), h, seed);

let setup_degree = 3 * domain_size;
let pcs_params = CS::setup(setup_degree, rng);
Expand All @@ -52,7 +70,7 @@ mod tests {

// PROOF generation
let secret = Fr::rand(rng); // prover's secret scalar
let result = piop_params.h.mul(secret) + pk;
let result = h.mul(secret) + pk;
let ring_prover = RingProver::init(prover_key, piop_params.clone(), k, Transcript::new(b"ring-vrf-test"));
let t_prove = start_timer!(|| "Prove");
let proof = ring_prover.prove(secret);
Expand All @@ -65,6 +83,14 @@ mod tests {
assert!(res);
}

#[test]
fn test_complement_point() {
let p = find_complement_point::<BandersnatchConfig>();
assert!(p.is_on_curve());
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
assert_eq!(p, SWAffine::new_unchecked(MontFp!("0"), MontFp!("11982629110561008531870698410380659621661946968466267969586599013782997959645")))
}

#[test]
fn test_ring_proof_kzg() {
_test_ring_proof::<fflonk::pcs::kzg::KZG<ark_bls12_381::Bls12_381>>(2usize.pow(10));
Expand Down
34 changes: 22 additions & 12 deletions ring/src/piop/params.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use ark_ec::{AffineRepr, CurveGroup, Group};
use ark_ec::short_weierstrass::{Affine, SWCurveConfig};
use ark_ff::{BigInteger, PrimeField};
use ark_std::rand::Rng;
use ark_std::UniformRand;
use ark_std::{vec, vec::Vec};
use ark_std::{rand, vec, vec::Vec};

use common::domain::Domain;
use common::gadgets::sw_cond_add::AffineColumn;
Expand All @@ -23,23 +21,23 @@ pub struct PiopParams<F: PrimeField, Curve: SWCurveConfig<BaseField=F>> {

// The blinding base, a point from jubjub.
pub h: Affine<Curve>,

// The point to start the summation from (as zero doesn't have a SW affine representation),
// should be from the jubjub prime-order subgroup complement.
pub seed: Affine<Curve>,
}

impl<F: PrimeField, Curve: SWCurveConfig<BaseField=F>> PiopParams<F, Curve> {
pub fn setup<R: Rng>(domain: Domain<F>, rng: &mut R) -> Self {
pub fn setup(domain: Domain<F>, h: Affine<Curve>, seed: Affine<Curve>) -> Self {
let scalar_bitlen = Curve::ScalarField::MODULUS_BIT_SIZE as usize;
// 1 accounts for the last cells of the points and bits columns that remain unconstrained
let keyset_part_size = domain.capacity - scalar_bitlen - 1;

let h = Affine::<Curve>::rand(rng);
// let powers_of_h = Self::power_of_2_multiples(scalar_bitlen, h.into_projective());
// let powers_of_h = CurveGroup::batch_normalization_into_affine(&powers_of_h);

Self {
domain,
scalar_bitlen,
keyset_part_size,
h,
seed,
}
}

Expand All @@ -53,7 +51,7 @@ impl<F: PrimeField, Curve: SWCurveConfig<BaseField=F>> PiopParams<F, Curve> {
pub fn points_column(&self, keys: &[Affine<Curve>]) -> AffineColumn<F, Affine<Curve>> {
assert!(keys.len() <= self.keyset_part_size);
let padding_len = self.keyset_part_size - keys.len();
let padding_point = Affine::<Curve>::generator(); //TODO!!!
let padding_point = hash_to_curve::<Affine<Curve>>(b"w3f/ring-proof/common/padding");
let padding = vec![padding_point; padding_len];
let points = [
keys,
Expand Down Expand Up @@ -89,9 +87,19 @@ impl<F: PrimeField, Curve: SWCurveConfig<BaseField=F>> PiopParams<F, Curve> {
}
}

// TODO: switch to better hash to curve when available
fn hash_to_curve<A: AffineRepr>(message: &[u8]) -> A {
use blake2::Digest;
use ark_std::rand::SeedableRng;

let seed = blake2::Blake2s::digest(message);
let rng = &mut rand::rngs::StdRng::from_seed(seed.into());
A::rand(rng)
}

#[cfg(test)]
mod tests {
use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, Fq, Fr};
use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, Fq, Fr, SWAffine};
use ark_std::{test_rng, UniformRand};
use ark_std::ops::Mul;

Expand All @@ -103,8 +111,10 @@ mod tests {
#[test]
fn test_powers_of_h() {
let rng = &mut test_rng();
let h = SWAffine::rand(rng);
let seed = SWAffine::rand(rng);
let domain = Domain::new(1024, false);
let params = PiopParams::<Fq, BandersnatchConfig>::setup(domain, rng);
let params = PiopParams::<Fq, BandersnatchConfig>::setup(domain, h, seed);
let t = Fr::rand(rng);
let t_bits = params.scalar_part(t);
let th = cond_sum(&t_bits, &params.power_of_2_multiples_of_h());
Expand Down
2 changes: 1 addition & 1 deletion ring/src/piop/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<F: PrimeField, Curve: SWCurveConfig<BaseField=F>> PiopProver<F, Curve>
let FixedColumns { points, ring_selector } = fixed_columns;
let bits = Self::bits_column(&params, prover_index_in_keys, secret);
let inner_prod = InnerProd::init(ring_selector.clone(), bits.col.clone(), &domain);
let cond_add = CondAdd::init(bits.clone(), points.clone(), &domain);
let cond_add = CondAdd::init(bits.clone(), points.clone(), params.seed, &domain);
let booleanity = Booleanity::init(bits.clone());
let cond_add_acc_x = FixedCells::init(cond_add.acc.xs.clone(), &domain);
let cond_add_acc_y = FixedCells::init(cond_add.acc.ys.clone(), &domain);
Expand Down
13 changes: 6 additions & 7 deletions ring/src/ring_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use ark_ff::PrimeField;
use fflonk::pcs::{PCS, RawVerifierKey};

use common::domain::EvaluatedDomain;
use common::gadgets::sw_cond_add::CondAdd;
use common::piop::VerifierPiop;
use common::verifier::PlonkVerifier;

Expand Down Expand Up @@ -33,27 +32,27 @@ impl<F: PrimeField, CS: PCS<F>, Curve: SWCurveConfig<BaseField=F>> RingVerifier<
}

pub fn verify_ring_proof(&self, proof: RingProof<F, CS>, result: Affine<Curve>) -> bool {
let challenges = self.plonk_verifier.restore_challenges(
let (challenges, mut rng) = self.plonk_verifier.restore_challenges(
&result,
&proof,
// '1' accounts for the quotient polynomial that is aggregated together with the columns
PiopVerifier::<F, CS::C>::N_COLUMNS + 1,
PiopVerifier::<F, CS::C>::N_CONSTRAINTS,
);
let init = CondAdd::<F, Affine<Curve>>::point_in_g1_complement();
let init_plus_result = (init + result).into_affine();
let seed = self.piop_params.seed;
let seed_plus_result = (seed + result).into_affine();
let domain_eval = EvaluatedDomain::new(self.piop_params.domain.domain(), challenges.zeta, self.piop_params.domain.hiding);

let piop = PiopVerifier::init(
domain_eval,
self.fixed_columns_committed.clone(),
proof.column_commitments.clone(),
proof.columns_at_zeta.clone(),
(init.x, init.y),
(init_plus_result.x, init_plus_result.y),
(seed.x, seed.y),
(seed_plus_result.x, seed_plus_result.y),
);

self.plonk_verifier.verify(piop, proof, challenges)
self.plonk_verifier.verify(piop, proof, challenges, &mut rng)
}

pub fn piop_params(&self) -> &PiopParams<F, Curve> {
Expand Down