use crate::curve::{EmbeddedGroupAffine, outer};
use crate::curve::{FR_BYTES_STORED, Fr, embedded};
use crate::repr::{FieldRepr, FromFieldRepr};
pub use base_crypto::hash::{HashOutput, PERSISTENT_HASH_BYTES};
pub use base_crypto::repr::MemWrite;
use midnight_circuits::ecc::hash_to_curve::HashToCurveGadget;
use midnight_circuits::ecc::native::EccChip;
use midnight_circuits::hash::poseidon::PoseidonChip;
use midnight_circuits::instructions::HashToCurveCPU;
use midnight_circuits::instructions::hash::HashCPU;
use midnight_circuits::types::AssignedNative;
impl FieldRepr for HashOutput {
fn field_repr<W: MemWrite<Fr>>(&self, writer: &mut W) {
self.0.field_repr(writer);
}
fn field_size(&self) -> usize {
self.0.field_size()
}
}
impl FromFieldRepr for HashOutput {
const FIELD_SIZE: usize = <[u8; PERSISTENT_HASH_BYTES] as FromFieldRepr>::FIELD_SIZE;
fn from_field_repr(mut repr: &[Fr]) -> Option<Self> {
let size = <[u8; PERSISTENT_HASH_BYTES] as FromFieldRepr>::FIELD_SIZE;
if size > repr.len() {
return None;
}
let field_0 = <[u8; PERSISTENT_HASH_BYTES]>::from_field_repr(&repr[..size])?;
repr = &repr[size..];
if repr.is_empty() {
Some(HashOutput(field_0))
} else {
None
}
}
}
pub fn hash_to_field(data: &[u8]) -> Fr {
let mut preimage = vec![];
b"midnight:field_hash".field_repr(&mut preimage);
data.field_repr(&mut preimage);
transient_hash(&preimage)
}
pub fn upgrade_from_transient(transient: Fr) -> HashOutput {
let mut res = [0u8; PERSISTENT_HASH_BYTES];
res[..FR_BYTES_STORED].copy_from_slice(&transient.as_le_bytes()[..FR_BYTES_STORED]);
HashOutput(res)
}
pub fn degrade_to_transient(persistent: HashOutput) -> Fr {
persistent.field_vec()[1]
}
pub fn transient_hash(elems: &[Fr]) -> Fr {
let h = <PoseidonChip<outer::Scalar> as HashCPU<outer::Scalar, outer::Scalar>>::hash(
&elems.iter().map(|x| x.0).collect::<Vec<_>>(),
);
Fr(h)
}
pub fn transient_commit<T: FieldRepr + ?Sized>(value: &T, opening: Fr) -> Fr {
let mut preimage = vec![opening];
value.field_repr(&mut preimage);
transient_hash(&preimage)
}
pub fn hash_to_curve<T: FieldRepr + ?Sized>(value: &T) -> EmbeddedGroupAffine {
let preimage = value
.field_vec()
.into_iter()
.map(|f| f.0)
.collect::<Vec<_>>();
let point = <HashToCurveGadget<
outer::Scalar,
embedded::AffineExtended,
AssignedNative<outer::Scalar>,
PoseidonChip<outer::Scalar>,
EccChip<embedded::AffineExtended>,
> as HashToCurveCPU<embedded::AffineExtended, outer::Scalar>>::hash_to_curve(
&preimage
);
EmbeddedGroupAffine(point)
}