Skip to content

Commit

Permalink
Add h_bold_weights to the Inner-Product statement
Browse files Browse the repository at this point in the history
  • Loading branch information
kayabaNerve committed May 1, 2024
1 parent 494f3d2 commit 23d59c7
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 34 deletions.
24 changes: 5 additions & 19 deletions crypto/generalized-bulletproofs/src/arithmetic_circuit_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,22 +511,19 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,
let ip = {
// P = t_caret * g + l * g_bold + r * (y_inv * h_bold)

let mut hi = vec![]; // y_inv * h_bold
let mut P_terms = Vec::with_capacity(1 + (2 * self.generators.len()));
for (i, (l, r)) in l.0.iter().zip(r.0.iter()).enumerate() {
P_terms.push((*l, self.generators.g_bold(i)));

let new_hi = self.generators.h_bold(i) * y_inv[i];
P_terms.push((*r, new_hi));
hi.push(new_hi);
P_terms.push((y_inv[i] * r, self.generators.h_bold(i)));
}

// Protocol 1, inlined, since our IpStatement is for Protocol 2
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(),
&hi,
self.generators.h_bold_slice(),
y_inv,
self.generators.g() * ip_x,
P_terms,
)
Expand Down Expand Up @@ -573,18 +570,6 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,

let x = Self::transcript_Ts(transcript, &proof.T_before_ni, &proof.T_after_ni);

// h' is described as the inverted powers of y * h_bold
// We keep it in terms of the discrete logarithm to save on intermediary group operations
// TODO let hi = y_inv.clone()
let hi = {
let mut hi = vec![];
for i in 0 .. n {
hi.push(self.generators.h_bold(i) * y_inv[i]);
}
debug_assert_eq!(self.generators.h_bold(0), hi[0]);
PointVector::<C>(hi)
};

// 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())];
Expand Down Expand Up @@ -660,7 +645,8 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ArithmeticCircuitStatement<'a,
P_terms.push((ip_x * proof.t_caret, self.generators.g()));
IpStatement::new_without_P_transcript(
self.generators.g_bold_slice(),
&hi.0,
self.generators.h_bold_slice(),
y_inv,
self.generators.g() * ip_x,
P_terms,
)
Expand Down
46 changes: 34 additions & 12 deletions crypto/generalized-bulletproofs/src/inner_product.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub struct IpStatement<'a, C: Ciphersuite> {
g_bold: &'a [C::G],
// h
h_bold: &'a [C::G],
// Weights for h_bold
h_bold_weights: ScalarVector<C::F>,
// u
u: C::G,
// P
Expand Down Expand Up @@ -86,36 +88,53 @@ pub struct IpProof<C: Ciphersuite> {
impl<'a, C: Ciphersuite> IpStatement<'a, C> {
/// Create a new Inner-Product statement.
///
/// The generators are not transcripted. If your generators are variable, independently
/// transcript them.
pub fn new(g_bold: &'a [C::G], h_bold: &'a [C::G], u: C::G, P: C::G) -> Result<Self, IpError> {
/// `h_bold_weights` is weights for `h_bold` making the effective `h_bold`
/// `h_bold_weights * h_bold`, while remaining in terms of `h_bold`.
///
/// The generators are not transcripted (nor weights for the generators). If your generators are
/// variable, independently transcript them. If your weights aren't deterministic to the
/// transcript, independently transcript them.
pub fn new(
g_bold: &'a [C::G],
h_bold: &'a [C::G],
h_bold_weights: ScalarVector<C::F>,
u: C::G,
P: C::G,
) -> Result<Self, IpError> {
if g_bold.len() != h_bold.len() {
Err(IpError::IncorrectAmountOfGenerators)?
}
Ok(Self { g_bold, h_bold, u, P: P::Point(P) })
if g_bold.len() != h_bold_weights.len() {
Err(IpError::IncorrectAmountOfGenerators)?
}
Ok(Self { g_bold, h_bold, h_bold_weights, u, P: P::Point(P) })
}

/// Create a new Inner-Product statement which won't transcript P.
///
/// This MUST only be called when P is deterministic to already transcripted elements.
///
/// The generators are not transcripted. If your generators are variable, independently
/// transcript them.
/// The generators are not transcripted (nor weights for the generators). If your generators are
/// variable, independently transcript them. If your weights aren't deterministic to the
/// transcript, independently transcript them.
pub(crate) fn new_without_P_transcript(
g_bold: &'a [C::G],
h_bold: &'a [C::G],
h_bold_weights: ScalarVector<C::F>,
u: C::G,
P: Vec<(C::F, C::G)>,
) -> Result<Self, IpError> {
if g_bold.len() != h_bold.len() {
Err(IpError::IncorrectAmountOfGenerators)?
}
Ok(Self { g_bold, h_bold, u, P: P::Terms(P) })
if g_bold.len() != h_bold_weights.len() {
Err(IpError::IncorrectAmountOfGenerators)?
}
Ok(Self { g_bold, h_bold, h_bold_weights, u, P: P::Terms(P) })
}

fn initial_transcript<T: Transcript>(&mut self, transcript: &mut T) {
transcript.domain_separate(b"inner_product");
transcript.append_message(b"u", self.u.to_bytes());
// If P is a point, transcript it
// If P is terms, as it will be if this was constructed by `new_without_P_transcript`, P
// is expected to be deterministic to already transcripted items (and therefore not need
Expand Down Expand Up @@ -152,15 +171,15 @@ impl<'a, C: Ciphersuite> IpStatement<'a, C> {
self.initial_transcript(transcript);

let (mut g_bold, mut h_bold, u, mut P, mut a, mut b) = {
let IpStatement { g_bold, h_bold, u, P } = self;
let IpStatement { g_bold, h_bold, h_bold_weights, u, P } = self;

// Ensure we have the exact amount of generators
if g_bold.len() != witness.a.len() {
Err(IpError::IncorrectAmountOfGenerators)?;
}
// Acquire a local copy of the generators
let g_bold = PointVector::<C>(g_bold.to_vec());
let h_bold = PointVector::<C>(h_bold.to_vec());
let h_bold = PointVector::<C>(h_bold.to_vec()).mul_vec(&h_bold_weights);

let IpWitness { a, b } = witness;

Expand Down Expand Up @@ -329,7 +348,7 @@ impl<'a, C: Ciphersuite> IpStatement<'a, C> {
) -> Result<(), IpError> {
self.initial_transcript(transcript);

let IpStatement { g_bold, h_bold, u, P } = self;
let IpStatement { g_bold, h_bold, h_bold_weights, u, P } = self;

// Verify the L/R lengths
{
Expand Down Expand Up @@ -411,7 +430,10 @@ impl<'a, C: Ciphersuite> IpStatement<'a, C> {
}
// The h_bold * b term case from line 16
for i in 0 .. g_bold.len() {
multiexp.push((-(product_cache[product_cache.len() - 1 - i] * proof.b), h_bold[i]));
multiexp.push((
-(product_cache[product_cache.len() - 1 - i] * proof.b * h_bold_weights[i]),
h_bold[i],
));
}
// The c * u term case from line 16
multiexp.push((-c, u));
Expand Down
1 change: 0 additions & 1 deletion crypto/generalized-bulletproofs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ impl<'a, T: 'static + Transcript, C: Ciphersuite> ProofGenerators<'a, T, C> {
self.g_bold
}

#[cfg(test)]
pub(crate) fn h_bold_slice(&self) -> &[C::G] {
self.h_bold
}
Expand Down
4 changes: 2 additions & 2 deletions crypto/generalized-bulletproofs/src/point_vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite};
#[cfg(test)]
use multiexp::multiexp;

// use crate::ScalarVector;
use crate::ScalarVector;

/// A point vector struct with the functionality necessary for Bulletproofs.
///
Expand Down Expand Up @@ -74,6 +74,7 @@ impl<C: Ciphersuite> PointVector<C> {
}
res
}
*/

pub(crate) fn mul_vec(&self, vector: &ScalarVector<C::F>) -> Self {
assert_eq!(self.len(), vector.len());
Expand All @@ -83,7 +84,6 @@ impl<C: Ciphersuite> PointVector<C> {
}
res
}
*/

#[cfg(test)]
pub(crate) fn multiexp(&self, vector: &crate::ScalarVector<C::F>) -> C::G {
Expand Down
2 changes: 2 additions & 0 deletions crypto/generalized-bulletproofs/src/tests/inner_product.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fn test_zero_inner_product() {
let statement = IpStatement::<Ristretto>::new(
reduced.g_bold_slice(),
reduced.h_bold_slice(),
ScalarVector(vec![<Ristretto as Ciphersuite>::F::ONE; 1]),
generators.g(),
P,
)
Expand Down Expand Up @@ -74,6 +75,7 @@ fn test_inner_product() {
let statement = IpStatement::<Ristretto>::new(
generators.g_bold_slice(),
generators.h_bold_slice(),
ScalarVector(vec![<Ristretto as Ciphersuite>::F::ONE; i]),
generators.g(),
P,
)
Expand Down

0 comments on commit 23d59c7

Please sign in to comment.