mirror of https://github.com/status-im/rln.git
poseidon with generic engine
This commit is contained in:
parent
6821b0f574
commit
9352948baf
|
@ -1,48 +1,45 @@
|
|||
use blake2::{Blake2s, Digest};
|
||||
|
||||
use sapling_crypto::bellman::pairing::bn256;
|
||||
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr};
|
||||
use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use sapling_crypto::bellman::pairing::Engine;
|
||||
|
||||
#[test]
|
||||
fn test_poseidon() {
|
||||
use sapling_crypto::bellman::pairing::bn256;
|
||||
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr};
|
||||
let (t, rf, rp) = (3usize, 8usize, 57usize);
|
||||
let mut hasher = Blake2s::new();
|
||||
hasher.input(b"rln poseidion t3rf4rp57");
|
||||
let seed = hasher.result().to_vec();
|
||||
let person_full_round_constant = b"rlnhds01";
|
||||
let full_round_constants = PoseidonParams::generate_constants(person_full_round_constant, seed.clone(), rf);
|
||||
let full_round_constants = PoseidonParams::<Bn256>::generate_constants(person_full_round_constant, seed.clone(), rf);
|
||||
let person_partial_round_constant = b"rlnhds02";
|
||||
let partial_round_constants = PoseidonParams::generate_constants(person_partial_round_constant, seed.clone(), rp);
|
||||
let partial_round_constants =
|
||||
PoseidonParams::<Bn256>::generate_constants(person_partial_round_constant, seed.clone(), rp);
|
||||
let person_mds_matrix = b"rlnhds03";
|
||||
let mds_matrix = PoseidonParams::generate_mds_matrix(person_mds_matrix, seed.clone(), t);
|
||||
let mds_matrix = PoseidonParams::<Bn256>::generate_mds_matrix(person_mds_matrix, seed.clone(), t);
|
||||
let mut constants: Vec<Fr> = Vec::new();
|
||||
for i in 0..rf / 2 {
|
||||
constants.push(full_round_constants[i]);
|
||||
}
|
||||
for i in 0..rp {
|
||||
constants.push(partial_round_constants[i]);
|
||||
}
|
||||
for i in 0..rf / 2 {
|
||||
constants.push(full_round_constants[i]);
|
||||
}
|
||||
let mut hasher = Poseidon::new_with_params(rf, rp, t, constants, mds_matrix);
|
||||
constants.extend_from_slice(&full_round_constants[0..rf / 2]);
|
||||
constants.extend_from_slice(&partial_round_constants);
|
||||
constants.extend_from_slice(&full_round_constants[(rf / 2)..rf]);
|
||||
let mut hasher = Poseidon::<Bn256>::new_with_params(rf, rp, t, constants, mds_matrix);
|
||||
let input = [Fr::zero()];
|
||||
let r1 = hasher.hash(&input);
|
||||
let r2 = hasher.hash(&input);
|
||||
let r1: Fr = hasher.hash(&input);
|
||||
let r2: Fr = hasher.hash(&input);
|
||||
println!("{}", r1);
|
||||
assert_eq!(r1, r2, "just to see if internal state resets");
|
||||
}
|
||||
|
||||
struct PoseidonParams {
|
||||
struct PoseidonParams<E: Engine> {
|
||||
rf: usize,
|
||||
rp: usize,
|
||||
t: usize,
|
||||
round_constants: Vec<Fr>,
|
||||
mds_matrix: Vec<Fr>,
|
||||
round_constants: Vec<E::Fr>,
|
||||
mds_matrix: Vec<E::Fr>,
|
||||
}
|
||||
|
||||
impl PoseidonParams {
|
||||
pub fn new(rf: usize, rp: usize, t: usize, round_constants: Vec<Fr>, mds_matrix: Vec<Fr>) -> PoseidonParams {
|
||||
impl<E: Engine> PoseidonParams<E> {
|
||||
pub fn new(rf: usize, rp: usize, t: usize, round_constants: Vec<E::Fr>, mds_matrix: Vec<E::Fr>) -> PoseidonParams<E> {
|
||||
assert_eq!(rf + rp, round_constants.len());
|
||||
PoseidonParams {
|
||||
rf,
|
||||
|
@ -52,19 +49,19 @@ impl PoseidonParams {
|
|||
mds_matrix,
|
||||
}
|
||||
}
|
||||
pub fn generate_mds_matrix(persona: &[u8; 8], seed: Vec<u8>, t: usize) -> Vec<Fr> {
|
||||
let mut matrix: Vec<Fr> = Vec::with_capacity(t * t);
|
||||
let mut xs: Vec<Fr> = Vec::with_capacity(t);
|
||||
let mut ys: Vec<Fr> = Vec::with_capacity(t);
|
||||
pub fn generate_mds_matrix(persona: &[u8; 8], seed: Vec<u8>, t: usize) -> Vec<E::Fr> {
|
||||
let mut matrix: Vec<E::Fr> = Vec::with_capacity(t * t);
|
||||
let mut xs: Vec<E::Fr> = Vec::with_capacity(t);
|
||||
let mut ys: Vec<E::Fr> = Vec::with_capacity(t);
|
||||
let mut source = seed.clone();
|
||||
loop {
|
||||
let mut hasher = Blake2s::new();
|
||||
hasher.input(persona);
|
||||
hasher.input(source);
|
||||
source = hasher.result().to_vec();
|
||||
let mut candidate_repr = <bn256::Fr as PrimeField>::Repr::default();
|
||||
let mut candidate_repr = <E::Fr as PrimeField>::Repr::default();
|
||||
candidate_repr.read_le(&source[..]).unwrap();
|
||||
if let Ok(candidate) = bn256::Fr::from_repr(candidate_repr) {
|
||||
if let Ok(candidate) = E::Fr::from_repr(candidate_repr) {
|
||||
xs.push(candidate);
|
||||
if xs.len() == t {
|
||||
break;
|
||||
|
@ -76,9 +73,9 @@ impl PoseidonParams {
|
|||
hasher.input(persona);
|
||||
hasher.input(source);
|
||||
source = hasher.result().to_vec();
|
||||
let mut candidate_repr = <bn256::Fr as PrimeField>::Repr::default();
|
||||
let mut candidate_repr = <E::Fr as PrimeField>::Repr::default();
|
||||
candidate_repr.read_le(&source[..]).unwrap();
|
||||
if let Ok(candidate) = bn256::Fr::from_repr(candidate_repr) {
|
||||
if let Ok(candidate) = E::Fr::from_repr(candidate_repr) {
|
||||
ys.push(candidate);
|
||||
if ys.len() == t {
|
||||
break;
|
||||
|
@ -96,17 +93,17 @@ impl PoseidonParams {
|
|||
matrix
|
||||
}
|
||||
|
||||
fn generate_constants(persona: &[u8; 8], seed: Vec<u8>, len: usize) -> Vec<Fr> {
|
||||
let mut constants: Vec<Fr> = Vec::new();
|
||||
fn generate_constants(persona: &[u8; 8], seed: Vec<u8>, len: usize) -> Vec<E::Fr> {
|
||||
let mut constants: Vec<E::Fr> = Vec::new();
|
||||
let mut source = seed.clone();
|
||||
loop {
|
||||
let mut hasher = Blake2s::new();
|
||||
hasher.input(persona);
|
||||
hasher.input(source);
|
||||
source = hasher.result().to_vec();
|
||||
let mut candidate_repr = <bn256::Fr as PrimeField>::Repr::default();
|
||||
let mut candidate_repr = <E::Fr as PrimeField>::Repr::default();
|
||||
candidate_repr.read_le(&source[..]).unwrap();
|
||||
if let Ok(candidate) = bn256::Fr::from_repr(candidate_repr) {
|
||||
if let Ok(candidate) = E::Fr::from_repr(candidate_repr) {
|
||||
constants.push(candidate);
|
||||
if constants.len() == len {
|
||||
break;
|
||||
|
@ -117,18 +114,24 @@ impl PoseidonParams {
|
|||
}
|
||||
}
|
||||
|
||||
struct Poseidon {
|
||||
state: Vec<Fr>,
|
||||
struct Poseidon<E: Engine> {
|
||||
state: Vec<E::Fr>,
|
||||
round: usize,
|
||||
params: PoseidonParams,
|
||||
params: PoseidonParams<E>,
|
||||
}
|
||||
|
||||
impl Poseidon {
|
||||
pub fn new_with_params(rf: usize, rp: usize, t: usize, round_constants: Vec<Fr>, mds_matrix: Vec<Fr>) -> Poseidon {
|
||||
impl<E: Engine> Poseidon<E> {
|
||||
pub fn new_with_params(
|
||||
rf: usize,
|
||||
rp: usize,
|
||||
t: usize,
|
||||
round_constants: Vec<E::Fr>,
|
||||
mds_matrix: Vec<E::Fr>,
|
||||
) -> Poseidon<E> {
|
||||
let params = PoseidonParams::new(rf, rp, t, round_constants, mds_matrix);
|
||||
Poseidon::new(params)
|
||||
}
|
||||
pub fn new(params: PoseidonParams) -> Poseidon {
|
||||
pub fn new(params: PoseidonParams<E>) -> Poseidon<E> {
|
||||
Poseidon {
|
||||
round: 0,
|
||||
state: Vec::new(),
|
||||
|
@ -136,25 +139,25 @@ impl Poseidon {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn hash(&mut self, inputs: &[Fr]) -> Fr {
|
||||
pub fn hash(&mut self, inputs: &[E::Fr]) -> E::Fr {
|
||||
self.new_state(inputs);
|
||||
while self.round() {}
|
||||
self.round = 0;
|
||||
self.result()
|
||||
}
|
||||
|
||||
fn new_state(&mut self, inputs: &[Fr]) {
|
||||
fn new_state(&mut self, inputs: &[E::Fr]) {
|
||||
let t = self.t();
|
||||
assert!(inputs.len() < t);
|
||||
self.state = inputs.to_vec();
|
||||
self.state.resize(t, Fr::zero());
|
||||
self.state.resize(t, E::Fr::zero());
|
||||
}
|
||||
|
||||
fn t(&self) -> usize {
|
||||
self.params.t
|
||||
}
|
||||
|
||||
fn result(&self) -> Fr {
|
||||
fn result(&self) -> E::Fr {
|
||||
self.state[0]
|
||||
}
|
||||
|
||||
|
@ -214,7 +217,7 @@ impl Poseidon {
|
|||
|
||||
fn mul_mds_matrix(&mut self) {
|
||||
let w = self.params.t;
|
||||
let mut new_state = vec![Fr::zero(); w];
|
||||
let mut new_state = vec![E::Fr::zero(); w];
|
||||
for (i, ns) in new_state.iter_mut().enumerate() {
|
||||
// slice and zip
|
||||
for (j, s) in self.state.iter().enumerate() {
|
||||
|
|
Loading…
Reference in New Issue