Skip to content

Commit

Permalink
feat: use precomputation for default commitments (#136)
Browse files Browse the repository at this point in the history
This work adds precomputation support for Pedersen commitments that use a provided generator. Basepoint tables are created via `lazy_static` alongside the generators themselves. When computing a commitment using the default generators, the corresponding tables are used. Commitments using any other generators are unchanged.

Closes [issue #135](#135).
  • Loading branch information
AaronFeickert authored Oct 25, 2022
1 parent 532ccc0 commit acdcee6
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 10 deletions.
33 changes: 33 additions & 0 deletions benches/commitment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2019. The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::time::Duration;

use criterion::{criterion_group, Criterion};
use rand::thread_rng;
use tari_crypto::{
commitment::HomomorphicCommitmentFactory,
keys::SecretKey,
ristretto::{
pedersen::commitment_factory::PedersenCommitmentFactory,
RistrettoSecretKey,
},
};

pub fn commit_default(c: &mut Criterion) {
let factory = PedersenCommitmentFactory::default();
let mut rng = thread_rng();

c.bench_function("commit_default key pair", |b| {
// Commitment value and mask
let v = RistrettoSecretKey::random(&mut rng);
let m = RistrettoSecretKey::random(&mut rng);
b.iter(|| factory.commit(&m, &v));
});
}

criterion_group!(
name = commitment;
config = Criterion::default().warm_up_time(Duration::from_millis(500));
targets = commit_default
);
4 changes: 3 additions & 1 deletion benches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

use criterion::criterion_main;

pub mod commitment;
pub mod range_proof;
pub mod signatures;

use commitment::commitment;
use range_proof::range_proofs;
use signatures::signatures;

criterion_main!(signatures, range_proofs);
criterion_main!(commitment, signatures, range_proofs);
32 changes: 24 additions & 8 deletions src/ristretto/constants.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
// Copyright 2019. The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

//! Constant [NUMS](https://tools.ietf.org/id/draft-black-numscurves-02.html) points for the Ristretto curve. There are 10 provided, but this library currently only
//! Constant [NUMS](https://www.ietf.org/archive/id/draft-black-numscurves-02.txt) points for the Ristretto curve. There are 10 provided, but this library currently only
//! uses the first
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint, RistrettoBasepointTable};

const NUMBER_NUMS_POINTS: usize = 10;

/// These points on the Ristretto curve have been created by hashing domain separation labels with SHA512 and converting
/// the hash output to a Ristretto generator point by using the byte string representation of the hash as input into the
/// `from_uniform_bytes` constructor in [RistrettoPoint](Struct.RistrettoPoint.html). This process is validated with the
/// `check_nums_points` test below.
pub const RISTRETTO_NUMS_POINTS_COMPRESSED: [CompressedRistretto; 10] = [
pub const RISTRETTO_NUMS_POINTS_COMPRESSED: [CompressedRistretto; NUMBER_NUMS_POINTS] = [
CompressedRistretto([
206, 56, 152, 65, 192, 200, 105, 138, 185, 91, 112, 36, 42, 238, 166, 72, 64, 177, 234, 197, 246, 68, 183, 208,
8, 172, 5, 135, 207, 71, 29, 112,
Expand Down Expand Up @@ -55,24 +57,27 @@ pub const RISTRETTO_NUMS_POINTS_COMPRESSED: [CompressedRistretto; 10] = [

lazy_static! {
/// A static array of pre-generated NUMS points
pub static ref RISTRETTO_NUMS_POINTS: [RistrettoPoint; 10] = {
let mut arr = [RistrettoPoint::default(); 10];
for i in 0..10 {
pub static ref RISTRETTO_NUMS_POINTS: [RistrettoPoint; NUMBER_NUMS_POINTS] = {
let mut arr = [RistrettoPoint::default(); NUMBER_NUMS_POINTS];
for i in 0..NUMBER_NUMS_POINTS {
arr[i] = RISTRETTO_NUMS_POINTS_COMPRESSED[i].decompress().unwrap();
}
arr
};

/// Precomputation table for the first point, which is used as the default commitment generator
pub static ref RISTRETTO_NUMS_TABLE_0: RistrettoBasepointTable = RistrettoBasepointTable::create(&RISTRETTO_NUMS_POINTS[0]);
}

#[cfg(test)]
mod test {
use curve25519_dalek::{
constants::{RISTRETTO_BASEPOINT_COMPRESSED, RISTRETTO_BASEPOINT_POINT},
ristretto::{CompressedRistretto, RistrettoPoint},
ristretto::{CompressedRistretto, RistrettoPoint}, scalar::Scalar, traits::Identity,
};
use sha2::{Digest, Sha512};

use crate::ristretto::constants::{RISTRETTO_NUMS_POINTS, RISTRETTO_NUMS_POINTS_COMPRESSED};
use crate::ristretto::constants::{RISTRETTO_NUMS_POINTS, RISTRETTO_NUMS_POINTS_COMPRESSED, RISTRETTO_NUMS_TABLE_0};

/// Generate a set of NUMS points by hashing domain separation labels and converting the hash output to a Ristretto
/// generator point. By using `RistrettoPoint::from_uniform_bytes`, the resulting point is a NUMS point if the input
Expand Down Expand Up @@ -116,4 +121,15 @@ mod test {
}
}
}

/// Check that precomputation works as expected
#[test]
pub fn check_tables() {
// Perform test multiplications
assert_eq!(&*RISTRETTO_NUMS_TABLE_0 * &Scalar::zero(), RistrettoPoint::identity());

for j in 0..15u8 {
assert_eq!(&*RISTRETTO_NUMS_TABLE_0 * &Scalar::from(j), RISTRETTO_NUMS_POINTS[0] * Scalar::from(j));
}
}
}
10 changes: 9 additions & 1 deletion src/ristretto/pedersen/commitment_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
//! Pedersen commitment types and factories for Ristretto
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_TABLE,
ristretto::RistrettoPoint,
traits::{Identity, MultiscalarMul},
};

use crate::{
commitment::{HomomorphicCommitment, HomomorphicCommitmentFactory},
ristretto::{
constants::RISTRETTO_NUMS_TABLE_0,
pedersen::{PedersenCommitment, RISTRETTO_PEDERSEN_G, RISTRETTO_PEDERSEN_H},
RistrettoPublicKey,
RistrettoSecretKey,
Expand Down Expand Up @@ -45,8 +47,14 @@ impl Default for PedersenCommitmentFactory {
impl HomomorphicCommitmentFactory for PedersenCommitmentFactory {
type P = RistrettoPublicKey;

#[allow(non_snake_case)]
fn commit(&self, k: &RistrettoSecretKey, v: &RistrettoSecretKey) -> PedersenCommitment {
let c = RistrettoPoint::multiscalar_mul(&[v.0, k.0], &[self.H, self.G]);
// If we're using the default generators, speed it up using precomputation tables
let c = if (self.G, self.H) == (RISTRETTO_PEDERSEN_G, *RISTRETTO_PEDERSEN_H) {
&RISTRETTO_BASEPOINT_TABLE * &k.0 + &*RISTRETTO_NUMS_TABLE_0 * &v.0
} else {
RistrettoPoint::multiscalar_mul(&[v.0, k.0], &[self.H, self.G])
};
HomomorphicCommitment(RistrettoPublicKey::new_from_pk(c))
}

Expand Down

0 comments on commit acdcee6

Please sign in to comment.