frost_bluepallas/
hasher.rs1use alloc::string::String;
4use ark_ff::PrimeField;
5use frost_core::Field;
6use mina_hasher::{create_legacy, Hashable, Hasher, ROInput};
7
8use crate::PallasScalarField;
9
10#[derive(Clone, Debug)]
13pub(crate) struct PallasHashElement<'a> {
14 value: &'a [&'a [u8]],
15}
16
17impl Hashable for PallasHashElement<'_> {
19 type D = ();
20
21 fn to_roinput(&self) -> ROInput {
22 let mut roi = ROInput::new();
23
24 for val in self.value {
25 roi = roi.append_bytes(val);
26 }
27
28 roi
29 }
30
31 fn domain_string(_domain_param: Self::D) -> Option<String> {
33 None
34 }
35}
36
37type Fq = <PallasScalarField as Field>::Scalar;
38
39pub fn hash_to_scalar(input: &[&[u8]]) -> Fq {
41 let wrap = PallasHashElement { value: input };
42 let mut hasher = create_legacy::<PallasHashElement>(());
43
44 Fq::from(hasher.hash(&wrap).into_bigint())
48}
49
50pub fn hash_to_array(input: &[&[u8]]) -> <PallasScalarField as frost_core::Field>::Serialization {
52 let scalar = hash_to_scalar(input);
53
54 PallasScalarField::serialize(&scalar)
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_hash_to_scalar_is_deterministic_and_differs() {
63 let input = &[&b"abc"[..]];
64 let s1 = hash_to_scalar(input);
65 let s2 = hash_to_scalar(input);
66 assert_eq!(s1, s2, "same input must yield same scalar");
67
68 let other = &[&b"def"[..]];
69 let s3 = hash_to_scalar(other);
70 assert_ne!(s1, s3, "different input must yield a different scalar");
71 }
72
73 #[test]
74 fn test_hash_to_array_length() {
75 let arr = hash_to_array(&[&b"hello"[..]]);
76 assert_eq!(arr.len(), 32);
78 }
79}