sapling_crypto_ce/
baby_pedersen_hash.rs1use babyjubjub::*;
2use bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
3
4#[derive(Copy, Clone)]
5pub enum Personalization {
6 NoteCommitment,
7 MerkleTree(usize)
8}
9
10impl Personalization {
11 pub fn get_bits(&self) -> Vec<bool> {
12 match *self {
13 Personalization::NoteCommitment =>
14 vec![true, true, true, true, true, true],
15 Personalization::MerkleTree(num) => {
16 assert!(num < 62);
17
18 (0..6).map(|i| (num >> i) & 1 == 1).collect()
19 }
20 }
21 }
22}
23
24pub fn pedersen_hash<E, I>(
25 personalization: Personalization,
26 bits: I,
27 params: &E::Params
28) -> edwards::Point<E, PrimeOrder>
29 where I: IntoIterator<Item=bool>,
30 E: JubjubEngine
31{
32 let mut bits = personalization.get_bits().into_iter().chain(bits.into_iter());
33
34 let mut result = edwards::Point::zero();
35 let mut generators = params.pedersen_hash_exp_table().iter();
36
37 loop {
38 let mut acc = E::Fs::zero();
39 let mut cur = E::Fs::one();
40 let mut chunks_remaining = params.pedersen_hash_chunks_per_generator();
41 let mut encountered_bits = false;
42
43 while let Some(a) = bits.next() {
45 encountered_bits = true;
46
47 let b = bits.next().unwrap_or(false);
48 let c = bits.next().unwrap_or(false);
49
50 let mut tmp = cur;
52 if a {
53 tmp.add_assign(&cur);
54 }
55 cur.double(); if b {
57 tmp.add_assign(&cur);
58 }
59
60 if c {
62 tmp.negate();
63 }
64
65 acc.add_assign(&tmp);
66
67 chunks_remaining -= 1;
68
69 if chunks_remaining == 0 {
70 break;
71 } else {
72 cur.double(); cur.double(); cur.double(); }
76 }
77
78 if !encountered_bits {
79 break;
80 }
81
82 let mut table: &[Vec<edwards::Point<E, _>>] = &generators.next().expect("we don't have enough generators");
83 let window = JubjubBn256::pedersen_hash_exp_window_size();
84 let window_mask = (1 << window) - 1;
85
86 let mut acc = acc.into_repr();
87
88 let mut tmp = edwards::Point::zero();
89
90 while !acc.is_zero() {
91 let i = (acc.as_ref()[0] & window_mask) as usize;
92
93 tmp = tmp.add(&table[0][i], params);
94
95 acc.shr(window);
96 table = &table[1..];
97 }
98
99 result = result.add(&tmp, params);
100 }
101
102 result
103}