|
@ -1,6 +1,6 @@ |
|
|
extern crate rand;
|
|
|
|
|
|
#[macro_use]
|
|
|
|
|
|
|
|
|
#![allow(clippy::derive_hash_xor_eq, clippy::too_many_arguments)]
|
|
|
extern crate ff;
|
|
|
extern crate ff;
|
|
|
|
|
|
extern crate rand;
|
|
|
use ff::*;
|
|
|
use ff::*;
|
|
|
|
|
|
|
|
|
#[derive(PrimeField)]
|
|
|
#[derive(PrimeField)]
|
|
@ -20,21 +20,21 @@ pub struct Constants { |
|
|
pub fn load_constants() -> Constants {
|
|
|
pub fn load_constants() -> Constants {
|
|
|
let (c_str, m_str) = constants::constants();
|
|
|
let (c_str, m_str) = constants::constants();
|
|
|
let mut c: Vec<Vec<Fr>> = Vec::new();
|
|
|
let mut c: Vec<Vec<Fr>> = Vec::new();
|
|
|
for i in 0..c_str.len() {
|
|
|
|
|
|
|
|
|
for v1 in c_str {
|
|
|
let mut cci: Vec<Fr> = Vec::new();
|
|
|
let mut cci: Vec<Fr> = Vec::new();
|
|
|
for j in 0..c_str[i].len() {
|
|
|
|
|
|
let b: Fr = Fr::from_str(c_str[i][j]).unwrap();
|
|
|
|
|
|
|
|
|
for v2 in v1 {
|
|
|
|
|
|
let b: Fr = Fr::from_str(v2).unwrap();
|
|
|
cci.push(b);
|
|
|
cci.push(b);
|
|
|
}
|
|
|
}
|
|
|
c.push(cci);
|
|
|
c.push(cci);
|
|
|
}
|
|
|
}
|
|
|
let mut m: Vec<Vec<Vec<Fr>>> = Vec::new();
|
|
|
let mut m: Vec<Vec<Vec<Fr>>> = Vec::new();
|
|
|
for i in 0..m_str.len() {
|
|
|
|
|
|
|
|
|
for v1 in m_str {
|
|
|
let mut mi: Vec<Vec<Fr>> = Vec::new();
|
|
|
let mut mi: Vec<Vec<Fr>> = Vec::new();
|
|
|
for j in 0..m_str[i].len() {
|
|
|
|
|
|
|
|
|
for v2 in v1 {
|
|
|
let mut mij: Vec<Fr> = Vec::new();
|
|
|
let mut mij: Vec<Fr> = Vec::new();
|
|
|
for k in 0..m_str[i][j].len() {
|
|
|
|
|
|
let b: Fr = Fr::from_str(m_str[i][j][k]).unwrap();
|
|
|
|
|
|
|
|
|
for s in v2 {
|
|
|
|
|
|
let b: Fr = Fr::from_str(s).unwrap();
|
|
|
mij.push(b);
|
|
|
mij.push(b);
|
|
|
}
|
|
|
}
|
|
|
mi.push(mij);
|
|
|
mi.push(mij);
|
|
@ -42,8 +42,8 @@ pub fn load_constants() -> Constants { |
|
|
m.push(mi);
|
|
|
m.push(mi);
|
|
|
}
|
|
|
}
|
|
|
Constants {
|
|
|
Constants {
|
|
|
c: c,
|
|
|
|
|
|
m: m,
|
|
|
|
|
|
|
|
|
c,
|
|
|
|
|
|
m,
|
|
|
n_rounds_f: 8,
|
|
|
n_rounds_f: 8,
|
|
|
n_rounds_p: vec![56, 57, 56, 60, 60, 63, 64, 63],
|
|
|
n_rounds_p: vec![56, 57, 56, 60, 60, 63, 64, 63],
|
|
|
}
|
|
|
}
|
|
@ -52,13 +52,20 @@ pub fn load_constants() -> Constants { |
|
|
pub struct Poseidon {
|
|
|
pub struct Poseidon {
|
|
|
constants: Constants,
|
|
|
constants: Constants,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Default for Poseidon {
|
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
|
Self::new()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
impl Poseidon {
|
|
|
impl Poseidon {
|
|
|
pub fn new() -> Poseidon {
|
|
|
pub fn new() -> Poseidon {
|
|
|
Poseidon {
|
|
|
Poseidon {
|
|
|
constants: load_constants(),
|
|
|
constants: load_constants(),
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
pub fn ark(&self, state: &mut Vec<Fr>, c: &Vec<Fr>, it: usize) {
|
|
|
|
|
|
|
|
|
pub fn ark(&self, state: &mut Vec<Fr>, c: &[Fr], it: usize) {
|
|
|
for i in 0..state.len() {
|
|
|
for i in 0..state.len() {
|
|
|
state[i].add_assign(&c[it + i]);
|
|
|
state[i].add_assign(&c[it + i]);
|
|
|
}
|
|
|
}
|
|
@ -66,11 +73,11 @@ impl Poseidon { |
|
|
|
|
|
|
|
|
pub fn sbox(&self, n_rounds_f: usize, n_rounds_p: usize, state: &mut Vec<Fr>, i: usize) {
|
|
|
pub fn sbox(&self, n_rounds_f: usize, n_rounds_p: usize, state: &mut Vec<Fr>, i: usize) {
|
|
|
if i < n_rounds_f / 2 || i >= n_rounds_f / 2 + n_rounds_p {
|
|
|
if i < n_rounds_f / 2 || i >= n_rounds_f / 2 + n_rounds_p {
|
|
|
for j in 0..state.len() {
|
|
|
|
|
|
let aux = state[j];
|
|
|
|
|
|
state[j].square();
|
|
|
|
|
|
state[j].square();
|
|
|
|
|
|
state[j].mul_assign(&aux);
|
|
|
|
|
|
|
|
|
for x in state {
|
|
|
|
|
|
let aux = *x;
|
|
|
|
|
|
x.square();
|
|
|
|
|
|
x.square();
|
|
|
|
|
|
x.mul_assign(&aux);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
} else {
|
|
|
let aux = state[0];
|
|
|
let aux = state[0];
|
|
@ -80,13 +87,13 @@ impl Poseidon { |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn mix(&self, state: &Vec<Fr>, m: &Vec<Vec<Fr>>) -> Vec<Fr> {
|
|
|
|
|
|
|
|
|
pub fn mix(&self, state: &Vec<Fr>, m: &[Vec<Fr>]) -> Vec<Fr> {
|
|
|
let mut new_state: Vec<Fr> = Vec::new();
|
|
|
let mut new_state: Vec<Fr> = Vec::new();
|
|
|
for i in 0..state.len() {
|
|
|
for i in 0..state.len() {
|
|
|
new_state.push(Fr::zero());
|
|
|
new_state.push(Fr::zero());
|
|
|
for j in 0..state.len() {
|
|
|
|
|
|
|
|
|
for (j, x) in state.iter().enumerate() {
|
|
|
let mut mij = m[i][j];
|
|
|
let mut mij = m[i][j];
|
|
|
mij.mul_assign(&state[j]);
|
|
|
|
|
|
|
|
|
mij.mul_assign(x);
|
|
|
new_state[i].add_assign(&mij);
|
|
|
new_state[i].add_assign(&mij);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -95,11 +102,11 @@ impl Poseidon { |
|
|
|
|
|
|
|
|
pub fn hash(&self, inp: Vec<Fr>) -> Result<Fr, String> {
|
|
|
pub fn hash(&self, inp: Vec<Fr>) -> Result<Fr, String> {
|
|
|
let t = inp.len() + 1;
|
|
|
let t = inp.len() + 1;
|
|
|
if inp.len() == 0 || inp.len() >= self.constants.n_rounds_p.len() - 1 {
|
|
|
|
|
|
|
|
|
if inp.is_empty() || inp.len() >= self.constants.n_rounds_p.len() - 1 {
|
|
|
return Err("Wrong inputs length".to_string());
|
|
|
return Err("Wrong inputs length".to_string());
|
|
|
}
|
|
|
}
|
|
|
let n_rounds_f = self.constants.n_rounds_f.clone();
|
|
|
|
|
|
let n_rounds_p = self.constants.n_rounds_p[t - 2].clone();
|
|
|
|
|
|
|
|
|
let n_rounds_f = self.constants.n_rounds_f;
|
|
|
|
|
|
let n_rounds_p = self.constants.n_rounds_p[t - 2];
|
|
|
|
|
|
|
|
|
let mut state = vec![Fr::zero(); t];
|
|
|
let mut state = vec![Fr::zero(); t];
|
|
|
state[1..].clone_from_slice(&inp);
|
|
|
state[1..].clone_from_slice(&inp);
|
|
@ -160,6 +167,8 @@ mod tests { |
|
|
|
|
|
|
|
|
#[test]
|
|
|
#[test]
|
|
|
fn test_hash() {
|
|
|
fn test_hash() {
|
|
|
|
|
|
let poseidon = Poseidon::new();
|
|
|
|
|
|
|
|
|
let b0: Fr = Fr::from_str("0").unwrap();
|
|
|
let b0: Fr = Fr::from_str("0").unwrap();
|
|
|
let b1: Fr = Fr::from_str("1").unwrap();
|
|
|
let b1: Fr = Fr::from_str("1").unwrap();
|
|
|
let b2: Fr = Fr::from_str("2").unwrap();
|
|
|
let b2: Fr = Fr::from_str("2").unwrap();
|
|
@ -168,86 +177,43 @@ mod tests { |
|
|
let b5: Fr = Fr::from_str("5").unwrap();
|
|
|
let b5: Fr = Fr::from_str("5").unwrap();
|
|
|
let b6: Fr = Fr::from_str("6").unwrap();
|
|
|
let b6: Fr = Fr::from_str("6").unwrap();
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b1.clone());
|
|
|
|
|
|
let poseidon = Poseidon::new();
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b1]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x29176100eaa962bdc1fe6c654d6a3c130e96a4d1168b33848b897dc502820133)" // "18586133768512220936620570745912940619677854269274689475585506675881198879027"
|
|
|
"Fr(0x29176100eaa962bdc1fe6c654d6a3c130e96a4d1168b33848b897dc502820133)" // "18586133768512220936620570745912940619677854269274689475585506675881198879027"
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b1.clone());
|
|
|
|
|
|
big_arr.push(b2.clone());
|
|
|
|
|
|
let poseidon = Poseidon::new();
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b1, b2]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a)" // "7853200120776062878684798364095072458815029376092732009249414926327459813530"
|
|
|
"Fr(0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a)" // "7853200120776062878684798364095072458815029376092732009249414926327459813530"
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b1.clone());
|
|
|
|
|
|
big_arr.push(b2.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
let poseidon = Poseidon::new();
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b1, b2, b0, b0, b0]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x024058dd1e168f34bac462b6fffe58fd69982807e9884c1c6148182319cee427)" // "1018317224307729531995786483840663576608797660851238720571059489595066344487"
|
|
|
"Fr(0x024058dd1e168f34bac462b6fffe58fd69982807e9884c1c6148182319cee427)" // "1018317224307729531995786483840663576608797660851238720571059489595066344487"
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b1.clone());
|
|
|
|
|
|
big_arr.push(b2.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
let poseidon = Poseidon::new();
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b1, b2, b0, b0, b0, b0]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x21e82f465e00a15965e97a44fe3c30f3bf5279d8bf37d4e65765b6c2550f42a1)" // "15336558801450556532856248569924170992202208561737609669134139141992924267169"
|
|
|
"Fr(0x21e82f465e00a15965e97a44fe3c30f3bf5279d8bf37d4e65765b6c2550f42a1)" // "15336558801450556532856248569924170992202208561737609669134139141992924267169"
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b3.clone());
|
|
|
|
|
|
big_arr.push(b4.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
let poseidon = Poseidon::new();
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b3, b4, b0, b0, b0]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x0cd93f1bab9e8c9166ef00f2a1b0e1d66d6a4145e596abe0526247747cc71214)" // "5811595552068139067952687508729883632420015185677766880877743348592482390548"
|
|
|
"Fr(0x0cd93f1bab9e8c9166ef00f2a1b0e1d66d6a4145e596abe0526247747cc71214)" // "5811595552068139067952687508729883632420015185677766880877743348592482390548"
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b3.clone());
|
|
|
|
|
|
big_arr.push(b4.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
big_arr.push(b0.clone());
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b3, b4, b0, b0, b0, b0]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x1b1caddfc5ea47e09bb445a7447eb9694b8d1b75a97fff58e884398c6b22825a)" // "12263118664590987767234828103155242843640892839966517009184493198782366909018"
|
|
|
"Fr(0x1b1caddfc5ea47e09bb445a7447eb9694b8d1b75a97fff58e884398c6b22825a)" // "12263118664590987767234828103155242843640892839966517009184493198782366909018"
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
let mut big_arr: Vec<Fr> = Vec::new();
|
|
|
|
|
|
big_arr.push(b1.clone());
|
|
|
|
|
|
big_arr.push(b2.clone());
|
|
|
|
|
|
big_arr.push(b3.clone());
|
|
|
|
|
|
big_arr.push(b4.clone());
|
|
|
|
|
|
big_arr.push(b5.clone());
|
|
|
|
|
|
big_arr.push(b6.clone());
|
|
|
|
|
|
let h = poseidon.hash(big_arr.clone()).unwrap();
|
|
|
|
|
|
|
|
|
let h = poseidon.hash(vec![b1, b2, b3, b4, b5, b6]).unwrap();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
h.to_string(),
|
|
|
h.to_string(),
|
|
|
"Fr(0x2d1a03850084442813c8ebf094dea47538490a68b05f2239134a4cca2f6302e1)" // "20400040500897583745843009878988256314335038853985262692600694741116813247201"
|
|
|
"Fr(0x2d1a03850084442813c8ebf094dea47538490a68b05f2239134a4cca2f6302e1)" // "20400040500897583745843009878988256314335038853985262692600694741116813247201"
|
|
|