From 37446bf34db4e62637770962cb75b02e426b0c42 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Mon, 28 Oct 2024 09:17:45 +0000 Subject: [PATCH 01/24] wip --- oracles/Cargo.lock | 1941 ++++++++++++++++++++++++++++++ oracles/Cargo.toml | 24 + oracles/src/foreign_call.rs | 98 ++ oracles/src/handlers.rs | 183 +++ oracles/src/main.rs | 131 ++ oracles/src/ops.rs | 22 + src/fns/unconstrained_helpers.nr | 103 +- src/fns/unconstrained_ops.nr | 53 +- src/runtime_bignum.nr | 2 +- src/tests/bignum_test.nr | 33 + 10 files changed, 2529 insertions(+), 61 deletions(-) create mode 100644 oracles/Cargo.lock create mode 100644 oracles/Cargo.toml create mode 100644 oracles/src/foreign_call.rs create mode 100644 oracles/src/handlers.rs create mode 100644 oracles/src/main.rs create mode 100644 oracles/src/ops.rs diff --git a/oracles/Cargo.lock b/oracles/Cargo.lock new file mode 100644 index 00000000..b70ad1a7 --- /dev/null +++ b/oracles/Cargo.lock @@ -0,0 +1,1941 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "log", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jsonrpsee" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-proc-macros", + "jsonrpsee-server", + "jsonrpsee-types", + "jsonrpsee-ws-client", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548125b159ba1314104f5bb5f38519e03a41862786aa3925cf349aae9cdd546e" +dependencies = [ + "base64", + "futures-util", + "http", + "jsonrpsee-core", + "pin-project", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "soketto", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2882f6f8acb9fdaec7cefc4fd607119a9bd709831df7d7672a1d3b644628280" +dependencies = [ + "async-trait", + "bytes", + "futures-timer", + "futures-util", + "http", + "http-body", + "http-body-util", + "jsonrpsee-types", + "parking_lot", + "pin-project", + "rand", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3638bc4617f96675973253b3a45006933bde93c2fd8a6170b33c777cc389e5b" +dependencies = [ + "async-trait", + "base64", + "http-body", + "hyper", + "hyper-rustls", + "hyper-util", + "jsonrpsee-core", + "jsonrpsee-types", + "rustls", + "rustls-platform-verifier", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06c01ae0007548e73412c08e2285ffe5d723195bf268bce67b1b77c3bb2a14d" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ad8ddc14be1d4290cd68046e7d1d37acd408efed6d3ca08aefcc3ad6da069c" +dependencies = [ + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project", + "route-recognizer", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a178c60086f24cc35bb82f57c651d0d25d99c4742b4d335de04e97fa1f08a8a1" +dependencies = [ + "http", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe322e0896d0955a3ebdd5bf813571c53fea29edd713bc315b76620b327e86d" +dependencies = [ + "http", + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", + "url", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "oracle" +version = "0.1.0" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-ff", + "jsonrpsee", + "num-bigint", + "num-traits", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "route-recognizer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.23.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-roots", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "soketto" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53" +dependencies = [ + "base64", + "bytes", + "futures", + "http", + "httparse", + "log", + "rand", + "sha1", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] diff --git a/oracles/Cargo.toml b/oracles/Cargo.toml new file mode 100644 index 00000000..f99e662f --- /dev/null +++ b/oracles/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "oracle" +version = "0.1.0" +edition = "2021" + +[dependencies] +# For the server +anyhow = "1" +# hyper = "1.5.0" +jsonrpsee = { version = "0.24.7", features = ["server", "http-client", "ws-client", "macros", "client-ws-transport-tls"] } +serde = "1.0.213" +serde_json = "1.0.132" +tokio = "1.41.0" +tokio-stream = { version = "0.1.16", features = ["sync"] } +# tower = { version = "0.4.13", features= ["full"]} +# tower-http = { version = "0.6.1", features = ["full"] } +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } + +# For the example ops +ark-bn254 = "0.4.0" +ark-ff = "0.4.2" +num-bigint = "0.4.6" # todo: find a way to remove this dep +num-traits = "0.2.19" # todo: find a way to remove this dep diff --git a/oracles/src/foreign_call.rs b/oracles/src/foreign_call.rs new file mode 100644 index 00000000..ee0235dc --- /dev/null +++ b/oracles/src/foreign_call.rs @@ -0,0 +1,98 @@ +// This is basically a copy of noir/acvm-repo/brillig/src/foreign_call.rs + +use serde::{de::value, Deserialize, Serialize}; + +/// Single output of a [foreign call][crate::Opcode::ForeignCall]. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] +#[serde(untagged)] +pub enum ForeignCallParam { + Single(F), + Array(Vec), +} + +impl From for ForeignCallParam { + fn from(value: F) -> Self { + ForeignCallParam::Single(value) + } +} + +impl From> for ForeignCallParam { + fn from(values: Vec) -> Self { + ForeignCallParam::Array(values) + } +} + +impl ForeignCallParam where F: Clone { + pub fn len(&self) -> usize { + match self { + ForeignCallParam::Single(_) => 1, + ForeignCallParam::Array(values) => values.len(), + } + } + + pub fn get_values(&self) -> Vec { + match self { + ForeignCallParam::Single(value) => vec![value.clone()], + ForeignCallParam::Array(values) => values.clone(), + } + } + +} + + +// impl len> for ForeignCallParam { +// fn len(&self) -> usize { +// match self { +// ForeignCallParam::Single(_) => 1, +// ForeignCallParam::Array(values) => values.len(), +// } +// } +// } + +// /// Represents the full output of a [foreign call][crate::Opcode::ForeignCall]. +// #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Default)] +// pub struct ForeignCallResult { +// /// Resolved output values of the foreign call. +// pub values: Vec>, +// } + +// impl From for ForeignCallResult { +// fn from(value: F) -> Self { +// ForeignCallResult { +// values: vec![value.into()], +// } +// } +// } + +// impl From> for ForeignCallResult { +// fn from(values: Vec) -> Self { +// ForeignCallResult { +// values: vec![values.into()], +// } +// } +// } + +// impl From>> for ForeignCallResult { +// fn from(values: Vec>) -> Self { +// ForeignCallResult { values } +// } +// } + +// impl ForeignCallParam +// where +// F: Clone + Copy, +// { +// pub fn unwrap_fields(&self) -> Vec { +// match self { +// ForeignCallParam::Single(value) => vec![*value], +// ForeignCallParam::Array(values) => values.to_vec(), +// } +// } + +// pub fn unwrap_field(&self) -> F { +// match self { +// ForeignCallParam::Single(value) => *value, +// ForeignCallParam::Array(_) => panic!("Expected single value, found array"), +// } +// } +// } diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs new file mode 100644 index 00000000..bb14b89e --- /dev/null +++ b/oracles/src/handlers.rs @@ -0,0 +1,183 @@ +use ark_bn254::Fr; +use num_bigint::BigUint; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? +use num_traits::Num; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? +use serde_json::{json, Value}; +// use std::str::FromStr; + +use crate::foreign_call::ForeignCallParam; + +use crate::ops::sqrt; + +/**** THERE'S A LOT OF BOILERPLATE INSIDE THESE "HANDLERS", THAT WE CAN PROBABLY PUT INTO COMMON HELPER FUNCTIONS ****/ + +/** Note: I _think_ the type `Vec>` will be generically applicable to _any_ oracle call arguments, so I've made _all_ handlers receive this type. */ +pub(crate) fn handle_get_sqrt(inputs: &Vec>) -> Value { + /**** EXTRACT INPUT STRING(S) ****/ + println!("inputs: {:?}", inputs); + assert!(inputs.len() == 1); + + let input_param = &inputs[0]; + + let input_string = match input_param { + ForeignCallParam::Single(value) => value.trim_start_matches('0'), // Trimming leading zeroes turned out to be very important, otherwise `from_str` on the next line was erroring! + ForeignCallParam::Array(_) => panic!("Expected single value, found array"), + }; + + println!("input_string: {:?}", input_string); + + /**** CONVERT INPUT STRING(S) TO MEANINGFUL TYPE(S) ****/ + let x_big_uint: BigUint = BigUint::from_str_radix(input_string, 16).unwrap(); + let x: Fr = x_big_uint.into(); + // let x: Fr = Fr::from_str(input_string).unwrap(); // This was incorrectly assuming the input_string to be decimal. + println!("x: {:?}", x); + + /**** OPERATE ****/ + let sqrt = sqrt(x); + println!("Computed sqrt: {:?}", sqrt); + + /**** ENSURE HEX ****/ + let as_big_uint: BigUint = sqrt.unwrap().into(); + let as_hex_str = as_big_uint.to_str_radix(16); + + let oracle_return_data_the_noir_program_expects = as_hex_str; + + /**** FORMAT RESULT FOR NOIR CONSUMPTION, AND CONVERT RESULT TO JSON `Value` TYPE ****/ + //** Note: I'm converting to `Value` within these "handler" functions, instead of within the main callback (the callback inside run_server --> module.register_method --> resolve_foreign_call), because the return types can be subtly different: Vec, or Vec>, or maybe some more-complex arrangement of Strings and Vec. It felt easiest to have the "hander" functions figure out how to serialise their return data. */ + let return_vec = vec![oracle_return_data_the_noir_program_expects]; + println!("return_vec: {:?}", return_vec); + + let json_response = json!({"values" : return_vec}); + println!("json_response: {:?}", json_response); + json_response +} + + +pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value { + /**** EXTRACT INPUT STRING(S) ****/ + println!("inputs: {:?}", inputs); + + let input_param = &inputs[0]; + let input_strings: Vec<&str> = match input_param { + ForeignCallParam::Single(_value) => panic!("Expected array, found single value"), + ForeignCallParam::Array(values) => values + .into_iter() + .map(|v| v.trim_start_matches('0')) + .collect(), + }; + + println!("input_strings: {:?}", input_strings); + + let mut sqrts: Vec = vec![]; + + for input_string in input_strings { + /**** CONVERT INPUT STRING(S) TO MEANINGFUL TYPE(S) ****/ + println!("input_string: {:?}", input_string); + + let x_big_uint: BigUint = BigUint::from_str_radix(input_string, 16).unwrap(); + let x: Fr = x_big_uint.into(); + // let x: Fr = Fr::from_str(input_string).unwrap(); // This was incorrectly assuming the input_string to be decimal. + println!("x: {:?}", x); + + /**** OPERATE ****/ + let sqrt = sqrt(x); + println!("Computed sqrt: {:?}", sqrt); + + /**** ENSURE HEX ****/ + let as_big_uint: BigUint = sqrt.unwrap().into(); + let as_hex_str = as_big_uint.to_str_radix(16); + + sqrts.push(as_hex_str); + } + + let oracle_return_data_the_noir_program_expects = sqrts; + + /**** FORMAT RESULT FOR NOIR CONSUMPTION, AND CONVERT RESULT TO JSON `Value` TYPE ****/ + let return_vec = vec![oracle_return_data_the_noir_program_expects]; // Notice! This is a different type from the singular handle_get_sqrt function! Hence why the `Value` is being computed inside this function, instead in the calling function. + println!("return_vec: {:?}", return_vec); + + let json_response = json!({"values" : return_vec}); + println!("json_response: {:?}", json_response); + json_response +} + + + + +// ============================== +// ============================== +// ============================== +// call handler for is_zero +pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { + println!("you called the is_zero function with inputs: {:?}", inputs); + // Create a vector with a single boolean value (true) as the result + let return_vec = vec![true]; + + // Create a JSON object with a "values" key containing the return_vec + let json_response = json!({"values" : return_vec}); + + // Print the JSON response for debugging purposes + println!("json_response: {:?}", json_response); + json_response +} + +// ============================== +// ============================== +// ============================== +// call handler for add +pub(crate) fn handle_add(inputs: &Vec>) -> Value { + println!("inputs for add: {:?}", inputs); + + let input_param = &inputs[0]; + // println!("input_param: {:?}", input_param); + + // println!("inputs length: {:?}", inputs.len()); + let mut has_multiplicative_inverse = inputs[0].clone(); + let mut modulus = inputs[1].clone(); + let mut modulus_u60 = inputs[2].clone(); + let mut modulus_u60_x4 = inputs[3].clone(); + let mut double_modulus = inputs[4].clone(); + let mut redc_param = inputs[5].clone(); + let mut lhs = inputs[6].clone(); + let mut rhs = inputs[7].clone(); + + // get the number of limbs from the length of the modulus + let N = modulus.len(); + println!("number of limbs {:?}", N); + let modulus_values: Vec = modulus.get_values(); + println!("modulus_values length: {:?}", modulus_values.len()); + let has_multiplicative_inverse_value = has_multiplicative_inverse.get_values(); + println!("has_multiplicative_inverse_value: {:?}", has_multiplicative_inverse_value); + // println!("modulus: {:?}", modulus_values); + + // println!("has_multiplicative_inverse: {:?}", has_multiplicative_inverse); + // println!("modulus length: {:?}", modulus.len()); + // println!("modulus_u60: {:?}", modulus_u60); + // println!("modulus_u60_x4: {:?}", modulus_u60_x4); + // println!("double_modulus: {:?}", double_modulus); + // println!("redc_param: {:?}", redc_param); + // println!("lhs: {:?}", lhs); + // println!("rhs: {:?}", rhs); + + + // println!("number_of_limbs: {:?}", number_of_limbs); + + // compute what the number of limbs are + // println!("lhs: {:?}", lhs); + // println!("rhs: {:?}", rhs); + + // println!("input_param type: {:?}", input_param.type_name()); + // let input_strings = inputs.unwrap(); + // println!("input_strings: {:?}", input_strings); + // let input_strings: Vec<&str> = match input_param { + // ForeignCallParam::Single(_value) => panic!("Expected array, found single value"), + // ForeignCallParam::Array(values) => values + // .into_iter() + // .map(|v| v.trim_start_matches('0')) + // .collect(), + // }; + + + let return_vec = vec![true]; + let json_response = json!({"values" : return_vec}); + json_response +} \ No newline at end of file diff --git a/oracles/src/main.rs b/oracles/src/main.rs new file mode 100644 index 00000000..5e8f0c7e --- /dev/null +++ b/oracles/src/main.rs @@ -0,0 +1,131 @@ +// This copyright notice relates to the `jsonrpsee` boilerplate that was used to kickstart this project: + +// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the +// Software without restriction, including without +// limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +mod foreign_call; +mod handlers; +mod ops; + +use jsonrpsee::server::{RpcModule, Server}; +use std::net::SocketAddr; +use tracing_subscriber::util::SubscriberInitExt; + +use serde::Deserialize; +use serde_json::{json, Value}; + +use crate::foreign_call::ForeignCallParam; +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add}; + +// SPIN UP THE SERVER +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let filter = tracing_subscriber::EnvFilter::try_from_default_env()? + .add_directive("jsonrpsee[method_call{name = \"say_hello\"}]=trace".parse()?); + tracing_subscriber::FmtSubscriber::builder() + .with_env_filter(filter) + .finish() + .try_init()?; + + let _server_addr = run_server().await?; + + Ok(()) +} + +fn print_type(_: &T) { + println!("{:?}", std::any::type_name::()); +} + +#[derive(Debug, Deserialize)] +struct RequestData { + session_id: u64, + function: String, + inputs: Vec>, + root_path: String, + package_name: String, +} + +#[derive(Debug, Deserialize)] +struct Requests(Vec); // Wrap it in a struct to handle the array + +pub(crate) fn handle_unknown_function(_input: &RequestData) -> Value { + println!("oops"); + json!(vec![String::from("oops")]) +} + +async fn run_server() -> anyhow::Result { + let server = Server::builder() + .build("127.0.0.1:3000".parse::()?) + .await?; + let mut module = RpcModule::new(()); + + module.register_method("say_hello", |_, _, _| "hello, world")?; + + module.register_method("resolve_foreign_call", |params, _, _| { + // println!("\n\nNEW REQUEST!!!"); + // print_type(¶ms); + // println!("params{:?}", params); + + let response: Value = if let Some(json_string) = params.as_str() { + // Deserialize the JSON string into the Requests struct: + let requests: Requests = + serde_json::from_str(&json_string).expect("Failed to parse JSON"); + + let request = &requests.0[0]; + + // println!("Request function{:?}", request.function); + + let result: Value = match request.function.as_str() { + "get_sqrt" => handle_get_sqrt(&request.inputs), // the inputs to this are effectively a Vec + "get_sqrts" => handle_get_sqrts(&request.inputs), // the inputs to this are effectively a Vec> + "is_zero" => handle_is_zero(&request.inputs), // the inputs to this are effectively a Vec + "add" => handle_add(&request.inputs), // the inputs to this are effectively a Vec + _ => handle_unknown_function(&request), + }; + + result + } else { + println!("No parameters provided"); + json!(vec![String::from("Bad query")]) + }; + + response + })?; + + let addr = server.local_addr()?; + let handle = server.start(module); + + println!("Server is running on 127.0.0.1:3000"); + + // In this example we don't care about doing shutdown so let's it run forever. + // You may use the `ServerHandle` to shut it down or manage it yourself. + // tokio::spawn(handle.stopped()); + + // Keep the server running until it's interrupted + handle.stopped().await; + + Ok(addr) +} diff --git a/oracles/src/ops.rs b/oracles/src/ops.rs new file mode 100644 index 00000000..0b5ed7e9 --- /dev/null +++ b/oracles/src/ops.rs @@ -0,0 +1,22 @@ +use ark_bn254::Fr; +use ark_ff::Field; + +pub(crate) fn sqrt(x: Fr) -> Option { + let sqrt: Option = if x.legendre().is_qr() { + let sqrt = x.sqrt().unwrap(); + assert_eq!(sqrt.square(), x); + + Some(sqrt) + } else { + assert_eq!(x.sqrt(), None); + + None + }; + + if sqrt == None { + // I can't be bothered figuring out how to serialise an `Option::None` back to Noir-land, so I'm panicking in this case, instead. + panic!("NO SQUARE ROOT EXISTS"); + } + + sqrt +} \ No newline at end of file diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 694971e5..0849e44d 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -97,55 +97,72 @@ pub(crate) unconstrained fn __neg_with_flags( (result, borrow_flags) } + +//this is the actual function that be changed to use oracles +#[oracle(add)] +pub (crate) unconstrained fn oracle_add( + params: P, + lhs: [Field; N], + rhs: [Field; N], +) -> ([Field; N], [bool; N], [bool; N], bool) {} pub(crate) unconstrained fn __add_with_flags( params: P, lhs: [Field; N], rhs: [Field; N], -) -> ([Field; N], [bool; N], [bool; N], bool) { - let a_u60: U60Repr = U60Repr::from(lhs); - let b_u60: U60Repr = U60Repr::from(rhs); - let add_u60 = a_u60 + b_u60; - - let overflow = add_u60.gte(params.modulus_u60); - - let mut subtrahend_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; - let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; - - if overflow { - subtrahend_u60 = params.modulus_u60; - } - - let mut carry: u64 = 0; - let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; - let mut borrow_in: u64 = 0; - let mut borrow_flags: [bool; N] = [false; N]; - let mut carry_flags: [bool; N] = [false; N]; - for i in 0..2 * N { - let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; - borrow_in = borrow; +) -> ([Field; N], [bool; N], [bool; N], bool){ + oracle_add(params, lhs, rhs) +} - if ((i & 1) == 1) { - let idx = (i - 1) / 2; - if (carry & borrow == 1) { - carry = 0; - borrow = 0; - } - carry_flags[idx] = carry as bool; - borrow_flags[idx] = borrow as bool; - } - } - let result = U60Repr::into(result_u60); - (result, carry_flags, borrow_flags, overflow) -} +// pub(crate) unconstrained fn __add_with_flags( +// params: P, +// lhs: [Field; N], +// rhs: [Field; N], +// ) -> ([Field; N], [bool; N], [bool; N], bool) { +// let a_u60: U60Repr = U60Repr::from(lhs); +// let b_u60: U60Repr = U60Repr::from(rhs); +// let add_u60 = a_u60 + b_u60; + +// let overflow = add_u60.gte(params.modulus_u60); + +// let mut subtrahend_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; +// let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; + +// if overflow { +// subtrahend_u60 = params.modulus_u60; +// } + +// let mut carry: u64 = 0; +// let mut carry_in: u64 = 0; +// let mut borrow: u64 = 0; +// let mut borrow_in: u64 = 0; +// let mut borrow_flags: [bool; N] = [false; N]; +// let mut carry_flags: [bool; N] = [false; N]; +// for i in 0..2 * N { +// let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; +// carry = (add_term >= 0x1000000000000000) as u64; +// add_term -= (carry as u64 * 0x1000000000000000); +// result_u60.limbs[i] = add_term; +// carry_in = carry as u64; +// borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; +// let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; +// result_u60.limbs[i] = sub; +// borrow_in = borrow; + +// if ((i & 1) == 1) { +// let idx = (i - 1) / 2; +// if (carry & borrow == 1) { +// carry = 0; +// borrow = 0; +// } +// carry_flags[idx] = carry as bool; +// borrow_flags[idx] = borrow as bool; +// } +// } +// let result = U60Repr::into(result_u60); + +// (result, carry_flags, borrow_flags, overflow) +// } pub(crate) unconstrained fn __sub_with_flags( params: P, diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index b72f913b..bb9ac02e 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -119,14 +119,17 @@ pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) - lhs == rhs } -pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool { - let mut result: bool = true; - for i in 0..N { - result = result & (limbs[i] == 0); - } - result -} +//switching this function to use oracles instead +// pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool { +// let mut result: bool = true; +// for i in 0..N { +// result = result & (limbs[i] == 0); +// } +// result +// } + #[oracle(is_zero)] +pub (crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} /** * @brief given an input `x`, compute `2p - x` (unconstrained) * @@ -146,20 +149,36 @@ pub(crate) unconstrained fn __neg( U60Repr::into(params.modulus_u60 - x_u60) } -pub(crate) unconstrained fn __add( +// switching this function to use oracles instead +// pub(crate) unconstrained fn __add( +// params: P, +// lhs: [Field; N], +// rhs: [Field; N], +// ) -> [Field; N] { +// let x_u60: U60Repr = U60Repr::from(lhs); +// let y_u60: U60Repr = U60Repr::from(rhs); + +// let mut z_u60 = x_u60 + y_u60; + +// if z_u60.gte(params.modulus_u60) { +// z_u60 = z_u60 - params.modulus_u60; +// } +// U60Repr::into(z_u60) +// } +// the oracle function to get the add result + #[oracle(add)] + pub (crate) unconstrained fn add_oracle( params: P, lhs: [Field; N], rhs: [Field; N], -) -> [Field; N] { - let x_u60: U60Repr = U60Repr::from(lhs); - let y_u60: U60Repr = U60Repr::from(rhs); - - let mut z_u60 = x_u60 + y_u60; +) -> [Field; N] {} - if z_u60.gte(params.modulus_u60) { - z_u60 = z_u60 - params.modulus_u60; - } - U60Repr::into(z_u60) +pub (crate) unconstrained fn __add( + params: P, + lhs: [Field; N], + rhs: [Field; N], +) -> [Field; N] { + add_oracle(params, lhs, rhs) } /** diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 66e091eb..135de7da 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -226,7 +226,7 @@ impl RuntimeBigNumTrait for RuntimeB // UNCONSTRAINED! (Hence `__` prefix). fn __sub(self, other: Self) -> Self { - let params = self.params; + let params: BigNumParams = self.params; let limbs = unsafe { __sub(params, self.limbs, other.limbs) }; Self { params, limbs } } diff --git a/src/tests/bignum_test.nr b/src/tests/bignum_test.nr index 9449ddc3..35fcc069 100644 --- a/src/tests/bignum_test.nr +++ b/src/tests/bignum_test.nr @@ -632,6 +632,7 @@ fn test_udiv_mod_U256() { assert(product == a); } + // // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_div_2048() { @@ -790,3 +791,35 @@ fn test_expressions() { assert(wx_constrained.limbs == wx.limbs); } + + + +#[test] +fn test_oracle_add() { + // type Fq = BigNum <3,254, BN254_Fq_Params> ; + let a: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000003 + ]}; + let b: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000001 + ]}; + let c : Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000002 + ]} ; + + let result: Fq = a + b; + assert(result == c); + + // let b: Fq = BigNum::one(); + // let result = a + b; + assert(result == c) ; +} + +// type Fq = BigNum<3, 254, BN254_Fq_Params>; + From 10ca34c866b7c279c11e2ab03f0d8a09b490a168 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 29 Nov 2024 16:40:59 +0000 Subject: [PATCH 02/24] added helpers for parsing inputs, implemented is_zero, working on __add --- oracles/src/handlers.rs | 187 +++++++++++++++++++++---------- oracles/src/ops.rs | 9 ++ src/bignum.nr | 5 +- src/fns/unconstrained_helpers.nr | 7 -- src/fns/unconstrained_ops.nr | 23 ++-- src/tests/bignum_test.nr | 18 ++- 6 files changed, 170 insertions(+), 79 deletions(-) diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index bb14b89e..6d5fc8a2 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -1,13 +1,24 @@ use ark_bn254::Fr; +use ark_ff::Zero; use num_bigint::BigUint; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use num_traits::Num; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use serde_json::{json, Value}; // use std::str::FromStr; use crate::foreign_call::ForeignCallParam; - +use crate::ops::is_zero; use crate::ops::sqrt; + + +// a struct that emulates the bignum Params params from the params.nr file +struct Params { + has_multiplicative_inverse: bool, + modulus: Vec, + double_modulus: Vec, + redc_param: Vec, +} + /**** THERE'S A LOT OF BOILERPLATE INSIDE THESE "HANDLERS", THAT WE CAN PROBABLY PUT INTO COMMON HELPER FUNCTIONS ****/ /** Note: I _think_ the type `Vec>` will be generically applicable to _any_ oracle call arguments, so I've made _all_ handlers receive this type. */ @@ -110,74 +121,136 @@ pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { println!("you called the is_zero function with inputs: {:?}", inputs); // Create a vector with a single boolean value (true) as the result - let return_vec = vec![true]; + let input_param = &inputs[0]; + println!("input_param: {:?}", input_param); + // parse the input into strings + let mut input_strings = vec![]; + for input in inputs { + input_strings.push(callparam_to_string(input)[0]); + } + let limbs = gets_limbs(input_strings); + // call the is_zero function from the ops.rs + let result= is_zero(limbs); + // print the result + println!("Computed result: {:?}", result); + /**** ENSURE HEX ****/ + let as_big_uint: BigUint = result.into(); + let as_hex_str = as_big_uint.to_str_radix(16); + let mut results: Vec = vec![]; + println!("as_hex_str: {:?}", as_hex_str); + results.push(as_hex_str); + let oracle_return_data_the_noir_program_expects = results; - // Create a JSON object with a "values" key containing the return_vec - let json_response = json!({"values" : return_vec}); + /**** FORMAT RESULT FOR NOIR CONSUMPTION, AND CONVERT RESULT TO JSON `Value` TYPE ****/ + let return_vec = oracle_return_data_the_noir_program_expects; // Notice! This is a different type from the singular handle_get_sqrt function! Hence why the `Value` is being computed inside this function, instead in the calling function. + println!("return_vec: {:?}", return_vec); - // Print the JSON response for debugging purposes + let json_response = json!({"values" : return_vec}); println!("json_response: {:?}", json_response); - json_response + json_response } // ============================== // ============================== // ============================== // call handler for add +// the inputs of the function are params, lhs, rhs, num_limbs, mod_bits, returns the result of the addition which is a vector of hex limbs +// params are of form +// lhs and rhs are vector of limbs +// the input is 8 elements pub(crate) fn handle_add(inputs: &Vec>) -> Value { - println!("inputs for add: {:?}", inputs); - - let input_param = &inputs[0]; - // println!("input_param: {:?}", input_param); - // println!("inputs length: {:?}", inputs.len()); - let mut has_multiplicative_inverse = inputs[0].clone(); - let mut modulus = inputs[1].clone(); - let mut modulus_u60 = inputs[2].clone(); - let mut modulus_u60_x4 = inputs[3].clone(); - let mut double_modulus = inputs[4].clone(); - let mut redc_param = inputs[5].clone(); - let mut lhs = inputs[6].clone(); - let mut rhs = inputs[7].clone(); - - // get the number of limbs from the length of the modulus - let N = modulus.len(); - println!("number of limbs {:?}", N); - let modulus_values: Vec = modulus.get_values(); - println!("modulus_values length: {:?}", modulus_values.len()); - let has_multiplicative_inverse_value = has_multiplicative_inverse.get_values(); - println!("has_multiplicative_inverse_value: {:?}", has_multiplicative_inverse_value); - // println!("modulus: {:?}", modulus_values); - - // println!("has_multiplicative_inverse: {:?}", has_multiplicative_inverse); - // println!("modulus length: {:?}", modulus.len()); - // println!("modulus_u60: {:?}", modulus_u60); - // println!("modulus_u60_x4: {:?}", modulus_u60_x4); - // println!("double_modulus: {:?}", double_modulus); - // println!("redc_param: {:?}", redc_param); - // println!("lhs: {:?}", lhs); - // println!("rhs: {:?}", rhs); - - - // println!("number_of_limbs: {:?}", number_of_limbs); - - // compute what the number of limbs are - // println!("lhs: {:?}", lhs); - // println!("rhs: {:?}", rhs); - - // println!("input_param type: {:?}", input_param.type_name()); - // let input_strings = inputs.unwrap(); - // println!("input_strings: {:?}", input_strings); - // let input_strings: Vec<&str> = match input_param { - // ForeignCallParam::Single(_value) => panic!("Expected array, found single value"), - // ForeignCallParam::Array(values) => values - // .into_iter() - // .map(|v| v.trim_start_matches('0')) - // .collect(), - // }; - + // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs + let modulus_bits_fc = &inputs[inputs.len()-1]; + let num_limbs_fc = &inputs[inputs.len()-2]; + let modulus_bits = get_u32_from_callparam(&modulus_bits_fc); + let num_limbs = get_u32_from_callparam(&num_limbs_fc); + // parse out the limbs of the lhs and rhs and cast them into Fr elements + let lhs_fc = &inputs[inputs.len()-3]; + let rhs_fc = &inputs[inputs.len()-4]; + let limbs_lhs = gets_limbs(callparam_to_string(lhs_fc)); + let limbs_rhs = gets_limbs(callparam_to_string(rhs_fc)); + + // lastly parse out the params + // the params consist of has_multiplicative_inverse, modulus, double_modulus, redc_param + let has_multiplicative_inverse_fc = &inputs[0]; + let modulus_fc = &inputs[1]; + let double_modulus_fc = &inputs[4]; + let redc_param_fc = &inputs[5]; + // create the params struct + let params: Params = Params::from_foreign_call_params(&inputs); + println!("params: {:?}", params); - let return_vec = vec![true]; + let return_vec:Vec = vec![]; let json_response = json!({"values" : return_vec}); json_response + +} + + +// helper function to get limbs of a big num and pack them into a vector of Fr elements +pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { + let mut limbs: Vec = vec![]; + for input_string in input_strings { + // handle the case of a zero input + if input_string == "" { + let x_big_uint = BigUint::from_str_radix("0", 16).unwrap(); + let limb: Fr = x_big_uint.into(); + limbs.push(limb); + } + else{ + let x_big_uint: BigUint = BigUint::from_str_radix(input_string, 16).unwrap(); + let limb: Fr = x_big_uint.into(); + limbs.push(limb); + } + } + limbs +} + + + +pub (crate) fn callparam_to_string(input: &ForeignCallParam) -> Vec<&str> { + match input { + ForeignCallParam::Single(value) => vec![value.trim_start_matches('0')], + ForeignCallParam::Array(values) => values.into_iter().map(|v| v.trim_start_matches('0')).collect(), + } +} + +pub (crate) fn get_u32_from_callparam(input: &ForeignCallParam) -> u32 { + let input_string = callparam_to_string(input)[0]; + u32::from_str_radix(input_string, 16).unwrap() +} + +pub (crate) fn get_bool_from_callparam(input: &ForeignCallParam) -> bool { + let input_string = callparam_to_string(input)[0]; + let res = u32::from_str_radix(input_string, 16).unwrap(); + res == 1 +} + + +impl Params { + // this function takes the foreign call params and returns a Params struct + pub fn from_foreign_call_params(inputs: &Vec>) -> Params { + let has_multiplicative_inverse_fc = &inputs[0]; + let has_multiplicative_inverse = get_bool_from_callparam(&has_multiplicative_inverse_fc); + let modulus_fc = &inputs[1]; + let modulus = gets_limbs(callparam_to_string(modulus_fc)); + let double_modulus_fc = &inputs[4]; + let double_modulus = gets_limbs(callparam_to_string(double_modulus_fc)); + let redc_param_fc = &inputs[5]; + let redc_param = gets_limbs(callparam_to_string(redc_param_fc)); + + Params { + has_multiplicative_inverse: has_multiplicative_inverse, + modulus: modulus, + double_modulus: double_modulus, + redc_param: redc_param, + } + } +} + +impl std::fmt::Debug for Params { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Params {{ has_multiplicative_inverse: {:?}, modulus: {:?}, double_modulus: {:?}, redc_param: {:?}", self.has_multiplicative_inverse, self.modulus, self.double_modulus, self.redc_param) + } } \ No newline at end of file diff --git a/oracles/src/ops.rs b/oracles/src/ops.rs index 0b5ed7e9..f6eaf2e1 100644 --- a/oracles/src/ops.rs +++ b/oracles/src/ops.rs @@ -1,5 +1,6 @@ use ark_bn254::Fr; use ark_ff::Field; +use ark_ff::Zero; pub(crate) fn sqrt(x: Fr) -> Option { let sqrt: Option = if x.legendre().is_qr() { @@ -19,4 +20,12 @@ pub(crate) fn sqrt(x: Fr) -> Option { } sqrt +} + +pub(crate) fn is_zero(limbs: Vec) -> bool { + let mut result: bool = true; + for limb in limbs { + result = result & (limb == Fr::zero()); + } + result } \ No newline at end of file diff --git a/src/bignum.nr b/src/bignum.nr index 52002bd7..fdf52234 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -165,7 +165,10 @@ where } unconstrained fn __is_zero(self) -> bool { - __is_zero(self.limbs) + let a = __is_zero(self.limbs); + println("the oracle return value is"); + println(a); + a } unconstrained fn __neg(self) -> Self { diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 716c91b5..640fc150 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -98,13 +98,6 @@ pub(crate) unconstrained fn __neg_with_flags( } -//this is the actual function that be changed to use oracles -#[oracle(add)] -pub (crate) unconstrained fn oracle_add( - params: P, - lhs: [Field; N], - rhs: [Field; N], -) -> ([Field; N], [bool; N], [bool; N], bool) {} diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index 9a21ebce..29c1eba0 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -128,9 +128,6 @@ pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) - // } // result // } - #[oracle(is_zero)] -pub (crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} - //switching this function to use oracles instead // pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool { // let mut result: bool = true; @@ -182,9 +179,11 @@ pub(crate) unconstrained fn __neg( params: P, lhs: [Field; N], rhs: [Field; N], + num_limbs: u32, + mod_bits: u32, ) -> [Field; N] {} -pub (crate) unconstrained fn __add( +// pub (crate) unconstrained fn __add( // switching this function to use oracles instead // pub(crate) unconstrained fn __add( // params: P, @@ -202,19 +201,21 @@ pub (crate) unconstrained fn __add( // U60Repr::into(z_u60) // } // the oracle function to get the add result - #[oracle(add)] - pub (crate) unconstrained fn add_oracle( - params: P, - lhs: [Field; N], - rhs: [Field; N], -) -> [Field; N] {} + pub (crate) unconstrained fn __add( params: P, lhs: [Field; N], rhs: [Field; N], ) -> [Field; N] { - add_oracle(params, lhs, rhs) + let modulus = params.modulus; + let redc_param = params.redc_param; + let has_multiplicative_inverse = params.has_multiplicative_inverse; + println("the parameters are"); + println(modulus); + println(redc_param); + println(has_multiplicative_inverse); + add_oracle(params, lhs, rhs, N, MOD_BITS) } /** diff --git a/src/tests/bignum_test.nr b/src/tests/bignum_test.nr index 47cc4c52..ca8dd434 100644 --- a/src/tests/bignum_test.nr +++ b/src/tests/bignum_test.nr @@ -800,7 +800,7 @@ fn test_oracle_add() { let a: Fq = BigNum{limbs : [ 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000003 + 0x0000000000000000000000000000000000000000000000000000000000000002 ]}; let b: Fq = BigNum{limbs : [ 0x0000000000000000000000000000000000000000000000000000000000000000, @@ -810,10 +810,10 @@ fn test_oracle_add() { let c : Fq = BigNum{limbs : [ 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000002 + 0x0000000000000000000000000000000000000000000000000000000000000003 ]} ; - let result: Fq = a + b; + let result: Fq = a.__add(b); assert(result == c); // let b: Fq = BigNum::one(); @@ -821,5 +821,17 @@ fn test_oracle_add() { assert(result == c) ; } +#[test] +fn test_oracle_is_zero() { + let a: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000 + ]}; + let result = a.__is_zero(); + assert(result == true); + // assert(true); +} + // type Fq = BigNum<3, 254, BN254_Fq_Params>; From 8ee971d8727387d1df6cc7c98aeb1c826dd4914d Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Tue, 3 Dec 2024 17:29:07 +0000 Subject: [PATCH 03/24] added the oracle resolver for addition --- oracles/Cargo.lock | 447 +++++++++++++++++++++++-------- oracles/src/handlers.rs | 109 ++++++-- oracles/src/params.rs | 38 +++ src/fns/unconstrained_helpers.nr | 124 +++++---- src/fns/unconstrained_ops.nr | 55 ++-- src/runtime_bignum.nr | 1 + src/tests/bignum_test.nr | 13 +- src/tests/runtime_bignum_test.nr | 5 + 8 files changed, 566 insertions(+), 226 deletions(-) create mode 100644 oracles/src/params.rs diff --git a/oracles/Cargo.lock b/oracles/Cargo.lock index b70ad1a7..26552aef 100644 --- a/oracles/Cargo.lock +++ b/oracles/Cargo.lock @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "ark-bn254" @@ -169,7 +169,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -228,15 +228,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -281,9 +281,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -319,6 +319,17 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "either" version = "1.13.0" @@ -390,7 +401,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -458,9 +469,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -486,9 +497,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -496,12 +507,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "http" version = "1.1.0" @@ -550,9 +555,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", @@ -589,9 +594,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -606,14 +611,143 @@ dependencies = [ "tracing", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -623,7 +757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -637,9 +771,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" @@ -762,7 +896,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -825,9 +959,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + +[[package]] +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -871,11 +1011,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi", "windows-sys 0.52.0", @@ -1016,7 +1155,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1051,9 +1190,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1114,7 +1253,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -1129,9 +1268,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1194,9 +1333,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "log", "once_cell", @@ -1290,9 +1429,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -1319,9 +1458,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -1335,29 +1474,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1408,9 +1547,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1438,6 +1577,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "subtle" version = "2.6.1" @@ -1457,33 +1602,44 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1497,25 +1653,20 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -1535,7 +1686,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] @@ -1621,9 +1772,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -1633,20 +1784,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -1665,9 +1816,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -1693,26 +1844,11 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "untrusted" @@ -1722,15 +1858,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "valuable" version = "0.1.0" @@ -1770,9 +1918,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -1899,6 +2047,42 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -1917,7 +2101,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", ] [[package]] @@ -1937,5 +2142,27 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.89", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 6d5fc8a2..b9be7158 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -1,6 +1,7 @@ use ark_bn254::Fr; use ark_ff::Zero; -use num_bigint::BigUint; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? +use num_bigint::BigUint; use num_traits::ConstZero; +// It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use num_traits::Num; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use serde_json::{json, Value}; // use std::str::FromStr; @@ -14,7 +15,7 @@ use crate::ops::sqrt; // a struct that emulates the bignum Params params from the params.nr file struct Params { has_multiplicative_inverse: bool, - modulus: Vec, + modulus: BigUint, double_modulus: Vec, redc_param: Vec, } @@ -105,6 +106,7 @@ pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value /**** FORMAT RESULT FOR NOIR CONSUMPTION, AND CONVERT RESULT TO JSON `Value` TYPE ****/ let return_vec = vec![oracle_return_data_the_noir_program_expects]; // Notice! This is a different type from the singular handle_get_sqrt function! Hence why the `Value` is being computed inside this function, instead in the calling function. println!("return_vec: {:?}", return_vec); + let json_response = json!({"values" : return_vec}); println!("json_response: {:?}", json_response); @@ -119,10 +121,8 @@ pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value // ============================== // call handler for is_zero pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { - println!("you called the is_zero function with inputs: {:?}", inputs); // Create a vector with a single boolean value (true) as the result let input_param = &inputs[0]; - println!("input_param: {:?}", input_param); // parse the input into strings let mut input_strings = vec![]; for input in inputs { @@ -132,21 +132,17 @@ pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { // call the is_zero function from the ops.rs let result= is_zero(limbs); // print the result - println!("Computed result: {:?}", result); /**** ENSURE HEX ****/ let as_big_uint: BigUint = result.into(); let as_hex_str = as_big_uint.to_str_radix(16); let mut results: Vec = vec![]; - println!("as_hex_str: {:?}", as_hex_str); results.push(as_hex_str); let oracle_return_data_the_noir_program_expects = results; /**** FORMAT RESULT FOR NOIR CONSUMPTION, AND CONVERT RESULT TO JSON `Value` TYPE ****/ let return_vec = oracle_return_data_the_noir_program_expects; // Notice! This is a different type from the singular handle_get_sqrt function! Hence why the `Value` is being computed inside this function, instead in the calling function. - println!("return_vec: {:?}", return_vec); let json_response = json!({"values" : return_vec}); - println!("json_response: {:?}", json_response); json_response } @@ -159,35 +155,69 @@ pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { // lhs and rhs are vector of limbs // the input is 8 elements pub(crate) fn handle_add(inputs: &Vec>) -> Value { - // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs - let modulus_bits_fc = &inputs[inputs.len()-1]; - let num_limbs_fc = &inputs[inputs.len()-2]; - let modulus_bits = get_u32_from_callparam(&modulus_bits_fc); - let num_limbs = get_u32_from_callparam(&num_limbs_fc); - // parse out the limbs of the lhs and rhs and cast them into Fr elements + // let modulus_bits_fc = &inputs[inputs.len()-1]; + // let modulus_bits = get_u32_from_callparam(&modulus_bits_fc); + // get the number of limbs from the input + println!("length of inputs: {:?}", inputs.len()); + for input in inputs { + println!("input: {:?}", input); + } + // let num_limbs_fc = &inputs[inputs.len()-2]; + // let num_limbs = get_u32_from_callparam(&num_limbs_fc); + let num_limbs = 4; + // convert the lhs and rhs to biguints let lhs_fc = &inputs[inputs.len()-3]; + let lhs_str = callparam_to_string(lhs_fc); + let lhs_biguint = cast_to_biguint(lhs_str); let rhs_fc = &inputs[inputs.len()-4]; - let limbs_lhs = gets_limbs(callparam_to_string(lhs_fc)); - let limbs_rhs = gets_limbs(callparam_to_string(rhs_fc)); - + let rhs_str = callparam_to_string(rhs_fc); + let rhs_biguint = cast_to_biguint(rhs_str); // lastly parse out the params - // the params consist of has_multiplicative_inverse, modulus, double_modulus, redc_param - let has_multiplicative_inverse_fc = &inputs[0]; - let modulus_fc = &inputs[1]; - let double_modulus_fc = &inputs[4]; - let redc_param_fc = &inputs[5]; // create the params struct let params: Params = Params::from_foreign_call_params(&inputs); - println!("params: {:?}", params); - - let return_vec:Vec = vec![]; + let modulus = params.modulus; + let result = lhs_biguint + rhs_biguint; + let result_mod = result % modulus; + // cast the result to limbs + let limbs = cast_biguint_to_bignum_limbs(&result_mod, num_limbs); + // pack it in a json response + let return_vec:Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); + json_response } + + +pub (crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { + // split the limbs + let mut limbs: Vec = vec![]; + for input_string in input_strings { + // handle the case of a zero input + if input_string == "" { + let x_big_uint = BigUint::from_str_radix("0", 16).unwrap(); + limbs.push(x_big_uint); + } + else{ + let x_big_uint: BigUint = BigUint::from_str_radix(input_string, 16).unwrap(); + limbs.push(x_big_uint); + } + } + // a constant 2^120 as biguint + let base: BigUint = BigUint::from(2u32); + let exp = 120u32; + let shift_constant = base.pow(exp); + let mut res = BigUint::ZERO; + for i in 0..limbs.len() { + res = res + &limbs[i] * &shift_constant.pow(i as u32); + } + res + +} + // helper function to get limbs of a big num and pack them into a vector of Fr elements pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { let mut limbs: Vec = vec![]; @@ -218,6 +248,8 @@ pub (crate) fn callparam_to_string(input: &ForeignCallParam) -> Vec<&str pub (crate) fn get_u32_from_callparam(input: &ForeignCallParam) -> u32 { let input_string = callparam_to_string(input)[0]; + println!(""); + println!("input_string: {:?}", input_string); u32::from_str_radix(input_string, 16).unwrap() } @@ -227,6 +259,23 @@ pub (crate) fn get_bool_from_callparam(input: &ForeignCallParam) -> bool res == 1 } +pub (crate) fn cast_biguint_to_bignum_limbs(input: &BigUint, num_limbs: u32) -> Vec { + // a constant 2^120 as biguint + let base: BigUint = BigUint::from(2u32); + let exp = 120u32; + let shift_constant = base.pow(exp); + let mut input_copy = input.clone(); + // an empty array of size num_limbs of type hex limbs + let mut limbs_hex: Vec = vec![]; + for i in 0..num_limbs { + let remainder = &input_copy % &shift_constant; + limbs_hex.push(remainder.to_str_radix(16)); + let quetient: BigUint = input_copy / &shift_constant; + input_copy = quetient.clone(); + } + limbs_hex +} + impl Params { // this function takes the foreign call params and returns a Params struct @@ -234,7 +283,9 @@ impl Params { let has_multiplicative_inverse_fc = &inputs[0]; let has_multiplicative_inverse = get_bool_from_callparam(&has_multiplicative_inverse_fc); let modulus_fc = &inputs[1]; - let modulus = gets_limbs(callparam_to_string(modulus_fc)); + // let modulus = gets_limbs(callparam_to_string(modulus_fc)); + let modulus_str = callparam_to_string(modulus_fc); + let modulus = cast_to_biguint(modulus_str); let double_modulus_fc = &inputs[4]; let double_modulus = gets_limbs(callparam_to_string(double_modulus_fc)); let redc_param_fc = &inputs[5]; @@ -253,4 +304,8 @@ impl std::fmt::Debug for Params { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "Params {{ has_multiplicative_inverse: {:?}, modulus: {:?}, double_modulus: {:?}, redc_param: {:?}", self.has_multiplicative_inverse, self.modulus, self.double_modulus, self.redc_param) } -} \ No newline at end of file +} + + + + diff --git a/oracles/src/params.rs b/oracles/src/params.rs new file mode 100644 index 00000000..d5e27bfe --- /dev/null +++ b/oracles/src/params.rs @@ -0,0 +1,38 @@ + + +// a struct that emulates the bignum Params params from the params.nr file +pub (crate) struct Params { + has_multiplicative_inverse: bool, + modulus: Vec, + double_modulus: Vec, + redc_param: Vec, +} + +impl Params { + // this function takes the foreign call params and returns a Params struct + pub fn from_foreign_call_params(inputs: &Vec>) -> Params { + let has_multiplicative_inverse_fc = &inputs[0]; + let has_multiplicative_inverse = get_bool_from_callparam(&has_multiplicative_inverse_fc); + let modulus_fc = &inputs[1]; + let modulus = gets_limbs(callparam_to_string(modulus_fc)); + let double_modulus_fc = &inputs[4]; + let double_modulus = gets_limbs(callparam_to_string(double_modulus_fc)); + let redc_param_fc = &inputs[5]; + let redc_param = gets_limbs(callparam_to_string(redc_param_fc)); + + Params { + has_multiplicative_inverse: has_multiplicative_inverse, + modulus: modulus, + double_modulus: double_modulus, + redc_param: redc_param, + } + } +} + +impl std::fmt::Debug for Params { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Params {{ has_multiplicative_inverse: {:?}, modulus: {:?}, double_modulus: {:?}, redc_param: {:?}", self.has_multiplicative_inverse, self.modulus, self.double_modulus, self.redc_param) + } +} + + diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 640fc150..89996af8 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -102,71 +102,75 @@ pub(crate) unconstrained fn __neg_with_flags( //this is the actual function that be changed to use oracles -#[oracle(add)] -pub (crate) unconstrained fn oracle_add( + #[oracle(add)] + pub (crate) unconstrained fn add_oracle( params: P, lhs: [Field; N], rhs: [Field; N], -) -> ([Field; N], [bool; N], [bool; N], bool) {} -pub(crate) unconstrained fn __add_with_flags( - params: P, - lhs: [Field; N], - rhs: [Field; N], -) -> ([Field; N], [bool; N], [bool; N], bool){ - oracle_add(params, lhs, rhs) -} + num_limbs: u32, + mod_bits: u32, +) -> [Field; N] {} // pub(crate) unconstrained fn __add_with_flags( // params: P, // lhs: [Field; N], // rhs: [Field; N], -// ) -> ([Field; N], [bool; N], [bool; N], bool) { -// let a_u60: U60Repr = U60Repr::from(lhs); -// let b_u60: U60Repr = U60Repr::from(rhs); -// let add_u60 = a_u60 + b_u60; - -// let overflow = add_u60.gte(params.modulus_u60); - -// let mut subtrahend_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; -// let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; - -// if overflow { -// subtrahend_u60 = params.modulus_u60; -// } - -// let mut carry: u64 = 0; -// let mut carry_in: u64 = 0; -// let mut borrow: u64 = 0; -// let mut borrow_in: u64 = 0; -// let mut borrow_flags: [bool; N] = [false; N]; -// let mut carry_flags: [bool; N] = [false; N]; -// for i in 0..2 * N { -// let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; -// carry = (add_term >= 0x1000000000000000) as u64; -// add_term -= (carry as u64 * 0x1000000000000000); -// result_u60.limbs[i] = add_term; -// carry_in = carry as u64; -// borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; -// let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; -// result_u60.limbs[i] = sub; -// borrow_in = borrow; - -// if ((i & 1) == 1) { -// let idx = (i - 1) / 2; -// if (carry & borrow == 1) { -// carry = 0; -// borrow = 0; -// } -// carry_flags[idx] = carry as bool; -// borrow_flags[idx] = borrow as bool; -// } -// } -// let result = U60Repr::into(result_u60); - -// (result, carry_flags, borrow_flags, overflow) +// ) -> ([Field; N], [bool; N], [bool; N], bool){ +// let limbs = add_oracle(params, lhs, rhs, N, MOD_BITS); // } + +pub(crate) unconstrained fn __add_with_flags( + params: P, + lhs: [Field; N], + rhs: [Field; N], +) -> ([Field; N], [bool; N], [bool; N], bool) { + let a_u60: U60Repr = U60Repr::from(lhs); + let b_u60: U60Repr = U60Repr::from(rhs); + let add_u60 = a_u60 + b_u60; + + let overflow = add_u60.gte(params.modulus_u60); + + let mut subtrahend_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; + let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; + + if overflow { + subtrahend_u60 = params.modulus_u60; + } + + let mut carry: u64 = 0; + let mut carry_in: u64 = 0; + let mut borrow: u64 = 0; + let mut borrow_in: u64 = 0; + let mut borrow_flags: [bool; N] = [false; N]; + let mut carry_flags: [bool; N] = [false; N]; + for i in 0..2 * N { + let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; + carry = (add_term >= 0x1000000000000000) as u64; + add_term -= (carry as u64 * 0x1000000000000000); + result_u60.limbs[i] = add_term; + carry_in = carry as u64; + borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; + let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; + result_u60.limbs[i] = sub; + borrow_in = borrow; + + if ((i & 1) == 1) { + let idx = (i - 1) / 2; + if (carry & borrow == 1) { + carry = 0; + borrow = 0; + } + carry_flags[idx] = carry as bool; + borrow_flags[idx] = borrow as bool; + } + } + let result = U60Repr::into(result_u60); + + (result, carry_flags, borrow_flags, overflow) +} + pub(crate) unconstrained fn __sub_with_flags( params: P, lhs: [Field; N], @@ -234,7 +238,7 @@ pub(crate) unconstrained fn __barrett_reduction( mulout[i + j] += x[i] * redc_param[j]; } } - mulout = split_bits::__normalize_limbs(mulout, 3 * N - 2); + mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); let mulout_u60: U60Repr = U60Repr::new(mulout); // When we apply the barrett reduction, the maximum value of the output will be @@ -282,6 +286,16 @@ pub(crate) unconstrained fn __barrett_reduction( let x_u60: U60Repr = U60Repr::new(x); let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; + if (remainder_u60.gte(modulus_u60)) { + remainder_u60 = remainder_u60 - modulus_u60; + quotient_u60.increment(); + } else {} + + if (remainder_u60.gte(modulus_u60)) { + remainder_u60 = remainder_u60 - modulus_u60; + quotient_u60.increment(); + } else {} + if (remainder_u60.gte(modulus_u60)) { remainder_u60 = remainder_u60 - modulus_u60; quotient_u60.increment(); diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index 29c1eba0..aae1452a 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -174,6 +174,7 @@ pub(crate) unconstrained fn __neg( // U60Repr::into(z_u60) // } // the oracle function to get the add result + #[oracle(add)] pub (crate) unconstrained fn add_oracle( params: P, @@ -181,42 +182,40 @@ pub(crate) unconstrained fn __neg( rhs: [Field; N], num_limbs: u32, mod_bits: u32, -) -> [Field; N] {} +) -> [Field; N] {} +//this is the actual function that be changed to use oracles // pub (crate) unconstrained fn __add( // switching this function to use oracles instead -// pub(crate) unconstrained fn __add( -// params: P, -// lhs: [Field; N], -// rhs: [Field; N], -// ) -> [Field; N] { -// let x_u60: U60Repr = U60Repr::from(lhs); -// let y_u60: U60Repr = U60Repr::from(rhs); - -// let mut z_u60 = x_u60 + y_u60; - -// if z_u60.gte(params.modulus_u60) { -// z_u60 = z_u60 - params.modulus_u60; -// } -// U60Repr::into(z_u60) -// } -// the oracle function to get the add result - - -pub (crate) unconstrained fn __add( +pub(crate) unconstrained fn __add( params: P, lhs: [Field; N], rhs: [Field; N], ) -> [Field; N] { - let modulus = params.modulus; - let redc_param = params.redc_param; - let has_multiplicative_inverse = params.has_multiplicative_inverse; - println("the parameters are"); - println(modulus); - println(redc_param); - println(has_multiplicative_inverse); - add_oracle(params, lhs, rhs, N, MOD_BITS) + let x_u60: U60Repr = U60Repr::from(lhs); + let y_u60: U60Repr = U60Repr::from(rhs); + + let mut z_u60 = x_u60 + y_u60; + + if z_u60.gte(params.modulus_u60) { + z_u60 = z_u60 - params.modulus_u60; + } + U60Repr::into(z_u60) } +// the oracle function to get the add result + + +// pub (crate) unconstrained fn __add( +// params: P, +// lhs: [Field; N], +// rhs: [Field; N], +// ) -> [Field; N] { +// println("N is: "); +// println(N); +// let res = add_oracle(params, lhs, rhs, N, MOD_BITS); +// println(res); +// res +// } /** * @brief given inputs `x, y` compute 2p + x - y (unconstrained) diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 135de7da..f16e9d06 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -345,6 +345,7 @@ impl RuntimeBigNumTrait for RuntimeB } fn validate_in_range(self) { + println( self.limbs); validate_in_range::<_, MOD_BITS>(self.limbs); } diff --git a/src/tests/bignum_test.nr b/src/tests/bignum_test.nr index ca8dd434..53eefd6b 100644 --- a/src/tests/bignum_test.nr +++ b/src/tests/bignum_test.nr @@ -798,22 +798,23 @@ fn test_expressions() { fn test_oracle_add() { // type Fq = BigNum <3,254, BN254_Fq_Params> ; let a: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000002 + 0x0000000000000000000000000000000000000000000000000000000000000000 ]}; let b: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000001 + 0x0000000000000000000000000000000000000000000000000000000000000000 ]}; let c : Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000003 + 0x0000000000000000000000000000000000000000000000000000000000000000 ]} ; let result: Fq = a.__add(b); + assert(result == c); // let b: Fq = BigNum::one(); diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index 3b7fe4f0..d37e1ce9 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -214,10 +214,15 @@ fn test_add() { let a: $RuntimeBigNum<$N, $MOD_BITS> = unsafe{ $RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; let b: $RuntimeBigNum<$N, $MOD_BITS> = unsafe{ $RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) }; let one: $RuntimeBigNum<$N, $MOD_BITS> = $RuntimeBigNum::one(params); + println("we got here"); a.validate_in_range(); + println("we got here 2"); a.validate_in_field(); + println("we got here 3"); b.validate_in_range(); + println("we got here 4"); b.validate_in_field(); + println("we got here 5"); let mut c = a + b; c = c + c; From 788eddd895a242abeb6665923e66977752e7dbdf Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Thu, 5 Dec 2024 12:14:04 +0000 Subject: [PATCH 04/24] the failing change --- oracles/src/handlers.rs | 180 +++++++++++++++++++++++++--- oracles/src/main.rs | 9 +- oracles/src/ops.rs | 72 +++++++++++- src/bignum.nr | 2 - src/fns/constrained_ops.nr | 4 +- src/fns/unconstrained_helpers.nr | 4 + src/fns/unconstrained_ops.nr | 195 ++++++++++++++++++++----------- src/runtime_bignum.nr | 1 - src/tests/runtime_bignum_test.nr | 5 - 9 files changed, 379 insertions(+), 93 deletions(-) diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index b9be7158..03fdafb4 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -1,6 +1,8 @@ use ark_bn254::Fr; use ark_ff::Zero; -use num_bigint::BigUint; use num_traits::ConstZero; +use num_bigint::BigUint; +use num_bigint::BigInt; +use num_traits::ConstZero; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use num_traits::Num; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use serde_json::{json, Value}; @@ -9,8 +11,8 @@ use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; use crate::ops::is_zero; use crate::ops::sqrt; - - +use crate::ops::extended_gcd; +use crate::ops::invert; // a struct that emulates the bignum Params params from the params.nr file struct Params { @@ -146,6 +148,44 @@ pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { json_response } + + + +// ============================== +// ============================== +// ============================== +// call handler for add +pub(crate) fn handle_mul_with_quotient(inputs: &Vec>) -> Value { + // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs + let num_limbs_fc = &inputs[inputs.len()-2]; + let num_limbs = get_u32_from_callparam(&num_limbs_fc); + // create the params struct + let params: Params = Params::from_foreign_call_params(&inputs); + // get the lhs and rhs + let lhs_fc = &inputs[inputs.len()-3]; + let lhs_str = callparam_to_string(lhs_fc); + let lhs_biguint = cast_to_biguint(lhs_str); + let rhs_fc = &inputs[inputs.len()-4]; + let rhs_str = callparam_to_string(rhs_fc); + let rhs_biguint = cast_to_biguint(rhs_str); + let mul_res = lhs_biguint * rhs_biguint; + let modulus = params.modulus; + let q = &mul_res / &modulus; + let r = &mul_res % &modulus; + // cast the q and r to limbs + let q_limbs = cast_biguint_to_bignum_limbs(&q, num_limbs); + let r_limbs = cast_biguint_to_bignum_limbs(&r, num_limbs); + // call the mul_with_quotient function from the ops.rs file + let return_vec: Vec> = vec![q_limbs, r_limbs]; + let json_response = json!({"values" : return_vec}); + json_response +} + + + + + + // ============================== // ============================== // ============================== @@ -156,19 +196,13 @@ pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { // the input is 8 elements pub(crate) fn handle_add(inputs: &Vec>) -> Value { // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs - // let modulus_bits_fc = &inputs[inputs.len()-1]; - // let modulus_bits = get_u32_from_callparam(&modulus_bits_fc); // get the number of limbs from the input - println!("length of inputs: {:?}", inputs.len()); - for input in inputs { - println!("input: {:?}", input); - } // let num_limbs_fc = &inputs[inputs.len()-2]; // let num_limbs = get_u32_from_callparam(&num_limbs_fc); - let num_limbs = 4; // convert the lhs and rhs to biguints let lhs_fc = &inputs[inputs.len()-3]; let lhs_str = callparam_to_string(lhs_fc); + let num_limbs = lhs_str.len(); let lhs_biguint = cast_to_biguint(lhs_str); let rhs_fc = &inputs[inputs.len()-4]; let rhs_str = callparam_to_string(rhs_fc); @@ -180,7 +214,7 @@ pub(crate) fn handle_add(inputs: &Vec>) -> Value { let result = lhs_biguint + rhs_biguint; let result_mod = result % modulus; // cast the result to limbs - let limbs = cast_biguint_to_bignum_limbs(&result_mod, num_limbs); + let limbs = cast_biguint_to_bignum_limbs(&result_mod, num_limbs as u32); // pack it in a json response let return_vec:Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); @@ -189,6 +223,99 @@ pub(crate) fn handle_add(inputs: &Vec>) -> Value { } +pub (crate) fn handle_neg(inputs: &Vec>) -> Value { + // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs + // create the params struct + + let params: Params = Params::from_foreign_call_params(&inputs); + let modulus = params.modulus; + let limbs_fc = &inputs[inputs.len()-3]; + let num_limbs = limbs_fc.len(); + let mut limbs_biguint = cast_to_biguint(callparam_to_string(limbs_fc)); + if limbs_biguint > modulus { + limbs_biguint = limbs_biguint % &modulus; + } + let neg = &modulus - &limbs_biguint; + let neg_limbs = cast_biguint_to_bignum_limbs(&neg, num_limbs as u32); + let return_vec:Vec> = vec![neg_limbs]; + let json_response = json!({"values" : return_vec}); + json_response +} + + +pub (crate) fn handle_udiv_mod(inputs: &Vec>) -> Value { + // get the numerator and the divisor + let numerator_fc = &inputs[0]; + let numerator_str = callparam_to_string(&numerator_fc); + let numerator = cast_to_biguint(numerator_str); + let divisor_fc = &inputs[1]; + let divisor_str = callparam_to_string(divisor_fc); + let divisor = cast_to_biguint(divisor_str); + // get the number of limbs + let num_limbs = numerator_fc.len(); + + // divide the numerator by the divisor + let quotient = &numerator / &divisor; + let remainder = &numerator % &divisor; + + // cast the quotient and the remainder to limbs + let quotient_limbs = cast_biguint_to_bignum_limbs("ient, num_limbs as u32); + let remainder_limbs = cast_biguint_to_bignum_limbs(&remainder, num_limbs as u32); + + let return_vec:Vec> = vec![quotient_limbs, remainder_limbs]; + let json_response = json!({"values" : return_vec}); + json_response +} + +// a handler for modular inversion +pub (crate) fn handle_invmod(inputs: &Vec>) -> Value { + // get the params + let params: Params = Params::from_foreign_call_params(&inputs); + // get the value to be inverted + let val_fc = &inputs[inputs.len()-1]; + let val_str = callparam_to_string(val_fc); + let val = cast_to_biguint(val_str); + let num_limbs = val_fc.len(); + // invert the value + println!("modulus: {:?}", params.modulus); + println!("val: {:?}", val); + let inv = invert(&val, ¶ms.modulus); + // cast the inverse to limbs + let limbs = cast_bigint_to_bignum_limbs(&inv, num_limbs as u32); + // return an empty json response for now + let return_vec:Vec> = vec![limbs]; + let json_response = json!({"values" : return_vec}); + json_response +} + +// a handler for modular exponentiation +pub (crate) fn handle_pow(inputs: &Vec>) -> Value { + // return an empty json response for now + let return_vec:Vec> = vec![]; + let json_response = json!({"values" : return_vec}); + json_response +} + +// a handler for modular division +pub (crate) fn handle_divmod(inputs: &Vec>) -> Value { + // return an empty json response for now + let return_vec:Vec> = vec![]; + let json_response = json!({"values" : return_vec}); + json_response +} + + + + + + + +// ============================== +// ============================== +// ============================== +// helper functions + + @@ -248,17 +375,23 @@ pub (crate) fn callparam_to_string(input: &ForeignCallParam) -> Vec<&str pub (crate) fn get_u32_from_callparam(input: &ForeignCallParam) -> u32 { let input_string = callparam_to_string(input)[0]; - println!(""); - println!("input_string: {:?}", input_string); u32::from_str_radix(input_string, 16).unwrap() } pub (crate) fn get_bool_from_callparam(input: &ForeignCallParam) -> bool { - let input_string = callparam_to_string(input)[0]; + // println!("the bool oracle was called"); + // println!("input: {:?}", input); + let mut input_string = callparam_to_string(input)[0]; + if input_string == "" { + input_string = "0"; + } + // println!("input_string: {:?}", input_string); let res = u32::from_str_radix(input_string, 16).unwrap(); res == 1 } + + pub (crate) fn cast_biguint_to_bignum_limbs(input: &BigUint, num_limbs: u32) -> Vec { // a constant 2^120 as biguint let base: BigUint = BigUint::from(2u32); @@ -277,6 +410,25 @@ pub (crate) fn cast_biguint_to_bignum_limbs(input: &BigUint, num_limbs: u32) -> } +pub (crate) fn cast_bigint_to_bignum_limbs(input: &BigInt, num_limbs: u32) -> Vec { + // a constant 2^120 as biguint + let base: BigInt = BigInt::from(2u32); + let exp = 120u32; + let shift_constant = base.pow(exp); + let mut input_copy = input.clone(); + // an empty array of size num_limbs of type hex limbs + let mut limbs_hex: Vec = vec![]; + for i in 0..num_limbs { + let remainder = &input_copy % &shift_constant; + limbs_hex.push(remainder.to_str_radix(16)); + let quetient: BigInt = input_copy / &shift_constant; + input_copy = quetient.clone(); + } + limbs_hex +} + + + impl Params { // this function takes the foreign call params and returns a Params struct pub fn from_foreign_call_params(inputs: &Vec>) -> Params { diff --git a/oracles/src/main.rs b/oracles/src/main.rs index 5e8f0c7e..22c24021 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -30,6 +30,7 @@ mod foreign_call; mod handlers; mod ops; + use jsonrpsee::server::{RpcModule, Server}; use std::net::SocketAddr; use tracing_subscriber::util::SubscriberInitExt; @@ -38,7 +39,7 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add}; +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_divmod}; // SPIN UP THE SERVER #[tokio::main] @@ -103,6 +104,12 @@ async fn run_server() -> anyhow::Result { "get_sqrts" => handle_get_sqrts(&request.inputs), // the inputs to this are effectively a Vec> "is_zero" => handle_is_zero(&request.inputs), // the inputs to this are effectively a Vec "add" => handle_add(&request.inputs), // the inputs to this are effectively a Vec + "neg" => handle_neg(&request.inputs), // the inputs to this are effectively a Vec + "mul_with_quotient" => handle_mul_with_quotient(&request.inputs), // the inputs to this are effectively a Vec + "udiv_mod" => handle_udiv_mod(&request.inputs), // the inputs to this are effectively a Vec + "invmod" => handle_invmod(&request.inputs), // the inputs to this are effectively a Vec + "pow" => handle_pow(&request.inputs), // the inputs to this are effectively a Vec + "divmod" => handle_divmod(&request.inputs), // the inputs to this are effectively a Vec _ => handle_unknown_function(&request), }; diff --git a/oracles/src/ops.rs b/oracles/src/ops.rs index f6eaf2e1..fcd7d336 100644 --- a/oracles/src/ops.rs +++ b/oracles/src/ops.rs @@ -1,6 +1,9 @@ use ark_bn254::Fr; use ark_ff::Field; -use ark_ff::Zero; +use ark_ff::Zero as ZeroField; +use num_bigint::BigUint; +use num_bigint::BigInt; +use num_traits::{Zero, One}; pub(crate) fn sqrt(x: Fr) -> Option { let sqrt: Option = if x.legendre().is_qr() { @@ -25,7 +28,70 @@ pub(crate) fn sqrt(x: Fr) -> Option { pub(crate) fn is_zero(limbs: Vec) -> bool { let mut result: bool = true; for limb in limbs { - result = result & (limb == Fr::zero()); + result = result & (limb == ZeroField::zero()); } result -} \ No newline at end of file +} + + + +pub(crate) fn extended_gcd(_a: &BigInt, _b: &BigInt) -> (BigInt, BigInt, BigInt) { + let (mut x, mut y) = (BigInt::from(0), BigInt::from(1)); + let (mut u, mut v) = (BigInt::from(1), BigInt::from(0)); + let mut a = _a.clone(); + let mut b = _b.clone(); + while a != BigInt::from(0) { + let q = &b / &a; + let r = &b % &a; + let m = &x - &u * &q; + let n = &y - &v * &q; + b = a.clone(); + a = r; + x = u; + y = v; + u = m; + v = n; + } + (b.clone(), x.clone(), y.clone()) +} + + +pub(crate) fn invert(a: &BigUint , modulus: &BigUint) -> BigInt { + // perform a -> BigInt conversion + let a_bigint = BigInt::from(a.clone()); + let modulus_bigint = BigInt::from(modulus.clone()); + let (gcd , r, _) = extended_gcd(&a_bigint, &modulus_bigint); + assert_eq!(gcd, BigInt::from(1), "input and modulus are not coprime"); + let mut res = r.clone(); + while res < BigInt::from(0) { + res = res + &modulus_bigint; + } + res +} + + +// some tests to check the behaviour of the extended gcd +#[test] +fn test_extended_euclidean() { + let (s, r, t) = extended_gcd(&mut BigInt::from(10u64), &mut BigInt::from(6u64)); + assert_eq!(s, BigInt::from(2u64)); +} + +#[test] +fn test_invert() { + let a = BigUint::from(5u64); + let modulus = BigUint::from(6u64); + let r = invert(&a, &modulus); + let modulus_bigint = BigInt::from(modulus.clone()); + let a_bigint = BigInt::from(a.clone()); + assert_eq!((r * a_bigint) % modulus_bigint , BigInt::from(1u64)); +} + +// #[test] +// #[should_panic(expected = "input and modulus are no coprime")] +// fn test_invert_fail() { +// let a = BigUint::from(4u64); +// let modulus = BigUint::from(8u64); +// invert(&a, &modulus); +// } + diff --git a/src/bignum.nr b/src/bignum.nr index fdf52234..81f9510e 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -166,8 +166,6 @@ where unconstrained fn __is_zero(self) -> bool { let a = __is_zero(self.limbs); - println("the oracle return value is"); - println(a); a } diff --git a/src/fns/constrained_ops.nr b/src/fns/constrained_ops.nr index 758e23dc..972e0d0b 100644 --- a/src/fns/constrained_ops.nr +++ b/src/fns/constrained_ops.nr @@ -268,7 +268,7 @@ pub(crate) fn validate_gt(lhs: [Field; N], rhs: [ // so we do... p - x - r = 0 and there might be borrow flags // a - b = r // p + a - b - r = 0 - let (result, carry_flags, borrow_flags) = unsafe { __validate_gt_remainder(lhs, rhs) }; + let (result, carry_flags, borrow_flags) = unsafe { __validate_gt_remainder::(lhs, rhs) }; validate_in_range::<_, MOD_BITS>(result); let borrow_shift = 0x1000000000000000000000000000000; @@ -445,7 +445,7 @@ pub(crate) fn udiv_mod( numerator: [Field; N], divisor: [Field; N], ) -> ([Field; N], [Field; N]) { - let (quotient, remainder) = unsafe { __udiv_mod(numerator, divisor) }; + let (quotient, remainder) = unsafe { __udiv_mod::(numerator, divisor) }; // self / divisor = quotient rounded // quotient * divisor + remainder - self = 0 diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 89996af8..5b19ccd8 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -218,6 +218,10 @@ pub(crate) unconstrained fn __sub_with_flags( (result, carry_flags, borrow_flags, underflow) } + +// instead of using barrett reduction, we use the oracle to do the reduction + + /** * @brief BARRETT_REDUCTION_OVERFLOW_BITS defines how large an input to barrett reduction can be * @details maximum value = modulus^2 <(limbs: [Field; N]) -> bool {} * N.B. constrained BigNum operations do not fully constrain outputs to be in the range [0, p-1] * because such a check is expensive and usually unneccesary. */ -pub(crate) unconstrained fn __neg( +// pub(crate) unconstrained fn __neg( +// params: P, +// limbs: [Field; N], +// ) -> [Field; N] { +// let f: [Field; N] = limbs; +// let x_u60: U60Repr = U60Repr::from(f); +// U60Repr::into(params.modulus_u60 - x_u60) +// } +pub (crate) unconstrained fn __neg( params: P, limbs: [Field; N], ) -> [Field; N] { - let f: [Field; N] = limbs; - let x_u60: U60Repr = U60Repr::from(f); - U60Repr::into(params.modulus_u60 - x_u60) + neg_oracle(params, limbs,N,MOD_BITS) } + + #[oracle(neg)] +unconstrained fn neg_oracle( + params: P, + limbs: [Field; N], + num_limbs: u32, + mod_bits: u32, + ) -> [Field; N] {} + // switching this function to use oracles instead // pub(crate) unconstrained fn __add( // params: P, @@ -192,15 +207,16 @@ pub(crate) unconstrained fn __add( lhs: [Field; N], rhs: [Field; N], ) -> [Field; N] { - let x_u60: U60Repr = U60Repr::from(lhs); - let y_u60: U60Repr = U60Repr::from(rhs); + // let x_u60: U60Repr = U60Repr::from(lhs); + // let y_u60: U60Repr = U60Repr::from(rhs); - let mut z_u60 = x_u60 + y_u60; + // let mut z_u60 = x_u60 + y_u60; - if z_u60.gte(params.modulus_u60) { - z_u60 = z_u60 - params.modulus_u60; - } - U60Repr::into(z_u60) + // if z_u60.gte(params.modulus_u60) { + // z_u60 = z_u60 - params.modulus_u60; + // } + // U60Repr::into(z_u60) + add_oracle(params, lhs, rhs, N, MOD_BITS) } // the oracle function to get the add result @@ -234,23 +250,36 @@ pub(crate) unconstrained fn __mul_with_quotient( lhs: [Field; N], rhs: [Field; N], ) -> ([Field; N], [Field; N]) { - let mut mul: [Field; 2 * N] = [0; 2 * N]; - for i in 0..N { - for j in 0..N { - mul[i + j] += lhs[i] * rhs[j]; - } - } - let to_reduce = split_bits::__normalize_limbs(mul, 2 * N); - let (q, r) = __barrett_reduction( - to_reduce, - params.redc_param, - MOD_BITS, - params.modulus, - params.modulus_u60_x4, - ); - - (q, r) + let res = mul_with_quotient_oracle(params, lhs, rhs, N, MOD_BITS); + res } +// let mut mul: [Field; 2 * N] = [0; 2 * N]; +// for i in 0..N { +// for j in 0..N { +// mul[i + j] += lhs[i] * rhs[j]; +// } +// } +// let to_reduce = split_bits::__normalize_limbs(mul, 2 * N); +// let (q, r) = __barrett_reduction( +// to_reduce, +// params.redc_param, +// MOD_BITS, +// params.modulus, +// params.modulus_u60_x4, +// ); + +// (q, r) +// } + + + #[oracle(mul_with_quotient)] + pub (crate) unconstrained fn mul_with_quotient_oracle( + params: P, + lhs: [Field; N], + rhs: [Field; N], + num_limbs: u32, + mod_bits: u32, + ) -> ([Field; N], [Field; N]) {} pub(crate) unconstrained fn __mul( params: P, @@ -277,57 +306,93 @@ pub(crate) unconstrained fn __div( * 2. numerator % divisor = remainder * 3. divisor * quotient + remainder = numerator **/ -pub(crate) unconstrained fn __udiv_mod( - numerator: [Field; N], - divisor: [Field; N], -) -> ([Field; N], [Field; N]) { - let mut quotient_u60: U60Repr = U60Repr::from([0; N]); - let mut remainder_u60: U60Repr = U60Repr::from(numerator); +// pub(crate) unconstrained fn __udiv_mod( +// numerator: [Field; N], +// divisor: [Field; N], +// ) -> ([Field; N], [Field; N]) { +// let mut quotient_u60: U60Repr = U60Repr::from([0; N]); +// let mut remainder_u60: U60Repr = U60Repr::from(numerator); - let mut divisor_u60: U60Repr = U60Repr::from(divisor); - let b = divisor_u60; +// let mut divisor_u60: U60Repr = U60Repr::from(divisor); +// let b = divisor_u60; - let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb(); +// let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb(); - let mut accumulator_u60: U60Repr = U60Repr::one(); - divisor_u60 = divisor_u60.shl(bit_difference); - accumulator_u60 = accumulator_u60.shl(bit_difference); +// let mut accumulator_u60: U60Repr = U60Repr::one(); +// divisor_u60 = divisor_u60.shl(bit_difference); +// accumulator_u60 = accumulator_u60.shl(bit_difference); - if (divisor_u60.gte(remainder_u60 + U60Repr::one())) { - divisor_u60.shr1(); - accumulator_u60.shr1(); - } - for _ in 0..(N * 120) { - if (remainder_u60.gte(b) == false) { - break; - } +// if (divisor_u60.gte(remainder_u60 + U60Repr::one())) { +// divisor_u60.shr1(); +// accumulator_u60.shr1(); +// } +// for _ in 0..(N * 120) { +// if (remainder_u60.gte(b) == false) { +// break; +// } + +// // we've shunted 'divisor' up to have the same bit length as our remainder. +// // If remainder >= divisor, then a is at least '1 << bit_difference' multiples of b +// if (remainder_u60.gte(divisor_u60)) { +// remainder_u60 -= divisor_u60; +// // we can use OR here instead of +, as +// // accumulator is always a nice power of two +// quotient_u60 = quotient_u60 + accumulator_u60; +// } +// divisor_u60.shr1(); // >>= 1; +// accumulator_u60.shr1(); // >>= 1; +// } - // we've shunted 'divisor' up to have the same bit length as our remainder. - // If remainder >= divisor, then a is at least '1 << bit_difference' multiples of b - if (remainder_u60.gte(divisor_u60)) { - remainder_u60 -= divisor_u60; - // we can use OR here instead of +, as - // accumulator is always a nice power of two - quotient_u60 = quotient_u60 + accumulator_u60; - } - divisor_u60.shr1(); // >>= 1; - accumulator_u60.shr1(); // >>= 1; - } +// (U60Repr::into(quotient_u60), U60Repr::into(remainder_u60)) +// } - (U60Repr::into(quotient_u60), U60Repr::into(remainder_u60)) +pub(crate) unconstrained fn __udiv_mod( + numerator: [Field; N], + divisor: [Field; N], +) -> ([Field; N], [Field; N]) { + let res: ([Field; N], [Field; N]) = udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); + res } -pub(crate) unconstrained fn __invmod( + #[oracle(udiv_mod)] + pub (crate) unconstrained fn udiv_mod_oracle( + numerator: [Field; N], + divisor: [Field; N], + num_limbs: u32, + mod_bits: u32, + ) -> ([Field; N], [Field; N]) {} + + +// current implementation of invmod only works for prime fields +// we could use xgcd to extend this to all fields +// pub(crate) unconstrained fn __invmod( +// params: P, +// val: [Field; N], +// ) -> [Field; N] { +// let one: [Field; N] = __one::(); +// let one_u60: U60Repr = U60Repr::from(one); +// let exp_u60 = params.modulus_u60.sub(one_u60.add(one_u60)); +// let exp = U60Repr::into(exp_u60); +// __pow::<_, MOD_BITS>(params, val, exp) +// } +pub (crate) unconstrained fn __invmod( params: P, val: [Field; N], ) -> [Field; N] { - let one: [Field; N] = __one::(); - let one_u60: U60Repr = U60Repr::from(one); - let exp_u60 = params.modulus_u60.sub(one_u60.add(one_u60)); - let exp = U60Repr::into(exp_u60); - __pow::<_, MOD_BITS>(params, val, exp) + let res = invmod_oracle::(params, val, N, MOD_BITS); + res } + #[oracle(invmod)] + pub (crate) unconstrained fn invmod_oracle( + params: P, + val: [Field; N], + num_limbs: u32, + mod_bits: u32, + ) -> [Field; N] {} + + + pub(crate) unconstrained fn __pow( params: P, val: [Field; N], diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index f16e9d06..135de7da 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -345,7 +345,6 @@ impl RuntimeBigNumTrait for RuntimeB } fn validate_in_range(self) { - println( self.limbs); validate_in_range::<_, MOD_BITS>(self.limbs); } diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index d37e1ce9..3b7fe4f0 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -214,15 +214,10 @@ fn test_add() { let a: $RuntimeBigNum<$N, $MOD_BITS> = unsafe{ $RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]) }; let b: $RuntimeBigNum<$N, $MOD_BITS> = unsafe{ $RuntimeBigNum::__derive_from_seed(params, [4, 5, 6, 7]) }; let one: $RuntimeBigNum<$N, $MOD_BITS> = $RuntimeBigNum::one(params); - println("we got here"); a.validate_in_range(); - println("we got here 2"); a.validate_in_field(); - println("we got here 3"); b.validate_in_range(); - println("we got here 4"); b.validate_in_field(); - println("we got here 5"); let mut c = a + b; c = c + c; From 8a540bbe8c5d23f7da5d57dd851961beba38b81b Mon Sep 17 00:00:00 2001 From: kashbrti Date: Thu, 5 Dec 2024 15:23:42 +0000 Subject: [PATCH 05/24] pow oracle added, modular inversion fixed. modular division fixed (#70) --- oracles/src/handlers.rs | 47 +++++++++++++++++------- oracles/src/main.rs | 4 +-- oracles/src/ops.rs | 29 +++++++++++++++ src/fns/unconstrained_ops.nr | 70 +++++++++++++++++++++++++++--------- 4 files changed, 118 insertions(+), 32 deletions(-) diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 03fdafb4..2d11af8d 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -1,5 +1,6 @@ use ark_bn254::Fr; use ark_ff::Zero; +use jsonrpsee::core::params; use num_bigint::BigUint; use num_bigint::BigInt; use num_traits::ConstZero; @@ -13,6 +14,7 @@ use crate::ops::is_zero; use crate::ops::sqrt; use crate::ops::extended_gcd; use crate::ops::invert; +use crate::ops::pow_bn; // a struct that emulates the bignum Params params from the params.nr file struct Params { @@ -272,17 +274,15 @@ pub (crate) fn handle_invmod(inputs: &Vec>) -> Value { // get the params let params: Params = Params::from_foreign_call_params(&inputs); // get the value to be inverted - let val_fc = &inputs[inputs.len()-1]; + let val_fc = &inputs[inputs.len()-3]; let val_str = callparam_to_string(val_fc); let val = cast_to_biguint(val_str); let num_limbs = val_fc.len(); // invert the value - println!("modulus: {:?}", params.modulus); - println!("val: {:?}", val); let inv = invert(&val, ¶ms.modulus); // cast the inverse to limbs let limbs = cast_bigint_to_bignum_limbs(&inv, num_limbs as u32); - // return an empty json response for now + // return the json response for now let return_vec:Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); json_response @@ -291,15 +291,41 @@ pub (crate) fn handle_invmod(inputs: &Vec>) -> Value { // a handler for modular exponentiation pub (crate) fn handle_pow(inputs: &Vec>) -> Value { // return an empty json response for now - let return_vec:Vec> = vec![]; + let params: Params = Params::from_foreign_call_params(&inputs); + let exponent_fc = &inputs[inputs.len()-3]; + let exponent_str = callparam_to_string(exponent_fc); + let exponent = cast_to_biguint(exponent_str); + let num_limbs = exponent_fc.len(); + let val_fc = &inputs[inputs.len()-4]; + let val_str = callparam_to_string(val_fc); + let val = cast_to_biguint(val_str); + + let res = pow_bn(&val ,&exponent, ¶ms.modulus); + let limbs = cast_biguint_to_bignum_limbs(&res, num_limbs as u32); + let return_vec:Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); json_response } // a handler for modular division -pub (crate) fn handle_divmod(inputs: &Vec>) -> Value { - // return an empty json response for now - let return_vec:Vec> = vec![]; +pub (crate) fn handle_div(inputs: &Vec>) -> Value { + let params: Params = Params::from_foreign_call_params(&inputs); + let numerator_fc = &inputs[inputs.len()-4]; + let numerator_str = callparam_to_string(numerator_fc); + let numerator = cast_to_biguint(numerator_str); + let divisor_fc = &inputs[inputs.len()-3]; + let divisor_str = callparam_to_string(divisor_fc); + let divisor = cast_to_biguint(divisor_str); + let num_limbs = numerator_fc.len(); + + // compute the inverse of the divisor with respect to the modulus + let inv = invert(&divisor, ¶ms.modulus); + // multiply the numerator by the inverse + let result = (BigInt::from(numerator.clone())) * &inv; + let reduced = result % BigInt::from(params.modulus.clone()); + // cast the result to limbs + let limbs = cast_bigint_to_bignum_limbs(&reduced, num_limbs as u32); + let return_vec:Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); json_response } @@ -309,7 +335,6 @@ pub (crate) fn handle_divmod(inputs: &Vec>) -> Value { - // ============================== // ============================== // ============================== @@ -379,13 +404,10 @@ pub (crate) fn get_u32_from_callparam(input: &ForeignCallParam) -> u32 { } pub (crate) fn get_bool_from_callparam(input: &ForeignCallParam) -> bool { - // println!("the bool oracle was called"); - // println!("input: {:?}", input); let mut input_string = callparam_to_string(input)[0]; if input_string == "" { input_string = "0"; } - // println!("input_string: {:?}", input_string); let res = u32::from_str_radix(input_string, 16).unwrap(); res == 1 } @@ -460,4 +482,3 @@ impl std::fmt::Debug for Params { - diff --git a/oracles/src/main.rs b/oracles/src/main.rs index 22c24021..162446f4 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -39,7 +39,7 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_divmod}; +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div}; // SPIN UP THE SERVER #[tokio::main] @@ -109,7 +109,7 @@ async fn run_server() -> anyhow::Result { "udiv_mod" => handle_udiv_mod(&request.inputs), // the inputs to this are effectively a Vec "invmod" => handle_invmod(&request.inputs), // the inputs to this are effectively a Vec "pow" => handle_pow(&request.inputs), // the inputs to this are effectively a Vec - "divmod" => handle_divmod(&request.inputs), // the inputs to this are effectively a Vec + "div" => handle_div(&request.inputs), // the inputs to this are effectively a Vec _ => handle_unknown_function(&request), }; diff --git a/oracles/src/ops.rs b/oracles/src/ops.rs index fcd7d336..d13b595d 100644 --- a/oracles/src/ops.rs +++ b/oracles/src/ops.rs @@ -1,3 +1,5 @@ +use core::fmt; + use ark_bn254::Fr; use ark_ff::Field; use ark_ff::Zero as ZeroField; @@ -70,6 +72,23 @@ pub(crate) fn invert(a: &BigUint , modulus: &BigUint) -> BigInt { } +pub (crate) fn pow_bn(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint { + // cast the exponent into bytes + let exponent_bytes = exponent.to_bytes_be(); + // do a square and multiply type algorithm + let mut result = BigUint::from(1u64); + for exponent_byte in exponent_bytes { + // this will be potentially horribly slow + result = result.pow(256); + result = result % modulus; + result = result * base.pow(exponent_byte as u32); + result = result % modulus; + } + result +} + + + // some tests to check the behaviour of the extended gcd #[test] fn test_extended_euclidean() { @@ -87,6 +106,16 @@ fn test_invert() { assert_eq!((r * a_bigint) % modulus_bigint , BigInt::from(1u64)); } + +#[test] +fn test_pow_bn() { + let base = BigUint::from(3u64); + let exponent = BigUint::from(10u64); + let modulus = BigUint::from(1000000000u64); + let result = pow_bn(&base, &exponent, &modulus); + assert_eq!(result, BigUint::from(59049u64)); +} + // #[test] // #[should_panic(expected = "input and modulus are no coprime")] // fn test_invert_fail() { diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index d9e4aa0f..5b68125b 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -290,15 +290,32 @@ pub(crate) unconstrained fn __mul( b } -pub(crate) unconstrained fn __div( +// pub(crate) unconstrained fn __div( +// params: P, +// numerator: [Field; N], +// divisor: [Field; N], +// ) -> [Field; N] { +// let inv_divisor = __invmod::<_, MOD_BITS>(params, divisor); +// __mul::<_, MOD_BITS>(params, numerator, inv_divisor) +// } + +pub (crate) unconstrained fn __div( params: P, numerator: [Field; N], divisor: [Field; N], ) -> [Field; N] { - let inv_divisor = __invmod::<_, MOD_BITS>(params, divisor); - __mul::<_, MOD_BITS>(params, numerator, inv_divisor) + div_oracle(params, numerator, divisor, N, MOD_BITS) } + #[oracle(div)] + pub (crate) unconstrained fn div_oracle( + params: P, + numerator: [Field; N], + divisor: [Field; N], + num_limbs: u32, + mod_bits: u32, + ) -> [Field; N] {} + /** * @brief __udiv_mod performs *unconstrained* integer division between numerator, divisor * @@ -393,26 +410,45 @@ pub (crate) unconstrained fn __invmod( -pub(crate) unconstrained fn __pow( +// pub(crate) unconstrained fn __pow( +// params: P, +// val: [Field; N], +// exponent: [Field; N], +// ) -> [Field; N] { +// let x: U60Repr = U60Repr::from(exponent); + +// let num_bits = MOD_BITS + 1; + +// let mut accumulator: [Field; N] = __one::(); + +// for i in 0..num_bits { +// accumulator = __mul::<_, MOD_BITS>(params, accumulator, accumulator); +// if x.get_bit(num_bits - i - 1) { +// accumulator = __mul::<_, MOD_BITS>(params, accumulator, val); +// } +// } +// accumulator +// } + +pub (crate) unconstrained fn __pow( params: P, val: [Field; N], exponent: [Field; N], ) -> [Field; N] { - let x: U60Repr = U60Repr::from(exponent); - - let num_bits = MOD_BITS + 1; - - let mut accumulator: [Field; N] = __one::(); - - for i in 0..num_bits { - accumulator = __mul::<_, MOD_BITS>(params, accumulator, accumulator); - if x.get_bit(num_bits - i - 1) { - accumulator = __mul::<_, MOD_BITS>(params, accumulator, val); - } - } - accumulator + pow_oracle(params, val, exponent, N, MOD_BITS) } + #[oracle(pow)] + pub (crate) unconstrained fn pow_oracle( + params: P, + val: [Field; N], + exponent: [Field; N], + num_limbs: u32, + mod_bits: u32, + ) -> [Field; N] {} + + + pub(crate) unconstrained fn __batch_invert( params: P, x: [[Field; N]; M], From f6e07dd7df4dafc8093e5e3dfdc8c6731bb9460b Mon Sep 17 00:00:00 2001 From: kashbrti Date: Thu, 5 Dec 2024 17:14:55 +0000 Subject: [PATCH 06/24] Kb/oracles merge fix (#71) Co-authored-by: Riley --- .github/workflows/test.yml | 4 +- Nargo.toml | 2 +- oracles/src/handlers.rs | 22 ++++ oracles/src/main.rs | 5 +- src/bignum.nr | 3 +- src/fns/constrained_ops.nr | 3 +- src/fns/unconstrained_helpers.nr | 167 +++++++++++++++++-------------- src/fns/unconstrained_ops.nr | 166 +++++++++++++++++------------- src/runtime_bignum.nr | 11 +- src/tests/bignum_test.nr | 59 ++++++----- 10 files changed, 258 insertions(+), 184 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1691bfea..37e91392 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [nightly, 0.36.0] + toolchain: [nightly, 1.0.0-beta.0] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -38,7 +38,7 @@ jobs: - name: Install Nargo uses: noir-lang/noirup@v0.1.3 with: - toolchain: 0.36.0 + toolchain: 1.0.0-beta.0 - name: Run formatter run: nargo fmt --check diff --git a/Nargo.toml b/Nargo.toml index 337a2e09..7750cbbe 100644 --- a/Nargo.toml +++ b/Nargo.toml @@ -2,6 +2,6 @@ name = "bignum" type = "lib" authors = [""] -compiler_version = ">=0.36.0" +compiler_version = "1.0.0" [dependencies] diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 2d11af8d..42214a20 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -333,6 +333,27 @@ pub (crate) fn handle_div(inputs: &Vec>) -> Value { +pub (crate) fn handle_barrett_reduction(inputs: &Vec>) -> Value { + // return an empty json response for now + // the inputs are x , modulus + let x_fc = &inputs[0]; + let x_str = callparam_to_string(x_fc); + let modulus_fc = &inputs[1]; + let modulus_str = callparam_to_string(modulus_fc); + let x = cast_to_biguint(x_str); + let modulus = cast_to_biguint(modulus_str); + let num_limbs = modulus_fc.len(); + let quotient = &x / &modulus; + let remainder = &x % &modulus; + //cast the quotient and the remainder to limbs + let quotient_limbs = cast_biguint_to_bignum_limbs("ient, num_limbs as u32); + let remainder_limbs = cast_biguint_to_bignum_limbs(&remainder, num_limbs as u32); + let return_vec:Vec> = vec![quotient_limbs, remainder_limbs]; + let json_response = json!({"values" : return_vec}); + json_response +} + + // ============================== @@ -370,6 +391,7 @@ pub (crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { } + // helper function to get limbs of a big num and pack them into a vector of Fr elements pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { let mut limbs: Vec = vec![]; diff --git a/oracles/src/main.rs b/oracles/src/main.rs index 162446f4..bf172de4 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -39,7 +39,9 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div}; + +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div, handle_barrett_reduction}; + // SPIN UP THE SERVER #[tokio::main] @@ -110,6 +112,7 @@ async fn run_server() -> anyhow::Result { "invmod" => handle_invmod(&request.inputs), // the inputs to this are effectively a Vec "pow" => handle_pow(&request.inputs), // the inputs to this are effectively a Vec "div" => handle_div(&request.inputs), // the inputs to this are effectively a Vec + "barrett_reduction" => handle_barrett_reduction(&request.inputs), // the inputs to this are effectively a Vec _ => handle_unknown_function(&request), }; diff --git a/src/bignum.nr b/src/bignum.nr index 81f9510e..713aadca 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -6,7 +6,8 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, + expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, diff --git a/src/fns/constrained_ops.nr b/src/fns/constrained_ops.nr index 972e0d0b..db515e35 100644 --- a/src/fns/constrained_ops.nr +++ b/src/fns/constrained_ops.nr @@ -5,7 +5,8 @@ use crate::fns::{ unconstrained_helpers::{ __add_with_flags, __neg_with_flags, __sub_with_flags, __validate_gt_remainder, __validate_in_field_compute_borrow_flags, - }, unconstrained_ops::{__div, __mul, __udiv_mod}, + }, + unconstrained_ops::{__div, __mul, __udiv_mod}, }; /** diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 5b19ccd8..2798e42b 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -227,7 +227,92 @@ pub(crate) unconstrained fn __sub_with_flags( * @details maximum value = modulus^2 <( +// x: [Field; 2 * N], +// redc_param: [Field; N], +// k: u32, +// modulus: [Field; N], +// modulus_u60: U60Repr, +// ) -> ([Field; N], [Field; N]) { +// // for each i in 0..(N + N), adds x[i] * redc_param[j] to mulout[i + j] for each j in 0..N +// let mut mulout: [Field; 3 * N] = [0; 3 * N]; +// for i in 0..(N + N) { +// for j in 0..N { +// mulout[i + j] += x[i] * redc_param[j]; +// } +// } + +// mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); +// let mulout_u60: U60Repr = U60Repr::new(mulout); + +// // When we apply the barrett reduction, the maximum value of the output will be +// // <= p * (1 + x/2^{2k}) +// // where p = modulus, +// // x = reduction input +// // if x > p * p, we need k to be larger than modulus_bits() +// // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p +// // this should be larger than most values put into `evaluate_quadratic_expression` +// // TODO: try and detect cases where x might be too large at comptime +// // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. +// // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus +// // NOTE: very niche edge case error that we need to be aware of: +// // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS +// // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction +// let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); + +// // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. +// // (partial_quotient_full should be just slightly larger than the modulus, we could probably represent with a size N+1 array) +// let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); + +// // quotient_mul_modulus_normalized can never exceed input value `x` so can fit into size-2 array +// let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; + +// // First, accumulate the products into quotient_mul_modulus_normalized +// for j in 0..N { +// for i in 0..(N + N - j) { +// quotient_mul_modulus_normalized[i + j] += partial_quotient_full[i] * modulus[j]; +// } +// } + +// // Then, split the accumulated values and propagate higher bits +// for i in 0..(N + N) { +// let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus_normalized[i]); +// quotient_mul_modulus_normalized[i] = lo; + +// // Propagate higher bits to the next index +// // TODO: what is faster, leaving this if statement in or out? +// // (array is size-1 too large so we can tolerate adding 0 into max element) +// if (i + 1 < N + N) { +// quotient_mul_modulus_normalized[i + 1] += hi; +// } +// } + +// let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); +// // convert the input into U60Repr +// let x_u60: U60Repr = U60Repr::new(x); +// let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; +// // barrett reduction is quircky so might need to remove a few modulus_u60 from the remainder +// if (remainder_u60.gte(modulus_u60)) { +// remainder_u60 = remainder_u60 - modulus_u60; +// quotient_u60.increment(); +// } else {} +// if (remainder_u60.gte(modulus_u60)) { +// remainder_u60 = remainder_u60 - modulus_u60; +// quotient_u60.increment(); +// } +// if (remainder_u60.gte(modulus_u60)) { +// remainder_u60 = remainder_u60 - modulus_u60; +// quotient_u60.increment(); +// } + +// let q: [Field; N] = U60Repr::into(quotient_u60); +// let r: [Field; N] = U60Repr::into(remainder_u60); + +// (q, r) +// } + pub(crate) unconstrained fn __barrett_reduction( x: [Field; 2 * N], @@ -236,81 +321,15 @@ pub(crate) unconstrained fn __barrett_reduction( modulus: [Field; N], modulus_u60: U60Repr, ) -> ([Field; N], [Field; N]) { - let mut mulout: [Field; 3 * N] = [0; 3 * N]; - for i in 0..(N + N) { - for j in 0..N { - mulout[i + j] += x[i] * redc_param[j]; - } - } - mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); - let mulout_u60: U60Repr = U60Repr::new(mulout); - - // When we apply the barrett reduction, the maximum value of the output will be - // <= p * (1 + x/2^{2k}) - // where p = modulus, - // x = reduction input - // if x > p * p, we need k to be larger than modulus_bits() - // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p - // this should be larger than most values put into `evaluate_quadratic_expression` - // TODO: try and detect cases where x might be too large at comptime - // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. - // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus - // NOTE: very niche edge case error that we need to be aware of: - // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS - // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction - let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); - - // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. - // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) - let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); - let mut partial_quotient: [Field; 2 * N] = [0; 2 * N]; - for i in 0..2 * N { - partial_quotient[i] = partial_quotient_full[i]; - } - // quotient_mul_modulus can never exceed input value `x` so can fit into size-2 array - let mut quotient_mul_modulus: [Field; 2 * N] = [0; 2 * N]; - let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; - for j in 0..N { - for i in 0..(N + N - j) { - quotient_mul_modulus[i + j] += partial_quotient[i] * modulus[j]; - } - } - - for i in 0..(N + N) { - let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus[i]); - quotient_mul_modulus_normalized[i] = lo; - // TODO: what is faster, leaving this if statement in or out? - // (array is size-1 too large so we can tolerate adding 0 into max element) - if (i + 1 < N + N) { - quotient_mul_modulus[i + 1] += hi; - } - } - let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); - - let x_u60: U60Repr = U60Repr::new(x); - let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; - - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - - let q: [Field; N] = U60Repr::into(quotient_u60); - let r: [Field; N] = U60Repr::into(remainder_u60); - - (q, r) + barrett_reduction_oracle(x, modulus) } + #[oracle(barrett_reduction)] + pub (crate) unconstrained fn barrett_reduction_oracle( + x: [Field; 2 * N], + modulus: [Field; N], + ) -> ([Field; N], [Field; N]) {} + /** * @brief compute the log of the size of the primitive root * @details find the maximum value k where x^k = 1, where x = primitive root diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index 5b68125b..a4bcab82 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -56,64 +56,19 @@ pub(crate) unconstrained fn __derive_from_seed(limbs: [Field; N]) -> bool { +// let mut result: bool = true; +// for i in 0..N { +// result = result & (limbs[i] == 0); +// } - for i in 0..(N - 1) { - let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); - let hash: [u8; 30] = hash.to_le_bytes(); - let mut lo: Field = 0; - let mut hi: Field = 0; - for j in 0..15 { - hi *= 256; - lo *= 256; - - if (i < 2 * N - 2) { - lo += hash[j + 15] as Field; - hi += hash[j] as Field; - } - } - to_reduce[2 * i] = lo; - to_reduce[2 * i + 1] = hi; - rolling_hash[1] += 1; - } +// result +// } - { - let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); - let hash: [u8; 30] = hash.to_le_bytes(); - let mut hi: Field = 0; - for j in 0..(last_limb_bytes - 1) { - hi *= 256; - hi += hash[j] as Field; - } - hi *= 256; - let last_byte = hash[last_limb_bytes - 1]; - let mask = (1 as u64 << (last_limb_bits) as u8) - 1; - let last_bits = last_byte as u64 & mask; - hi += last_bits as Field; - to_reduce[2 * N - 2] = hi; - } +#[oracle(is_zero)] +pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} - let (_, remainder) = __barrett_reduction( - to_reduce, - params.redc_param, - MOD_BITS, - params.modulus, - params.modulus_u60_x4, - ); - let result = remainder; - result -} pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) -> bool { lhs == rhs @@ -156,6 +111,15 @@ pub (crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} // let x_u60: U60Repr = U60Repr::from(f); // U60Repr::into(params.modulus_u60 - x_u60) // } + +pub(crate) unconstrained fn __neg( + params: P, + limbs: [Field; N], +) -> [Field; N] { + neg_oracle(params, limbs, N, MOD_BITS) +} + +#[oracle(neg)] pub (crate) unconstrained fn __neg( params: P, limbs: [Field; N], @@ -170,9 +134,8 @@ unconstrained fn neg_oracle( limbs: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} +) -> [Field; N] {} -// switching this function to use oracles instead // pub(crate) unconstrained fn __add( // params: P, // lhs: [Field; N], @@ -188,6 +151,9 @@ unconstrained fn neg_oracle( // } // U60Repr::into(z_u60) // } + + + // the oracle function to get the add result #[oracle(add)] @@ -197,25 +163,18 @@ unconstrained fn neg_oracle( rhs: [Field; N], num_limbs: u32, mod_bits: u32, + ) -> [Field; N] {} //this is the actual function that be changed to use oracles // pub (crate) unconstrained fn __add( // switching this function to use oracles instead + pub(crate) unconstrained fn __add( params: P, lhs: [Field; N], rhs: [Field; N], ) -> [Field; N] { - // let x_u60: U60Repr = U60Repr::from(lhs); - // let y_u60: U60Repr = U60Repr::from(rhs); - - // let mut z_u60 = x_u60 + y_u60; - - // if z_u60.gte(params.modulus_u60) { - // z_u60 = z_u60 - params.modulus_u60; - // } - // U60Repr::into(z_u60) add_oracle(params, lhs, rhs, N, MOD_BITS) } // the oracle function to get the add result @@ -245,6 +204,29 @@ pub(crate) unconstrained fn __sub( __add(params, lhs, __neg(params, rhs)) } +// pub(crate) unconstrained fn __mul_with_quotient( +// params: P, +// lhs: [Field; N], +// rhs: [Field; N], +// ) -> ([Field; N], [Field; N]) { +// let mut mul: [Field; 2 * N] = [0; 2 * N]; +// for i in 0..N { +// for j in 0..N { +// mul[i + j] += lhs[i] * rhs[j]; +// } +// } +// let to_reduce = split_bits::__normalize_limbs(mul, 2 * N); +// let (q, r) = __barrett_reduction( +// to_reduce, +// params.redc_param, +// MOD_BITS, +// params.modulus, +// params.modulus_u60_x4, +// ); + +// (q, r) +// } + pub(crate) unconstrained fn __mul_with_quotient( params: P, lhs: [Field; N], @@ -281,6 +263,15 @@ pub(crate) unconstrained fn __mul_with_quotient( mod_bits: u32, ) -> ([Field; N], [Field; N]) {} +#[oracle(mul_with_quotient)] +pub(crate) unconstrained fn mul_with_quotient_oracle( + params: P, + lhs: [Field; N], + rhs: [Field; N], + num_limbs: u32, + mod_bits: u32, +) -> ([Field; N], [Field; N]) {} + pub(crate) unconstrained fn __mul( params: P, lhs: [Field; N], @@ -299,7 +290,9 @@ pub(crate) unconstrained fn __mul( // __mul::<_, MOD_BITS>(params, numerator, inv_divisor) // } -pub (crate) unconstrained fn __div( + +pub(crate) unconstrained fn __div( + params: P, numerator: [Field; N], divisor: [Field; N], @@ -307,8 +300,10 @@ pub (crate) unconstrained fn __div( div_oracle(params, numerator, divisor, N, MOD_BITS) } + #[oracle(div)] pub (crate) unconstrained fn div_oracle( + params: P, numerator: [Field; N], divisor: [Field; N], @@ -316,6 +311,7 @@ pub (crate) unconstrained fn __div( mod_bits: u32, ) -> [Field; N] {} + /** * @brief __udiv_mod performs *unconstrained* integer division between numerator, divisor * @@ -323,6 +319,7 @@ pub (crate) unconstrained fn __div( * 2. numerator % divisor = remainder * 3. divisor * quotient + remainder = numerator **/ + // pub(crate) unconstrained fn __udiv_mod( // numerator: [Field; N], // divisor: [Field; N], @@ -367,6 +364,31 @@ pub(crate) unconstrained fn __udiv_mod( numerator: [Field; N], divisor: [Field; N], ) -> ([Field; N], [Field; N]) { + let res: ([Field; N], [Field; N]) = + udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); + res +} + +#[oracle(udiv_mod)] +pub(crate) unconstrained fn udiv_mod_oracle( + numerator: [Field; N], + divisor: [Field; N], + num_limbs: u32, + mod_bits: u32, +) -> ([Field; N], [Field; N]) {} + +// pub(crate) unconstrained fn __invmod( +// params: P, +// val: [Field; N], +// ) -> [Field; N] { +// let one: [Field; N] = __one::(); +// let one_u60: U60Repr = U60Repr::from(one); +// let exp_u60 = params.modulus_u60.sub(one_u60.add(one_u60)); +// let exp = U60Repr::into(exp_u60); +// __pow::<_, MOD_BITS>(params, val, exp) +// } + +pub(crate) unconstrained fn __invmod( let res: ([Field; N], [Field; N]) = udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); res } @@ -435,19 +457,19 @@ pub (crate) unconstrained fn __pow( val: [Field; N], exponent: [Field; N], ) -> [Field; N] { - pow_oracle(params, val, exponent, N, MOD_BITS) + let res = invmod_oracle::(params, val, N, MOD_BITS); + res } - #[oracle(pow)] - pub (crate) unconstrained fn pow_oracle( + +#[oracle(pow)] +pub(crate) unconstrained fn pow_oracle( params: P, val: [Field; N], exponent: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} - - +) -> [Field; N] {} pub(crate) unconstrained fn __batch_invert( params: P, diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 135de7da..f4df4ec5 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -5,13 +5,12 @@ use crate::params::BigNumParams; use crate::fns::{ constrained_ops::{ - derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, - validate_in_range, neg, add, sub, mul, div, udiv_mod, udiv, umod, + + add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, + udiv, udiv_mod, umod, validate_in_field, validate_in_range, }, - unconstrained_ops::{ - __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, - __invmod, __pow, __batch_invert, __batch_invert_slice, __tonelli_shanks_sqrt, - }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + serialization::{from_be_bytes, to_le_bytes}, }; diff --git a/src/tests/bignum_test.nr b/src/tests/bignum_test.nr index 53eefd6b..233535e3 100644 --- a/src/tests/bignum_test.nr +++ b/src/tests/bignum_test.nr @@ -792,47 +792,54 @@ fn test_expressions() { } - - #[test] fn test_oracle_add() { - // type Fq = BigNum <3,254, BN254_Fq_Params> ; - let a: Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000001, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]}; - let b: Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000002, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]}; - let c : Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000003, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]} ; + let a: Fq = BigNum { + limbs: [ + 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + ], + }; + let b: Fq = BigNum { + limbs: [ + 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + ], + }; + let c: Fq = BigNum { + limbs: [ + 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + ], + }; let result: Fq = a.__add(b); - + assert(result == c); - // let b: Fq = BigNum::one(); - // let result = a + b; - assert(result == c) ; } #[test] fn test_oracle_is_zero() { + + let a: Fq = BigNum { + limbs: [ + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000, + ], + }; + let a: Fq = BigNum{limbs : [ 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000 ]}; - let result = a.__is_zero(); - assert(result == true); - // assert(true); + + let result = a.__is_zero(); } -// type Fq = BigNum<3, 254, BN254_Fq_Params>; From f64e4cdd79f91c360239455b80189b691a344a22 Mon Sep 17 00:00:00 2001 From: kashbrti Date: Thu, 5 Dec 2024 17:18:06 +0000 Subject: [PATCH 07/24] Revert "Kb/oracles merge fix" (#72) --- .github/workflows/test.yml | 4 +- Nargo.toml | 2 +- oracles/src/handlers.rs | 22 ---- oracles/src/main.rs | 5 +- src/bignum.nr | 3 +- src/fns/constrained_ops.nr | 3 +- src/fns/unconstrained_helpers.nr | 167 ++++++++++++++----------------- src/fns/unconstrained_ops.nr | 166 +++++++++++++----------------- src/runtime_bignum.nr | 11 +- src/tests/bignum_test.nr | 59 +++++------ 10 files changed, 184 insertions(+), 258 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 37e91392..1691bfea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [nightly, 1.0.0-beta.0] + toolchain: [nightly, 0.36.0] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -38,7 +38,7 @@ jobs: - name: Install Nargo uses: noir-lang/noirup@v0.1.3 with: - toolchain: 1.0.0-beta.0 + toolchain: 0.36.0 - name: Run formatter run: nargo fmt --check diff --git a/Nargo.toml b/Nargo.toml index 7750cbbe..337a2e09 100644 --- a/Nargo.toml +++ b/Nargo.toml @@ -2,6 +2,6 @@ name = "bignum" type = "lib" authors = [""] -compiler_version = "1.0.0" +compiler_version = ">=0.36.0" [dependencies] diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 42214a20..2d11af8d 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -333,27 +333,6 @@ pub (crate) fn handle_div(inputs: &Vec>) -> Value { -pub (crate) fn handle_barrett_reduction(inputs: &Vec>) -> Value { - // return an empty json response for now - // the inputs are x , modulus - let x_fc = &inputs[0]; - let x_str = callparam_to_string(x_fc); - let modulus_fc = &inputs[1]; - let modulus_str = callparam_to_string(modulus_fc); - let x = cast_to_biguint(x_str); - let modulus = cast_to_biguint(modulus_str); - let num_limbs = modulus_fc.len(); - let quotient = &x / &modulus; - let remainder = &x % &modulus; - //cast the quotient and the remainder to limbs - let quotient_limbs = cast_biguint_to_bignum_limbs("ient, num_limbs as u32); - let remainder_limbs = cast_biguint_to_bignum_limbs(&remainder, num_limbs as u32); - let return_vec:Vec> = vec![quotient_limbs, remainder_limbs]; - let json_response = json!({"values" : return_vec}); - json_response -} - - // ============================== @@ -391,7 +370,6 @@ pub (crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { } - // helper function to get limbs of a big num and pack them into a vector of Fr elements pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { let mut limbs: Vec = vec![]; diff --git a/oracles/src/main.rs b/oracles/src/main.rs index bf172de4..162446f4 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -39,9 +39,7 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; - -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div, handle_barrett_reduction}; - +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div}; // SPIN UP THE SERVER #[tokio::main] @@ -112,7 +110,6 @@ async fn run_server() -> anyhow::Result { "invmod" => handle_invmod(&request.inputs), // the inputs to this are effectively a Vec "pow" => handle_pow(&request.inputs), // the inputs to this are effectively a Vec "div" => handle_div(&request.inputs), // the inputs to this are effectively a Vec - "barrett_reduction" => handle_barrett_reduction(&request.inputs), // the inputs to this are effectively a Vec _ => handle_unknown_function(&request), }; diff --git a/src/bignum.nr b/src/bignum.nr index 713aadca..81f9510e 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -6,8 +6,7 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, - expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, diff --git a/src/fns/constrained_ops.nr b/src/fns/constrained_ops.nr index db515e35..972e0d0b 100644 --- a/src/fns/constrained_ops.nr +++ b/src/fns/constrained_ops.nr @@ -5,8 +5,7 @@ use crate::fns::{ unconstrained_helpers::{ __add_with_flags, __neg_with_flags, __sub_with_flags, __validate_gt_remainder, __validate_in_field_compute_borrow_flags, - }, - unconstrained_ops::{__div, __mul, __udiv_mod}, + }, unconstrained_ops::{__div, __mul, __udiv_mod}, }; /** diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 2798e42b..5b19ccd8 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -227,92 +227,7 @@ pub(crate) unconstrained fn __sub_with_flags( * @details maximum value = modulus^2 <( -// x: [Field; 2 * N], -// redc_param: [Field; N], -// k: u32, -// modulus: [Field; N], -// modulus_u60: U60Repr, -// ) -> ([Field; N], [Field; N]) { -// // for each i in 0..(N + N), adds x[i] * redc_param[j] to mulout[i + j] for each j in 0..N -// let mut mulout: [Field; 3 * N] = [0; 3 * N]; -// for i in 0..(N + N) { -// for j in 0..N { -// mulout[i + j] += x[i] * redc_param[j]; -// } -// } - -// mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); -// let mulout_u60: U60Repr = U60Repr::new(mulout); - -// // When we apply the barrett reduction, the maximum value of the output will be -// // <= p * (1 + x/2^{2k}) -// // where p = modulus, -// // x = reduction input -// // if x > p * p, we need k to be larger than modulus_bits() -// // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p -// // this should be larger than most values put into `evaluate_quadratic_expression` -// // TODO: try and detect cases where x might be too large at comptime -// // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. -// // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus -// // NOTE: very niche edge case error that we need to be aware of: -// // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS -// // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction -// let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); - -// // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. -// // (partial_quotient_full should be just slightly larger than the modulus, we could probably represent with a size N+1 array) -// let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); - -// // quotient_mul_modulus_normalized can never exceed input value `x` so can fit into size-2 array -// let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; - -// // First, accumulate the products into quotient_mul_modulus_normalized -// for j in 0..N { -// for i in 0..(N + N - j) { -// quotient_mul_modulus_normalized[i + j] += partial_quotient_full[i] * modulus[j]; -// } -// } - -// // Then, split the accumulated values and propagate higher bits -// for i in 0..(N + N) { -// let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus_normalized[i]); -// quotient_mul_modulus_normalized[i] = lo; - -// // Propagate higher bits to the next index -// // TODO: what is faster, leaving this if statement in or out? -// // (array is size-1 too large so we can tolerate adding 0 into max element) -// if (i + 1 < N + N) { -// quotient_mul_modulus_normalized[i + 1] += hi; -// } -// } - -// let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); -// // convert the input into U60Repr -// let x_u60: U60Repr = U60Repr::new(x); -// let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; -// // barrett reduction is quircky so might need to remove a few modulus_u60 from the remainder -// if (remainder_u60.gte(modulus_u60)) { -// remainder_u60 = remainder_u60 - modulus_u60; -// quotient_u60.increment(); -// } else {} -// if (remainder_u60.gte(modulus_u60)) { -// remainder_u60 = remainder_u60 - modulus_u60; -// quotient_u60.increment(); -// } -// if (remainder_u60.gte(modulus_u60)) { -// remainder_u60 = remainder_u60 - modulus_u60; -// quotient_u60.increment(); -// } - -// let q: [Field; N] = U60Repr::into(quotient_u60); -// let r: [Field; N] = U60Repr::into(remainder_u60); - -// (q, r) -// } - +comptime global BARRETT_REDUCTION_OVERFLOW_BITS: u32 = 4; pub(crate) unconstrained fn __barrett_reduction( x: [Field; 2 * N], @@ -321,14 +236,80 @@ pub(crate) unconstrained fn __barrett_reduction( modulus: [Field; N], modulus_u60: U60Repr, ) -> ([Field; N], [Field; N]) { - barrett_reduction_oracle(x, modulus) -} + let mut mulout: [Field; 3 * N] = [0; 3 * N]; + for i in 0..(N + N) { + for j in 0..N { + mulout[i + j] += x[i] * redc_param[j]; + } + } + mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); + let mulout_u60: U60Repr = U60Repr::new(mulout); + + // When we apply the barrett reduction, the maximum value of the output will be + // <= p * (1 + x/2^{2k}) + // where p = modulus, + // x = reduction input + // if x > p * p, we need k to be larger than modulus_bits() + // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p + // this should be larger than most values put into `evaluate_quadratic_expression` + // TODO: try and detect cases where x might be too large at comptime + // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. + // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus + // NOTE: very niche edge case error that we need to be aware of: + // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS + // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction + let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); + + // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. + // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) + let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); + let mut partial_quotient: [Field; 2 * N] = [0; 2 * N]; + for i in 0..2 * N { + partial_quotient[i] = partial_quotient_full[i]; + } + // quotient_mul_modulus can never exceed input value `x` so can fit into size-2 array + let mut quotient_mul_modulus: [Field; 2 * N] = [0; 2 * N]; + let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; + for j in 0..N { + for i in 0..(N + N - j) { + quotient_mul_modulus[i + j] += partial_quotient[i] * modulus[j]; + } + } - #[oracle(barrett_reduction)] - pub (crate) unconstrained fn barrett_reduction_oracle( - x: [Field; 2 * N], - modulus: [Field; N], - ) -> ([Field; N], [Field; N]) {} + for i in 0..(N + N) { + let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus[i]); + quotient_mul_modulus_normalized[i] = lo; + // TODO: what is faster, leaving this if statement in or out? + // (array is size-1 too large so we can tolerate adding 0 into max element) + if (i + 1 < N + N) { + quotient_mul_modulus[i + 1] += hi; + } + } + let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); + + let x_u60: U60Repr = U60Repr::new(x); + let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; + + if (remainder_u60.gte(modulus_u60)) { + remainder_u60 = remainder_u60 - modulus_u60; + quotient_u60.increment(); + } else {} + + if (remainder_u60.gte(modulus_u60)) { + remainder_u60 = remainder_u60 - modulus_u60; + quotient_u60.increment(); + } else {} + + if (remainder_u60.gte(modulus_u60)) { + remainder_u60 = remainder_u60 - modulus_u60; + quotient_u60.increment(); + } else {} + + let q: [Field; N] = U60Repr::into(quotient_u60); + let r: [Field; N] = U60Repr::into(remainder_u60); + + (q, r) +} /** * @brief compute the log of the size of the primitive root diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index a4bcab82..5b68125b 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -56,19 +56,64 @@ pub(crate) unconstrained fn __derive_from_seed(limbs: [Field; N]) -> bool { -// let mut result: bool = true; -// for i in 0..N { -// result = result & (limbs[i] == 0); -// } + let mut last_limb_bytes = double_modulus_bytes % 15; + if (last_limb_bytes == 0) { + last_limb_bytes = 15; + } + let mut last_limb_bits = double_modulus_bits % 8; + if (last_limb_bits == 0) { + last_limb_bits = 8; + } -// result -// } + for i in 0..(N - 1) { + let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); + let hash: [u8; 30] = hash.to_le_bytes(); + let mut lo: Field = 0; + let mut hi: Field = 0; + for j in 0..15 { + hi *= 256; + lo *= 256; + + if (i < 2 * N - 2) { + lo += hash[j + 15] as Field; + hi += hash[j] as Field; + } + } + to_reduce[2 * i] = lo; + to_reduce[2 * i + 1] = hi; + rolling_hash[1] += 1; + } -#[oracle(is_zero)] -pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} + { + let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); + let hash: [u8; 30] = hash.to_le_bytes(); + let mut hi: Field = 0; + for j in 0..(last_limb_bytes - 1) { + hi *= 256; + hi += hash[j] as Field; + } + hi *= 256; + let last_byte = hash[last_limb_bytes - 1]; + let mask = (1 as u64 << (last_limb_bits) as u8) - 1; + let last_bits = last_byte as u64 & mask; + hi += last_bits as Field; + to_reduce[2 * N - 2] = hi; + } + let (_, remainder) = __barrett_reduction( + to_reduce, + params.redc_param, + MOD_BITS, + params.modulus, + params.modulus_u60_x4, + ); + let result = remainder; + result +} pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) -> bool { lhs == rhs @@ -111,15 +156,6 @@ pub (crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} // let x_u60: U60Repr = U60Repr::from(f); // U60Repr::into(params.modulus_u60 - x_u60) // } - -pub(crate) unconstrained fn __neg( - params: P, - limbs: [Field; N], -) -> [Field; N] { - neg_oracle(params, limbs, N, MOD_BITS) -} - -#[oracle(neg)] pub (crate) unconstrained fn __neg( params: P, limbs: [Field; N], @@ -134,8 +170,9 @@ unconstrained fn neg_oracle( limbs: [Field; N], num_limbs: u32, mod_bits: u32, -) -> [Field; N] {} + ) -> [Field; N] {} +// switching this function to use oracles instead // pub(crate) unconstrained fn __add( // params: P, // lhs: [Field; N], @@ -151,9 +188,6 @@ unconstrained fn neg_oracle( // } // U60Repr::into(z_u60) // } - - - // the oracle function to get the add result #[oracle(add)] @@ -163,18 +197,25 @@ unconstrained fn neg_oracle( rhs: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} //this is the actual function that be changed to use oracles // pub (crate) unconstrained fn __add( // switching this function to use oracles instead - pub(crate) unconstrained fn __add( params: P, lhs: [Field; N], rhs: [Field; N], ) -> [Field; N] { + // let x_u60: U60Repr = U60Repr::from(lhs); + // let y_u60: U60Repr = U60Repr::from(rhs); + + // let mut z_u60 = x_u60 + y_u60; + + // if z_u60.gte(params.modulus_u60) { + // z_u60 = z_u60 - params.modulus_u60; + // } + // U60Repr::into(z_u60) add_oracle(params, lhs, rhs, N, MOD_BITS) } // the oracle function to get the add result @@ -204,29 +245,6 @@ pub(crate) unconstrained fn __sub( __add(params, lhs, __neg(params, rhs)) } -// pub(crate) unconstrained fn __mul_with_quotient( -// params: P, -// lhs: [Field; N], -// rhs: [Field; N], -// ) -> ([Field; N], [Field; N]) { -// let mut mul: [Field; 2 * N] = [0; 2 * N]; -// for i in 0..N { -// for j in 0..N { -// mul[i + j] += lhs[i] * rhs[j]; -// } -// } -// let to_reduce = split_bits::__normalize_limbs(mul, 2 * N); -// let (q, r) = __barrett_reduction( -// to_reduce, -// params.redc_param, -// MOD_BITS, -// params.modulus, -// params.modulus_u60_x4, -// ); - -// (q, r) -// } - pub(crate) unconstrained fn __mul_with_quotient( params: P, lhs: [Field; N], @@ -263,15 +281,6 @@ pub(crate) unconstrained fn __mul_with_quotient( mod_bits: u32, ) -> ([Field; N], [Field; N]) {} -#[oracle(mul_with_quotient)] -pub(crate) unconstrained fn mul_with_quotient_oracle( - params: P, - lhs: [Field; N], - rhs: [Field; N], - num_limbs: u32, - mod_bits: u32, -) -> ([Field; N], [Field; N]) {} - pub(crate) unconstrained fn __mul( params: P, lhs: [Field; N], @@ -290,9 +299,7 @@ pub(crate) unconstrained fn __mul( // __mul::<_, MOD_BITS>(params, numerator, inv_divisor) // } - -pub(crate) unconstrained fn __div( - +pub (crate) unconstrained fn __div( params: P, numerator: [Field; N], divisor: [Field; N], @@ -300,10 +307,8 @@ pub(crate) unconstrained fn __div( div_oracle(params, numerator, divisor, N, MOD_BITS) } - #[oracle(div)] pub (crate) unconstrained fn div_oracle( - params: P, numerator: [Field; N], divisor: [Field; N], @@ -311,7 +316,6 @@ pub(crate) unconstrained fn __div( mod_bits: u32, ) -> [Field; N] {} - /** * @brief __udiv_mod performs *unconstrained* integer division between numerator, divisor * @@ -319,7 +323,6 @@ pub(crate) unconstrained fn __div( * 2. numerator % divisor = remainder * 3. divisor * quotient + remainder = numerator **/ - // pub(crate) unconstrained fn __udiv_mod( // numerator: [Field; N], // divisor: [Field; N], @@ -364,31 +367,6 @@ pub(crate) unconstrained fn __udiv_mod( numerator: [Field; N], divisor: [Field; N], ) -> ([Field; N], [Field; N]) { - let res: ([Field; N], [Field; N]) = - udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); - res -} - -#[oracle(udiv_mod)] -pub(crate) unconstrained fn udiv_mod_oracle( - numerator: [Field; N], - divisor: [Field; N], - num_limbs: u32, - mod_bits: u32, -) -> ([Field; N], [Field; N]) {} - -// pub(crate) unconstrained fn __invmod( -// params: P, -// val: [Field; N], -// ) -> [Field; N] { -// let one: [Field; N] = __one::(); -// let one_u60: U60Repr = U60Repr::from(one); -// let exp_u60 = params.modulus_u60.sub(one_u60.add(one_u60)); -// let exp = U60Repr::into(exp_u60); -// __pow::<_, MOD_BITS>(params, val, exp) -// } - -pub(crate) unconstrained fn __invmod( let res: ([Field; N], [Field; N]) = udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); res } @@ -457,19 +435,19 @@ pub (crate) unconstrained fn __pow( val: [Field; N], exponent: [Field; N], ) -> [Field; N] { - let res = invmod_oracle::(params, val, N, MOD_BITS); - res + pow_oracle(params, val, exponent, N, MOD_BITS) } - -#[oracle(pow)] -pub(crate) unconstrained fn pow_oracle( + #[oracle(pow)] + pub (crate) unconstrained fn pow_oracle( params: P, val: [Field; N], exponent: [Field; N], num_limbs: u32, mod_bits: u32, -) -> [Field; N] {} + ) -> [Field; N] {} + + pub(crate) unconstrained fn __batch_invert( params: P, diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index f4df4ec5..135de7da 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -5,12 +5,13 @@ use crate::params::BigNumParams; use crate::fns::{ constrained_ops::{ - - add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, - udiv, udiv_mod, umod, validate_in_field, validate_in_range, + derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, + validate_in_range, neg, add, sub, mul, div, udiv_mod, udiv, umod, }, - expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, - + unconstrained_ops::{ + __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, + __invmod, __pow, __batch_invert, __batch_invert_slice, __tonelli_shanks_sqrt, + }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, }; diff --git a/src/tests/bignum_test.nr b/src/tests/bignum_test.nr index 233535e3..53eefd6b 100644 --- a/src/tests/bignum_test.nr +++ b/src/tests/bignum_test.nr @@ -792,54 +792,47 @@ fn test_expressions() { } + + #[test] fn test_oracle_add() { - let a: Fq = BigNum { - limbs: [ - 0x0000000000000000000000000000000000000000000000000000000000000001, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - ], - }; - let b: Fq = BigNum { - limbs: [ - 0x0000000000000000000000000000000000000000000000000000000000000002, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - ], - }; - let c: Fq = BigNum { - limbs: [ - 0x0000000000000000000000000000000000000000000000000000000000000003, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - ], - }; + // type Fq = BigNum <3,254, BN254_Fq_Params> ; + let a: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000 + ]}; + let b: Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000 + ]}; + let c : Fq = BigNum{limbs : [ + 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000000 + ]} ; let result: Fq = a.__add(b); - + assert(result == c); + // let b: Fq = BigNum::one(); + // let result = a + b; + assert(result == c) ; } #[test] fn test_oracle_is_zero() { - - let a: Fq = BigNum { - limbs: [ - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - ], - }; - let a: Fq = BigNum{limbs : [ 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000 ]}; - - let result = a.__is_zero(); + let result = a.__is_zero(); + assert(result == true); + // assert(true); } +// type Fq = BigNum<3, 254, BN254_Fq_Params>; From 449cae0a255cfe23db52d1e3fbb9658ee170f419 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Thu, 5 Dec 2024 18:05:36 +0000 Subject: [PATCH 08/24] rip barrett reduction --- oracles/src/handlers.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 2d11af8d..633bac00 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -332,6 +332,27 @@ pub (crate) fn handle_div(inputs: &Vec>) -> Value { +pub (crate) fn handle_barrett_reduction(inputs: &Vec>) -> Value { + // return an empty json response for now + // the inputs are x , modulus + let x_fc = &inputs[0]; + let x_str = callparam_to_string(x_fc); + let modulus_fc = &inputs[1]; + let modulus_str = callparam_to_string(modulus_fc); + let x = cast_to_biguint(x_str); + let modulus = cast_to_biguint(modulus_str); + let num_limbs = modulus_fc.len(); + let quotient = &x / &modulus; + let remainder = &x % &modulus; + //cast the quotient and the remainder to limbs + let quotient_limbs = cast_biguint_to_bignum_limbs("ient, num_limbs as u32); + let remainder_limbs = cast_biguint_to_bignum_limbs(&remainder, num_limbs as u32); + let return_vec:Vec> = vec![quotient_limbs, remainder_limbs]; + let json_response = json!({"values" : return_vec}); + json_response +} + + @@ -370,6 +391,7 @@ pub (crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { } + // helper function to get limbs of a big num and pack them into a vector of Fr elements pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { let mut limbs: Vec = vec![]; From f87dc749fab7aad3dbe1eb8965c989a5fca98fb7 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 11:27:37 +0000 Subject: [PATCH 09/24] wip --- oracles/src/main.rs | 3 +- src/fns/unconstrained_helpers.nr | 162 ++++++++++++++++++------------- 2 files changed, 95 insertions(+), 70 deletions(-) diff --git a/oracles/src/main.rs b/oracles/src/main.rs index 162446f4..1ec0bcf0 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -39,7 +39,7 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div}; +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div, handle_barrett_reduction}; // SPIN UP THE SERVER #[tokio::main] @@ -110,6 +110,7 @@ async fn run_server() -> anyhow::Result { "invmod" => handle_invmod(&request.inputs), // the inputs to this are effectively a Vec "pow" => handle_pow(&request.inputs), // the inputs to this are effectively a Vec "div" => handle_div(&request.inputs), // the inputs to this are effectively a Vec + "barrett_reduction" => handle_barrett_reduction(&request.inputs), // the inputs to this are effectively a Vec _ => handle_unknown_function(&request), }; diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index 5b19ccd8..fb3ee6d9 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -227,7 +227,90 @@ pub(crate) unconstrained fn __sub_with_flags( * @details maximum value = modulus^2 <( +// x: [Field; 2 * N], +// redc_param: [Field; N], +// k: u32, +// modulus: [Field; N], +// modulus_u60: U60Repr, +// ) -> ([Field; N], [Field; N]) { +// let mut mulout: [Field; 3 * N] = [0; 3 * N]; +// for i in 0..(N + N) { +// for j in 0..N { +// mulout[i + j] += x[i] * redc_param[j]; +// } +// } +// mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); +// let mulout_u60: U60Repr = U60Repr::new(mulout); + +// // When we apply the barrett reduction, the maximum value of the output will be +// // <= p * (1 + x/2^{2k}) +// // where p = modulus, +// // x = reduction input +// // if x > p * p, we need k to be larger than modulus_bits() +// // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p +// // this should be larger than most values put into `evaluate_quadratic_expression` +// // TODO: try and detect cases where x might be too large at comptime +// // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. +// // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus +// // NOTE: very niche edge case error that we need to be aware of: +// // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS +// // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction +// let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); + +// // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. +// // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) +// let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); +// let mut partial_quotient: [Field; 2 * N] = [0; 2 * N]; +// for i in 0..2 * N { +// partial_quotient[i] = partial_quotient_full[i]; +// } +// // quotient_mul_modulus can never exceed input value `x` so can fit into size-2 array +// let mut quotient_mul_modulus: [Field; 2 * N] = [0; 2 * N]; +// let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; +// for j in 0..N { +// for i in 0..(N + N - j) { +// quotient_mul_modulus[i + j] += partial_quotient[i] * modulus[j]; +// } +// } + +// for i in 0..(N + N) { +// let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus[i]); +// quotient_mul_modulus_normalized[i] = lo; +// // TODO: what is faster, leaving this if statement in or out? +// // (array is size-1 too large so we can tolerate adding 0 into max element) +// if (i + 1 < N + N) { +// quotient_mul_modulus[i + 1] += hi; +// } +// } +// let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); + +// let x_u60: U60Repr = U60Repr::new(x); +// let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; + +// if (remainder_u60.gte(modulus_u60)) { +// remainder_u60 = remainder_u60 - modulus_u60; +// quotient_u60.increment(); +// } else {} + +// if (remainder_u60.gte(modulus_u60)) { +// remainder_u60 = remainder_u60 - modulus_u60; +// quotient_u60.increment(); +// } else {} + +// if (remainder_u60.gte(modulus_u60)) { +// remainder_u60 = remainder_u60 - modulus_u60; +// quotient_u60.increment(); +// } else {} + +// let q: [Field; N] = U60Repr::into(quotient_u60); +// let r: [Field; N] = U60Repr::into(remainder_u60); + +// (q, r) +// } + pub(crate) unconstrained fn __barrett_reduction( x: [Field; 2 * N], @@ -236,80 +319,21 @@ pub(crate) unconstrained fn __barrett_reduction( modulus: [Field; N], modulus_u60: U60Repr, ) -> ([Field; N], [Field; N]) { - let mut mulout: [Field; 3 * N] = [0; 3 * N]; - for i in 0..(N + N) { - for j in 0..N { - mulout[i + j] += x[i] * redc_param[j]; - } - } - mulout = split_bits::__normalize_limbs(mulout, 3 * N - 1); - let mulout_u60: U60Repr = U60Repr::new(mulout); - - // When we apply the barrett reduction, the maximum value of the output will be - // <= p * (1 + x/2^{2k}) - // where p = modulus, - // x = reduction input - // if x > p * p, we need k to be larger than modulus_bits() - // we hardcode k = 4, which means that the maximum value of x is approx. 16 * p * p - // this should be larger than most values put into `evaluate_quadratic_expression` - // TODO: try and detect cases where x might be too large at comptime - // N.B. BARRETT_REDUCTION_OVERFLOW_BITS affects how `redc_param` is generated. - // `redc_param` = 2^{modulus_bits() * 2 + BARRETT_REDUCTION_OVERFLOW_BITS} / modulus - // NOTE: very niche edge case error that we need to be aware of: - // N must be large enough to cover the modulus *plus* BARRETT_REDUCTION_OVERFLOW_BITS - // i.e. a 359-bit prime needs (I think) 4 limbs to represent or we may overflow when calling __barrett_reduction - let mut quotient_u60 = mulout_u60.shr((k + k + BARRETT_REDUCTION_OVERFLOW_BITS)); - - // N.B. we assume that the shifted quotient cannot exceed 2 times original bit size. - // (partial_quotient should be just slightly larger than the modulus, we could probably represent with a size N+1 array) - let partial_quotient_full: [Field; 3 * N] = quotient_u60.into_field_array(); - let mut partial_quotient: [Field; 2 * N] = [0; 2 * N]; - for i in 0..2 * N { - partial_quotient[i] = partial_quotient_full[i]; - } - // quotient_mul_modulus can never exceed input value `x` so can fit into size-2 array - let mut quotient_mul_modulus: [Field; 2 * N] = [0; 2 * N]; - let mut quotient_mul_modulus_normalized: [Field; 2 * N] = [0; 2 * N]; - for j in 0..N { - for i in 0..(N + N - j) { - quotient_mul_modulus[i + j] += partial_quotient[i] * modulus[j]; - } - } + barrett_reduction_oracle(x, modulus) +} - for i in 0..(N + N) { - let (lo, hi) = split_bits::split_120_bits(quotient_mul_modulus[i]); - quotient_mul_modulus_normalized[i] = lo; - // TODO: what is faster, leaving this if statement in or out? - // (array is size-1 too large so we can tolerate adding 0 into max element) - if (i + 1 < N + N) { - quotient_mul_modulus[i + 1] += hi; - } - } - let quotient_mul_modulus_u60: U60Repr = U60Repr::new(quotient_mul_modulus_normalized); - let x_u60: U60Repr = U60Repr::new(x); - let mut remainder_u60 = x_u60 - quotient_mul_modulus_u60; +#[oracle(barrett_reduction)] +pub(crate) unconstrained fn barrett_reduction_oracle( + x: [Field; 2 * N], + modulus: [Field; N], +) -> ([Field; N], [Field; N]) { + // return an empty array for now +} - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - if (remainder_u60.gte(modulus_u60)) { - remainder_u60 = remainder_u60 - modulus_u60; - quotient_u60.increment(); - } else {} - let q: [Field; N] = U60Repr::into(quotient_u60); - let r: [Field; N] = U60Repr::into(remainder_u60); - (q, r) -} /** * @brief compute the log of the size of the primitive root From b82250a731d91e6db44f49d8b27ea10462e1b45e Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 12:05:19 +0000 Subject: [PATCH 10/24] finally fixed the merge issuegit statusgit status --- .DS_Store | Bin 0 -> 8196 bytes Nargo.toml | 2 +- oracles/.DS_Store | Bin 0 -> 6148 bytes src/.DS_Store | Bin 0 -> 8196 bytes src/fns/constrained_ops.nr | 7 ++- src/fns/unconstrained_helpers.nr | 103 +++++++++++-------------------- src/fns/unconstrained_ops.nr | 89 +++----------------------- src/runtime_bignum.nr | 36 ++++++++--- src/tests/bignum_test.nr | 46 -------------- 9 files changed, 76 insertions(+), 207 deletions(-) create mode 100644 .DS_Store create mode 100644 oracles/.DS_Store create mode 100644 src/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2a0f1bea296ae3808ccdba3c6569e3d695825c76 GIT binary patch literal 8196 zcmeHMO=}ZD7=E`&&8F2FM4?2K1;JArn}WsSB~25wP(Nt=IH<&I5|h=(MDglCA+7+xD7r;LJ;5tLOJPRgKq5wv3~36KriQv=7}6a5 zmf~d;4kSu*GSub6P@WBSLotMR%x?)g85xPX)CyPMhZ_)-l<>9A5`5@ak7h<1+e+SWNQHeUJF?cE>GqkGkHfDXsi_jc1@KnMK zHL=1D$_BY1zdvBJ7}ygNKFj2CKSB0XE#x7FIr$0|+aJlfy7Lw65W^qI_d5r74HLwMvWB47AGFA&)VSMT(w+ zgLY6A;*s{x83C(Bac7jJfu(Ub62w)m|}idYyTllH*ld!oaCiL3w!J@hYsBWnHh*7PbXBV8+dO zF_G-|7nfI-7p!!8d3Afi>R(x1U9eUzFKutf%`+D+UEL}^a~mGp<>KOSRfjO0knO{A z4>h%G|1&_5&(lXE{@9=Y{-M7o-z3V;AM?>sf2?WxH6|VUdtPXHF7x=4$yaAsD3J8| zFLltRRv@fEM0U*c`+t7&_y4e&Zfga!0{@T#Ml@H*WwD{*u^!$VziV5_kCA!eyn#ev mfS5T0p^1cXxX;&BoB06lt(B|bsHv$mCZXi3qEN8?p|2%o^m@HzD8Tlme+ zXg3-?is%gNew+E-e30D?5%KtPJ|Y?rQHCMNvS<-ex0*WUEJl_bqsgpVu3A$3UX|>< zOBZxbvqhQi|N3@gSyn|cT~t$OvX`sQ@b2dEAhpiFv98Y2toI0`En3qFDwcFg>$GaW z+*$uuz4Vnh!rG26s;aX&&n%%Mc$QM4f5 z^dv7N5`_0?Q+Yk{e_Zmf_1tM}# zxtyCtGp2AouOlU+MqEe+f1)0Rv_uiLH-iytJ75v82v`Ix0u}*_z`uY1?rdJ1L+*X4 zwXH?KBJf`#z@HB;DwicChf<112O5zAK;|$k3i`+cgpaFaNy(vs#P?u1beu#n|(KOwMN0S0-P-inRY+wJ%*6Vj#YTh?qEATtr<>ikolg&*{&p0#A ztaG=z6Zfm#dbigp*W0)GryFq`c>Ddjchhh7YjYIZDVf!-LqgRO7p`Oq0zZiRujXF+K=2o+P|z76-hHw=j7b zVgc}y_@{W`+DR)}xuFG~|6e)${r{wG+wR9AU=h#|V7W@QQpUjk4_-|tx;)o*QSYJh z!tI7q3KujY9fuU@IArpNA^I*%xlc*Sp_CXw`QtAF_^)^E{x(lhs: [Field; N], rhs: [ // so we do... p - x - r = 0 and there might be borrow flags // a - b = r // p + a - b - r = 0 - let (result, carry_flags, borrow_flags) = unsafe { __validate_gt_remainder::(lhs, rhs) }; + let (result, carry_flags, borrow_flags) = unsafe { __validate_gt_remainder(lhs, rhs) }; validate_in_range::<_, MOD_BITS>(result); let borrow_shift = 0x1000000000000000000000000000000; @@ -445,7 +446,7 @@ pub(crate) fn udiv_mod( numerator: [Field; N], divisor: [Field; N], ) -> ([Field; N], [Field; N]) { - let (quotient, remainder) = unsafe { __udiv_mod::(numerator, divisor) }; + let (quotient, remainder) = unsafe { __udiv_mod::(numerator, divisor) }; // self / divisor = quotient rounded // quotient * divisor + remainder - self = 0 diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index fb3ee6d9..ed4071b9 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -1,8 +1,10 @@ -use crate::utils::u60_representation::U60Repr; use crate::utils::split_bits; +use crate::utils::u60_representation::U60Repr; +use crate::fns::unconstrained_ops::{__add, __eq, __mul, __neg, __one, __pow}; use crate::params::BigNumParams as P; -use crate::fns::unconstrained_ops::{__one, __eq, __neg, __add, __mul, __pow}; + +global TWO_POW_60: u64 = 0x1000000000000000; /** * In this file: @@ -29,7 +31,7 @@ pub(crate) unconstrained fn __validate_in_field_compute_borrow_flags( +pub(crate) unconstrained fn __validate_gt_remainder( lhs: [Field; N], rhs: [Field; N], ) -> ([Field; N], [bool; N], [bool; N]) { @@ -39,24 +41,22 @@ pub(crate) unconstrained fn __validate_gt_remainder = U60Repr { limbs: [0; 2 * N] }; let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; - let mut carry: u64 = 0; let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; let mut borrow_in: u64 = 0; let mut borrow_flags: [bool; N] = [false; N]; let mut carry_flags: [bool; N] = [false; N]; for i in 0..2 * N { - let mut add_term: u64 = a_u60.limbs[i] + addend_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((b_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - b_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; + let mut add_term: u64 = a_u60.limbs[i] + carry_in; + let mut carry = (add_term >= TWO_POW_60) as u64; + add_term -= carry * TWO_POW_60; + carry_in = carry; + + let sub_term = b_u60.limbs[i] + borrow_in; + let mut borrow = (sub_term > add_term) as u64; + result_u60.limbs[i] = borrow * TWO_POW_60 + add_term - sub_term; + borrow_in = borrow; if ((i & 1) == 1) { @@ -68,7 +68,6 @@ pub(crate) unconstrained fn __validate_gt_remainder( let x_u60: U60Repr = U60Repr::from(val); let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; - let mut borrow: u64 = 0; let mut borrow_in: u64 = 0; let mut borrow_flags: [bool; N] = [false; N]; for i in 0..2 * N { - borrow = ((x_u60.limbs[i] + borrow_in) > params.modulus_u60.limbs[i]) as u64; - let sub = (borrow << 60) + params.modulus_u60.limbs[i] - x_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; + let sub_term = x_u60.limbs[i] + borrow_in; + let borrow = (sub_term > params.modulus_u60.limbs[i]) as u64; + result_u60.limbs[i] = borrow * TWO_POW_60 + params.modulus_u60.limbs[i] - sub_term; + borrow_in = borrow; if ((i & 1) == 1) { borrow_flags[i / 2] = borrow as bool; @@ -97,30 +96,6 @@ pub(crate) unconstrained fn __neg_with_flags( (result, borrow_flags) } - - - - -//this is the actual function that be changed to use oracles - #[oracle(add)] - pub (crate) unconstrained fn add_oracle( - params: P, - lhs: [Field; N], - rhs: [Field; N], - num_limbs: u32, - mod_bits: u32, -) -> [Field; N] {} - - -// pub(crate) unconstrained fn __add_with_flags( -// params: P, -// lhs: [Field; N], -// rhs: [Field; N], -// ) -> ([Field; N], [bool; N], [bool; N], bool){ -// let limbs = add_oracle(params, lhs, rhs, N, MOD_BITS); -// } - - pub(crate) unconstrained fn __add_with_flags( params: P, lhs: [Field; N], @@ -139,21 +114,19 @@ pub(crate) unconstrained fn __add_with_flags( subtrahend_u60 = params.modulus_u60; } - let mut carry: u64 = 0; let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; let mut borrow_in: u64 = 0; let mut borrow_flags: [bool; N] = [false; N]; let mut carry_flags: [bool; N] = [false; N]; for i in 0..2 * N { let mut add_term: u64 = a_u60.limbs[i] + b_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((subtrahend_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - subtrahend_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; + let mut carry = (add_term >= TWO_POW_60) as u64; + add_term -= carry * TWO_POW_60; + carry_in = carry; + + let sub_term = subtrahend_u60.limbs[i] + borrow_in; + let mut borrow = (sub_term > add_term) as u64; + result_u60.limbs[i] = borrow * TWO_POW_60 + add_term - sub_term; borrow_in = borrow; if ((i & 1) == 1) { @@ -181,28 +154,26 @@ pub(crate) unconstrained fn __sub_with_flags( let underflow = b_u60.gte(a_u60 + U60Repr::one()); - let mut addend_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; + let addend_u60: U60Repr = if underflow { + params.modulus_u60 + } else { + U60Repr { limbs: [0; 2 * N] } + }; let mut result_u60: U60Repr = U60Repr { limbs: [0; 2 * N] }; - if underflow { - addend_u60 = params.modulus_u60; - } - - let mut carry: u64 = 0; let mut carry_in: u64 = 0; - let mut borrow: u64 = 0; let mut borrow_in: u64 = 0; let mut borrow_flags: [bool; N] = [false; N]; let mut carry_flags: [bool; N] = [false; N]; for i in 0..2 * N { let mut add_term: u64 = a_u60.limbs[i] + addend_u60.limbs[i] + carry_in; - carry = (add_term >= 0x1000000000000000) as u64; - add_term -= (carry as u64 * 0x1000000000000000); - result_u60.limbs[i] = add_term; - carry_in = carry as u64; - borrow = ((b_u60.limbs[i] + borrow_in) > result_u60.limbs[i]) as u64; - let sub = (borrow << 60) + result_u60.limbs[i] - b_u60.limbs[i] - borrow_in; - result_u60.limbs[i] = sub; + let mut carry = (add_term >= TWO_POW_60) as u64; + add_term -= carry * TWO_POW_60; + carry_in = carry; + + let sub_term = b_u60.limbs[i] + borrow_in; + let mut borrow = (sub_term > add_term) as u64; + result_u60.limbs[i] = borrow * TWO_POW_60 + add_term - sub_term; borrow_in = borrow; if ((i & 1) == 1) { diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index 5b68125b..1c2bfcd8 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -1,11 +1,11 @@ -use crate::utils::u60_representation::U60Repr; -use crate::utils::split_bits; - -use crate::params::BigNumParams as P; +use crate::fns::constrained_ops::derive_from_seed; use crate::fns::unconstrained_helpers::{ - __barrett_reduction, __primitive_root_log_size, __multiplicative_generator, + __barrett_reduction, __multiplicative_generator, __primitive_root_log_size, __tonelli_shanks_sqrt_inner_loop_check, }; +use crate::params::BigNumParams as P; +use crate::utils::split_bits; +use crate::utils::u60_representation::U60Repr; /** * In this file: @@ -33,86 +33,13 @@ pub(crate) unconstrained fn __one() -> [Field; N] { limbs } +/// An array of field elements derived from the seed (the limbs of the big_num) pub(crate) unconstrained fn __derive_from_seed( params: P, seed: [u8; SeedBytes], ) -> [Field; N] { - let mut rolling_hash_fields: [Field; (SeedBytes / 31) + 1] = [0; (SeedBytes / 31) + 1]; - let mut seed_ptr = 0; - for i in 0..(SeedBytes / 31) + 1 { - let mut packed: Field = 0; - for _ in 0..31 { - if (seed_ptr < SeedBytes) { - packed *= 256; - packed += seed[seed_ptr] as Field; - seed_ptr += 1; - } - } - rolling_hash_fields[i] = packed; - } - let compressed = - std::hash::poseidon2::Poseidon2::hash(rolling_hash_fields, (SeedBytes / 31) + 1); - let mut rolling_hash: [Field; 2] = [compressed, 0]; - - let mut to_reduce: [Field; 2 * N] = [0; 2 * N]; - - let mut double_modulus_bits = MOD_BITS * 2; - let mut double_modulus_bytes = - (double_modulus_bits) / 8 + (double_modulus_bits % 8 != 0) as u32; - - let mut last_limb_bytes = double_modulus_bytes % 15; - if (last_limb_bytes == 0) { - last_limb_bytes = 15; - } - let mut last_limb_bits = double_modulus_bits % 8; - if (last_limb_bits == 0) { - last_limb_bits = 8; - } - - for i in 0..(N - 1) { - let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); - let hash: [u8; 30] = hash.to_le_bytes(); - let mut lo: Field = 0; - let mut hi: Field = 0; - for j in 0..15 { - hi *= 256; - lo *= 256; - - if (i < 2 * N - 2) { - lo += hash[j + 15] as Field; - hi += hash[j] as Field; - } - } - to_reduce[2 * i] = lo; - to_reduce[2 * i + 1] = hi; - rolling_hash[1] += 1; - } - - { - let hash = std::hash::poseidon2::Poseidon2::hash(rolling_hash, 2); - let hash: [u8; 30] = hash.to_le_bytes(); - let mut hi: Field = 0; - for j in 0..(last_limb_bytes - 1) { - hi *= 256; - hi += hash[j] as Field; - } - hi *= 256; - let last_byte = hash[last_limb_bytes - 1]; - let mask = (1 as u64 << (last_limb_bits) as u8) - 1; - let last_bits = last_byte as u64 & mask; - hi += last_bits as Field; - to_reduce[2 * N - 2] = hi; - } - - let (_, remainder) = __barrett_reduction( - to_reduce, - params.redc_param, - MOD_BITS, - params.modulus, - params.modulus_u60_x4, - ); - let result = remainder; - result + let out = derive_from_seed::(params, seed); + out } pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) -> bool { diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 135de7da..ec141ebd 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -1,18 +1,17 @@ -use dep::std; -use crate::utils::map::map; - use crate::params::BigNumParams; +use crate::utils::map::map; use crate::fns::{ constrained_ops::{ - derive_from_seed, conditional_select, assert_is_not_equal, eq, validate_in_field, - validate_in_range, neg, add, sub, mul, div, udiv_mod, udiv, umod, + add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, + udiv, udiv_mod, umod, validate_in_field, validate_in_range, }, - unconstrained_ops::{ - __derive_from_seed, __eq, __is_zero, __neg, __add, __sub, __mul, __div, __udiv_mod, - __invmod, __pow, __batch_invert, __batch_invert_slice, __tonelli_shanks_sqrt, - }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, + unconstrained_ops::{ + __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, + __is_zero, __mul, __neg, __pow, __sub, __tonelli_shanks_sqrt, __udiv_mod, + }, }; pub struct RuntimeBigNum { @@ -203,6 +202,7 @@ impl RuntimeBigNumTrait for RuntimeB } unconstrained fn __eq(self, other: Self) -> bool { + assert(self.params == other.params); __eq(self.limbs, other.limbs) } @@ -220,13 +220,15 @@ impl RuntimeBigNumTrait for RuntimeB // UNCONSTRAINED! (Hence `__` prefix). fn __add(self, other: Self) -> Self { let params = self.params; + assert(params == other.params); let limbs = unsafe { __add(params, self.limbs, other.limbs) }; Self { params, limbs } } // UNCONSTRAINED! (Hence `__` prefix). fn __sub(self, other: Self) -> Self { - let params: BigNumParams = self.params; + let params = self.params; + assert(params == other.params); let limbs = unsafe { __sub(params, self.limbs, other.limbs) }; Self { params, limbs } } @@ -234,6 +236,7 @@ impl RuntimeBigNumTrait for RuntimeB // UNCONSTRAINED! (Hence `__` prefix). fn __mul(self, other: Self) -> Self { let params = self.params; + assert(params == other.params); let limbs = unsafe { __mul::<_, MOD_BITS>(params, self.limbs, other.limbs) }; Self { params, limbs } } @@ -241,6 +244,7 @@ impl RuntimeBigNumTrait for RuntimeB // UNCONSTRAINED! (Hence `__` prefix). fn __div(self, divisor: Self) -> Self { let params = self.params; + assert(params == divisor.params); let limbs = unsafe { __div::<_, MOD_BITS>(params, self.limbs, divisor.limbs) }; Self { params, limbs } } @@ -248,6 +252,7 @@ impl RuntimeBigNumTrait for RuntimeB // UNCONSTRAINED! (Hence `__` prefix). fn __udiv_mod(self, divisor: Self) -> (Self, Self) { let params = self.params; + assert(params == divisor.params); let (q, r) = unsafe { __udiv_mod(self.limbs, divisor.limbs) }; (Self { limbs: q, params }, Self { limbs: r, params }) } @@ -263,6 +268,7 @@ impl RuntimeBigNumTrait for RuntimeB // UNCONSTRAINED! (Hence `__` prefix). fn __pow(self, exponent: Self) -> Self { let params = self.params; + assert(params == exponent.params); let limbs = unsafe { __pow::<_, MOD_BITS>(params, self.limbs, exponent.limbs) }; Self { limbs, params } } @@ -350,6 +356,7 @@ impl RuntimeBigNumTrait for RuntimeB fn assert_is_not_equal(self, other: Self) { let params = self.params; + assert(params == other.params); assert_is_not_equal(params, self.limbs, other.limbs); } @@ -360,22 +367,26 @@ impl RuntimeBigNumTrait for RuntimeB fn udiv_mod(self, divisor: Self) -> (Self, Self) { let params = self.params; + assert(params == divisor.params); let (q, r) = udiv_mod::<_, MOD_BITS>(params, self.limbs, divisor.limbs); (Self { limbs: q, params }, Self { limbs: r, params }) } fn udiv(self, divisor: Self) -> Self { let params = self.params; + assert(params == divisor.params); Self { limbs: udiv::<_, MOD_BITS>(params, self.limbs, divisor.limbs), params } } fn umod(self, divisor: Self) -> Self { let params = self.params; + assert(params == divisor.params); Self { limbs: umod::<_, MOD_BITS>(params, self.limbs, divisor.limbs), params } } fn conditional_select(lhs: Self, rhs: Self, predicate: bool) -> Self { let params = lhs.params; + assert(params == rhs.params); Self { limbs: conditional_select(lhs.limbs, rhs.limbs, predicate), params } } } @@ -385,6 +396,7 @@ impl std::ops::Add for RuntimeBigNum // via evaluate_quadratic_expression fn add(self, other: Self) -> Self { let params = self.params; + assert(params == other.params); Self { limbs: add::<_, MOD_BITS>(params, self.limbs, other.limbs), params } } } @@ -394,6 +406,7 @@ impl std::ops::Sub for RuntimeBigNum // via evaluate_quadratic_expression fn sub(self, other: Self) -> Self { let params = self.params; + assert(params == other.params); Self { limbs: sub::<_, MOD_BITS>(params, self.limbs, other.limbs), params } } } @@ -405,6 +418,7 @@ impl std::ops::Mul for RuntimeBigNum // will create much fewer constraints than calling `mul` and `add` directly fn mul(self, other: Self) -> Self { let params = self.params; + assert(params == other.params); Self { limbs: mul::<_, MOD_BITS>(params, self.limbs, other.limbs), params } } } @@ -413,6 +427,7 @@ impl std::ops::Div for RuntimeBigNum // Note: this method is expensive! Witness computation is extremely expensive as it requires modular exponentiation fn div(self, divisor: Self) -> Self { let params = self.params; + assert(params == divisor.params); Self { limbs: div::<_, MOD_BITS>(params, self.limbs, divisor.limbs), params } } } @@ -420,6 +435,7 @@ impl std::ops::Div for RuntimeBigNum impl std::cmp::Eq for RuntimeBigNum { fn eq(self, other: Self) -> bool { let params = self.params; + assert(params == other.params); eq::<_, MOD_BITS>(params, self.limbs, other.limbs) } } diff --git a/src/tests/bignum_test.nr b/src/tests/bignum_test.nr index 53eefd6b..ffc8f524 100644 --- a/src/tests/bignum_test.nr +++ b/src/tests/bignum_test.nr @@ -632,7 +632,6 @@ fn test_udiv_mod_U256() { assert(product == a); } - // // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_div_2048() { @@ -791,48 +790,3 @@ fn test_expressions() { assert(wx_constrained.limbs == wx.limbs); } - - - -#[test] -fn test_oracle_add() { - // type Fq = BigNum <3,254, BN254_Fq_Params> ; - let a: Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000001, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]}; - let b: Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000002, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]}; - let c : Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000003, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]} ; - - let result: Fq = a.__add(b); - - assert(result == c); - - // let b: Fq = BigNum::one(); - // let result = a + b; - assert(result == c) ; -} - -#[test] -fn test_oracle_is_zero() { - let a: Fq = BigNum{limbs : [ - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000000000000000000000000000 - ]}; - let result = a.__is_zero(); - assert(result == true); - // assert(true); -} - -// type Fq = BigNum<3, 254, BN254_Fq_Params>; - From 4ff31b75190863eb90e72b0f90fdfcc9f4798b45 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 12:05:36 +0000 Subject: [PATCH 11/24] fmt --- src/bignum.nr | 5 +- src/fns/constrained_ops.nr | 2 +- src/fns/unconstrained_helpers.nr | 14 +---- src/fns/unconstrained_ops.nr | 96 +++++++++++++++----------------- 4 files changed, 51 insertions(+), 66 deletions(-) diff --git a/src/bignum.nr b/src/bignum.nr index 81f9510e..90830992 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -6,7 +6,8 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, + expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, @@ -165,7 +166,7 @@ where } unconstrained fn __is_zero(self) -> bool { - let a = __is_zero(self.limbs); + let a = __is_zero(self.limbs); a } diff --git a/src/fns/constrained_ops.nr b/src/fns/constrained_ops.nr index a683492c..092b4baa 100644 --- a/src/fns/constrained_ops.nr +++ b/src/fns/constrained_ops.nr @@ -446,7 +446,7 @@ pub(crate) fn udiv_mod( numerator: [Field; N], divisor: [Field; N], ) -> ([Field; N], [Field; N]) { - let (quotient, remainder) = unsafe { __udiv_mod::(numerator, divisor) }; + let (quotient, remainder) = unsafe { __udiv_mod::(numerator, divisor) }; // self / divisor = quotient rounded // quotient * divisor + remainder - self = 0 diff --git a/src/fns/unconstrained_helpers.nr b/src/fns/unconstrained_helpers.nr index ed4071b9..5f7103ec 100644 --- a/src/fns/unconstrained_helpers.nr +++ b/src/fns/unconstrained_helpers.nr @@ -189,9 +189,7 @@ pub(crate) unconstrained fn __sub_with_flags( (result, carry_flags, borrow_flags, underflow) } - -// instead of using barrett reduction, we use the oracle to do the reduction - +// instead of using barrett reduction, we use the oracle to do the reduction /** * @brief BARRETT_REDUCTION_OVERFLOW_BITS defines how large an input to barrett reduction can be @@ -265,7 +263,7 @@ pub(crate) unconstrained fn __sub_with_flags( // remainder_u60 = remainder_u60 - modulus_u60; // quotient_u60.increment(); // } else {} - + // if (remainder_u60.gte(modulus_u60)) { // remainder_u60 = remainder_u60 - modulus_u60; // quotient_u60.increment(); @@ -282,7 +280,6 @@ pub(crate) unconstrained fn __sub_with_flags( // (q, r) // } - pub(crate) unconstrained fn __barrett_reduction( x: [Field; 2 * N], redc_param: [Field; N], @@ -293,19 +290,14 @@ pub(crate) unconstrained fn __barrett_reduction( barrett_reduction_oracle(x, modulus) } - #[oracle(barrett_reduction)] pub(crate) unconstrained fn barrett_reduction_oracle( x: [Field; 2 * N], modulus: [Field; N], ) -> ([Field; N], [Field; N]) { - // return an empty array for now + // return an empty array for now } - - - - /** * @brief compute the log of the size of the primitive root * @details find the maximum value k where x^k = 1, where x = primitive root diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index 1c2bfcd8..dde0d687 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -46,8 +46,7 @@ pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) - lhs == rhs } - -//switching this function to use oracles instead +//switching this function to use oracles instead // pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool { // let mut result: bool = true; // for i in 0..N { @@ -55,7 +54,7 @@ pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) - // } // result // } -//switching this function to use oracles instead +//switching this function to use oracles instead // pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool { // let mut result: bool = true; // for i in 0..N { @@ -63,8 +62,8 @@ pub(crate) unconstrained fn __eq(lhs: [Field; N], rhs: [Field; N]) - // } // result // } - #[oracle(is_zero)] -pub (crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} +#[oracle(is_zero)] +pub(crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} /** * @brief given an input `x`, compute `2p - x` (unconstrained) * @@ -83,23 +82,22 @@ pub (crate) unconstrained fn __is_zero(limbs: [Field; N]) -> bool {} // let x_u60: U60Repr = U60Repr::from(f); // U60Repr::into(params.modulus_u60 - x_u60) // } -pub (crate) unconstrained fn __neg( +pub(crate) unconstrained fn __neg( params: P, limbs: [Field; N], ) -> [Field; N] { - neg_oracle(params, limbs,N,MOD_BITS) + neg_oracle(params, limbs, N, MOD_BITS) } - - #[oracle(neg)] +#[oracle(neg)] unconstrained fn neg_oracle( params: P, limbs: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} +) -> [Field; N] {} -// switching this function to use oracles instead +// switching this function to use oracles instead // pub(crate) unconstrained fn __add( // params: P, // lhs: [Field; N], @@ -117,18 +115,18 @@ unconstrained fn neg_oracle( // } // the oracle function to get the add result - #[oracle(add)] - pub (crate) unconstrained fn add_oracle( +#[oracle(add)] +pub(crate) unconstrained fn add_oracle( params: P, lhs: [Field; N], rhs: [Field; N], num_limbs: u32, mod_bits: u32, -) -> [Field; N] {} +) -> [Field; N] {} -//this is the actual function that be changed to use oracles +//this is the actual function that be changed to use oracles // pub (crate) unconstrained fn __add( -// switching this function to use oracles instead +// switching this function to use oracles instead pub(crate) unconstrained fn __add( params: P, lhs: [Field; N], @@ -147,17 +145,16 @@ pub(crate) unconstrained fn __add( } // the oracle function to get the add result - // pub (crate) unconstrained fn __add( // params: P, // lhs: [Field; N], // rhs: [Field; N], // ) -> [Field; N] { -// println("N is: "); -// println(N); -// let res = add_oracle(params, lhs, rhs, N, MOD_BITS); -// println(res); -// res +// println("N is: "); +// println(N); +// let res = add_oracle(params, lhs, rhs, N, MOD_BITS); +// println(res); +// res // } /** @@ -177,8 +174,8 @@ pub(crate) unconstrained fn __mul_with_quotient( lhs: [Field; N], rhs: [Field; N], ) -> ([Field; N], [Field; N]) { - let res = mul_with_quotient_oracle(params, lhs, rhs, N, MOD_BITS); - res + let res = mul_with_quotient_oracle(params, lhs, rhs, N, MOD_BITS); + res } // let mut mul: [Field; 2 * N] = [0; 2 * N]; // for i in 0..N { @@ -198,15 +195,14 @@ pub(crate) unconstrained fn __mul_with_quotient( // (q, r) // } - - #[oracle(mul_with_quotient)] - pub (crate) unconstrained fn mul_with_quotient_oracle( +#[oracle(mul_with_quotient)] +pub(crate) unconstrained fn mul_with_quotient_oracle( params: P, lhs: [Field; N], rhs: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> ([Field; N], [Field; N]) {} +) -> ([Field; N], [Field; N]) {} pub(crate) unconstrained fn __mul( params: P, @@ -226,7 +222,7 @@ pub(crate) unconstrained fn __mul( // __mul::<_, MOD_BITS>(params, numerator, inv_divisor) // } -pub (crate) unconstrained fn __div( +pub(crate) unconstrained fn __div( params: P, numerator: [Field; N], divisor: [Field; N], @@ -234,14 +230,14 @@ pub (crate) unconstrained fn __div( div_oracle(params, numerator, divisor, N, MOD_BITS) } - #[oracle(div)] - pub (crate) unconstrained fn div_oracle( +#[oracle(div)] +pub(crate) unconstrained fn div_oracle( params: P, numerator: [Field; N], divisor: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} +) -> [Field; N] {} /** * @brief __udiv_mod performs *unconstrained* integer division between numerator, divisor @@ -294,21 +290,21 @@ pub(crate) unconstrained fn __udiv_mod( numerator: [Field; N], divisor: [Field; N], ) -> ([Field; N], [Field; N]) { - let res: ([Field; N], [Field; N]) = udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); + let res: ([Field; N], [Field; N]) = + udiv_mod_oracle::(numerator, divisor, N, MOD_BITS); res } - #[oracle(udiv_mod)] - pub (crate) unconstrained fn udiv_mod_oracle( +#[oracle(udiv_mod)] +pub(crate) unconstrained fn udiv_mod_oracle( numerator: [Field; N], divisor: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> ([Field; N], [Field; N]) {} - +) -> ([Field; N], [Field; N]) {} -// current implementation of invmod only works for prime fields -// we could use xgcd to extend this to all fields +// current implementation of invmod only works for prime fields +// we could use xgcd to extend this to all fields // pub(crate) unconstrained fn __invmod( // params: P, // val: [Field; N], @@ -319,23 +315,21 @@ pub(crate) unconstrained fn __udiv_mod( // let exp = U60Repr::into(exp_u60); // __pow::<_, MOD_BITS>(params, val, exp) // } -pub (crate) unconstrained fn __invmod( +pub(crate) unconstrained fn __invmod( params: P, val: [Field; N], ) -> [Field; N] { - let res = invmod_oracle::(params, val, N, MOD_BITS); + let res = invmod_oracle::(params, val, N, MOD_BITS); res } - #[oracle(invmod)] - pub (crate) unconstrained fn invmod_oracle( +#[oracle(invmod)] +pub(crate) unconstrained fn invmod_oracle( params: P, val: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} - - +) -> [Field; N] {} // pub(crate) unconstrained fn __pow( // params: P, @@ -357,7 +351,7 @@ pub (crate) unconstrained fn __invmod( // accumulator // } -pub (crate) unconstrained fn __pow( +pub(crate) unconstrained fn __pow( params: P, val: [Field; N], exponent: [Field; N], @@ -365,16 +359,14 @@ pub (crate) unconstrained fn __pow( pow_oracle(params, val, exponent, N, MOD_BITS) } - #[oracle(pow)] - pub (crate) unconstrained fn pow_oracle( +#[oracle(pow)] +pub(crate) unconstrained fn pow_oracle( params: P, val: [Field; N], exponent: [Field; N], num_limbs: u32, mod_bits: u32, - ) -> [Field; N] {} - - +) -> [Field; N] {} pub(crate) unconstrained fn __batch_invert( params: P, From 9ac136ca77098e39f8dc63c0e8675a11188c898c Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 14:57:29 +0000 Subject: [PATCH 12/24] added workflow for the RPC server --- .github/workflows/test.yml | 15 ++++++-- oracles/src/handlers.rs | 15 ++++++++ oracles/src/main.rs | 3 +- src/.DS_Store | Bin 8196 -> 8196 bytes src/fns/unconstrained_ops.nr | 61 ++++++++++++++++++++----------- src/tests/runtime_bignum_test.nr | 4 +- 6 files changed, 71 insertions(+), 27 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1691bfea..cf2480ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,14 +20,23 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + # install rust + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true - name: Install Nargo uses: noir-lang/noirup@v0.1.3 with: toolchain: ${{ matrix.toolchain }} - - - name: Run Noir tests - run: nargo test + # run the PRC server in the oracles directory in the background + - name: run the PRC server + run: cd oracles && cargo build && RUST_LOG=info cargo run & + - name: Run Noir tests with oracle resolver. + run: nargo test --oracle-resolver http://127.0.0.1:3000 format: runs-on: ubuntu-latest diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 633bac00..9a272dc8 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -353,6 +353,21 @@ pub (crate) fn handle_barrett_reduction(inputs: &Vec>) } +pub (crate) fn handle_batch_invert(inputs: &Vec>) -> Value { + // get the params + let params: Params = Params::from_foreign_call_params(&inputs); + // get the number of input bignums + let m_fc = &inputs[inputs.len()-1]; + let m = get_u32_from_callparam(&m_fc); + // get the array of bignums + let xs = &inputs[inputs.len()-4]; + println!("xs: {:?}", xs); + // return an empty json response for now + let return_vec:Vec> = vec![]; + let json_response = json!({"values" : return_vec}); + json_response +} + diff --git a/oracles/src/main.rs b/oracles/src/main.rs index 1ec0bcf0..274395c7 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -39,7 +39,7 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div, handle_barrett_reduction}; +use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div, handle_barrett_reduction , handle_batch_invert}; // SPIN UP THE SERVER #[tokio::main] @@ -111,6 +111,7 @@ async fn run_server() -> anyhow::Result { "pow" => handle_pow(&request.inputs), // the inputs to this are effectively a Vec "div" => handle_div(&request.inputs), // the inputs to this are effectively a Vec "barrett_reduction" => handle_barrett_reduction(&request.inputs), // the inputs to this are effectively a Vec + "batch_invert" => handle_batch_invert(&request.inputs), // the inputs to this are effectively a Vec _ => handle_unknown_function(&request), }; diff --git a/src/.DS_Store b/src/.DS_Store index f1c4ea7fde6defdfb4ded4f5c60806e494f87479..ad56fc8c74969d341a7a02f669035f785339114c 100644 GIT binary patch delta 63 zcmZp1XmOa}&nU1lU^hRbz-Ar+7skyu1bG-YhY0Ur+}tB7!8ln({PD(yAB>yXCBCst QmKRi+JX4GtBKVaN0GiVl1poj5 literal 8196 zcmeHM&1(}u6n~SX?S>*$uuz4Vnh!rG26s;aX&&n%%Mc$QM4f5 z^dv7N5`_0?Q+Yk{e_Zmf_1tM}# zxtyCtGp2AouOlU+MqEe+f1)0Rv_uiLH-iytJ75v82v`Ix0u}*_z`uY1?rdJ1L+*X4 zwXH?KBJf`#z@HB;DwicChf<112O5zAK;|$k3i`+cgpaFaNy(vs#P?u1beu#n|(KOwMN0S0-P-inRY+wJ%*6Vj#YTh?qEATtr<>ikolg&*{&p0#A ztaG=z6Zfm#dbigp*W0)GryFq`c>Ddjchhh7YjYIZDVf!-LqgRO7p`Oq0zZiRujXF+K=2o+P|z76-hHw=j7b zVgc}y_@{W`+DR)}xuFG~|6e)${r{wG+wR9AU=h#|V7W@QQpUjk4_-|tx;)o*QSYJh z!tI7q3KujY9fuU@IArpNA^I*%xlc*Sp_CXw`QtAF_^)^E{x( mod_bits: u32, ) -> [Field; N] {} + +// pub(crate) unconstrained fn __batch_invert( +// params: P, +// x: [[Field; N]; M], +// ) -> [[Field; N]; M] { +// // TODO: ugly! Will fail if input slice is empty +// let mut accumulator: [Field; N] = __one::(); +// let mut result: [[Field; N]; M] = [[0; N]; M]; +// let mut temporaries: [[Field; N]] = &[]; +// for i in 0..x.len() { +// temporaries = temporaries.push_back(accumulator); +// if (__is_zero(x[i]) == false) { +// accumulator = __mul::<_, MOD_BITS>(params, accumulator, x[i]); +// } +// } + +// accumulator = __invmod::<_, MOD_BITS>(params, accumulator); +// let mut T0: [Field; N] = [0; N]; +// for i in 0..x.len() { +// let idx = x.len() - 1 - i; +// if (__is_zero(x[idx]) == false) { +// T0 = __mul::<_, MOD_BITS>(params, accumulator, temporaries[idx]); +// accumulator = __mul::<_, MOD_BITS>(params, accumulator, x[idx]); +// result[idx] = T0; +// } +// } +// result +// } + pub(crate) unconstrained fn __batch_invert( params: P, x: [[Field; N]; M], ) -> [[Field; N]; M] { - // TODO: ugly! Will fail if input slice is empty - let mut accumulator: [Field; N] = __one::(); - let mut result: [[Field; N]; M] = [[0; N]; M]; - let mut temporaries: [[Field; N]] = &[]; - for i in 0..x.len() { - temporaries = temporaries.push_back(accumulator); - if (__is_zero(x[i]) == false) { - accumulator = __mul::<_, MOD_BITS>(params, accumulator, x[i]); - } - } - - accumulator = __invmod::<_, MOD_BITS>(params, accumulator); - let mut T0: [Field; N] = [0; N]; - for i in 0..x.len() { - let idx = x.len() - 1 - i; - if (__is_zero(x[idx]) == false) { - T0 = __mul::<_, MOD_BITS>(params, accumulator, temporaries[idx]); - accumulator = __mul::<_, MOD_BITS>(params, accumulator, x[idx]); - result[idx] = T0; - } - } - result + batch_invert_oracle(params, x, N, MOD_BITS, M) } +#[oracle(batch_invert)] +pub(crate) unconstrained fn batch_invert_oracle( + params: P, + x: [[Field; N]; M], + num_limbs: u32, + mod_bits: u32, + m: u32, +) -> [[Field; N]; M] {} + pub(crate) unconstrained fn __batch_invert_slice( params: P, x: [[Field; N]], diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index 3b7fe4f0..5cefd1e2 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -1,4 +1,6 @@ -use crate::fns::unconstrained_helpers::__barrett_reduction; + +use crate::fns::unconstrained_ops::__batch_invert; +use crate::fns::unconstrained_helpers::__barrett_reduction; use crate::params::{BigNumParams, BigNumParamsGetter}; use crate::runtime_bignum::RuntimeBigNum; use crate::utils::u60_representation::U60Repr; From e3fdf65f9d65ab8ba66841f67950e6da32fbac73 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 14:57:50 +0000 Subject: [PATCH 13/24] fixed small typo --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cf2480ee..000b727c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: - name: run the PRC server run: cd oracles && cargo build && RUST_LOG=info cargo run & - name: Run Noir tests with oracle resolver. - run: nargo test --oracle-resolver http://127.0.0.1:3000 + run: cd .. && nargo test --oracle-resolver http://127.0.0.1:3000 format: runs-on: ubuntu-latest From 31f5be63ae2c06e2f4b45c13b6868cf1836df10e Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 14:59:42 +0000 Subject: [PATCH 14/24] wip --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 000b727c..cf2480ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: - name: run the PRC server run: cd oracles && cargo build && RUST_LOG=info cargo run & - name: Run Noir tests with oracle resolver. - run: cd .. && nargo test --oracle-resolver http://127.0.0.1:3000 + run: nargo test --oracle-resolver http://127.0.0.1:3000 format: runs-on: ubuntu-latest From 6f2a4555e2e27260bfdf3d29181dca34025cc02b Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 15:02:00 +0000 Subject: [PATCH 15/24] wip --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cf2480ee..5b0b39c2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: - name: run the PRC server run: cd oracles && cargo build && RUST_LOG=info cargo run & - name: Run Noir tests with oracle resolver. - run: nargo test --oracle-resolver http://127.0.0.1:3000 + run: cd oracles && cargo build && RUST_LOG=info cargo run & && cd .. && nargo test --oracle-resolver http://127.0.0.1:3000 format: runs-on: ubuntu-latest From dccbd3c09b78e69cd322717bfcf4d5c5a6e29d3b Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 15:02:51 +0000 Subject: [PATCH 16/24] wip --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b0b39c2..af3ded01 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: - name: run the PRC server run: cd oracles && cargo build && RUST_LOG=info cargo run & - name: Run Noir tests with oracle resolver. - run: cd oracles && cargo build && RUST_LOG=info cargo run & && cd .. && nargo test --oracle-resolver http://127.0.0.1:3000 + run: cd oracles && cargo build && RUST_LOG=info cargo run && cd .. && nargo test --oracle-resolver http://127.0.0.1:3000 format: runs-on: ubuntu-latest From 68310f5147a602cf9271a25dd013f35fb18c5379 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 15:06:36 +0000 Subject: [PATCH 17/24] reverted back to the more sensible one --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index af3ded01..c8632a43 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: - name: run the PRC server run: cd oracles && cargo build && RUST_LOG=info cargo run & - name: Run Noir tests with oracle resolver. - run: cd oracles && cargo build && RUST_LOG=info cargo run && cd .. && nargo test --oracle-resolver http://127.0.0.1:3000 + run: nargo test --oracle-resolver http://127.0.0.1:3000 format: runs-on: ubuntu-latest From 826423b6ffcb8595db61dca215e52c83355a46ae Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 15:14:52 +0000 Subject: [PATCH 18/24] added wait for server to start --- .github/workflows/test.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c8632a43..eb91e755 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,8 +33,14 @@ jobs: with: toolchain: ${{ matrix.toolchain }} # run the PRC server in the oracles directory in the background - - name: run the PRC server - run: cd oracles && cargo build && RUST_LOG=info cargo run & + - name: run the PRC server + run: | + cd oracles && cargo build + RUST_LOG=info cargo run & + echo "Waiting for server to start..." + # Wait for port 3000 to become available + timeout 30 bash -c 'until nc -z localhost 3000; do sleep 1; done' + echo "Server is ready!" - name: Run Noir tests with oracle resolver. run: nargo test --oracle-resolver http://127.0.0.1:3000 From be38fcd5435e1bd08ff86ea03f36bc47e37114cb Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 15:17:20 +0000 Subject: [PATCH 19/24] formatter --- src/fns/unconstrained_ops.nr | 1 - src/tests/runtime_bignum_test.nr | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index 1dbd77de..e570d206 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -368,7 +368,6 @@ pub(crate) unconstrained fn pow_oracle( mod_bits: u32, ) -> [Field; N] {} - // pub(crate) unconstrained fn __batch_invert( // params: P, // x: [[Field; N]; M], diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index 5cefd1e2..ec0e1922 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -1,6 +1,5 @@ - +use crate::fns::unconstrained_helpers::__barrett_reduction; use crate::fns::unconstrained_ops::__batch_invert; -use crate::fns::unconstrained_helpers::__barrett_reduction; use crate::params::{BigNumParams, BigNumParamsGetter}; use crate::runtime_bignum::RuntimeBigNum; use crate::utils::u60_representation::U60Repr; From 788c6450fc67e1372c6f11e34c88577263a6204b Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 18:57:30 +0000 Subject: [PATCH 20/24] batch_inv also moved to the oracle --- oracles/src/handlers.rs | 37 ++++++++++++++++++++++++++++--- oracles/src/ops.rs | 27 ++++++++++++++++++++++ src/.DS_Store | Bin 8196 -> 8196 bytes src/tests/runtime_bignum_test.nr | 16 +++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 9a272dc8..910096fc 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -15,6 +15,7 @@ use crate::ops::sqrt; use crate::ops::extended_gcd; use crate::ops::invert; use crate::ops::pow_bn; +use crate::ops::batch_invert; // a struct that emulates the bignum Params params from the params.nr file struct Params { @@ -359,11 +360,41 @@ pub (crate) fn handle_batch_invert(inputs: &Vec>) -> Va // get the number of input bignums let m_fc = &inputs[inputs.len()-1]; let m = get_u32_from_callparam(&m_fc); + // get the number of limbs + let num_limbs_fc = &inputs[inputs.len()-3]; + let num_limbs = get_u32_from_callparam(&num_limbs_fc); // get the array of bignums let xs = &inputs[inputs.len()-4]; - println!("xs: {:?}", xs); - // return an empty json response for now - let return_vec:Vec> = vec![]; + let xs_vec = xs.get_values(); + // cast the xs_vec into a vector of &str + // this is gross but we have to switch back to &str + // and then we push them into a vector of bignum elements + let mut x_str: Vec<&str> = vec![]; + let mut inputs_bns: Vec = vec![]; + for i in 0..xs_vec.len() { + let y = xs_vec[i].as_str(); + x_str.push(y); + if x_str.len() as u32 % num_limbs == 0 { + let bn = cast_to_biguint(x_str); + x_str = vec![]; + inputs_bns.push(bn); + } + } + let results = batch_invert(&inputs_bns, ¶ms.modulus); + // cast BigInt to bignum limbs + let mut results_formatted: Vec = vec![]; + for result in results{ + let limbs = cast_bigint_to_bignum_limbs(&result, num_limbs); + for limb in limbs{ + results_formatted.push(limb); + } + } + + // println!("xs_str: {:?}", x_str); + // split the xs_vec into arrays of size num_limbs + + // let res = batch_invert(&chunks, ¶ms.modulus); + let return_vec:Vec> = vec![results_formatted]; let json_response = json!({"values" : return_vec}); json_response } diff --git a/oracles/src/ops.rs b/oracles/src/ops.rs index d13b595d..26d09a90 100644 --- a/oracles/src/ops.rs +++ b/oracles/src/ops.rs @@ -5,6 +5,7 @@ use ark_ff::Field; use ark_ff::Zero as ZeroField; use num_bigint::BigUint; use num_bigint::BigInt; +use num_bigint::ToBigInt; use num_traits::{Zero, One}; pub(crate) fn sqrt(x: Fr) -> Option { @@ -88,6 +89,32 @@ pub (crate) fn pow_bn(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> } +pub(crate) fn batch_invert(xs: &Vec, modulus: &BigUint) -> Vec { + // start with an array with 1 at position 0 + let mut intermediates: Vec = vec![BigUint::from(1u32)]; + let m = xs.len(); + let mut temp: BigUint = BigUint::from(1u64); + for i in 0..m { + // the intermediates array will hold the multiplication of the first i elements in position i + temp = (&temp * &xs[i])% modulus ; + intermediates.push(temp.clone()); + } + + // invert the final multiplication + let mut mul_inv = invert(&intermediates[m], modulus); + // set up a vector of responses that will hold the results + let mut inverses: Vec = vec![BigInt::zero() ; m]; + // loop over m and compute the inverses + for i in 0..m { + inverses[m-i-1] = (&mul_inv * &BigInt::from(intermediates[m-i-1].clone()))% BigInt::from(modulus.clone()); + mul_inv = &mul_inv * &BigInt::from(xs[m-i-1].clone()); + } + + assert_eq!((BigInt::from(xs[0].clone()) * &inverses[0]) % BigInt::from(modulus.clone()) , BigInt::from(1u32)); + inverses +} + + // some tests to check the behaviour of the extended gcd #[test] diff --git a/src/.DS_Store b/src/.DS_Store index ad56fc8c74969d341a7a02f669035f785339114c..5227a72ef187087749b6469abfc2a995d4c955ec 100644 GIT binary patch delta 78 zcmZp1XmQvuU666dWFO%|b&2X~QxiiS1rtNlS{;RI3rkBN+svT0mXkwNS>HM+K07Bj hFTZQDf}lKO_vRp>t*o0_C4R6>Ruoj)tSI`F2>_Zc7g7KK delta 30 mcmZp1XmQvuU2w9e@V?E#LYr7OvrBwqnJh1;vRPjAF%tl_P72%r diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index ec0e1922..1a0ccf54 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -558,6 +558,7 @@ unconstrained fn test_invmod(params: BigNumParams } } + #[test] fn test_div_BN() { let params = BN254_Fq_Params::get_params(); @@ -570,6 +571,21 @@ fn test_invmod_BN() { unsafe { test_invmod(params) }; } +#[test] +fn test_batch_invert() { + let params = BN254_Fq_Params::get_params(); + let N = 3; + let MOD_BITS = 254; + let u: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]); + let v: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [2, 3, 4, 5]); + let w: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [3, 4, 5, 6]); + let batch = unsafe{__batch_invert::<3, 254, 3>(params, [u.limbs, v.limbs,w.limbs])}; + println(params.modulus); + assert(batch[0] == u.__invmod().limbs); + assert(batch[1] == v.__invmod().limbs); + assert(batch[2] == w.__invmod().limbs); +} + // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril // #[test] // fn test_div_2048() { From 084513ff8762d2d344a06b85188c832c609ea3d0 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 18:58:29 +0000 Subject: [PATCH 21/24] nargo fmt && cargo fmt --- oracles/src/foreign_call.rs | 7 +- oracles/src/handlers.rs | 274 ++++++++++++++----------------- oracles/src/main.rs | 7 +- oracles/src/ops.rs | 65 ++++---- src/tests/runtime_bignum_test.nr | 15 +- 5 files changed, 165 insertions(+), 203 deletions(-) diff --git a/oracles/src/foreign_call.rs b/oracles/src/foreign_call.rs index ee0235dc..41b9b1e1 100644 --- a/oracles/src/foreign_call.rs +++ b/oracles/src/foreign_call.rs @@ -22,7 +22,10 @@ impl From> for ForeignCallParam { } } -impl ForeignCallParam where F: Clone { +impl ForeignCallParam +where + F: Clone, +{ pub fn len(&self) -> usize { match self { ForeignCallParam::Single(_) => 1, @@ -36,10 +39,8 @@ impl ForeignCallParam where F: Clone { ForeignCallParam::Array(values) => values.clone(), } } - } - // impl len> for ForeignCallParam { // fn len(&self) -> usize { // match self { diff --git a/oracles/src/handlers.rs b/oracles/src/handlers.rs index 910096fc..ecedb8f2 100644 --- a/oracles/src/handlers.rs +++ b/oracles/src/handlers.rs @@ -1,8 +1,8 @@ use ark_bn254::Fr; use ark_ff::Zero; use jsonrpsee::core::params; -use num_bigint::BigUint; -use num_bigint::BigInt; +use num_bigint::BigInt; +use num_bigint::BigUint; use num_traits::ConstZero; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? use num_traits::Num; // It's pretty disgusting that I've introduced this library, just to convert to/from radix 16. I wonder if there's a better way with arkworks? @@ -10,12 +10,12 @@ use serde_json::{json, Value}; // use std::str::FromStr; use crate::foreign_call::ForeignCallParam; -use crate::ops::is_zero; -use crate::ops::sqrt; +use crate::ops::batch_invert; use crate::ops::extended_gcd; use crate::ops::invert; +use crate::ops::is_zero; use crate::ops::pow_bn; -use crate::ops::batch_invert; +use crate::ops::sqrt; // a struct that emulates the bignum Params params from the params.nr file struct Params { @@ -68,7 +68,6 @@ pub(crate) fn handle_get_sqrt(inputs: &Vec>) -> Value { json_response } - pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value { /**** EXTRACT INPUT STRING(S) ****/ println!("inputs: {:?}", inputs); @@ -111,16 +110,12 @@ pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value /**** FORMAT RESULT FOR NOIR CONSUMPTION, AND CONVERT RESULT TO JSON `Value` TYPE ****/ let return_vec = vec![oracle_return_data_the_noir_program_expects]; // Notice! This is a different type from the singular handle_get_sqrt function! Hence why the `Value` is being computed inside this function, instead in the calling function. println!("return_vec: {:?}", return_vec); - let json_response = json!({"values" : return_vec}); println!("json_response: {:?}", json_response); json_response } - - - // ============================== // ============================== // ============================== @@ -128,15 +123,15 @@ pub(crate) fn handle_get_sqrts(inputs: &Vec>) -> Value pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { // Create a vector with a single boolean value (true) as the result let input_param = &inputs[0]; - // parse the input into strings - let mut input_strings = vec![]; + // parse the input into strings + let mut input_strings = vec![]; for input in inputs { input_strings.push(callparam_to_string(input)[0]); } let limbs = gets_limbs(input_strings); - // call the is_zero function from the ops.rs - let result= is_zero(limbs); - // print the result + // call the is_zero function from the ops.rs + let result = is_zero(limbs); + // print the result /**** ENSURE HEX ****/ let as_big_uint: BigUint = result.into(); let as_hex_str = as_big_uint.to_str_radix(16); @@ -148,30 +143,27 @@ pub(crate) fn handle_is_zero(inputs: &Vec>) -> Value { let return_vec = oracle_return_data_the_noir_program_expects; // Notice! This is a different type from the singular handle_get_sqrt function! Hence why the `Value` is being computed inside this function, instead in the calling function. let json_response = json!({"values" : return_vec}); - json_response + json_response } - - - // ============================== // ============================== // ============================== // call handler for add pub(crate) fn handle_mul_with_quotient(inputs: &Vec>) -> Value { // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs - let num_limbs_fc = &inputs[inputs.len()-2]; - let num_limbs = get_u32_from_callparam(&num_limbs_fc); + let num_limbs_fc = &inputs[inputs.len() - 2]; + let num_limbs = get_u32_from_callparam(&num_limbs_fc); // create the params struct let params: Params = Params::from_foreign_call_params(&inputs); // get the lhs and rhs - let lhs_fc = &inputs[inputs.len()-3]; + let lhs_fc = &inputs[inputs.len() - 3]; let lhs_str = callparam_to_string(lhs_fc); let lhs_biguint = cast_to_biguint(lhs_str); - let rhs_fc = &inputs[inputs.len()-4]; + let rhs_fc = &inputs[inputs.len() - 4]; let rhs_str = callparam_to_string(rhs_fc); let rhs_biguint = cast_to_biguint(rhs_str); - let mul_res = lhs_biguint * rhs_biguint; + let mul_res = lhs_biguint * rhs_biguint; let modulus = params.modulus; let q = &mul_res / &modulus; let r = &mul_res % &modulus; @@ -181,72 +173,65 @@ pub(crate) fn handle_mul_with_quotient(inputs: &Vec>) - // call the mul_with_quotient function from the ops.rs file let return_vec: Vec> = vec![q_limbs, r_limbs]; let json_response = json!({"values" : return_vec}); - json_response + json_response } - - - - - // ============================== // ============================== // ============================== // call handler for add // the inputs of the function are params, lhs, rhs, num_limbs, mod_bits, returns the result of the addition which is a vector of hex limbs -// params are of form -// lhs and rhs are vector of limbs +// params are of form +// lhs and rhs are vector of limbs // the input is 8 elements pub(crate) fn handle_add(inputs: &Vec>) -> Value { // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs - // get the number of limbs from the input + // get the number of limbs from the input // let num_limbs_fc = &inputs[inputs.len()-2]; - // let num_limbs = get_u32_from_callparam(&num_limbs_fc); - // convert the lhs and rhs to biguints - let lhs_fc = &inputs[inputs.len()-3]; + // let num_limbs = get_u32_from_callparam(&num_limbs_fc); + // convert the lhs and rhs to biguints + let lhs_fc = &inputs[inputs.len() - 3]; let lhs_str = callparam_to_string(lhs_fc); let num_limbs = lhs_str.len(); let lhs_biguint = cast_to_biguint(lhs_str); - let rhs_fc = &inputs[inputs.len()-4]; + let rhs_fc = &inputs[inputs.len() - 4]; let rhs_str = callparam_to_string(rhs_fc); let rhs_biguint = cast_to_biguint(rhs_str); - // lastly parse out the params + // lastly parse out the params // create the params struct let params: Params = Params::from_foreign_call_params(&inputs); - let modulus = params.modulus; + let modulus = params.modulus; let result = lhs_biguint + rhs_biguint; let result_mod = result % modulus; // cast the result to limbs let limbs = cast_biguint_to_bignum_limbs(&result_mod, num_limbs as u32); // pack it in a json response - let return_vec:Vec> = vec![limbs]; + let return_vec: Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); - - json_response + json_response } -pub (crate) fn handle_neg(inputs: &Vec>) -> Value { +pub(crate) fn handle_neg(inputs: &Vec>) -> Value { // parse the input, the last 2 elements of the input are the modulus bits and the number of limbs // create the params struct let params: Params = Params::from_foreign_call_params(&inputs); - let modulus = params.modulus; - let limbs_fc = &inputs[inputs.len()-3]; + let modulus = params.modulus; + let limbs_fc = &inputs[inputs.len() - 3]; let num_limbs = limbs_fc.len(); let mut limbs_biguint = cast_to_biguint(callparam_to_string(limbs_fc)); if limbs_biguint > modulus { limbs_biguint = limbs_biguint % &modulus; } - let neg = &modulus - &limbs_biguint; + let neg = &modulus - &limbs_biguint; let neg_limbs = cast_biguint_to_bignum_limbs(&neg, num_limbs as u32); - let return_vec:Vec> = vec![neg_limbs]; + let return_vec: Vec> = vec![neg_limbs]; let json_response = json!({"values" : return_vec}); json_response } - -pub (crate) fn handle_udiv_mod(inputs: &Vec>) -> Value { +pub(crate) fn handle_udiv_mod(inputs: &Vec>) -> Value { // get the numerator and the divisor let numerator_fc = &inputs[0]; let numerator_str = callparam_to_string(&numerator_fc); @@ -258,84 +243,82 @@ pub (crate) fn handle_udiv_mod(inputs: &Vec>) -> Value let num_limbs = numerator_fc.len(); // divide the numerator by the divisor - let quotient = &numerator / &divisor; - let remainder = &numerator % &divisor; - + let quotient = &numerator / &divisor; + let remainder = &numerator % &divisor; + // cast the quotient and the remainder to limbs let quotient_limbs = cast_biguint_to_bignum_limbs("ient, num_limbs as u32); let remainder_limbs = cast_biguint_to_bignum_limbs(&remainder, num_limbs as u32); - let return_vec:Vec> = vec![quotient_limbs, remainder_limbs]; + let return_vec: Vec> = vec![quotient_limbs, remainder_limbs]; let json_response = json!({"values" : return_vec}); json_response } -// a handler for modular inversion -pub (crate) fn handle_invmod(inputs: &Vec>) -> Value { - // get the params +// a handler for modular inversion +pub(crate) fn handle_invmod(inputs: &Vec>) -> Value { + // get the params let params: Params = Params::from_foreign_call_params(&inputs); - // get the value to be inverted - let val_fc = &inputs[inputs.len()-3]; + // get the value to be inverted + let val_fc = &inputs[inputs.len() - 3]; let val_str = callparam_to_string(val_fc); let val = cast_to_biguint(val_str); let num_limbs = val_fc.len(); - // invert the value + // invert the value let inv = invert(&val, ¶ms.modulus); // cast the inverse to limbs let limbs = cast_bigint_to_bignum_limbs(&inv, num_limbs as u32); - // return the json response for now - let return_vec:Vec> = vec![limbs]; + // return the json response for now + let return_vec: Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); json_response } -// a handler for modular exponentiation -pub (crate) fn handle_pow(inputs: &Vec>) -> Value { - // return an empty json response for now +// a handler for modular exponentiation +pub(crate) fn handle_pow(inputs: &Vec>) -> Value { + // return an empty json response for now let params: Params = Params::from_foreign_call_params(&inputs); - let exponent_fc = &inputs[inputs.len()-3]; + let exponent_fc = &inputs[inputs.len() - 3]; let exponent_str = callparam_to_string(exponent_fc); let exponent = cast_to_biguint(exponent_str); let num_limbs = exponent_fc.len(); - let val_fc = &inputs[inputs.len()-4]; + let val_fc = &inputs[inputs.len() - 4]; let val_str = callparam_to_string(val_fc); let val = cast_to_biguint(val_str); - let res = pow_bn(&val ,&exponent, ¶ms.modulus); + let res = pow_bn(&val, &exponent, ¶ms.modulus); let limbs = cast_biguint_to_bignum_limbs(&res, num_limbs as u32); - let return_vec:Vec> = vec![limbs]; + let return_vec: Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); json_response } -// a handler for modular division -pub (crate) fn handle_div(inputs: &Vec>) -> Value { - let params: Params = Params::from_foreign_call_params(&inputs); - let numerator_fc = &inputs[inputs.len()-4]; +// a handler for modular division +pub(crate) fn handle_div(inputs: &Vec>) -> Value { + let params: Params = Params::from_foreign_call_params(&inputs); + let numerator_fc = &inputs[inputs.len() - 4]; let numerator_str = callparam_to_string(numerator_fc); let numerator = cast_to_biguint(numerator_str); - let divisor_fc = &inputs[inputs.len()-3]; + let divisor_fc = &inputs[inputs.len() - 3]; let divisor_str = callparam_to_string(divisor_fc); let divisor = cast_to_biguint(divisor_str); - let num_limbs = numerator_fc.len(); + let num_limbs = numerator_fc.len(); - // compute the inverse of the divisor with respect to the modulus + // compute the inverse of the divisor with respect to the modulus let inv = invert(&divisor, ¶ms.modulus); - // multiply the numerator by the inverse - let result = (BigInt::from(numerator.clone())) * &inv; - let reduced = result % BigInt::from(params.modulus.clone()); + // multiply the numerator by the inverse + let result = (BigInt::from(numerator.clone())) * &inv; + let reduced = result % BigInt::from(params.modulus.clone()); // cast the result to limbs let limbs = cast_bigint_to_bignum_limbs(&reduced, num_limbs as u32); - let return_vec:Vec> = vec![limbs]; + let return_vec: Vec> = vec![limbs]; let json_response = json!({"values" : return_vec}); json_response } - - -pub (crate) fn handle_barrett_reduction(inputs: &Vec>) -> Value { - // return an empty json response for now - // the inputs are x , modulus +pub(crate) fn handle_barrett_reduction(inputs: &Vec>) -> Value { + // return an empty json response for now + // the inputs are x , modulus let x_fc = &inputs[0]; let x_str = callparam_to_string(x_fc); let modulus_fc = &inputs[1]; @@ -343,89 +326,80 @@ pub (crate) fn handle_barrett_reduction(inputs: &Vec>) let x = cast_to_biguint(x_str); let modulus = cast_to_biguint(modulus_str); let num_limbs = modulus_fc.len(); - let quotient = &x / &modulus; - let remainder = &x % &modulus; - //cast the quotient and the remainder to limbs + let quotient = &x / &modulus; + let remainder = &x % &modulus; + //cast the quotient and the remainder to limbs let quotient_limbs = cast_biguint_to_bignum_limbs("ient, num_limbs as u32); let remainder_limbs = cast_biguint_to_bignum_limbs(&remainder, num_limbs as u32); - let return_vec:Vec> = vec![quotient_limbs, remainder_limbs]; + let return_vec: Vec> = vec![quotient_limbs, remainder_limbs]; let json_response = json!({"values" : return_vec}); json_response } - -pub (crate) fn handle_batch_invert(inputs: &Vec>) -> Value { - // get the params +pub(crate) fn handle_batch_invert(inputs: &Vec>) -> Value { + // get the params let params: Params = Params::from_foreign_call_params(&inputs); // get the number of input bignums - let m_fc = &inputs[inputs.len()-1]; + let m_fc = &inputs[inputs.len() - 1]; let m = get_u32_from_callparam(&m_fc); - // get the number of limbs - let num_limbs_fc = &inputs[inputs.len()-3]; + // get the number of limbs + let num_limbs_fc = &inputs[inputs.len() - 3]; let num_limbs = get_u32_from_callparam(&num_limbs_fc); - // get the array of bignums - let xs = &inputs[inputs.len()-4]; - let xs_vec = xs.get_values(); - // cast the xs_vec into a vector of &str - // this is gross but we have to switch back to &str - // and then we push them into a vector of bignum elements - let mut x_str: Vec<&str> = vec![]; - let mut inputs_bns: Vec = vec![]; + // get the array of bignums + let xs = &inputs[inputs.len() - 4]; + let xs_vec = xs.get_values(); + // cast the xs_vec into a vector of &str + // this is gross but we have to switch back to &str + // and then we push them into a vector of bignum elements + let mut x_str: Vec<&str> = vec![]; + let mut inputs_bns: Vec = vec![]; for i in 0..xs_vec.len() { let y = xs_vec[i].as_str(); x_str.push(y); if x_str.len() as u32 % num_limbs == 0 { - let bn = cast_to_biguint(x_str); - x_str = vec![]; + let bn = cast_to_biguint(x_str); + x_str = vec![]; inputs_bns.push(bn); } } - let results = batch_invert(&inputs_bns, ¶ms.modulus); - // cast BigInt to bignum limbs - let mut results_formatted: Vec = vec![]; - for result in results{ + let results = batch_invert(&inputs_bns, ¶ms.modulus); + // cast BigInt to bignum limbs + let mut results_formatted: Vec = vec![]; + for result in results { let limbs = cast_bigint_to_bignum_limbs(&result, num_limbs); - for limb in limbs{ - results_formatted.push(limb); + for limb in limbs { + results_formatted.push(limb); } } // println!("xs_str: {:?}", x_str); // split the xs_vec into arrays of size num_limbs - - // let res = batch_invert(&chunks, ¶ms.modulus); - let return_vec:Vec> = vec![results_formatted]; + + // let res = batch_invert(&chunks, ¶ms.modulus); + let return_vec: Vec> = vec![results_formatted]; let json_response = json!({"values" : return_vec}); json_response } - - - // ============================== // ============================== // ============================== // helper functions - - - - -pub (crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { +pub(crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { // split the limbs let mut limbs: Vec = vec![]; for input_string in input_strings { - // handle the case of a zero input + // handle the case of a zero input if input_string == "" { let x_big_uint = BigUint::from_str_radix("0", 16).unwrap(); limbs.push(x_big_uint); - } - else{ + } else { let x_big_uint: BigUint = BigUint::from_str_radix(input_string, 16).unwrap(); limbs.push(x_big_uint); } } - // a constant 2^120 as biguint + // a constant 2^120 as biguint let base: BigUint = BigUint::from(2u32); let exp = 120u32; let shift_constant = base.pow(exp); @@ -434,21 +408,18 @@ pub (crate) fn cast_to_biguint(input_strings: Vec<&str>) -> BigUint { res = res + &limbs[i] * &shift_constant.pow(i as u32); } res - } - // helper function to get limbs of a big num and pack them into a vector of Fr elements -pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { +pub(crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { let mut limbs: Vec = vec![]; for input_string in input_strings { - // handle the case of a zero input + // handle the case of a zero input if input_string == "" { let x_big_uint = BigUint::from_str_radix("0", 16).unwrap(); let limb: Fr = x_big_uint.into(); limbs.push(limb); - } - else{ + } else { let x_big_uint: BigUint = BigUint::from_str_radix(input_string, 16).unwrap(); let limb: Fr = x_big_uint.into(); limbs.push(limb); @@ -457,33 +428,32 @@ pub (crate) fn gets_limbs(input_strings: Vec<&str>) -> Vec { limbs } - - -pub (crate) fn callparam_to_string(input: &ForeignCallParam) -> Vec<&str> { +pub(crate) fn callparam_to_string(input: &ForeignCallParam) -> Vec<&str> { match input { ForeignCallParam::Single(value) => vec![value.trim_start_matches('0')], - ForeignCallParam::Array(values) => values.into_iter().map(|v| v.trim_start_matches('0')).collect(), + ForeignCallParam::Array(values) => values + .into_iter() + .map(|v| v.trim_start_matches('0')) + .collect(), } } -pub (crate) fn get_u32_from_callparam(input: &ForeignCallParam) -> u32 { +pub(crate) fn get_u32_from_callparam(input: &ForeignCallParam) -> u32 { let input_string = callparam_to_string(input)[0]; u32::from_str_radix(input_string, 16).unwrap() } -pub (crate) fn get_bool_from_callparam(input: &ForeignCallParam) -> bool { +pub(crate) fn get_bool_from_callparam(input: &ForeignCallParam) -> bool { let mut input_string = callparam_to_string(input)[0]; if input_string == "" { input_string = "0"; } - let res = u32::from_str_radix(input_string, 16).unwrap(); + let res = u32::from_str_radix(input_string, 16).unwrap(); res == 1 } - - -pub (crate) fn cast_biguint_to_bignum_limbs(input: &BigUint, num_limbs: u32) -> Vec { - // a constant 2^120 as biguint +pub(crate) fn cast_biguint_to_bignum_limbs(input: &BigUint, num_limbs: u32) -> Vec { + // a constant 2^120 as biguint let base: BigUint = BigUint::from(2u32); let exp = 120u32; let shift_constant = base.pow(exp); @@ -491,17 +461,16 @@ pub (crate) fn cast_biguint_to_bignum_limbs(input: &BigUint, num_limbs: u32) -> // an empty array of size num_limbs of type hex limbs let mut limbs_hex: Vec = vec![]; for i in 0..num_limbs { - let remainder = &input_copy % &shift_constant; - limbs_hex.push(remainder.to_str_radix(16)); + let remainder = &input_copy % &shift_constant; + limbs_hex.push(remainder.to_str_radix(16)); let quetient: BigUint = input_copy / &shift_constant; input_copy = quetient.clone(); } limbs_hex } - -pub (crate) fn cast_bigint_to_bignum_limbs(input: &BigInt, num_limbs: u32) -> Vec { - // a constant 2^120 as biguint +pub(crate) fn cast_bigint_to_bignum_limbs(input: &BigInt, num_limbs: u32) -> Vec { + // a constant 2^120 as biguint let base: BigInt = BigInt::from(2u32); let exp = 120u32; let shift_constant = base.pow(exp); @@ -509,17 +478,15 @@ pub (crate) fn cast_bigint_to_bignum_limbs(input: &BigInt, num_limbs: u32) -> Ve // an empty array of size num_limbs of type hex limbs let mut limbs_hex: Vec = vec![]; for i in 0..num_limbs { - let remainder = &input_copy % &shift_constant; - limbs_hex.push(remainder.to_str_radix(16)); + let remainder = &input_copy % &shift_constant; + limbs_hex.push(remainder.to_str_radix(16)); let quetient: BigInt = input_copy / &shift_constant; input_copy = quetient.clone(); } limbs_hex } - - -impl Params { +impl Params { // this function takes the foreign call params and returns a Params struct pub fn from_foreign_call_params(inputs: &Vec>) -> Params { let has_multiplicative_inverse_fc = &inputs[0]; @@ -547,6 +514,3 @@ impl std::fmt::Debug for Params { write!(f, "Params {{ has_multiplicative_inverse: {:?}, modulus: {:?}, double_modulus: {:?}, redc_param: {:?}", self.has_multiplicative_inverse, self.modulus, self.double_modulus, self.redc_param) } } - - - diff --git a/oracles/src/main.rs b/oracles/src/main.rs index 274395c7..e807e05d 100644 --- a/oracles/src/main.rs +++ b/oracles/src/main.rs @@ -30,7 +30,6 @@ mod foreign_call; mod handlers; mod ops; - use jsonrpsee::server::{RpcModule, Server}; use std::net::SocketAddr; use tracing_subscriber::util::SubscriberInitExt; @@ -39,7 +38,11 @@ use serde::Deserialize; use serde_json::{json, Value}; use crate::foreign_call::ForeignCallParam; -use crate::handlers::{handle_get_sqrt, handle_get_sqrts, handle_is_zero, handle_add, handle_mul_with_quotient, handle_neg, handle_udiv_mod, handle_invmod, handle_pow, handle_div, handle_barrett_reduction , handle_batch_invert}; +use crate::handlers::{ + handle_add, handle_barrett_reduction, handle_batch_invert, handle_div, handle_get_sqrt, + handle_get_sqrts, handle_invmod, handle_is_zero, handle_mul_with_quotient, handle_neg, + handle_pow, handle_udiv_mod, +}; // SPIN UP THE SERVER #[tokio::main] diff --git a/oracles/src/ops.rs b/oracles/src/ops.rs index 26d09a90..6895ab96 100644 --- a/oracles/src/ops.rs +++ b/oracles/src/ops.rs @@ -3,10 +3,10 @@ use core::fmt; use ark_bn254::Fr; use ark_ff::Field; use ark_ff::Zero as ZeroField; -use num_bigint::BigUint; use num_bigint::BigInt; +use num_bigint::BigUint; use num_bigint::ToBigInt; -use num_traits::{Zero, One}; +use num_traits::{One, Zero}; pub(crate) fn sqrt(x: Fr) -> Option { let sqrt: Option = if x.legendre().is_qr() { @@ -36,8 +36,6 @@ pub(crate) fn is_zero(limbs: Vec) -> bool { result } - - pub(crate) fn extended_gcd(_a: &BigInt, _b: &BigInt) -> (BigInt, BigInt, BigInt) { let (mut x, mut y) = (BigInt::from(0), BigInt::from(1)); let (mut u, mut v) = (BigInt::from(1), BigInt::from(0)); @@ -48,7 +46,7 @@ pub(crate) fn extended_gcd(_a: &BigInt, _b: &BigInt) -> (BigInt, BigInt, BigInt) let r = &b % &a; let m = &x - &u * &q; let n = &y - &v * &q; - b = a.clone(); + b = a.clone(); a = r; x = u; y = v; @@ -58,12 +56,11 @@ pub(crate) fn extended_gcd(_a: &BigInt, _b: &BigInt) -> (BigInt, BigInt, BigInt) (b.clone(), x.clone(), y.clone()) } - -pub(crate) fn invert(a: &BigUint , modulus: &BigUint) -> BigInt { +pub(crate) fn invert(a: &BigUint, modulus: &BigUint) -> BigInt { // perform a -> BigInt conversion let a_bigint = BigInt::from(a.clone()); let modulus_bigint = BigInt::from(modulus.clone()); - let (gcd , r, _) = extended_gcd(&a_bigint, &modulus_bigint); + let (gcd, r, _) = extended_gcd(&a_bigint, &modulus_bigint); assert_eq!(gcd, BigInt::from(1), "input and modulus are not coprime"); let mut res = r.clone(); while res < BigInt::from(0) { @@ -72,14 +69,13 @@ pub(crate) fn invert(a: &BigUint , modulus: &BigUint) -> BigInt { res } - -pub (crate) fn pow_bn(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint { - // cast the exponent into bytes +pub(crate) fn pow_bn(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint { + // cast the exponent into bytes let exponent_bytes = exponent.to_bytes_be(); - // do a square and multiply type algorithm - let mut result = BigUint::from(1u64); + // do a square and multiply type algorithm + let mut result = BigUint::from(1u64); for exponent_byte in exponent_bytes { - // this will be potentially horribly slow + // this will be potentially horribly slow result = result.pow(256); result = result % modulus; result = result * base.pow(exponent_byte as u32); @@ -88,34 +84,35 @@ pub (crate) fn pow_bn(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> result } - pub(crate) fn batch_invert(xs: &Vec, modulus: &BigUint) -> Vec { - // start with an array with 1 at position 0 + // start with an array with 1 at position 0 let mut intermediates: Vec = vec![BigUint::from(1u32)]; - let m = xs.len(); - let mut temp: BigUint = BigUint::from(1u64); + let m = xs.len(); + let mut temp: BigUint = BigUint::from(1u64); for i in 0..m { - // the intermediates array will hold the multiplication of the first i elements in position i - temp = (&temp * &xs[i])% modulus ; - intermediates.push(temp.clone()); + // the intermediates array will hold the multiplication of the first i elements in position i + temp = (&temp * &xs[i]) % modulus; + intermediates.push(temp.clone()); } - - // invert the final multiplication - let mut mul_inv = invert(&intermediates[m], modulus); - // set up a vector of responses that will hold the results - let mut inverses: Vec = vec![BigInt::zero() ; m]; - // loop over m and compute the inverses + + // invert the final multiplication + let mut mul_inv = invert(&intermediates[m], modulus); + // set up a vector of responses that will hold the results + let mut inverses: Vec = vec![BigInt::zero(); m]; + // loop over m and compute the inverses for i in 0..m { - inverses[m-i-1] = (&mul_inv * &BigInt::from(intermediates[m-i-1].clone()))% BigInt::from(modulus.clone()); - mul_inv = &mul_inv * &BigInt::from(xs[m-i-1].clone()); + inverses[m - i - 1] = (&mul_inv * &BigInt::from(intermediates[m - i - 1].clone())) + % BigInt::from(modulus.clone()); + mul_inv = &mul_inv * &BigInt::from(xs[m - i - 1].clone()); } - assert_eq!((BigInt::from(xs[0].clone()) * &inverses[0]) % BigInt::from(modulus.clone()) , BigInt::from(1u32)); + assert_eq!( + (BigInt::from(xs[0].clone()) * &inverses[0]) % BigInt::from(modulus.clone()), + BigInt::from(1u32) + ); inverses } - - // some tests to check the behaviour of the extended gcd #[test] fn test_extended_euclidean() { @@ -130,10 +127,9 @@ fn test_invert() { let r = invert(&a, &modulus); let modulus_bigint = BigInt::from(modulus.clone()); let a_bigint = BigInt::from(a.clone()); - assert_eq!((r * a_bigint) % modulus_bigint , BigInt::from(1u64)); + assert_eq!((r * a_bigint) % modulus_bigint, BigInt::from(1u64)); } - #[test] fn test_pow_bn() { let base = BigUint::from(3u64); @@ -150,4 +146,3 @@ fn test_pow_bn() { // let modulus = BigUint::from(8u64); // invert(&a, &modulus); // } - diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index 1a0ccf54..34035993 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -558,7 +558,6 @@ unconstrained fn test_invmod(params: BigNumParams } } - #[test] fn test_div_BN() { let params = BN254_Fq_Params::get_params(); @@ -574,16 +573,16 @@ fn test_invmod_BN() { #[test] fn test_batch_invert() { let params = BN254_Fq_Params::get_params(); - let N = 3; - let MOD_BITS = 254; - let u: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]); - let v: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [2, 3, 4, 5]); - let w: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [3, 4, 5, 6]); - let batch = unsafe{__batch_invert::<3, 254, 3>(params, [u.limbs, v.limbs,w.limbs])}; + let N = 3; + let MOD_BITS = 254; + let u: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [1, 2, 3, 4]); + let v: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [2, 3, 4, 5]); + let w: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [3, 4, 5, 6]); + let batch = unsafe { __batch_invert::<3, 254, 3>(params, [u.limbs, v.limbs, w.limbs]) }; println(params.modulus); assert(batch[0] == u.__invmod().limbs); assert(batch[1] == v.__invmod().limbs); - assert(batch[2] == w.__invmod().limbs); + assert(batch[2] == w.__invmod().limbs); } // N.B. witness generation times make these tests take ~15 minutes each! Uncomment at your peril From 0b5400edd94ababee3527c11173fc206c92799dd Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 19:02:19 +0000 Subject: [PATCH 22/24] fixed the toml --- Nargo.toml | 2 +- src/tests/runtime_bignum_test.nr | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Nargo.toml b/Nargo.toml index 7750cbbe..567caf95 100644 --- a/Nargo.toml +++ b/Nargo.toml @@ -2,6 +2,6 @@ name = "bignum" type = "lib" authors = [""] -compiler_version = "1.0.0" +compiler_version = ">= 0.36.0" [dependencies] diff --git a/src/tests/runtime_bignum_test.nr b/src/tests/runtime_bignum_test.nr index 34035993..855e4bc0 100644 --- a/src/tests/runtime_bignum_test.nr +++ b/src/tests/runtime_bignum_test.nr @@ -579,7 +579,6 @@ fn test_batch_invert() { let v: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [2, 3, 4, 5]); let w: RuntimeBigNum<3, 254> = RuntimeBigNum::__derive_from_seed(params, [3, 4, 5, 6]); let batch = unsafe { __batch_invert::<3, 254, 3>(params, [u.limbs, v.limbs, w.limbs]) }; - println(params.modulus); assert(batch[0] == u.__invmod().limbs); assert(batch[1] == v.__invmod().limbs); assert(batch[2] == w.__invmod().limbs); From b37c4048b44f947f040d1560d844dd16d6877710 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 19:04:33 +0000 Subject: [PATCH 23/24] changing the formatter version --- .github/workflows/test.yml | 2 +- src/bignum.nr | 3 +-- src/fns/constrained_ops.nr | 3 +-- src/fns/unconstrained_ops.nr | 2 -- src/runtime_bignum.nr | 3 +-- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eb91e755..2b15502f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [nightly, 0.36.0] + toolchain: [nightly, 0.36.0, 1.0.0-beta.0] steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/src/bignum.nr b/src/bignum.nr index 90830992..d4196021 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -6,8 +6,7 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, - expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, diff --git a/src/fns/constrained_ops.nr b/src/fns/constrained_ops.nr index 092b4baa..de934743 100644 --- a/src/fns/constrained_ops.nr +++ b/src/fns/constrained_ops.nr @@ -5,8 +5,7 @@ use crate::fns::{ unconstrained_helpers::{ __add_with_flags, __neg_with_flags, __sub_with_flags, __validate_gt_remainder, __validate_in_field_compute_borrow_flags, - }, - unconstrained_ops::{__div, __mul, __udiv_mod}, + }, unconstrained_ops::{__div, __mul, __udiv_mod}, }; /** diff --git a/src/fns/unconstrained_ops.nr b/src/fns/unconstrained_ops.nr index e570d206..927b807c 100644 --- a/src/fns/unconstrained_ops.nr +++ b/src/fns/unconstrained_ops.nr @@ -134,9 +134,7 @@ pub(crate) unconstrained fn __add( ) -> [Field; N] { // let x_u60: U60Repr = U60Repr::from(lhs); // let y_u60: U60Repr = U60Repr::from(rhs); - // let mut z_u60 = x_u60 + y_u60; - // if z_u60.gte(params.modulus_u60) { // z_u60 = z_u60 - params.modulus_u60; // } diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index ec141ebd..0325ca54 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -5,8 +5,7 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, - expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, From 6dbc9bb8a205fbe1f4fded758bd284edae2239a3 Mon Sep 17 00:00:00 2001 From: Khashayar Barooti Date: Fri, 6 Dec 2024 19:08:42 +0000 Subject: [PATCH 24/24] versionning complaints --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2b15502f..eb91e755 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [nightly, 0.36.0, 1.0.0-beta.0] + toolchain: [nightly, 0.36.0] steps: - name: Checkout sources uses: actions/checkout@v4