Last active
November 11, 2021 15:14
-
-
Save DrPeterVanNostrand/552ae2d08a0beb01d6919006caf53d0e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use blstrs::Scalar as Fr; | |
use halo::pasta::{Fp, Fq as Fv}; | |
// more imports... | |
lazy_static! { | |
pub static ref BLS_P_MINUS_1: [u8; 32] = (-Fr::one()).to_repr(); | |
pub static ref PALLAS_P_MINUS_1: [u8; 32] = (-Fp::one()).to_repr(); | |
pub static ref VESTA_P_MINUS_1: [u8; 32] = (-Fv::one()).to_repr(); | |
pub static ref POSEIDON_CONSTANTS_PALLAS_2: PoseidonConstants::<Fp, U2> = PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_PALLAS_4: PoseidonConstants::<Fp, U4> = PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_PALLAS_8: PoseidonConstants::<Fp, U8> = PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_PALLAS_16: PoseidonConstants::<Fp, U16> = PoseidonConstants::new(); | |
pub static ref POSEIDON_MD_CONSTANTS_PALLAS: PoseidonConstants::<Fp, PoseidonMDArity> = | |
PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_VESTA_2: PoseidonConstants::<Fv, U2> = PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_VESTA_4: PoseidonConstants::<Fv, U4> = PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_VESTA_8: PoseidonConstants::<Fv, U8> = PoseidonConstants::new(); | |
pub static ref POSEIDON_CONSTANTS_VESTA_16: PoseidonConstants::<Fv, U16> = PoseidonConstants::new(); | |
pub static ref POSEIDON_MD_CONSTANTS_VESTA: PoseidonConstants::<Fv, PoseidonMDArity> = | |
PoseidonConstants::new(); | |
} | |
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | |
enum FieldName { | |
Bls, | |
Pallas, | |
Vesta, | |
} | |
#[inline] | |
fn field_name<F: PrimeField<Repr = [u8; 32]>>() -> FieldName { | |
let p_minus_1 = (-F::one()).to_repr(); | |
if p_minus_1 == *BLS_P_MINUS_1 { | |
FieldName::Bls | |
} else if p_minus_1 == *PALLAS_P_MINUS_1 { | |
FieldName::Pallas | |
} else if p_minus_1 == *VESTA_P_MINUS_1 { | |
FieldName::Vesta | |
} else { | |
unimplemented!("provided field is not BLS12-381, Pallas, or Vesta scalar field"); | |
} | |
} | |
// Convert a field element from type `F1` to `F2`. | |
fn f1_into_f2<F1, F2>(f: F1) -> F2 | |
where | |
F1: PrimeField<Repr = [u8; 32]>, | |
F2: PrimeField<Repr = [u8; 32]>, | |
{ | |
debug_assert_eq!(field_name::<F1>(), field_name::<F2>()); | |
let mut repr_out = <F2 as PrimeField>::Repr::default(); | |
repr_out.as_mut().copy_from_slice(f.to_repr().as_ref()); | |
F2::from_repr_vartime(repr_out).unwrap() | |
} | |
fn poseidon<F: PrimeField<Repr = [u8; 32]>>(preimage: &[F]) -> F { | |
match field_name::<F>() { | |
FieldName::Bls => { | |
let preimage: Vec<Fr> = preimage.iter().copied().map(f1_into_f2::<F, Fr>).collect(); | |
let digest: Fr = match preimage.len() { | |
2 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_2).hash(), | |
4 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_4).hash(), | |
8 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_8).hash(), | |
16 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_16).hash(), | |
_ => unimplemented!("preimage length is not supported"), | |
}; | |
f1_into_f2::<Fr, F>(digest) | |
} | |
FieldName::Pallas => { | |
let preimage: Vec<Fp> = preimage.iter().copied().map(f1_into_f2::<F, Fp>).collect(); | |
let digest: Fp = match preimage.len() { | |
2 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_PALLAS_2).hash(), | |
4 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_PALLAS_4).hash(), | |
8 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_PALLAS_8).hash(), | |
16 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_PALLAS_16).hash(), | |
_ => unimplemented!("preimage length is not supported"), | |
}; | |
f1_into_f2::<Fp, F>(digest) | |
} | |
FieldName::Vesta => { | |
let preimage: Vec<Fv> = preimage.iter().copied().map(f1_into_f2::<F, Fv>).collect(); | |
let digest: Fv = match preimage.len() { | |
2 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_VESTA_2).hash(), | |
4 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_VESTA_4).hash(), | |
8 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_VESTA_8).hash(), | |
16 => Poseidon::new_with_preimage(&preimage, &*POSEIDON_CONSTANTS_VESTA_16).hash(), | |
_ => unimplemented!("preimage length is not supported"), | |
}; | |
f1_into_f2::<Fv, F>(digest) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment