use starknet_curve::{curve_params, AffinePoint, ProjectivePoint};
use starknet_ff::FieldElement;
use crate::pedersen_points::*;
const SHIFT_POINT: ProjectivePoint = ProjectivePoint::from_affine_point(&curve_params::SHIFT_POINT);
pub fn pedersen_hash(x: &FieldElement, y: &FieldElement) -> FieldElement {
let x = x.to_bits_le();
let y = y.to_bits_le();
let table_size = (1 << CURVE_CONSTS_BITS) - 1;
let add_points = |acc: &mut ProjectivePoint, bits: &[bool], prep: &[AffinePoint]| {
bits.chunks(CURVE_CONSTS_BITS)
.enumerate()
.for_each(|(i, v)| {
let offset = v
.iter()
.rev()
.fold(0, |acc, &bit| (acc << 1) + bit as usize);
if offset > 0 {
*acc += &prep[i * table_size + offset - 1];
}
});
};
let mut acc = SHIFT_POINT;
add_points(&mut acc, &x[..248], &CURVE_CONSTS_P0); add_points(&mut acc, &x[248..252], &CURVE_CONSTS_P1); add_points(&mut acc, &y[..248], &CURVE_CONSTS_P2); add_points(&mut acc, &y[248..252], &CURVE_CONSTS_P3); AffinePoint::from(&acc).x
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::field_element_from_be_hex;
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn test_pedersen_hash() {
let test_data = [
(
"03d937c035c878245caf64531a5756109c53068da139362728feb561405371cb",
"0208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a",
"030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662",
),
(
"058f580910a6ca59b28927c08fe6c43e2e303ca384badc365795fc645d479d45",
"078734f65a067be9bdb39de18434d71e79f7b6466a4b66bbd979ab9e7515fe0b",
"068cc0b76cddd1dd4ed2301ada9b7c872b23875d5ff837b3a87993e0d9996b87",
),
];
for (in1, in2, expected_hash) in test_data.into_iter() {
let in1 = field_element_from_be_hex(in1);
let in2 = field_element_from_be_hex(in2);
let expected_hash = field_element_from_be_hex(expected_hash);
assert_eq!(pedersen_hash(&in1, &in2), expected_hash);
}
}
}