use bn::{arith, Fq, G1};
use sha2::{Digest, Sha256};
use crate::{
error::{Error, Result},
utils,
};
pub(crate) const LAST_MULTIPLE_OF_FQ_MODULUS_LOWER_THAN_2_256: arith::U256 = arith::U256([
0xf587_14d7_0a38_f4c2_2ca2_bc72_3a70_f263,
0xf1f5_883e_65f8_20d0_9991_5c90_8786_b9d3,
]);
pub(crate) fn hash_to_try_and_increment<T: AsRef<[u8]>>(message: T) -> Result<G1> {
let mut v = [message.as_ref(), &[0x00]].concat();
let position = v.len() - 1;
let point = (0..255).find_map(|ctr| {
v[position] = ctr;
let hash = Sha256::digest(&v);
let attempted_hash = arith::U256::from_slice(&hash).unwrap();
if attempted_hash >= LAST_MULTIPLE_OF_FQ_MODULUS_LOWER_THAN_2_256 {
return None;
}
let module_hash = utils::mod_u256(attempted_hash, Fq::modulus());
let mut s = [0u8; 32];
module_hash
.to_big_endian(&mut s)
.ok()
.and_then(|_| utils::arbitrary_string_to_g1(&s).ok())
});
point.ok_or(Error::HashToPointError)
}