Skip to content

Commit

Permalink
Add a GBP-custom batchVerifier
Browse files Browse the repository at this point in the history
Uses an explicit layout to deduplicate for the constant generators.
  • Loading branch information
kayabaNerve committed May 5, 2024
1 parent fd82807 commit f25f6e5
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 161 deletions.
11 changes: 7 additions & 4 deletions crypto/fcmps/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use zeroize::Zeroize;

use transcript::Transcript;

use multiexp::{BatchVerifier, multiexp};
use multiexp::multiexp;
use ciphersuite::{
group::{
ff::{Field, PrimeField, PrimeFieldBits},
Expand All @@ -15,7 +15,9 @@ use ciphersuite::{
};

use ec_divisors::{Poly, DivisorCurve, new_divisor};
use generalized_bulletproofs::{Generators, arithmetic_circuit_proof::ArithmeticCircuitProof};
use generalized_bulletproofs::{
Generators, BatchVerifier, arithmetic_circuit_proof::ArithmeticCircuitProof,
};

mod lincomb;
pub(crate) use lincomb::*;
Expand Down Expand Up @@ -414,6 +416,7 @@ pub struct Branches<
}

/// The full-chain membership proof.
#[derive(Clone)]
pub struct Fcmp<C1: Ciphersuite, C2: Ciphersuite> {
proof_1: ArithmeticCircuitProof<C1>,
proof_1_vcs: Vec<C1::G>,
Expand Down Expand Up @@ -786,8 +789,8 @@ where
self,
rng: &mut R,
transcript: &mut T,
verifier_1: &mut BatchVerifier<(), C1::G>,
verifier_2: &mut BatchVerifier<(), C2::G>,
verifier_1: &mut BatchVerifier<C1>,
verifier_2: &mut BatchVerifier<C2>,
params: &FcmpParams<T, C1, C2>,
tree: TreeRoot<C1, C2>,
layer_lens: Vec<usize>,
Expand Down
32 changes: 17 additions & 15 deletions crypto/fcmps/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use rand_core::OsRng;

use transcript::RecommendedTranscript;

use multiexp::{BatchVerifier, multiexp_vartime};
use multiexp::multiexp_vartime;
use ciphersuite::{group::Group, Ciphersuite, Ed25519, Selene, Helios};

use crate::*;
Expand Down Expand Up @@ -147,21 +147,23 @@ fn test() {
branches,
);

let mut verifier_1 = BatchVerifier::new(1);
let mut verifier_2 = BatchVerifier::new(1);
let mut verifier_1 = params.curve_1_generators.batch_verifier();
let mut verifier_2 = params.curve_2_generators.batch_verifier();

let instant = std::time::Instant::now();
proof.verify::<_, _, Ed25519>(
&mut OsRng,
&mut RecommendedTranscript::new(b"FCMP Test"),
&mut verifier_1,
&mut verifier_2,
&params,
root,
layer_lens,
input,
);
assert!(verifier_1.verify_vartime());
assert!(verifier_2.verify_vartime());
for _ in 0 .. 10 {
proof.clone().verify::<_, _, Ed25519>(
&mut OsRng,
&mut RecommendedTranscript::new(b"FCMP Test"),
&mut verifier_1,
&mut verifier_2,
&params,
root,
layer_lens.clone(),
input,
);
}
assert!(params.curve_1_generators.verify(verifier_1));
assert!(params.curve_2_generators.verify(verifier_2));
dbg!((std::time::Instant::now() - instant).as_millis());
}
86 changes: 41 additions & 45 deletions crypto/generalized-bulletproofs/src/arithmetic_circuit_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};

use transcript::Transcript;

use multiexp::{multiexp, BatchVerifier};
use multiexp::{multiexp, multiexp_vartime};
use ciphersuite::{
group::{
ff::{Field, PrimeField},
Expand All @@ -15,8 +15,8 @@ use ciphersuite::{

use crate::{
ScalarVector, ScalarMatrix, PointVector, ProofGenerators, PedersenCommitment,
PedersenVectorCommitment,
inner_product::{IpError, IpStatement, IpWitness, IpProof},
PedersenVectorCommitment, BatchVerifier,
inner_product::{IpError, IpStatement, IpWitness, IpProof, P},
};

/// Bulletproofs' Arithmetic Circuit Statement from 5.1, modified per Generalized Bulletproofs.
Expand Down Expand Up @@ -540,11 +540,11 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,
let ip_x = Self::transcript_tau_x_u_t_caret(transcript, tau_x, u, t_caret);
P_terms.push((ip_x * t_caret, self.generators.g()));
IpStatement::new_without_P_transcript(
self.generators.g_bold_slice(),
self.generators.h_bold_slice(),
self.generators,
y_inv,
self.generators.g() * ip_x,
P_terms,
ip_x,
// Safe since IpStatement isn't a ZK proof
P::ProverWithoutTranscript(multiexp_vartime(&P_terms)),
)
.unwrap()
.prove(transcript, IpWitness::new(l, r).unwrap())
Expand All @@ -557,7 +557,7 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,
pub fn verify<R: RngCore + CryptoRng>(
self,
rng: &mut R,
verifier: &mut BatchVerifier<(), C::G>,
verifier: &mut BatchVerifier<C>,
transcript: &mut T,
proof: ArithmeticCircuitProof<C>,
) -> Result<(), AcError> {
Expand Down Expand Up @@ -591,41 +591,39 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,

// Lines 88-90, modified per Generalized Bulletproofs as needed w.r.t. t
{
let mut lhs = vec![(proof.t_caret, self.generators.g()), (proof.tau_x, self.generators.h())];

let mut rhs = Vec::with_capacity(self.V.len() + t_poly_len);
rhs.push((x[ni] * (delta + z.inner_product(&self.c)), self.generators.g()));
let verifier_weight = C::F::random(&mut *rng);
// lhs of the equation, weighted to enable batch verification
verifier.g += proof.t_caret * verifier_weight;
verifier.h += proof.tau_x * verifier_weight;

// rhs of the equation, negated to cause a sum to zero
verifier.g -= verifier_weight * x[ni] * (delta + z.inner_product(&self.c));
let V_weights = self.WV.mul_vec(m, &z) * x[ni];
assert_eq!(V_weights.len(), self.V.len());
for pair in V_weights.0.into_iter().zip(self.V.0) {
rhs.push(pair);
verifier.additional.push((-verifier_weight * pair.0, pair.1));
}
for (i, T) in proof.T_before_ni.into_iter().enumerate() {
rhs.push((x[i], T));
verifier.additional.push((-verifier_weight * x[i], T));
}
for (i, T) in proof.T_after_ni.into_iter().enumerate() {
rhs.push((x[ni + 1 + i], T));
}

lhs.reserve(rhs.len());
for rhs in rhs {
lhs.push((-rhs.0, rhs.1));
verifier.additional.push((-verifier_weight * x[ni + 1 + i], T));
}
let check = lhs;

verifier.queue(rng, (), check);
}

let mut P_terms = {
let mut P_terms = vec![
(x[ilr], proof.AI),
(x[io], proof.AO),
// h' ** y is equivalent to h as h' is h ** y_inv
(-C::F::ONE, self.generators.h_sum()),
(x[is], proof.S),
];
P_terms.reserve((2 * n) + self.C.len() + 2);
let verifier_weight = C::F::random(&mut *rng);

// This following block effectively calculates P, within the multiexp
{
verifier.additional.push((verifier_weight * x[ilr], proof.AI));
verifier.additional.push((verifier_weight * x[io], proof.AO));
// h' ** y is equivalent to h as h' is h ** y_inv
let mut log2_n = 0;
while (1 << log2_n) != n {
log2_n += 1;
}
verifier.h_sum[log2_n] -= verifier_weight;
verifier.additional.push((verifier_weight * x[is], proof.S));

let mut h_bold_scalars = ScalarVector::new(n);
// Lines 85-87 calculate WL, WR, WO
Expand All @@ -635,7 +633,7 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,
h_bold_scalars = h_bold_scalars + &self.WO.mul_vec(n, &z);

for (i, wr) in (self.WR.mul_vec(n, &z) * &y_inv * x[jlr]).0.into_iter().enumerate() {
P_terms.push((wr, self.generators.g_bold(i)));
verifier.g_bold[i] += verifier_weight * wr;
}

// Push the terms for C, which increment from 0, and the terms for WC, which decrement from
Expand All @@ -646,32 +644,30 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,
i += 1;
}
let j = ni - i;
P_terms.push((x[i], C));
verifier.additional.push((verifier_weight * x[i], C));
h_bold_scalars = h_bold_scalars + &(WC.mul_vec(n, &z) * x[j]);
}

// All terms for h_bold here have actually been for h_bold', h_bold * y_inv
h_bold_scalars = h_bold_scalars * &y_inv;
for (i, scalar) in h_bold_scalars.0.into_iter().enumerate() {
P_terms.push((scalar, self.generators.h_bold(i)));
verifier.h_bold[i] += verifier_weight * scalar;
}

// Remove u * h
P_terms.push((-proof.u, self.generators.h()));

P_terms
};
// Remove u * h from P
verifier.h -= verifier_weight * proof.u;
}

// Prove for lines 88, 92 with an Inner-Product statement
// This inlines Protocol 1, as our IpStatement implements Protocol 2
let ip_x = Self::transcript_tau_x_u_t_caret(transcript, proof.tau_x, proof.u, proof.t_caret);
P_terms.push((ip_x * proof.t_caret, self.generators.g()));
// P is amended with this additional term
verifier.g += verifier_weight * ip_x * proof.t_caret;
IpStatement::new_without_P_transcript(
self.generators.g_bold_slice(),
self.generators.h_bold_slice(),
self.generators,
y_inv,
self.generators.g() * ip_x,
P_terms,
ip_x,
P::VerifierWithoutTranscript { verifier_weight },
)
.unwrap()
.verify(rng, verifier, transcript, proof.ip)
Expand Down
Loading

0 comments on commit f25f6e5

Please sign in to comment.