diff --git a/src/error.rs b/src/error.rs index c9a56208e..c06b9bf35 100644 --- a/src/error.rs +++ b/src/error.rs @@ -140,7 +140,7 @@ pub enum ErrorKind { GenericValueExpected(String), #[error("conflict generic values during binding for `{0}`: `{1}` and `{2}`")] - ConflictGenericValue(String, u32, u32), + ConflictGenericValue(String, String, String), #[error("unexpected generic parameter: `{0}`")] UnexpectedGenericParameter(String), diff --git a/src/mast/mod.rs b/src/mast/mod.rs index 89ad4cc6b..f2521c156 100644 --- a/src/mast/mod.rs +++ b/src/mast/mod.rs @@ -36,27 +36,27 @@ pub struct ExprMonoInfo { #[derive(Debug, Clone)] pub enum PropagatedConstant { - Single(u32), + Single(BigUint), Array(Vec), Custom(HashMap), } impl PropagatedConstant { - pub fn as_single(&self) -> u32 { + pub fn as_single(&self) -> BigUint { match self { - PropagatedConstant::Single(v) => *v, + PropagatedConstant::Single(v) => v.clone(), _ => panic!("expected single value"), } } - pub fn as_array(&self) -> Vec { + pub fn as_array(&self) -> Vec { match self { PropagatedConstant::Array(v) => v.iter().map(|c| c.as_single()).collect(), _ => panic!("expected array value"), } } - pub fn as_custom(&self) -> HashMap { + pub fn as_custom(&self) -> HashMap { match self { PropagatedConstant::Custom(v) => { v.iter().map(|(k, c)| (k.clone(), c.as_single())).collect() @@ -67,8 +67,8 @@ impl PropagatedConstant { } /// impl From trait for single value -impl From for PropagatedConstant { - fn from(v: u32) -> Self { +impl From for PropagatedConstant { + fn from(v: BigUint) -> Self { PropagatedConstant::Single(v) } } @@ -224,7 +224,10 @@ impl FnSig { TyKind::Array(ty, size) => TyKind::Array(Box::new(self.resolve_type(ty, ctx)), *size), TyKind::GenericSizedArray(ty, sym) => { let val = sym.eval(&self.generics, &ctx.tast); - TyKind::Array(Box::new(self.resolve_type(ty, ctx)), val) + TyKind::Array( + Box::new(self.resolve_type(ty, ctx)), + val.to_u32().expect("array size exceeded u32"), + ) } _ => typ.clone(), } @@ -381,9 +384,9 @@ impl MastCtx { impl Symbolic { /// Evaluate symbolic size to an integer. - pub fn eval(&self, gens: &GenericParameters, tast: &TypeChecker) -> u32 { + pub fn eval(&self, gens: &GenericParameters, tast: &TypeChecker) -> BigUint { match self { - Symbolic::Concrete(v) => *v, + Symbolic::Concrete(v) => v.clone(), Symbolic::Constant(var) => { let qualified = FullyQualified::local(var.value.clone()); let cst = tast.const_info(&qualified).expect("constant not found"); @@ -805,11 +808,7 @@ fn monomorphize_expr( Some(v) => { let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(v.clone())); - ExprMonoInfo::new( - mexpr, - typ, - Some(PropagatedConstant::from(v.to_u32().unwrap())), - ) + ExprMonoInfo::new(mexpr, typ, Some(PropagatedConstant::from(v))) } // keep as is _ => { @@ -846,13 +845,12 @@ fn monomorphize_expr( } ExprKind::BigUInt(inner) => { - let cst: u32 = inner.try_into().expect("biguint too large"); let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(inner.clone())); ExprMonoInfo::new( mexpr, Some(TyKind::Field { constant: true }), - Some(PropagatedConstant::from(cst)), + Some(PropagatedConstant::from(inner.clone())), ) } @@ -892,13 +890,12 @@ fn monomorphize_expr( // if it's a variable, // check if it's a constant first let bigint: BigUint = cst.value[0].into(); - let cst: u32 = bigint.clone().try_into().expect("biguint too large"); - let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(bigint)); + let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(bigint.clone())); ExprMonoInfo::new( mexpr, Some(TyKind::Field { constant: true }), - Some(PropagatedConstant::from(cst)), + Some(PropagatedConstant::from(bigint)), ) } else { // otherwise it's a local variable @@ -1090,7 +1087,10 @@ fn monomorphize_expr( ); if let Some(cst) = size_mono.constant { - let arr_typ = TyKind::Array(Box::new(item_typ), cst.as_single()); + let arr_typ = TyKind::Array( + Box::new(item_typ), + cst.as_single().to_u32().expect("array size too large"), + ); ExprMonoInfo::new(mexpr, Some(arr_typ), None) } else { return Err(error(ErrorKind::InvalidArraySize, expr.span)); diff --git a/src/parser/types.rs b/src/parser/types.rs index 0691f1356..4ce8645c8 100644 --- a/src/parser/types.rs +++ b/src/parser/types.rs @@ -1,4 +1,5 @@ use educe::Educe; +use num_bigint::BigUint; use std::{ collections::{HashMap, HashSet}, fmt::Display, @@ -7,7 +8,7 @@ use std::{ }; use ark_ff::Field; -use num_traits::ToPrimitive; +use num_traits::FromPrimitive; use serde::{Deserialize, Serialize}; use crate::{ @@ -15,7 +16,6 @@ use crate::{ constants::Span, error::{Error, ErrorKind, Result}, lexer::{Keyword, Token, TokenKind, Tokens}, - mast::ExprMonoInfo, stdlib::builtins::BUILTIN_FN_NAMES, syntax::{is_generic_parameter, is_type}, }; @@ -181,7 +181,7 @@ pub enum ModulePath { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub enum Symbolic { /// A literal number - Concrete(u32), + Concrete(BigUint), /// Point to a constant variable Constant(Ident), /// Generic parameter @@ -230,7 +230,7 @@ impl Symbolic { /// Parse from an expression node recursively. pub fn parse(node: &Expr) -> Result { match &node.kind { - ExprKind::BigUInt(n) => Ok(Symbolic::Concrete(n.to_u32().unwrap())), + ExprKind::BigUInt(n) => Ok(Symbolic::Concrete(n.clone())), ExprKind::Variable { module: _, name } => { if is_generic_parameter(&name.value) { Ok(Symbolic::Generic(name.clone())) @@ -571,7 +571,11 @@ impl FnSig { // resolve the generic parameter match sym { Symbolic::Generic(ident) => { - self.generics.assign(&ident.value, *observed_size, span)?; + self.generics.assign( + &ident.value, + BigUint::from_u32(*observed_size).unwrap(), + span, + )?; } _ => unreachable!("no operation allowed on symbolic size in function argument"), } @@ -633,7 +637,7 @@ impl FnSig { let generics = generics .iter() - .map(|(name, value)| format!("{}={}", name, value.unwrap())) + .map(|(name, value)| format!("{}={}", name, value.as_ref().unwrap())) .collect::>() .join("#"); @@ -742,7 +746,7 @@ pub struct ResolvedSig { #[derive(Debug, Default, Clone, Serialize, Deserialize)] /// Generic parameters for a function signature pub struct GenericParameters { - pub parameters: HashMap>, + pub parameters: HashMap>, pub resolved_sig: Option, } @@ -758,11 +762,13 @@ impl GenericParameters { } /// Get the value of a generic parameter - pub fn get(&self, name: &str) -> u32 { + pub fn get(&self, name: &str) -> BigUint { self.parameters .get(name) .expect("generic parameter not found") + .as_ref() .expect("generic value not assigned") + .clone() } /// Returns whether the generic parameters are empty @@ -771,7 +777,7 @@ impl GenericParameters { } /// Bind a generic parameter to a value - pub fn assign(&mut self, name: &String, value: u32, span: Span) -> Result<()> { + pub fn assign(&mut self, name: &String, value: BigUint, span: Span) -> Result<()> { let existing = self.parameters.get(name); match existing { Some(Some(v)) => { @@ -781,7 +787,11 @@ impl GenericParameters { Err(Error::new( "mast", - ErrorKind::ConflictGenericValue(name.to_string(), *v, value), + ErrorKind::ConflictGenericValue( + name.to_string(), + v.to_str_radix(10), + value.to_str_radix(10), + ), span, )) } diff --git a/src/stdlib/mod.rs b/src/stdlib/mod.rs index ae7aed820..e01489059 100644 --- a/src/stdlib/mod.rs +++ b/src/stdlib/mod.rs @@ -93,7 +93,7 @@ pub fn init_stdlib_dep( path_prefix: &str, ) -> usize { // list the stdlib dependency in order - let libs = vec!["bits", "comparator", "multiplexer", "int"]; + let libs = vec!["bits", "comparator", "multiplexer", "mimc", "int"]; let mut node_id = node_id; diff --git a/src/stdlib/native/mimc/lib.no b/src/stdlib/native/mimc/lib.no new file mode 100644 index 000000000..7681f1e4d --- /dev/null +++ b/src/stdlib/native/mimc/lib.no @@ -0,0 +1,153 @@ +/// MIMC hash function using exponentiation with 7. +/// This function allows a maximum of 91 rounds, with each round using exponentiation of 7. +/// +/// # Parameters +/// - `value`: The input value to be hashed. +/// - `key`: The secret key used in the hash computation. +/// +/// # Returns +/// - `Field`: The resulting hash after `ROUNDS` of MIMC operations. +/// +/// # Constraints +/// - `ROUNDS` must be within the range of constants defined in `csts`. +fn mimc7_cipher(value: Field, key: Field) -> Field { + let rounds = 91; + // Initial value: sum of the key and input value. + let init = key + value; + // Variable for the accumulative result of exponentiation with 7. + let mut exp7 = 0; + + // Predefined constants for each round of the hash function. + let csts = [ + 0, + 20888961410941983456478427210666206549300505294776164667214940546594746570981, + 15265126113435022738560151911929040668591755459209400716467504685752745317193, + 8334177627492981984476504167502758309043212251641796197711684499645635709656, + 1374324219480165500871639364801692115397519265181803854177629327624133579404, + 11442588683664344394633565859260176446561886575962616332903193988751292992472, + 2558901189096558760448896669327086721003508630712968559048179091037845349145, + 11189978595292752354820141775598510151189959177917284797737745690127318076389, + 3262966573163560839685415914157855077211340576201936620532175028036746741754, + 17029914891543225301403832095880481731551830725367286980611178737703889171730, + 4614037031668406927330683909387957156531244689520944789503628527855167665518, + 19647356996769918391113967168615123299113119185942498194367262335168397100658, + 5040699236106090655289931820723926657076483236860546282406111821875672148900, + 2632385916954580941368956176626336146806721642583847728103570779270161510514, + 17691411851977575435597871505860208507285462834710151833948561098560743654671, + 11482807709115676646560379017491661435505951727793345550942389701970904563183, + 8360838254132998143349158726141014535383109403565779450210746881879715734773, + 12663821244032248511491386323242575231591777785787269938928497649288048289525, + 3067001377342968891237590775929219083706800062321980129409398033259904188058, + 8536471869378957766675292398190944925664113548202769136103887479787957959589, + 19825444354178182240559170937204690272111734703605805530888940813160705385792, + 16703465144013840124940690347975638755097486902749048533167980887413919317592, + 13061236261277650370863439564453267964462486225679643020432589226741411380501, + 10864774797625152707517901967943775867717907803542223029967000416969007792571, + 10035653564014594269791753415727486340557376923045841607746250017541686319774, + 3446968588058668564420958894889124905706353937375068998436129414772610003289, + 4653317306466493184743870159523234588955994456998076243468148492375236846006, + 8486711143589723036499933521576871883500223198263343024003617825616410932026, + 250710584458582618659378487568129931785810765264752039738223488321597070280, + 2104159799604932521291371026105311735948154964200596636974609406977292675173, + 16313562605837709339799839901240652934758303521543693857533755376563489378839, + 6032365105133504724925793806318578936233045029919447519826248813478479197288, + 14025118133847866722315446277964222215118620050302054655768867040006542798474, + 7400123822125662712777833064081316757896757785777291653271747396958201309118, + 1744432620323851751204287974553233986555641872755053103823939564833813704825, + 8316378125659383262515151597439205374263247719876250938893842106722210729522, + 6739722627047123650704294650168547689199576889424317598327664349670094847386, + 21211457866117465531949733809706514799713333930924902519246949506964470524162, + 13718112532745211817410303291774369209520657938741992779396229864894885156527, + 5264534817993325015357427094323255342713527811596856940387954546330728068658, + 18884137497114307927425084003812022333609937761793387700010402412840002189451, + 5148596049900083984813839872929010525572543381981952060869301611018636120248, + 19799686398774806587970184652860783461860993790013219899147141137827718662674, + 19240878651604412704364448729659032944342952609050243268894572835672205984837, + 10546185249390392695582524554167530669949955276893453512788278945742408153192, + 5507959600969845538113649209272736011390582494851145043668969080335346810411, + 18177751737739153338153217698774510185696788019377850245260475034576050820091, + 19603444733183990109492724100282114612026332366576932662794133334264283907557, + 10548274686824425401349248282213580046351514091431715597441736281987273193140, + 1823201861560942974198127384034483127920205835821334101215923769688644479957, + 11867589662193422187545516240823411225342068709600734253659804646934346124945, + 18718569356736340558616379408444812528964066420519677106145092918482774343613, + 10530777752259630125564678480897857853807637120039176813174150229243735996839, + 20486583726592018813337145844457018474256372770211860618687961310422228379031, + 12690713110714036569415168795200156516217175005650145422920562694422306200486, + 17386427286863519095301372413760745749282643730629659997153085139065756667205, + 2216432659854733047132347621569505613620980842043977268828076165669557467682, + 6309765381643925252238633914530877025934201680691496500372265330505506717193, + 20806323192073945401862788605803131761175139076694468214027227878952047793390, + 4037040458505567977365391535756875199663510397600316887746139396052445718861, + 19948974083684238245321361840704327952464170097132407924861169241740046562673, + 845322671528508199439318170916419179535949348988022948153107378280175750024, + 16222384601744433420585982239113457177459602187868460608565289920306145389382, + 10232118865851112229330353999139005145127746617219324244541194256766741433339, + 6699067738555349409504843460654299019000594109597429103342076743347235369120, + 6220784880752427143725783746407285094967584864656399181815603544365010379208, + 6129250029437675212264306655559561251995722990149771051304736001195288083309, + 10773245783118750721454994239248013870822765715268323522295722350908043393604, + 4490242021765793917495398271905043433053432245571325177153467194570741607167, + 19596995117319480189066041930051006586888908165330319666010398892494684778526, + 837850695495734270707668553360118467905109360511302468085569220634750561083, + 11803922811376367215191737026157445294481406304781326649717082177394185903907, + 10201298324909697255105265958780781450978049256931478989759448189112393506592, + 13564695482314888817576351063608519127702411536552857463682060761575100923924, + 9262808208636973454201420823766139682381973240743541030659775288508921362724, + 173271062536305557219323722062711383294158572562695717740068656098441040230, + 18120430890549410286417591505529104700901943324772175772035648111937818237369, + 20484495168135072493552514219686101965206843697794133766912991150184337935627, + 19155651295705203459475805213866664350848604323501251939850063308319753686505, + 11971299749478202793661982361798418342615500543489781306376058267926437157297, + 18285310723116790056148596536349375622245669010373674803854111592441823052978, + 7069216248902547653615508023941692395371990416048967468982099270925308100727, + 6465151453746412132599596984628739550147379072443683076388208843341824127379, + 16143532858389170960690347742477978826830511669766530042104134302796355145785, + 19362583304414853660976404410208489566967618125972377176980367224623492419647, + 1702213613534733786921602839210290505213503664731919006932367875629005980493, + 10781825404476535814285389902565833897646945212027592373510689209734812292327, + 4212716923652881254737947578600828255798948993302968210248673545442808456151, + 7594017890037021425366623750593200398174488805473151513558919864633711506220, + 18979889247746272055963929241596362599320706910852082477600815822482192194401, + 13602139229813231349386885113156901793661719180900395818909719758150455500533, + ]; + + // Iterate through each round to compute the hash. + for round in 0..rounds { + // Calculate intermediate values based on the round. + let exp1_else = (key + exp7) + csts[round]; + let exp1 = if round == 0 { init } else { exp1_else }; + let exp2 = exp1 * exp1; + let exp4 = exp2 * exp2; + let exp6 = exp4 * exp2; + let exp7_then = exp6 * exp1; + let exp7_else = exp7_then + key; + // Update exp7 based on whether it's the last round. + exp7 = if round != (rounds - 1) { exp7_then } else { exp7_else }; + } + + // Return the final hash value. + return exp7; +} + +/// MIMC hash function for multiple values. +/// Uses the `mimc7_cipher` function iteratively to hash an array of values. +/// +/// # Parameters +/// - `values`: An array of `Field` values to be hashed. +/// - `key`: The secret key used in the hash computation. +/// +/// # Returns +/// - `Field`: The resulting hash after processing all input values. +/// +fn mimc7_hash(values: [Field; LEN], key: Field) -> Field { + // Initialize with the key. + let mut res = key; + // Iterate over each value in the input array. + for value in values { + // Update the result with the MIMC hash of the value and the current result. + res = res + (value + mimc7_cipher(value, res)); + } + // Return the final accumulated result. + return res; +} diff --git a/src/tests/stdlib/mimc/mimc_main.no b/src/tests/stdlib/mimc/mimc_main.no new file mode 100644 index 000000000..1e104d1f8 --- /dev/null +++ b/src/tests/stdlib/mimc/mimc_main.no @@ -0,0 +1,7 @@ +use std::mimc; + +fn main(pub key: Field, val: Field) -> Field { + let res = mimc::mimc7_cipher(val, key); + + return res; +} \ No newline at end of file diff --git a/src/tests/stdlib/mimc/mod.rs b/src/tests/stdlib/mimc/mod.rs new file mode 100644 index 000000000..cf11059be --- /dev/null +++ b/src/tests/stdlib/mimc/mod.rs @@ -0,0 +1,207 @@ +use crate::{ + backends::r1cs::R1csBn254Field, + error::{self}, +}; + +use super::test_stdlib; +use ark_ff::Field; +use error::Result; +use num_bigint::BigUint; +use num_traits::Zero; +use rstest::rstest; +use std::str::FromStr; + +/// Parses a decimal string into an Fq field element. +fn fq_from_str(s: &str) -> R1csBn254Field { + R1csBn254Field::from_str(s).unwrap() +} + +/// MiMC7 hash function implementation. +fn mimc7(x_in: R1csBn254Field, k: R1csBn254Field, n_rounds: usize) -> R1csBn254Field { + // Round constants c[91] + let c_strings = [ + "0", + "20888961410941983456478427210666206549300505294776164667214940546594746570981", + "15265126113435022738560151911929040668591755459209400716467504685752745317193", + "8334177627492981984476504167502758309043212251641796197711684499645635709656", + "1374324219480165500871639364801692115397519265181803854177629327624133579404", + "11442588683664344394633565859260176446561886575962616332903193988751292992472", + "2558901189096558760448896669327086721003508630712968559048179091037845349145", + "11189978595292752354820141775598510151189959177917284797737745690127318076389", + "3262966573163560839685415914157855077211340576201936620532175028036746741754", + "17029914891543225301403832095880481731551830725367286980611178737703889171730", + "4614037031668406927330683909387957156531244689520944789503628527855167665518", + "19647356996769918391113967168615123299113119185942498194367262335168397100658", + "5040699236106090655289931820723926657076483236860546282406111821875672148900", + "2632385916954580941368956176626336146806721642583847728103570779270161510514", + "17691411851977575435597871505860208507285462834710151833948561098560743654671", + "11482807709115676646560379017491661435505951727793345550942389701970904563183", + "8360838254132998143349158726141014535383109403565779450210746881879715734773", + "12663821244032248511491386323242575231591777785787269938928497649288048289525", + "3067001377342968891237590775929219083706800062321980129409398033259904188058", + "8536471869378957766675292398190944925664113548202769136103887479787957959589", + "19825444354178182240559170937204690272111734703605805530888940813160705385792", + "16703465144013840124940690347975638755097486902749048533167980887413919317592", + "13061236261277650370863439564453267964462486225679643020432589226741411380501", + "10864774797625152707517901967943775867717907803542223029967000416969007792571", + "10035653564014594269791753415727486340557376923045841607746250017541686319774", + "3446968588058668564420958894889124905706353937375068998436129414772610003289", + "4653317306466493184743870159523234588955994456998076243468148492375236846006", + "8486711143589723036499933521576871883500223198263343024003617825616410932026", + "250710584458582618659378487568129931785810765264752039738223488321597070280", + "2104159799604932521291371026105311735948154964200596636974609406977292675173", + "16313562605837709339799839901240652934758303521543693857533755376563489378839", + "6032365105133504724925793806318578936233045029919447519826248813478479197288", + "14025118133847866722315446277964222215118620050302054655768867040006542798474", + "7400123822125662712777833064081316757896757785777291653271747396958201309118", + "1744432620323851751204287974553233986555641872755053103823939564833813704825", + "8316378125659383262515151597439205374263247719876250938893842106722210729522", + "6739722627047123650704294650168547689199576889424317598327664349670094847386", + "21211457866117465531949733809706514799713333930924902519246949506964470524162", + "13718112532745211817410303291774369209520657938741992779396229864894885156527", + "5264534817993325015357427094323255342713527811596856940387954546330728068658", + "18884137497114307927425084003812022333609937761793387700010402412840002189451", + "5148596049900083984813839872929010525572543381981952060869301611018636120248", + "19799686398774806587970184652860783461860993790013219899147141137827718662674", + "19240878651604412704364448729659032944342952609050243268894572835672205984837", + "10546185249390392695582524554167530669949955276893453512788278945742408153192", + "5507959600969845538113649209272736011390582494851145043668969080335346810411", + "18177751737739153338153217698774510185696788019377850245260475034576050820091", + "19603444733183990109492724100282114612026332366576932662794133334264283907557", + "10548274686824425401349248282213580046351514091431715597441736281987273193140", + "1823201861560942974198127384034483127920205835821334101215923769688644479957", + "11867589662193422187545516240823411225342068709600734253659804646934346124945", + "18718569356736340558616379408444812528964066420519677106145092918482774343613", + "10530777752259630125564678480897857853807637120039176813174150229243735996839", + "20486583726592018813337145844457018474256372770211860618687961310422228379031", + "12690713110714036569415168795200156516217175005650145422920562694422306200486", + "17386427286863519095301372413760745749282643730629659997153085139065756667205", + "2216432659854733047132347621569505613620980842043977268828076165669557467682", + "6309765381643925252238633914530877025934201680691496500372265330505506717193", + "20806323192073945401862788605803131761175139076694468214027227878952047793390", + "4037040458505567977365391535756875199663510397600316887746139396052445718861", + "19948974083684238245321361840704327952464170097132407924861169241740046562673", + "845322671528508199439318170916419179535949348988022948153107378280175750024", + "16222384601744433420585982239113457177459602187868460608565289920306145389382", + "10232118865851112229330353999139005145127746617219324244541194256766741433339", + "6699067738555349409504843460654299019000594109597429103342076743347235369120", + "6220784880752427143725783746407285094967584864656399181815603544365010379208", + "6129250029437675212264306655559561251995722990149771051304736001195288083309", + "10773245783118750721454994239248013870822765715268323522295722350908043393604", + "4490242021765793917495398271905043433053432245571325177153467194570741607167", + "19596995117319480189066041930051006586888908165330319666010398892494684778526", + "837850695495734270707668553360118467905109360511302468085569220634750561083", + "11803922811376367215191737026157445294481406304781326649717082177394185903907", + "10201298324909697255105265958780781450978049256931478989759448189112393506592", + "13564695482314888817576351063608519127702411536552857463682060761575100923924", + "9262808208636973454201420823766139682381973240743541030659775288508921362724", + "173271062536305557219323722062711383294158572562695717740068656098441040230", + "18120430890549410286417591505529104700901943324772175772035648111937818237369", + "20484495168135072493552514219686101965206843697794133766912991150184337935627", + "19155651295705203459475805213866664350848604323501251939850063308319753686505", + "11971299749478202793661982361798418342615500543489781306376058267926437157297", + "18285310723116790056148596536349375622245669010373674803854111592441823052978", + "7069216248902547653615508023941692395371990416048967468982099270925308100727", + "6465151453746412132599596984628739550147379072443683076388208843341824127379", + "16143532858389170960690347742477978826830511669766530042104134302796355145785", + "19362583304414853660976404410208489566967618125972377176980367224623492419647", + "1702213613534733786921602839210290505213503664731919006932367875629005980493", + "10781825404476535814285389902565833897646945212027592373510689209734812292327", + "4212716923652881254737947578600828255798948993302968210248673545442808456151", + "7594017890037021425366623750593200398174488805473151513558919864633711506220", + "18979889247746272055963929241596362599320706910852082477600815822482192194401", + "13602139229813231349386885113156901793661719180900395818909719758150455500533", + ]; + + // Convert constants to field elements + let c: Vec = c_strings + .iter() + .map(|&s| R1csBn254Field::from_str(s).unwrap()) + .collect(); + + let mut t7 = Vec::with_capacity(n_rounds - 1); + let mut out = R1csBn254Field::zero(); + + for i in 0..n_rounds { + let t = if i == 0 { + k + x_in + } else { + k + t7[i - 1] + c[i] + }; + + let t2 = t.square(); // t^2 + let t4 = t2.square(); // t^4 + let t6 = t4 * t2; // t^6 + + if i < n_rounds - 1 { + let t7_i = t6 * t; // t^7 + t7.push(t7_i); + } else { + out = t6 * t + k; // Final output: t^7 + k + } + } + + out +} + +fn multi_mimc7(k: R1csBn254Field, values: Vec, n_rounds: usize) -> R1csBn254Field { + let mut res = k; + for x in values { + res = res + x + mimc7(x, res, n_rounds); + } + res +} + +#[rstest] +#[case(0, 1, 91)] +fn test_mimc(#[case] key: u32, #[case] val: u32, #[case] n_rounds: usize) -> Result<()> { + let public_inputs = format!(r#"{{"key": "{}"}}"#, key); + let private_inputs = format!(r#"{{"val": "{}"}}"#, val); + + let x = fq_from_str(val.to_string().as_str()); + let k = fq_from_str(key.to_string().as_str()); + + let expected_output: BigUint = mimc7(x, k, n_rounds).into(); + + test_stdlib( + "mimc/mimc_main.no", + None, + &public_inputs, + &private_inputs, + vec![&expected_output.to_string()], + )?; + + Ok(()) +} + +#[rstest] +#[case(0, vec![1, 2, 3])] +fn test_multi_mimc(#[case] key: u32, #[case] values: Vec) -> Result<()> { + let k = fq_from_str(key.to_string().as_str()); + let x = values + .iter() + .map(|v| fq_from_str(v.to_string().as_str())) + .collect(); + + let expected_output: BigUint = multi_mimc7(k, x, 91).into(); + + let public_inputs = format!(r#"{{"key": "{}"}}"#, key); + // convert to ["1", "2", ...] + let private_inputs = format!( + r#"{{"values": {:?}}}"#, + values + .iter() + .map(|v| v.to_string()) + .collect::>() + ); + + test_stdlib( + "mimc/multi_mimc_main.no", + None, + &public_inputs, + &private_inputs, + vec![&expected_output.to_string()], + )?; + + Ok(()) +} diff --git a/src/tests/stdlib/mimc/multi_mimc_main.no b/src/tests/stdlib/mimc/multi_mimc_main.no new file mode 100644 index 000000000..73f56d104 --- /dev/null +++ b/src/tests/stdlib/mimc/multi_mimc_main.no @@ -0,0 +1,7 @@ +use std::mimc; + +fn main(pub key: Field, values: [Field; 3]) -> Field { + let res = mimc::mimc7_hash(values, key); + + return res; +} \ No newline at end of file diff --git a/src/tests/stdlib/mod.rs b/src/tests/stdlib/mod.rs index 6f81d2a9f..3bac61a6f 100644 --- a/src/tests/stdlib/mod.rs +++ b/src/tests/stdlib/mod.rs @@ -1,4 +1,5 @@ mod comparator; +mod mimc; mod multiplexer; use std::{path::Path, str::FromStr}; diff --git a/src/type_checker/checker.rs b/src/type_checker/checker.rs index ffa802c9f..cb69360c9 100644 --- a/src/type_checker/checker.rs +++ b/src/type_checker/checker.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use num_traits::ToPrimitive; use serde::{Deserialize, Serialize}; use crate::{ @@ -619,7 +620,10 @@ impl TypeChecker { let sym = Symbolic::parse(size)?; let res = if let Symbolic::Concrete(size) = sym { // if sym is a concrete variant, then just return concrete array type - ExprTyInfo::new_anon(TyKind::Array(Box::new(item_node.typ), size)) + ExprTyInfo::new_anon(TyKind::Array( + Box::new(item_node.typ), + size.to_u32().expect("array size too large"), + )) } else { // use generic array as the size node might include generic parameters or constant vars ExprTyInfo::new_anon(TyKind::GenericSizedArray(