mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-08-01 12:51:30 +00:00
Move Jubjub, Pedersen hash and primitives into zcash_primitives
This commit is contained in:
103
zcash_primitives/src/pedersen_hash.rs
Normal file
103
zcash_primitives/src/pedersen_hash.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use jubjub::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Personalization {
|
||||
NoteCommitment,
|
||||
MerkleTree(usize)
|
||||
}
|
||||
|
||||
impl Personalization {
|
||||
pub fn get_bits(&self) -> Vec<bool> {
|
||||
match *self {
|
||||
Personalization::NoteCommitment =>
|
||||
vec![true, true, true, true, true, true],
|
||||
Personalization::MerkleTree(num) => {
|
||||
assert!(num < 63);
|
||||
|
||||
(0..6).map(|i| (num >> i) & 1 == 1).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pedersen_hash<E, I>(
|
||||
personalization: Personalization,
|
||||
bits: I,
|
||||
params: &E::Params
|
||||
) -> edwards::Point<E, PrimeOrder>
|
||||
where I: IntoIterator<Item=bool>,
|
||||
E: JubjubEngine
|
||||
{
|
||||
let mut bits = personalization.get_bits().into_iter().chain(bits.into_iter());
|
||||
|
||||
let mut result = edwards::Point::zero();
|
||||
let mut generators = params.pedersen_hash_exp_table().iter();
|
||||
|
||||
loop {
|
||||
let mut acc = E::Fs::zero();
|
||||
let mut cur = E::Fs::one();
|
||||
let mut chunks_remaining = params.pedersen_hash_chunks_per_generator();
|
||||
let mut encountered_bits = false;
|
||||
|
||||
// Grab three bits from the input
|
||||
while let Some(a) = bits.next() {
|
||||
encountered_bits = true;
|
||||
|
||||
let b = bits.next().unwrap_or(false);
|
||||
let c = bits.next().unwrap_or(false);
|
||||
|
||||
// Start computing this portion of the scalar
|
||||
let mut tmp = cur;
|
||||
if a {
|
||||
tmp.add_assign(&cur);
|
||||
}
|
||||
cur.double(); // 2^1 * cur
|
||||
if b {
|
||||
tmp.add_assign(&cur);
|
||||
}
|
||||
|
||||
// conditionally negate
|
||||
if c {
|
||||
tmp.negate();
|
||||
}
|
||||
|
||||
acc.add_assign(&tmp);
|
||||
|
||||
chunks_remaining -= 1;
|
||||
|
||||
if chunks_remaining == 0 {
|
||||
break;
|
||||
} else {
|
||||
cur.double(); // 2^2 * cur
|
||||
cur.double(); // 2^3 * cur
|
||||
cur.double(); // 2^4 * cur
|
||||
}
|
||||
}
|
||||
|
||||
if !encountered_bits {
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
Reference in New Issue
Block a user