diff --git a/Cargo.toml b/Cargo.toml index 824e242..7049207 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "poseidon-rs" -version = "0.0.1" +version = "0.0.3" authors = ["arnaucube "] edition = "2018" license = "GPL-3.0" @@ -9,8 +9,12 @@ repository = "https://github.com/arnaucube/poseidon-rs" readme = "README.md" [dependencies] -num = "0.2.0" -num-bigint = "0.2.2" -num-traits = "0.2.8" -blake2 = "0.8" -rustc-hex = "1.0.0" +ff = {package="ff_ce" , version="0.11", features = ["derive"]} +rand = "0.4" + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "bench_poseidon_hash" +harness = false diff --git a/README.md b/README.md index 33ddf33..3b0ba06 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,4 @@ Compatible with the Poseidon Go implementation done in https://github.com/iden3/ ## Warning Do not use in production + diff --git a/benches/bench_poseidon_hash.rs b/benches/bench_poseidon_hash.rs new file mode 100644 index 0000000..958acaf --- /dev/null +++ b/benches/bench_poseidon_hash.rs @@ -0,0 +1,30 @@ +use criterion::{criterion_group, criterion_main, Criterion}; + +extern crate rand; +#[macro_use] +extern crate ff; +use ff::*; + +use poseidon_rs::Poseidon; + +fn criterion_benchmark(c: &mut Criterion) { + let b1: poseidon_rs::Fr = poseidon_rs::Fr::from_str( + "12242166908188651009877250812424843524687801523336557272219921456462821518061", + ) + .unwrap(); + let b2: poseidon_rs::Fr = poseidon_rs::Fr::from_str( + "12242166908188651009877250812424843524687801523336557272219921456462821518061", + ) + .unwrap(); + let mut big_arr: Vec = Vec::new(); + big_arr.push(b1.clone()); + big_arr.push(b2.clone()); + let poseidon = Poseidon::new(); + + c.bench_function("hash", |b| { + b.iter(|| poseidon.hash(big_arr.clone()).unwrap()) + }); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/gen_constants/.gitignore b/gen_constants/.gitignore new file mode 100644 index 0000000..6936990 --- /dev/null +++ b/gen_constants/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/gen_constants/Cargo.toml b/gen_constants/Cargo.toml new file mode 100644 index 0000000..cb51b80 --- /dev/null +++ b/gen_constants/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "gen_constants" +version = "0.0.1" +authors = ["arnaucube "] +edition = "2018" +license = "GPL-3.0" + +[dependencies] +num = "0.2.0" +num-bigint = "0.2.2" +num-traits = "0.2.8" +blake2 = "0.8" +rustc-hex = "1.0.0" diff --git a/gen_constants/src/main.rs b/gen_constants/src/main.rs new file mode 100644 index 0000000..085ecf3 --- /dev/null +++ b/gen_constants/src/main.rs @@ -0,0 +1,154 @@ +use blake2::digest::{Input, VariableOutput}; +use blake2::VarBlake2b; + +extern crate num; +extern crate num_bigint; +extern crate num_traits; +use num_bigint::{BigInt, Sign}; +use num_traits::{One, Zero}; + +const SEED: &str = "poseidon"; +const NROUNDSF: usize = 8; +const NROUNDSP: usize = 57; +const T: usize = 6; + +#[derive(Debug)] +pub struct Constants { + c: Vec, + m: Vec>, +} + +pub fn generate_constants() -> Constants { + let r: BigInt = BigInt::parse_bytes( + b"21888242871839275222246405745257275088548364400416034343698204186575808495617", + 10, + ) + .unwrap(); + + let c = get_pseudo_random(&r, format!("{}{}", SEED, "_constants"), NROUNDSF + NROUNDSP); + let m = get_mds(&r); + Constants { c: c, m: m } +} + +pub fn get_pseudo_random(r: &BigInt, seed: String, n: usize) -> Vec { + let mut hasher = VarBlake2b::new(32).unwrap(); + hasher.input(seed.as_bytes()); + let mut h = hasher.vec_result(); + + let mut res: Vec = Vec::new(); + while res.len() < n { + let new_n: BigInt = modulus(&BigInt::from_bytes_le(Sign::Plus, &h), &r); + res.push(new_n); + let mut hasher = VarBlake2b::new(32).unwrap(); + hasher.input(h); + h = hasher.vec_result(); + } + res +} + +pub fn nonce_to_string(n: usize) -> String { + let mut r = format!("{}", n); + while r.len() < 4 { + r = format!("0{}", r); + } + r +} + +pub fn get_mds(r: &BigInt) -> Vec> { + let mut nonce = 0; + let mut cauchy_matrix = get_pseudo_random( + r, + format!("{}_matrix_{}", SEED, nonce_to_string(nonce)), + T * 2, + ); + while !check_all_different(&cauchy_matrix) { + nonce = nonce + 1; + cauchy_matrix = get_pseudo_random( + r, + format!("{}_matrix_{}", SEED, nonce_to_string(nonce)), + T * 2, + ); + } + let mut m: Vec> = Vec::new(); + for i in 0..T { + let mut mi: Vec = Vec::new(); + for j in 0..T { + mi.push(modinv( + &modulus(&(&cauchy_matrix[i] - &cauchy_matrix[T + j]), &r), + &r, + )); + } + m.push(mi); + } + m +} + +pub fn check_all_different(v: &Vec) -> bool { + let zero: BigInt = Zero::zero(); + for i in 0..v.len() { + if v[i] == zero { + return false; + } + for j in i + 1..v.len() { + if v[i] == v[j] { + return false; + } + } + } + true +} + +pub fn modulus(a: &BigInt, m: &BigInt) -> BigInt { + ((a % m) + m) % m +} + +pub fn modinv(a: &BigInt, q: &BigInt) -> BigInt { + let mut mn = (q.clone(), a.clone()); + let mut xy: (BigInt, BigInt) = (Zero::zero(), One::one()); + + let big_zero: BigInt = Zero::zero(); + while mn.1 != big_zero { + xy = (xy.1.clone(), xy.0 - (mn.0.clone() / mn.1.clone()) * xy.1); + mn = (mn.1.clone(), modulus(&mn.0, &mn.1)); + } + + while xy.0 < Zero::zero() { + xy.0 = modulus(&xy.0, q); + } + xy.0 +} + +fn main() { + let c = generate_constants(); + println!("let c_str: Vec<&str> = vec!["); + for i in 0..c.c.len() { + println!(" {:?},", c.c[i].to_string()); + } + println!("];\n"); + println!("let m_str: Vec> = vec!["); + for i in 0..c.m.len() { + println!(" vec!["); + for j in 0..c.m[i].len() { + println!(" {:?},", c.m[i][j].to_string()); + } + println!(" ],"); + } + println!("];\n"); +} + +#[cfg(test)] +mod tests { + use super::*; + use rustc_hex::ToHex; + + #[test] + fn test_blake2_version() { + let mut hasher = VarBlake2b::new(32).unwrap(); + hasher.input(b"poseidon_constants"); + let h = hasher.vec_result(); + assert_eq!( + h.to_hex(), + "e57ba154fb2c47811dc1a2369b27e25a44915b4e4ece4eb8ec74850cb78e01b1" + ); + } +} diff --git a/src/lib.rs b/src/lib.rs index 337fe30..a79480c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,136 +1,158 @@ -extern crate num; -extern crate num_bigint; -extern crate num_traits; +extern crate rand; +#[macro_use] +extern crate ff; +use ff::*; -use blake2::digest::{Input, VariableOutput}; -use blake2::VarBlake2b; +#[derive(PrimeField)] +#[PrimeFieldModulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"] +#[PrimeFieldGenerator = "7"] +pub struct Fr(FrRepr); -use num_bigint::{BigInt, Sign}; -use num_traits::{One, Zero}; - -const SEED: &str = "poseidon"; const NROUNDSF: usize = 8; const NROUNDSP: usize = 57; const T: usize = 6; +#[derive(Debug)] pub struct Constants { - r: BigInt, - c: Vec, - m: Vec>, -} - -pub fn generate_constants() -> Constants { - let r: BigInt = BigInt::parse_bytes( - b"21888242871839275222246405745257275088548364400416034343698204186575808495617", - 10, - ) - .unwrap(); - let c = get_pseudo_random(&r, format!("{}{}", SEED, "_constants"), NROUNDSF + NROUNDSP); - let m = get_mds(&r); - Constants { r: r, c: c, m: m } -} - -pub fn get_pseudo_random(r: &BigInt, seed: String, n: usize) -> Vec { - let mut hasher = VarBlake2b::new(32).unwrap(); - hasher.input(seed.as_bytes()); - let mut h = hasher.vec_result(); - - let mut res: Vec = Vec::new(); - while res.len() < n { - let new_n: BigInt = modulus(&BigInt::from_bytes_le(Sign::Plus, &h), &r); - res.push(new_n); - let mut hasher = VarBlake2b::new(32).unwrap(); - hasher.input(h); - h = hasher.vec_result(); - } - res -} - -pub fn nonce_to_string(n: usize) -> String { - let mut r = format!("{}", n); - while r.len() < 4 { - r = format!("0{}", r); - } - r -} -pub fn get_mds(r: &BigInt) -> Vec> { - let mut nonce = 0; - let mut cauchy_matrix = get_pseudo_random( - r, - format!("{}_matrix_{}", SEED, nonce_to_string(nonce)), - T * 2, - ); - while !check_all_different(&cauchy_matrix) { - nonce = nonce + 1; - cauchy_matrix = get_pseudo_random( - r, - format!("{}_matrix_{}", SEED, nonce_to_string(nonce)), - T * 2, - ); - } - let mut m: Vec> = Vec::new(); - for i in 0..T { - let mut mi: Vec = Vec::new(); - for j in 0..T { - mi.push(modinv( - &modulus(&(&cauchy_matrix[i] - &cauchy_matrix[T + j]), &r), - &r, - )); - } - m.push(mi); - } - m -} - -pub fn check_all_different(v: &Vec) -> bool { - let zero: BigInt = Zero::zero(); - for i in 0..v.len() { - if v[i] == zero { - return false; - } - for j in i + 1..v.len() { - if v[i] == v[j] { - return false; - } - } - } - true -} - -pub fn modulus(a: &BigInt, m: &BigInt) -> BigInt { - ((a % m) + m) % m -} - -pub fn modinv(a: &BigInt, q: &BigInt) -> BigInt { - let mut mn = (q.clone(), a.clone()); - let mut xy: (BigInt, BigInt) = (Zero::zero(), One::one()); - - let big_zero: BigInt = Zero::zero(); - while mn.1 != big_zero { - xy = (xy.1.clone(), xy.0 - (mn.0.clone() / mn.1.clone()) * xy.1); - mn = (mn.1.clone(), modulus(&mn.0, &mn.1)); - } - - while xy.0 < Zero::zero() { - xy.0 = modulus(&xy.0, q); - } - xy.0 + c: Vec, + m: Vec>, } -pub fn check_bigint_in_field(a: &BigInt, q: &BigInt) -> bool { - if a >= q { - return false; +pub fn load_constants() -> Constants { + let c_str: Vec<&str> = vec![ + "14397397413755236225575615486459253198602422701513067526754101844196324375522", + "10405129301473404666785234951972711717481302463898292859783056520670200613128", + "5179144822360023508491245509308555580251733042407187134628755730783052214509", + "9132640374240188374542843306219594180154739721841249568925550236430986592615", + "20360807315276763881209958738450444293273549928693737723235350358403012458514", + "17933600965499023212689924809448543050840131883187652471064418452962948061619", + "3636213416533737411392076250708419981662897009810345015164671602334517041153", + "2008540005368330234524962342006691994500273283000229509835662097352946198608", + "16018407964853379535338740313053768402596521780991140819786560130595652651567", + "20653139667070586705378398435856186172195806027708437373983929336015162186471", + "17887713874711369695406927657694993484804203950786446055999405564652412116765", + "4852706232225925756777361208698488277369799648067343227630786518486608711772", + "8969172011633935669771678412400911310465619639756845342775631896478908389850", + "20570199545627577691240476121888846460936245025392381957866134167601058684375", + "16442329894745639881165035015179028112772410105963688121820543219662832524136", + "20060625627350485876280451423010593928172611031611836167979515653463693899374", + "16637282689940520290130302519163090147511023430395200895953984829546679599107", + "15599196921909732993082127725908821049411366914683565306060493533569088698214", + "16894591341213863947423904025624185991098788054337051624251730868231322135455", + "1197934381747032348421303489683932612752526046745577259575778515005162320212", + "6172482022646932735745595886795230725225293469762393889050804649558459236626", + "21004037394166516054140386756510609698837211370585899203851827276330669555417", + "15262034989144652068456967541137853724140836132717012646544737680069032573006", + "15017690682054366744270630371095785995296470601172793770224691982518041139766", + "15159744167842240513848638419303545693472533086570469712794583342699782519832", + "11178069035565459212220861899558526502477231302924961773582350246646450941231", + "21154888769130549957415912997229564077486639529994598560737238811887296922114", + "20162517328110570500010831422938033120419484532231241180224283481905744633719", + "2777362604871784250419758188173029886707024739806641263170345377816177052018", + "15732290486829619144634131656503993123618032247178179298922551820261215487562", + "6024433414579583476444635447152826813568595303270846875177844482142230009826", + "17677827682004946431939402157761289497221048154630238117709539216286149983245", + "10716307389353583413755237303156291454109852751296156900963208377067748518748", + "14925386988604173087143546225719076187055229908444910452781922028996524347508", + "8940878636401797005293482068100797531020505636124892198091491586778667442523", + "18911747154199663060505302806894425160044925686870165583944475880789706164410", + "8821532432394939099312235292271438180996556457308429936910969094255825456935", + "20632576502437623790366878538516326728436616723089049415538037018093616927643", + "71447649211767888770311304010816315780740050029903404046389165015534756512", + "2781996465394730190470582631099299305677291329609718650018200531245670229393", + "12441376330954323535872906380510501637773629931719508864016287320488688345525", + "2558302139544901035700544058046419714227464650146159803703499681139469546006", + "10087036781939179132584550273563255199577525914374285705149349445480649057058", + "4267692623754666261749551533667592242661271409704769363166965280715887854739", + "4945579503584457514844595640661884835097077318604083061152997449742124905548", + "17742335354489274412669987990603079185096280484072783973732137326144230832311", + "6266270088302506215402996795500854910256503071464802875821837403486057988208", + "2716062168542520412498610856550519519760063668165561277991771577403400784706", + "19118392018538203167410421493487769944462015419023083813301166096764262134232", + "9386595745626044000666050847309903206827901310677406022353307960932745699524", + "9121640807890366356465620448383131419933298563527245687958865317869840082266", + "3078975275808111706229899605611544294904276390490742680006005661017864583210", + "7157404299437167354719786626667769956233708887934477609633504801472827442743", + "14056248655941725362944552761799461694550787028230120190862133165195793034373", + "14124396743304355958915937804966111851843703158171757752158388556919187839849", + "11851254356749068692552943732920045260402277343008629727465773766468466181076", + "9799099446406796696742256539758943483211846559715874347178722060519817626047", + "10156146186214948683880719664738535455146137901666656566575307300522957959544", + "19908645952733301583346063785055921934459499091029406575311417879963332475861", + "11766105336238068471342414351862472329437473380853789942065610694000443387471", + "11002137593249972174092192767251572171769044073555430468487809799220351297047", + "284136377911685911941431040940403846843630064858778505937392780738953624163", + "19448733709802908339787967270452055364068697565906862913410983275341804035680", + "14423660424692802524250720264041003098290275890428483723270346403986712981505", + "10635360132728137321700090133109897687122647659471659996419791842933639708516", + ]; + + let m_str: Vec> = vec![ + vec![ + "19167410339349846567561662441069598364702008768579734801591448511131028229281", + "14183033936038168803360723133013092560869148726790180682363054735190196956789", + "9067734253445064890734144122526450279189023719890032859456830213166173619761", + "16378664841697311562845443097199265623838619398287411428110917414833007677155", + "12968540216479938138647596899147650021419273189336843725176422194136033835172", + "3636162562566338420490575570584278737093584021456168183289112789616069756675", + ], + vec![ + "17034139127218860091985397764514160131253018178110701196935786874261236172431", + "2799255644797227968811798608332314218966179365168250111693473252876996230317", + "2482058150180648511543788012634934806465808146786082148795902594096349483974", + "16563522740626180338295201738437974404892092704059676533096069531044355099628", + "10468644849657689537028565510142839489302836569811003546969773105463051947124", + "3328913364598498171733622353010907641674136720305714432354138807013088636408", + ], + vec![ + "18985203040268814769637347880759846911264240088034262814847924884273017355969", + "8652975463545710606098548415650457376967119951977109072274595329619335974180", + "970943815872417895015626519859542525373809485973005165410533315057253476903", + "19406667490568134101658669326517700199745817783746545889094238643063688871948", + "17049854690034965250221386317058877242629221002521630573756355118745574274967", + "4964394613021008685803675656098849539153699842663541444414978877928878266244", + ], + vec![ + "19025623051770008118343718096455821045904242602531062247152770448380880817517", + "9077319817220936628089890431129759976815127354480867310384708941479362824016", + "4770370314098695913091200576539533727214143013236894216582648993741910829490", + "4298564056297802123194408918029088169104276109138370115401819933600955259473", + "6905514380186323693285869145872115273350947784558995755916362330070690839131", + "4783343257810358393326889022942241108539824540285247795235499223017138301952", + ], + vec![ + "16205238342129310687768799056463408647672389183328001070715567975181364448609", + "8303849270045876854140023508764676765932043944545416856530551331270859502246", + "20218246699596954048529384569730026273241102596326201163062133863539137060414", + "1712845821388089905746651754894206522004527237615042226559791118162382909269", + "13001155522144542028910638547179410124467185319212645031214919884423841839406", + "16037892369576300958623292723740289861626299352695838577330319504984091062115", + ], + vec![ + "15162889384227198851506890526431746552868519326873025085114621698588781611738", + "13272957914179340594010910867091459756043436017766464331915862093201960540910", + "9416416589114508529880440146952102328470363729880726115521103179442988482948", + "8035240799672199706102747147502951589635001418759394863664434079699838251138", + "21642389080762222565487157652540372010968704000567605990102641816691459811717", + "20261355950827657195644012399234591122288573679402601053407151083849785332516", + ], + ]; + + let mut c: Vec = Vec::new(); + for i in 0..c_str.len() { + let n: Fr = Fr::from_str(c_str[i]).unwrap(); + c.push(n); } - true -} - -pub fn check_bigint_array_in_field(arr: &Vec, q: &BigInt) -> bool { - for a in arr { - if !check_bigint_in_field(a, &q) { - return false; + let mut m: Vec> = Vec::new(); + for i in 0..m_str.len() { + let mut mj: Vec = Vec::new(); + for j in 0..m_str[i].len() { + let n: Fr = Fr::from_str(m_str[i][j]).unwrap(); + mj.push(n); } + m.push(mj); } - true + Constants { c: c, m: m } } pub struct Poseidon { @@ -139,244 +161,131 @@ pub struct Poseidon { impl Poseidon { pub fn new() -> Poseidon { Poseidon { - constants: generate_constants(), + constants: load_constants(), } } - pub fn ark(&self, state: &Vec, c: &BigInt) -> Vec { - let mut new_state: Vec = state.clone(); + pub fn ark(&self, state: &mut Vec, c: &Fr) { for i in 0..state.len() { - new_state[i] = modulus(&(&state[i] + c), &self.constants.r); + state[i].add_assign(c); } - - new_state - } - - pub fn cubic(&self, a: &BigInt) -> BigInt { - modulus(&(a * a * a * a * a), &self.constants.r) } - pub fn sbox(&self, state: &Vec, i: usize) -> Vec { - let mut new_state: Vec = state.clone(); + pub fn sbox(&self, state: &mut Vec, i: usize) { if i < NROUNDSF / 2 || i >= NROUNDSF / 2 + NROUNDSP { for j in 0..T { - new_state[j] = self.cubic(&state[j]); + let aux = state[j]; + state[j].square(); + state[j].square(); + state[j].mul_assign(&aux); } } else { - new_state[0] = self.cubic(&state[0]); + let aux = state[0]; + state[0].square(); + state[0].square(); + state[0].mul_assign(&aux); } - new_state } - pub fn mix(&self, state: &Vec, m: &Vec>) -> Vec { - let mut new_state: Vec = Vec::new(); + pub fn mix(&self, state: &Vec, m: &Vec>) -> Vec { + let mut new_state: Vec = Vec::new(); for i in 0..state.len() { - new_state.push(Zero::zero()); + new_state.push(Fr::zero()); for j in 0..state.len() { - new_state[i] = modulus( - &(&new_state[i] + modulus(&(&m[i][j] * &state[j]), &self.constants.r)), - &self.constants.r, - ) + let mut mij = m[i][j]; + mij.mul_assign(&state[j]); + new_state[i].add_assign(&mij); } } - new_state + new_state.clone() } - pub fn poseidon_hash(&self, inp: Vec) -> Result { + pub fn hash(&self, inp: Vec) -> Result { if inp.len() == 0 || inp.len() > T { return Err("Wrong inputs length".to_string()); } - // check if arr elements are inside the finite field over R - if !check_bigint_array_in_field(&inp, &self.constants.r) { - return Err("elements not inside the finite field over R".to_string()); - } let mut state = inp.clone(); for _ in inp.len()..T { - state.push(Zero::zero()); + state.push(Fr::zero()); } for i in 0..(NROUNDSF + NROUNDSP) { - state = self.ark(&state, &self.constants.c[i]); - state = self.sbox(&state, i); + self.ark(&mut state, &self.constants.c[i]); + self.sbox(&mut state, i); state = self.mix(&state, &self.constants.m); } - Ok(state[0].clone()) - } - - pub fn hash(&self, inp: Vec) -> Result { - // check if arr elements are inside the finite field over R - if !check_bigint_array_in_field(&inp, &self.constants.r) { - return Err("elements not inside the finite field over R".to_string()); - } - let mut r: BigInt = One::one(); - for i in (0..inp.len()).step_by(T - 1) { - let mut to_hash: Vec = Vec::new(); - let mut p = 0; - for j in 0..T - 1 { - p = j.clone(); - if i + j < inp.len() { - to_hash.push(inp[i + j].clone()); - } else { - p = j.clone(); - break; - } - } - to_hash.push(r.clone()); - for _ in p + 1..T - 1 { - to_hash.push(Zero::zero()); - } - let ph = &self.poseidon_hash(to_hash); - match ph { - Result::Err(err) => return Err(err.to_string()), - Result::Ok(res) => { - r = modulus(&(r + res), &self.constants.r); - } - } - } - Ok(r) - } - - pub fn hash_bytes(&self, b: Vec) -> Result { - let n = 31; - let mut ints: Vec = Vec::new(); - for i in 0..b.len() / n { - let v: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[n * i..n * (i + 1)]); - ints.push(v); - } - if b.len() % n != 0 { - let v: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[(b.len() / n) * n..]); - ints.push(v); - } - self.hash(ints) + Ok(state[0]) } } #[cfg(test)] mod tests { use super::*; - use rustc_hex::ToHex; #[test] - fn test_blake2_version() { - let mut hasher = VarBlake2b::new(32).unwrap(); - hasher.input(b"poseidon_constants"); - let h = hasher.vec_result(); + fn test_ff() { + let a = Fr::from_repr(FrRepr::from(2)).unwrap(); assert_eq!( - h.to_hex(), - "e57ba154fb2c47811dc1a2369b27e25a44915b4e4ece4eb8ec74850cb78e01b1" + "0000000000000000000000000000000000000000000000000000000000000002", + to_hex(&a) ); + + let b: Fr = Fr::from_str( + "21888242871839275222246405745257275088548364400416034343698204186575808495619", + ) + .unwrap(); + assert_eq!( + "0000000000000000000000000000000000000000000000000000000000000002", + to_hex(&b) + ); + assert_eq!(&a, &b); } #[test] - fn test_poseidon_hash() { - let b1: BigInt = BigInt::parse_bytes(b"1", 10).unwrap(); - let b2: BigInt = BigInt::parse_bytes(b"2", 10).unwrap(); - let mut big_arr: Vec = Vec::new(); - big_arr.push(b1.clone()); - big_arr.push(b2.clone()); - let poseidon = Poseidon::new(); - let h = poseidon.poseidon_hash(big_arr.clone()).unwrap(); + fn test_load_constants() { + let constants = load_constants(); assert_eq!( - h.to_string(), - "12242166908188651009877250812424843524687801523336557272219921456462821518061" + constants.c[0].to_string(), + "Fr(0x1fd4a35e68f0946f8f5dfd2ac9d7882ce2466ec1c9766f69b5a14c3f84a17be2)" ); - let h = poseidon.hash(big_arr).unwrap(); assert_eq!( - h.to_string(), - "4932297968297298434239270129193057052722409868268166443802652458940273154855" + constants.c[constants.c.len() - 1].to_string(), + "Fr(0x1783668830df79d79707da6a0e7c023c5f54a112be7ee3f7d49b420213ab7f64)" ); - - let b3: BigInt = BigInt::parse_bytes(b"3", 10).unwrap(); - let b4: BigInt = BigInt::parse_bytes(b"4", 10).unwrap(); - let mut big_arr34: Vec = Vec::new(); - big_arr34.push(b3.clone()); - big_arr34.push(b4.clone()); - let h34 = poseidon.poseidon_hash(big_arr34.clone()).unwrap(); assert_eq!( - h34.to_string(), - "17185195740979599334254027721507328033796809509313949281114643312710535000993" + constants.m[0][0].to_string(), + "Fr(0x2a605eab3c12c29701b9a8944a16ff3d64c199efa7c857c65e4c0560ab3b0ca1)" ); - let h34 = poseidon.hash(big_arr34).unwrap(); assert_eq!( - h34.to_string(), - "4635491972858758537477743930622086396911540895966845494943021655521913507504" + constants.m[constants.m.len() - 1][0].to_string(), + "Fr(0x2185e429a96435c62e21e7091f4262685769e43fa49c9d40f88c41016c588ada)" ); } #[test] - fn test_hash_bytes() { - let msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + fn test_hash() { + let b1: Fr = Fr::from_str("1").unwrap(); + let b2: Fr = Fr::from_str("2").unwrap(); + let mut big_arr: Vec = Vec::new(); + big_arr.push(b1.clone()); + big_arr.push(b2.clone()); let poseidon = Poseidon::new(); - let h = poseidon.hash_bytes(msg.as_bytes().to_vec()).unwrap(); + let h = poseidon.hash(big_arr.clone()).unwrap(); assert_eq!( h.to_string(), - "16019700159595764790637132363672701294192939959594423814006267756172551741065" + "Fr(0x1b10d227ef9aa736dc05bba919a8462ce45bc5b7d632e8ff9bfe6874a002eaed)" // "12242166908188651009877250812424843524687801523336557272219921456462821518061" ); - let msg2 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet."; - let h2 = poseidon.hash_bytes(msg2.as_bytes().to_vec()).unwrap(); + let b3: Fr = Fr::from_str("3").unwrap(); + let b4: Fr = Fr::from_str("4").unwrap(); + let mut big_arr34: Vec = Vec::new(); + big_arr34.push(b3.clone()); + big_arr34.push(b4.clone()); + let h34 = poseidon.hash(big_arr34.clone()).unwrap(); assert_eq!( - h2.to_string(), - "2978613163687734485261639854325792381691890647104372645321246092227111432722" + h34.to_string(), + "Fr(0x25fe79e16e9d530a400584ffe556b1fe69acda374065860c43698cab1c16b3a1)" // "17185195740979599334254027721507328033796809509313949281114643312710535000993" ); } - - #[test] - fn test_chunks() { - let b0: BigInt = BigInt::parse_bytes(b"0", 10).unwrap(); - let b1: BigInt = BigInt::parse_bytes(b"1", 10).unwrap(); - let b2: BigInt = BigInt::parse_bytes(b"2", 10).unwrap(); - let b3: BigInt = BigInt::parse_bytes(b"3", 10).unwrap(); - let b4: BigInt = BigInt::parse_bytes(b"4", 10).unwrap(); - let b5: BigInt = BigInt::parse_bytes(b"5", 10).unwrap(); - let b6: BigInt = BigInt::parse_bytes(b"6", 10).unwrap(); - let b7: BigInt = BigInt::parse_bytes(b"7", 10).unwrap(); - let b8: BigInt = BigInt::parse_bytes(b"8", 10).unwrap(); - let b9: BigInt = BigInt::parse_bytes(b"9", 10).unwrap(); - let big_arr: Vec = vec![ - b0.clone(), - b1.clone(), - b2.clone(), - b3.clone(), - b4.clone(), - b5.clone(), - b6.clone(), - b7.clone(), - b8.clone(), - b9.clone(), - ]; - - let poseidon = Poseidon::new(); - let h = poseidon.hash(big_arr).unwrap(); - - let big_arr2: Vec = vec![ - b5.clone(), - b6.clone(), - b7.clone(), - b8.clone(), - b9.clone(), - b0.clone(), - b1.clone(), - b2.clone(), - b3.clone(), - b4.clone(), - ]; - let h2 = poseidon.hash(big_arr2).unwrap(); - assert_ne!(h, h2); - } - - #[test] - fn test_padding() { - let b0: BigInt = BigInt::parse_bytes(b"0", 10).unwrap(); - let b1: BigInt = BigInt::parse_bytes(b"1", 10).unwrap(); - let big_arr: Vec = vec![b1.clone()]; - - let poseidon = Poseidon::new(); - let h = poseidon.hash(big_arr).unwrap(); - - let big_arr2: Vec = vec![b1.clone(), b0.clone()]; - let h2 = poseidon.hash(big_arr2).unwrap(); - assert_ne!(h, h2); - } }