Skip to content

Commit

Permalink
Merge pull request #75 from brave-experiments/verification_scalars
Browse files Browse the repository at this point in the history
bulletproofs: add a VerificationScalars struct
  • Loading branch information
rillian authored Jul 23, 2024
2 parents d1a0502 + 0a14f3e commit ae866fd
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 26 deletions.
52 changes: 33 additions & 19 deletions bulletproofs/src/inner_product_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ pub struct InnerProductProof<G: AffineRepr> {
pub(crate) b: G::ScalarField,
}

/// Sequences of scalar values for verifying a proof
///
/// Using these is usually more efficient than calling
/// the `verify` method on the proof itself. See
/// https://doc-internal.dalek.rs/bulletproofs/inner_product_proof/
pub struct VerificationScalars<G: AffineRepr> {
/// $u^{+2}_0, \dots, u^{+2}_k$
pub challenges_sq: Vec<G::ScalarField>,
/// $u^{-2}_0, \dots, u^{-2}_k$
pub challenges_inv_sq: Vec<G::ScalarField>,
/// $s_0, \dots, s_{n-1}$
pub s: Vec<G::ScalarField>,
}

impl<G: AffineRepr> InnerProductProof<G> {
/// Create an inner-product proof.
///
Expand Down Expand Up @@ -245,14 +259,7 @@ impl<G: AffineRepr> InnerProductProof<G> {
&self,
n: usize,
transcript: &mut Transcript,
) -> Result<
(
Vec<G::ScalarField>,
Vec<G::ScalarField>,
Vec<G::ScalarField>,
),
ProofError,
> {
) -> Result<VerificationScalars<G>, ProofError> {
let lg_n = self.L_vec.len();
if lg_n >= 32 {
// 4 billion multiplications should be enough for anyone
Expand Down Expand Up @@ -310,14 +317,20 @@ impl<G: AffineRepr> InnerProductProof<G> {
s.push(s[i - k] * u_lg_i_sq);
}

Ok((challenges_sq, challenges_inv_sq, s))
Ok(VerificationScalars {
challenges_sq,
challenges_inv_sq,
s,
})
}

/// This method is for testing that proof generation work,
/// but for efficiency the actual protocols would use `verification_scalars`
/// method to combine inner product verification with other checks
/// in a single multiscalar multiplication.
#[allow(dead_code)]
/// Verify a generated proof
///
/// This method is convenient for testing, but for efficiency
/// the actual protocols would use the `verification_scalars`
/// method to combine inner product verification with other
/// checks in a single multiscalar multiplication.
#[allow(dead_code, clippy::too_many_arguments)]
pub fn verify<IG, IH>(
&self,
n: usize,
Expand All @@ -335,24 +348,25 @@ impl<G: AffineRepr> InnerProductProof<G> {
IH: IntoIterator,
IH::Item: Borrow<G::ScalarField>,
{
let (u_sq, u_inv_sq, s) = self.verification_scalars(n, transcript)?;
// Compute scalar sequences u_sq[i], u_inv_sq[i], s[i]
let scalars = self.verification_scalars(n, transcript)?;

let g_times_a_times_s = G_factors
.into_iter()
.zip(s.iter())
.zip(scalars.s.iter())
.map(|(g_i, s_i)| (self.a * s_i) * g_i.borrow())
.take(G.len());

// 1/s[i] is s[!i], and !i runs from n-1 to 0 as i runs from 0 to n-1
let inv_s = s.iter().rev();
let inv_s = scalars.s.iter().rev();

let h_times_b_div_s = H_factors
.into_iter()
.zip(inv_s)
.map(|(h_i, s_i_inv)| (self.b * s_i_inv) * h_i.borrow());

let neg_u_sq = u_sq.iter().map(|ui| ui.neg());
let neg_u_inv_sq = u_inv_sq.iter().map(|ui| ui.neg());
let neg_u_sq = scalars.challenges_sq.iter().map(|ui| ui.neg());
let neg_u_inv_sq = scalars.challenges_inv_sq.iter().map(|ui| ui.neg());

let Ls = &self.L_vec;
let Rs = &self.R_vec;
Expand Down
11 changes: 8 additions & 3 deletions bulletproofs/src/r1cs/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use super::{

use crate::errors::R1CSError;
use crate::generators::{BulletproofGens, PedersenGens};
use crate::inner_product_proof::VerificationScalars;
use crate::transcript::TranscriptProtocol;

/// A [`ConstraintSystem`] implementation for use by the verifier.
Expand Down Expand Up @@ -462,7 +463,11 @@ impl<G: AffineRepr, T: BorrowMut<Transcript>> Verifier<G, T> {
let (wL, wR, wO, wV, wc) = self.flattened_constraints(&z);

// Get IPP variables
let (u_sq, u_inv_sq, s) = proof
let VerificationScalars {
challenges_sq,
challenges_inv_sq,
s,
} = proof
.ipp_proof
.verification_scalars(padded_n, self.transcript.borrow_mut())
.map_err(|_| R1CSError::VerificationError)?;
Expand Down Expand Up @@ -535,8 +540,8 @@ impl<G: AffineRepr, T: BorrowMut<Transcript>> Verifier<G, T> {
scalars.push(*wVi * rxx);
}
scalars.extend_from_slice(&T_scalars);
scalars.extend_from_slice(&u_sq);
scalars.extend_from_slice(&u_inv_sq);
scalars.extend_from_slice(&challenges_sq);
scalars.extend_from_slice(&challenges_inv_sq);
Ok((self, scalars))
}

Expand Down
12 changes: 8 additions & 4 deletions bulletproofs/src/range_proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use merlin::Transcript;

use crate::errors::ProofError;
use crate::generators::{BulletproofGens, PedersenGens};
use crate::inner_product_proof::InnerProductProof;
use crate::inner_product_proof::{InnerProductProof, VerificationScalars};
use crate::transcript::TranscriptProtocol;
use crate::util;

Expand Down Expand Up @@ -344,7 +344,11 @@ impl<G: AffineRepr> RangeProof<G> {
// Challenge value for batching statements to be verified
let c = G::ScalarField::rand(rng);

let (mut x_sq, mut x_inv_sq, s) = self.ipp_proof.verification_scalars(n * m, transcript)?;
let VerificationScalars {
mut challenges_sq,
mut challenges_inv_sq,
s,
} = self.ipp_proof.verification_scalars(n * m, transcript)?;
let s_inv = s.iter().rev();

let a: G::ScalarField = self.ipp_proof.a;
Expand Down Expand Up @@ -381,8 +385,8 @@ impl<G: AffineRepr> RangeProof<G> {
c * x, // T_1
c * x * x,
]; //T_2
scalars.append(&mut x_sq); // L_vec TODO avoid append, better chaining iterators
scalars.append(&mut x_inv_sq); // R_vec
scalars.append(&mut challenges_sq); // L_vec TODO avoid append, better chaining iterators
scalars.append(&mut challenges_inv_sq); // R_vec
scalars.append(&mut value_commitment_scalars); //Value com
scalars.push(self.e_blinding.neg() - c * self.t_x_blinding); // B_blinding
scalars.push(basepoint_scalar); // B
Expand Down

0 comments on commit ae866fd

Please sign in to comment.