Skip to content

Commit

Permalink
Change pedersen hash outside the circuit to use window table lookups.
Browse files Browse the repository at this point in the history
  • Loading branch information
ebfull committed Jul 30, 2018
1 parent c2862a4 commit 821810c
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 3 deletions.
23 changes: 23 additions & 0 deletions benches/pedersen_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![feature(test)]

extern crate rand;
extern crate test;
extern crate pairing;
extern crate sapling_crypto;

use rand::{Rand, thread_rng};
use pairing::bls12_381::Bls12;
use sapling_crypto::jubjub::JubjubBls12;
use sapling_crypto::pedersen_hash::{pedersen_hash, Personalization};

#[bench]
fn bench_pedersen_hash(b: &mut test::Bencher) {
let params = JubjubBls12::new();
let rng = &mut thread_rng();
let bits = (0..510).map(|_| bool::rand(rng)).collect::<Vec<_>>();
let personalization = Personalization::MerkleTree(31);

b.iter(|| {
pedersen_hash::<Bls12, _>(personalization, bits.clone(), &params)
});
}
49 changes: 49 additions & 0 deletions src/jubjub/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ pub trait JubjubParams<E: JubjubEngine>: Sized {
fn scale(&self) -> &E::Fr;
/// Returns the generators (for each segment) used in all Pedersen commitments.
fn pedersen_hash_generators(&self) -> &[edwards::Point<E, PrimeOrder>];
/// Returns the exp table for Pedersen hashes.
fn pedersen_hash_exp_table(&self) -> &[Vec<Vec<edwards::Point<E, PrimeOrder>>>];
/// Returns the maximum number of chunks per segment of the Pedersen hash.
fn pedersen_hash_chunks_per_generator(&self) -> usize;
/// Returns the pre-computed window tables [-4, 3, 2, 1, 1, 2, 3, 4] of different
Expand All @@ -126,6 +128,9 @@ pub trait JubjubParams<E: JubjubEngine>: Sized {
/// Returns a window table [0, 1, ..., 8] for different magnitudes of some
/// fixed generator.
fn circuit_generators(&self, FixedGenerators) -> &[Vec<(E::Fr, E::Fr)>];
/// Returns the window size for exponentiation of Pedersen hash generators
/// outside the circuit
fn pedersen_hash_exp_window_size() -> u32;
}

impl JubjubEngine for Bls12 {
Expand All @@ -140,6 +145,7 @@ pub struct JubjubBls12 {
scale: Fr,

pedersen_hash_generators: Vec<edwards::Point<Bls12, PrimeOrder>>,
pedersen_hash_exp: Vec<Vec<Vec<edwards::Point<Bls12, PrimeOrder>>>>,
pedersen_circuit_generators: Vec<Vec<Vec<(Fr, Fr)>>>,

fixed_base_generators: Vec<edwards::Point<Bls12, PrimeOrder>>,
Expand All @@ -154,6 +160,9 @@ impl JubjubParams<Bls12> for JubjubBls12 {
fn pedersen_hash_generators(&self) -> &[edwards::Point<Bls12, PrimeOrder>] {
&self.pedersen_hash_generators
}
fn pedersen_hash_exp_table(&self) -> &[Vec<Vec<edwards::Point<Bls12, PrimeOrder>>>] {
&self.pedersen_hash_exp
}
fn pedersen_hash_chunks_per_generator(&self) -> usize {
63
}
Expand All @@ -171,6 +180,9 @@ impl JubjubParams<Bls12> for JubjubBls12 {
{
&self.fixed_base_circuit_generators[base as usize][..]
}
fn pedersen_hash_exp_window_size() -> u32 {
8
}
}

impl JubjubBls12 {
Expand All @@ -191,6 +203,7 @@ impl JubjubBls12 {

// We'll initialize these below
pedersen_hash_generators: vec![],
pedersen_hash_exp: vec![],
pedersen_circuit_generators: vec![],
fixed_base_generators: vec![],
fixed_base_circuit_generators: vec![],
Expand Down Expand Up @@ -258,6 +271,42 @@ impl JubjubBls12 {
tmp_params.pedersen_hash_generators = pedersen_hash_generators;
}

// Create the exp table for the Pedersen hash generators
{
let mut pedersen_hash_exp = vec![];

for g in &tmp_params.pedersen_hash_generators {
let mut g = g.clone();

let window = JubjubBls12::pedersen_hash_exp_window_size();

let mut tables = vec![];

let mut num_bits = 0;
while num_bits <= fs::Fs::NUM_BITS {
let mut table = Vec::with_capacity(1 << window);

let mut base = edwards::Point::zero();

for _ in 0..(1 << window) {
table.push(base.clone());
base = base.add(&g, &tmp_params);
}

tables.push(table);
num_bits += window;

for _ in 0..window {
g = g.double(&tmp_params);
}
}

pedersen_hash_exp.push(tables);
}

tmp_params.pedersen_hash_exp = pedersen_hash_exp;
}

// Create the bases for other parts of the protocol
{
let mut fixed_base_generators = vec![edwards::Point::zero(); FixedGenerators::Max as usize];
Expand Down
22 changes: 19 additions & 3 deletions src/pedersen_hash.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use jubjub::*;
use pairing::*;

#[derive(Copy, Clone)]
pub enum Personalization {
NoteCommitment,
MerkleTree(usize)
Expand Down Expand Up @@ -31,7 +32,7 @@ pub fn pedersen_hash<E, I>(
let mut bits = personalization.get_bits().into_iter().chain(bits.into_iter());

let mut result = edwards::Point::zero();
let mut generators = params.pedersen_hash_generators().iter();
let mut generators = params.pedersen_hash_exp_table().iter();

loop {
let mut acc = E::Fs::zero();
Expand Down Expand Up @@ -78,8 +79,23 @@ pub fn pedersen_hash<E, I>(
break;
}

let mut tmp = generators.next().expect("we don't have enough generators").clone();
tmp = tmp.mul(acc, params);
let mut table: &[Vec<edwards::Point<E, _>>] = &generators.next().expect("we don't have enough generators");
let window = JubjubBls12::pedersen_hash_exp_window_size();
let window_mask = (1 << window) - 1;

let mut acc = acc.into_repr();

let mut tmp = edwards::Point::zero();

while !acc.is_zero() {
let i = (acc.as_ref()[0] & window_mask) as usize;

tmp = tmp.add(&table[0][i], params);

acc.shr(window);
table = &table[1..];
}

result = result.add(&tmp, params);
}

Expand Down

0 comments on commit 821810c

Please sign in to comment.