From 3d3235ec458dcc462647f26436d296c579247fd8 Mon Sep 17 00:00:00 2001 From: rymnc <43716372+rymnc@users.noreply.github.com> Date: Wed, 24 Jun 2026 12:07:33 +0200 Subject: [PATCH] chore: make binius-mayo zk --- libs/binius-mayo/Cargo.lock | 353 ++++++++++++++----------- libs/binius-mayo/Cargo.toml | 17 +- libs/binius-mayo/README.md | 8 +- libs/binius-mayo/src/api.rs | 82 ++++-- libs/binius-mayo/src/gf16/mod.rs | 8 +- libs/binius-mayo/src/gf16/mul.rs | 14 +- libs/binius-mayo/src/gf16/scalar.rs | 18 +- libs/binius-mayo/src/gf16/transpose.rs | 8 +- libs/binius-mayo/src/quadratic.rs | 10 +- libs/binius-mayo/src/shake256.rs | 2 +- libs/binius-mayo/src/whipping.rs | 4 +- libs/binius-mayo/tests/api_tests.rs | 29 ++ 12 files changed, 333 insertions(+), 220 deletions(-) diff --git a/libs/binius-mayo/Cargo.lock b/libs/binius-mayo/Cargo.lock index 16dd7ec..dd03b7c 100644 --- a/libs/binius-mayo/Cargo.lock +++ b/libs/binius-mayo/Cargo.lock @@ -10,7 +10,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -69,39 +69,40 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "binius-circuits" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-core", "binius-frontend", "hex-literal", "num-bigint", "num-integer", - "rand 0.9.4", + "rand", "sha2", - "sha3", + "sha3 0.12.0", ] [[package]] name = "binius-core" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-utils", "bytemuck", "bytes", "thiserror", + "tracing", ] [[package]] name = "binius-field" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-utils", "bytemuck", "cfg-if", "derive_more", - "rand 0.9.4", + "rand", "seq-macro", "thiserror", ] @@ -109,14 +110,14 @@ dependencies = [ [[package]] name = "binius-frontend" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-core", "cranelift-entity", "hex-literal", "num-bigint", "petgraph", - "rand 0.9.4", + "rand", "rustc-hash", "serde", "serde_json", @@ -126,7 +127,7 @@ dependencies = [ [[package]] name = "binius-hash" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-field", "binius-math", @@ -134,8 +135,9 @@ dependencies = [ "binius-utils", "bytemuck", "bytes", - "digest", + "digest 0.11.3", "itertools 0.14.0", + "rand", "sha2", "thiserror", "tracing", @@ -144,8 +146,9 @@ dependencies = [ [[package]] name = "binius-iop" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ + "auto_impl", "binius-field", "binius-hash", "binius-ip", @@ -153,7 +156,7 @@ dependencies = [ "binius-transcript", "binius-utils", "bytes", - "digest", + "digest 0.11.3", "getset", "itertools 0.14.0", "thiserror", @@ -163,7 +166,7 @@ dependencies = [ [[package]] name = "binius-iop-prover" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-field", "binius-hash", @@ -175,10 +178,10 @@ dependencies = [ "binius-utils", "bytes", "derive_more", - "digest", + "digest 0.11.3", "getset", "itertools 0.14.0", - "rand 0.9.4", + "rand", "thiserror", "tracing", ] @@ -186,8 +189,9 @@ dependencies = [ [[package]] name = "binius-ip" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ + "array-util", "binius-field", "binius-math", "binius-transcript", @@ -197,7 +201,7 @@ dependencies = [ [[package]] name = "binius-ip-prover" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-field", "binius-ip", @@ -213,14 +217,14 @@ dependencies = [ [[package]] name = "binius-math" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-field", "binius-utils", "bytemuck", "getset", "itertools 0.14.0", - "rand 0.9.4", + "rand", "thiserror", "tracing", "uninit", @@ -240,14 +244,14 @@ dependencies = [ "binius-verifier", "criterion", "hex", - "rand 0.8.6", - "sha3", + "rand", + "sha3 0.10.9", ] [[package]] name = "binius-prover" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-core", "binius-field", @@ -265,11 +269,11 @@ dependencies = [ "bytemuck", "bytes", "derive_more", - "digest", + "digest 0.11.3", "either", "getset", "itertools 0.14.0", - "rand 0.9.4", + "rand", "thiserror", "tracing", ] @@ -277,7 +281,7 @@ dependencies = [ [[package]] name = "binius-spartan-frontend" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-field", "binius-utils", @@ -290,8 +294,9 @@ dependencies = [ [[package]] name = "binius-spartan-prover" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ + "array-util", "binius-field", "binius-hash", "binius-iop", @@ -303,9 +308,9 @@ dependencies = [ "binius-spartan-verifier", "binius-transcript", "binius-utils", - "digest", + "digest 0.11.3", "itertools 0.14.0", - "rand 0.9.4", + "rand", "thiserror", "tracing", ] @@ -313,8 +318,9 @@ dependencies = [ [[package]] name = "binius-spartan-verifier" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ + "array-util", "binius-field", "binius-hash", "binius-iop", @@ -323,7 +329,7 @@ dependencies = [ "binius-spartan-frontend", "binius-transcript", "binius-utils", - "digest", + "digest 0.11.3", "thiserror", "tracing", ] @@ -331,13 +337,13 @@ dependencies = [ [[package]] name = "binius-transcript" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "auto_impl", "binius-field", "binius-utils", "bytes", - "digest", + "digest 0.11.3", "thiserror", "tracing", ] @@ -345,15 +351,15 @@ dependencies = [ [[package]] name = "binius-utils" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "array-util", "bytemuck", "bytes", "cfg-if", - "generic-array", + "hybrid-array", "itertools 0.14.0", - "rand 0.9.4", + "rand", "rayon", "thiserror", "trait-set", @@ -362,7 +368,7 @@ dependencies = [ [[package]] name = "binius-verifier" version = "0.1.0" -source = "git+https://github.com/binius-zk/binius64?rev=363e3ae52739679a77dbfa328b849c6441d5ea99#363e3ae52739679a77dbfa328b849c6441d5ea99" +source = "git+https://github.com/binius-zk/binius64?rev=3bc7451dc3c52af6383fcd99892c6892f57e89b0#3bc7451dc3c52af6383fcd99892c6892f57e89b0" dependencies = [ "binius-core", "binius-field", @@ -376,7 +382,7 @@ dependencies = [ "binius-utils", "bytemuck", "bytes", - "digest", + "digest 0.11.3", "getset", "itertools 0.14.0", "thiserror", @@ -392,6 +398,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -436,6 +451,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -469,7 +495,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] @@ -499,10 +525,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] -name = "convert_case" -version = "0.4.0" +name = "const-oid" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "cpufeatures" @@ -513,19 +539,32 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "cranelift-bitset" -version = "0.121.2" +version = "0.132.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebb6f5d0df5bd0d02c63ec48e8f2e38a176b123f59e084f22caf89a0d0593e7e" +checksum = "d216663191014aa63e1d2cffd058e609eaf207646d40b739d88250f65b2c4f69" +dependencies = [ + "wasmtime-internal-core", +] [[package]] name = "cranelift-entity" -version = "0.121.2" +version = "0.132.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee832f8329fa87c5df6c1d64a8506a58031e6f8a190d9b21b1900272a4dbb47d" +checksum = "668e56db75a54816cbdd7c7b7bfc558b08bf7b2cda9d0846491517e92f3b393b" dependencies = [ "cranelift-bitset", + "wasmtime-internal-core", ] [[package]] @@ -605,13 +644,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "derive_more" -version = "0.99.20" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case", "proc-macro2", "quote", "rustc_version", @@ -624,8 +680,19 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid", + "crypto-common 0.2.2", ] [[package]] @@ -652,6 +719,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "generic-array" version = "0.14.7" @@ -664,25 +737,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getrandom" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi", - "wasip2", + "rand_core", ] [[package]] @@ -714,7 +776,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -722,6 +784,9 @@ name = "hashbrown" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "hermit-abi" @@ -741,6 +806,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "indexmap" version = "2.14.0" @@ -811,7 +885,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", +] + +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", ] [[package]] @@ -820,6 +904,12 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "memchr" version = "2.8.0" @@ -912,15 +1002,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -963,68 +1044,26 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.6" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", -] - -[[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 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", + "chacha20", + "getrandom", + "rand_core", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rayon" @@ -1162,13 +1201,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.9" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -1177,8 +1216,19 @@ version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ - "digest", - "keccak", + "digest 0.10.7", + "keccak 0.1.6", +] + +[[package]] +name = "sha3" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9bad02c26382724b2d2692c6f179285e4b54eeecd7968f52a50059c3c11759" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.0", + "sponge-cursor", ] [[package]] @@ -1187,6 +1237,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "sponge-cursor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" + [[package]] name = "syn" version = "1.0.109" @@ -1315,21 +1371,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" version = "0.2.118" @@ -1375,6 +1416,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasmtime-internal-core" +version = "45.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1deaf6bc3430abd7497b00c64f06ca2b97ca0fe41af87836446ca30949965c" +dependencies = [ + "hashbrown 0.17.0", + "libm", +] + [[package]] name = "web-sys" version = "0.3.95" @@ -1409,12 +1460,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - [[package]] name = "zerocopy" version = "0.8.48" diff --git a/libs/binius-mayo/Cargo.toml b/libs/binius-mayo/Cargo.toml index 758b95c..8e841ce 100644 --- a/libs/binius-mayo/Cargo.toml +++ b/libs/binius-mayo/Cargo.toml @@ -5,19 +5,20 @@ edition = "2024" rust-version = "1.95" [dependencies] -binius-core = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } -binius-frontend = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } -binius-circuits = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } -binius-transcript = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } -binius-prover = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } -binius-verifier = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } -binius-hash = { git = "https://github.com/binius-zk/binius64", rev = "363e3ae52739679a77dbfa328b849c6441d5ea99" } +binius-core = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } +binius-frontend = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } +binius-circuits = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } +binius-transcript = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } +binius-prover = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } +binius-verifier = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } +binius-hash = { git = "https://github.com/binius-zk/binius64", rev = "3bc7451dc3c52af6383fcd99892c6892f57e89b0" } sha3 = "=0.10.9" aes = "=0.8.4" +rand = "0.10" [dev-dependencies] hex = "0.4" -rand = "0.8" +rand = "0.10" criterion = "0.5" [[bench]] diff --git a/libs/binius-mayo/README.md b/libs/binius-mayo/README.md index 92ec169..adcbf7a 100644 --- a/libs/binius-mayo/README.md +++ b/libs/binius-mayo/README.md @@ -45,11 +45,11 @@ The counterparty receives `(c, pk_id, π)` and verifies the SNARK. They learn th | `c` (32 B commitment) | ✓ | ✓ (recomputed) | ✓ (bundle) | | SNARK proof `π` | ✓ | ✓ | ✓ (bundle) | -The verifier's view of `payload` is application-dependent: in an attestation flow they know it (and recompute `c` locally); in a blinded flow they only know `c`. A public observer learns only the bundle and nothing about `cpk`, `sig`, or `payload`. Hiding of `cpk` is informal, not provably zero-knowledge; see [Limitations](#limitations). +The verifier's view of `payload` is application-dependent: in an attestation flow they know it (and recompute `c` locally); in a blinded flow they only know `c`. The SNARK proof `π` is zero-knowledge (binius64's ZK prover/verifier): it reveals nothing about `cpk`, `sig`, or `payload` beyond what `c` and `pk_id` already commit to. Those two commitments are binding but not hiding, so an observer who can guess `payload`, or who holds a candidate `cpk`, can confirm the guess by recomputing them; see [Limitations](#limitations). ## Build & test -The crate pins [`binius-zk/binius64`](https://github.com/binius-zk/binius64) at commit `363e3ae`. Toolchain: **Rust ≥ 1.95**, edition 2024. +The crate pins [`binius-zk/binius64`](https://github.com/binius-zk/binius64) at commit `3bc7451`, which includes binius64's zero-knowledge prover/verifier. Toolchain: **Rust ≥ 1.95**, edition 2024. ```bash # Build the library @@ -87,6 +87,8 @@ assert_eq!(bundle.pk_id, pk_id_local); verifier.verify(&bundle)?; ``` +Proofs are zero-knowledge and randomized: each `prove` call draws fresh blinding randomness from the OS CSPRNG, so proofs over identical input are not byte-identical. Use `prove_with_rng` to supply your own cryptographically-secure RNG (for reproducible test vectors, say). + The example at `examples/mayo2_e2e.rs` walks through the full flow end-to-end against the first NIST KAT entry. ### Advanced: low-level escape hatch @@ -136,7 +138,7 @@ Highlights: This is a **proof of concept** for research and evaluation. Known limitations: -1. **Hidden-pk hiding is informal, not provable.** Binius64 itself is not zero-knowledge as of `363e3ae` (per its `ARCHITECTURE.md`), and no formal hiding analysis was performed for this construction. Pk-hiding rests on the entropy of the MAYO-2 public key and the assumption that the proof transcript does not leak structured information about the witness; an attacker who can extract witness data from a Binius64 proof can recover the public key. Do not rely on this primitive for confidentiality without an independent analysis. +1. **The proof is zero-knowledge; the public commitments are not hiding.** The SNARK uses binius64's zero-knowledge prover/verifier (`zk_config::{ZKProver, ZKVerifier}`: a Spartan ZK wrapper over a blinded FRI-Binius commitment with masked sumcheck, per Diamond, [eprint 2025/1015](https://eprint.iacr.org/2025/1015)). The proof transcript reveals nothing about the witness data (the expanded pk, the signature, or the message digest). The residual exposure is the two public inputs: `c = keccak256(DOMAIN_C ‖ m)` and `pk_id = keccak256(DOMAIN_PK ‖ canonical_packed(P))` are binding but not hiding, so an adversary who can enumerate candidate payloads, or who holds a candidate `cpk`, can confirm a guess by recomputing them. For payload confidentiality against enumeration, fold a high-entropy salt into `payload` before proving (it flows into `c` with no circuit change); `pk_id` is a public identifier. Soundness is binius64's 96-bit target (`SECURITY_BITS`); see the `soundness` test. 2. **`pk_id` binds the expanded pk, not the 4912-byte compact form.** Off-circuit AES-128-CTR expansion is required by the signer once at keypair publication. Any external system holding "the prover's MAYO-2 pk" must hash the expanded form, not the cpk. diff --git a/libs/binius-mayo/src/api.rs b/libs/binius-mayo/src/api.rs index 0f72a78..3fff4b1 100644 --- a/libs/binius-mayo/src/api.rs +++ b/libs/binius-mayo/src/api.rs @@ -36,16 +36,11 @@ use aes::cipher::generic_array::GenericArray; use aes::cipher::{BlockEncrypt, KeyInit}; use binius_core::word::Word; use binius_frontend::{Circuit, CircuitBuilder}; -use binius_prover::{ - OptimalPackedB128, Prover as BiniusProver, - hash::parallel_compression::ParallelCompressionAdaptor, -}; +use binius_hash::sha256::Sha256HashSuite; +use binius_prover::{OptimalPackedB128, zk_config::ZKProver as BiniusProver}; use binius_transcript::{ProverTranscript, VerifierTranscript}; -use binius_verifier::{ - Verifier as BiniusVerifier, - config::StdChallenger, - hash::{StdCompression, StdDigest}, -}; +use binius_verifier::{config::StdChallenger, zk_config::ZKVerifier as BiniusVerifier}; +use rand::CryptoRng; use sha3::Shake256; use sha3::digest::{ExtendableOutput, Update, XofReader}; use sha3::{Digest, Keccak256}; @@ -364,6 +359,11 @@ pub(crate) const DOMAIN_TAG_C_WORD: u64 = u64::from_le_bytes(DOMAIN_TAG_C); /// `DOMAIN_TAG_PK` packed as a little-endian `u64` for in-circuit use. pub(crate) const DOMAIN_TAG_PK_WORD: u64 = u64::from_le_bytes(DOMAIN_TAG_PK); +/// Log of the inverse Reed-Solomon rate for the binius prover/verifier. +/// +/// Soundness is fixed by binius's `SECURITY_BITS` (96), not by this value +const LOG_INV_RATE: usize = 3; + /// Compiled SNARK prover for the MAYO-2 verifier circuit. /// /// Compile once with [`Prover::compile`] (around 3 s in release mode) and @@ -372,8 +372,7 @@ pub(crate) const DOMAIN_TAG_PK_WORD: u64 = u64::from_le_bytes(DOMAIN_TAG_PK); pub struct Prover { inner: Mayo2Verify, circuit: Circuit, - binius_prover: - BiniusProver, StdDigest>, + binius_prover: BiniusProver, } /// Compiled SNARK verifier for the MAYO-2 verifier circuit. @@ -382,7 +381,7 @@ pub struct Prover { /// [`Verifier::verify`] calls. #[must_use = "a `Verifier` is the result of an expensive compile step; drop it only when you're done verifying"] pub struct Verifier { - binius_verifier: BiniusVerifier, + binius_verifier: BiniusVerifier, /// Constants from the constraint system, copied into the public-input /// slice prefix at verify time. constants: Vec, @@ -402,12 +401,10 @@ impl Prover { let circuit = builder.build(); let cs = circuit.constraint_system(); - let binius_verifier = - BiniusVerifier::::setup(cs.clone(), 1, StdCompression::default()) - .map_err(|e| Error::Setup(Box::new(e)))?; - let compression = ParallelCompressionAdaptor::new(StdCompression::default()); + let binius_verifier = BiniusVerifier::::setup(cs.clone(), LOG_INV_RATE) + .map_err(|e| Error::Setup(Box::new(e)))?; let binius_prover = - BiniusProver::::setup(binius_verifier, compression) + BiniusProver::::setup(binius_verifier) .map_err(|e| Error::Setup(Box::new(e)))?; Ok(Self { @@ -417,9 +414,29 @@ impl Prover { }) } - /// Produce a proof bundle for the signed message. + /// Produce a proof bundle for the signed message, drawing zero-knowledge + /// blinding randomness from the OS CSPRNG. + /// + /// The proof is zero-knowledge: it reveals nothing about the witness beyond + /// what the public commitments `c` and `pk_id` already commit to. Each call + /// draws fresh randomness, so proofs over identical input differ byte-wise. #[must_use = "the returned `ProofBundle` is the only output; dropping it discards the proof"] pub fn prove(&self, signed: &SignedMessage<'_>) -> Result { + self.prove_with_rng(signed, rand::rng()) + } + + /// Like [`Prover::prove`] but draws the zero-knowledge blinding randomness + /// from a caller-supplied source. Use this for reproducible proofs in tests + /// or to bind a specific entropy source. + /// + /// The RNG must be cryptographically secure. Low-entropy or reused blinding + /// randomness breaks the zero-knowledge property. + #[must_use = "the returned `ProofBundle` is the only output; dropping it discards the proof"] + pub fn prove_with_rng( + &self, + signed: &SignedMessage<'_>, + rng: impl CryptoRng, + ) -> Result { // 1. Off-circuit: lift the variable-length payload to the 32-byte // MAYO digest the signature actually authenticates. let m = shake256_32(signed.payload); @@ -434,11 +451,12 @@ impl Prover { .populate_wire_witness(&mut w) .map_err(|e| Error::Prove(Box::new(e)))?; - // 4. Run the binius64 prover and finalize the transcript. + // 4. Run the binius64 ZK prover and finalize the transcript. The RNG + // supplies the masking randomness that hides the witness. let value_vec = w.into_value_vec(); let mut transcript = ProverTranscript::new(StdChallenger::default()); self.binius_prover - .prove(value_vec, &mut transcript) + .prove(value_vec, rng, &mut transcript) .map_err(|e| Error::Prove(Box::new(e)))?; let proof_bytes = transcript.finalize(); @@ -469,9 +487,8 @@ impl Verifier { let circuit = builder.build(); let cs = circuit.constraint_system(); - let binius_verifier = - BiniusVerifier::::setup(cs.clone(), 1, StdCompression::default()) - .map_err(|e| Error::Setup(Box::new(e)))?; + let binius_verifier = BiniusVerifier::::setup(cs.clone(), LOG_INV_RATE) + .map_err(|e| Error::Setup(Box::new(e)))?; let constants = cs.constants.clone(); let offset_inout = cs.value_vec_layout.offset_inout; @@ -670,3 +687,22 @@ fn unpack_m_vec_array(packed: &[u8], n_entries: usize) -> Vec<[u8; M]> { } out } + +#[cfg(test)] +mod soundness { + use super::LOG_INV_RATE; + + #[test] + fn binius_security_target_is_at_least_96_bits() { + assert!( + binius_verifier::SECURITY_BITS >= 96, + "binius soundness target dropped to {} bits", + binius_verifier::SECURITY_BITS, + ); + let n_queries = binius_verifier::fri::calculate_n_test_queries( + binius_verifier::SECURITY_BITS, + LOG_INV_RATE, + ); + assert!(n_queries >= binius_verifier::SECURITY_BITS); + } +} diff --git a/libs/binius-mayo/src/gf16/mod.rs b/libs/binius-mayo/src/gf16/mod.rs index 5ba8076..00ea3fa 100644 --- a/libs/binius-mayo/src/gf16/mod.rs +++ b/libs/binius-mayo/src/gf16/mod.rs @@ -89,7 +89,7 @@ impl BitslicedGf16Mvec { mod tests { use super::*; use binius_core::verify::verify_constraints; - use rand::{Rng, SeedableRng, rngs::StdRng}; + use rand::{RngExt, SeedableRng, rngs::StdRng}; /// Round-trip: populate a bitsliced m-vec from random lanes, evaluate /// the (empty) circuit, and read the lanes back. @@ -103,7 +103,7 @@ mod tests { let mut w = circuit.new_witness_filler(); let mut lanes = [0u8; 64]; for x in lanes.iter_mut() { - *x = rng.gen_range(0..16); + *x = rng.random_range(0..16); } v.populate(&mut w, &lanes); circuit.populate_wire_witness(&mut w).unwrap(); @@ -129,8 +129,8 @@ mod tests { let mut a_lanes = [0u8; 64]; let mut b_lanes = [0u8; 64]; for i in 0..64 { - a_lanes[i] = rng.gen_range(0..16); - b_lanes[i] = rng.gen_range(0..16); + a_lanes[i] = rng.random_range(0..16); + b_lanes[i] = rng.random_range(0..16); } let c_lanes: [u8; 64] = core::array::from_fn(|i| scalar::add(a_lanes[i], b_lanes[i])); a.populate(&mut w, &a_lanes); diff --git a/libs/binius-mayo/src/gf16/mul.rs b/libs/binius-mayo/src/gf16/mul.rs index b7e15f3..af301e7 100644 --- a/libs/binius-mayo/src/gf16/mul.rs +++ b/libs/binius-mayo/src/gf16/mul.rs @@ -174,7 +174,7 @@ mod tests { use super::*; use crate::gf16::scalar; use binius_core::verify::verify_constraints; - use rand::{Rng, SeedableRng, rngs::StdRng}; + use rand::{RngExt, SeedableRng, rngs::StdRng}; /// 100 random 64-lane pairs: in-circuit Karatsuba == lanewise scalar mul. #[test] @@ -193,8 +193,8 @@ mod tests { let mut a_lanes = [0u8; 64]; let mut b_lanes = [0u8; 64]; for i in 0..64 { - a_lanes[i] = rng.gen_range(0..16); - b_lanes[i] = rng.gen_range(0..16); + a_lanes[i] = rng.random_range(0..16); + b_lanes[i] = rng.random_range(0..16); } let c_lanes: [u8; 64] = core::array::from_fn(|i| scalar::mul(a_lanes[i], b_lanes[i])); a.populate(&mut w, &a_lanes); @@ -215,7 +215,7 @@ mod tests { let circuit = builder.build(); for _ in 0..50 { - let s: u8 = rng.gen_range(0..16); + let s: u8 = rng.random_range(0..16); let mut w = circuit.new_witness_filler(); w[scalar_w] = Word(s as u64); circuit.populate_wire_witness(&mut w).unwrap(); @@ -243,9 +243,9 @@ mod tests { for _ in 0..20 { let mut w = circuit.new_witness_filler(); - let s_lanes: [u8; 64] = core::array::from_fn(|_| rng.gen_range(0..16)); - let v_lanes: [u8; 64] = core::array::from_fn(|_| rng.gen_range(0..16)); - let acc_lanes: [u8; 64] = core::array::from_fn(|_| rng.gen_range(0..16)); + let s_lanes: [u8; 64] = core::array::from_fn(|_| rng.random_range(0..16)); + let v_lanes: [u8; 64] = core::array::from_fn(|_| rng.random_range(0..16)); + let acc_lanes: [u8; 64] = core::array::from_fn(|_| rng.random_range(0..16)); let exp_lanes: [u8; 64] = core::array::from_fn(|i| { scalar::add(acc_lanes[i], scalar::mul(s_lanes[i], v_lanes[i])) }); diff --git a/libs/binius-mayo/src/gf16/scalar.rs b/libs/binius-mayo/src/gf16/scalar.rs index 40d0579..e631ce5 100644 --- a/libs/binius-mayo/src/gf16/scalar.rs +++ b/libs/binius-mayo/src/gf16/scalar.rs @@ -102,7 +102,7 @@ pub(crate) fn bitsliced_to_lanes(planes: &[u64; 4]) -> [u8; 64] { #[cfg(test)] mod tests { use super::*; - use rand::{Rng, SeedableRng, rngs::StdRng}; + use rand::{RngExt, SeedableRng, rngs::StdRng}; /// Independent scalar reference: schoolbook multiply via shift-XOR, then /// reduce by directly applying x^4 = x + 1 to each high bit of the product. @@ -160,9 +160,9 @@ mod tests { fn given_random_triples_when_mul_then_associative() { let mut rng = StdRng::seed_from_u64(0xCAFE_BABE); for _ in 0..1000 { - let a: u8 = rng.gen_range(0..16); - let b: u8 = rng.gen_range(0..16); - let c: u8 = rng.gen_range(0..16); + let a: u8 = rng.random_range(0..16); + let b: u8 = rng.random_range(0..16); + let c: u8 = rng.random_range(0..16); assert_eq!(mul(mul(a, b), c), mul(a, mul(b, c))); } } @@ -171,9 +171,9 @@ mod tests { fn given_random_triples_when_mul_then_distributive_over_add() { let mut rng = StdRng::seed_from_u64(0xDEAD_BEEF); for _ in 0..1000 { - let a: u8 = rng.gen_range(0..16); - let b: u8 = rng.gen_range(0..16); - let c: u8 = rng.gen_range(0..16); + let a: u8 = rng.random_range(0..16); + let b: u8 = rng.random_range(0..16); + let c: u8 = rng.random_range(0..16); // a * (b + c) = a*b + a*c assert_eq!(mul(a, add(b, c)), add(mul(a, b), mul(a, c))); } @@ -185,7 +185,7 @@ mod tests { for _ in 0..50 { let mut lanes = [0u8; 64]; for v in lanes.iter_mut() { - *v = rng.gen_range(0..16); + *v = rng.random_range(0..16); } let packed = pack_lanes(&lanes); let back = unpack_lanes(&packed); @@ -223,7 +223,7 @@ mod tests { for _ in 0..50 { let mut lanes = [0u8; 64]; for v in lanes.iter_mut() { - *v = rng.gen_range(0..16); + *v = rng.random_range(0..16); } let planes = lanes_to_bitsliced(&lanes); let back = bitsliced_to_lanes(&planes); diff --git a/libs/binius-mayo/src/gf16/transpose.rs b/libs/binius-mayo/src/gf16/transpose.rs index dc9fb53..7d9e124 100644 --- a/libs/binius-mayo/src/gf16/transpose.rs +++ b/libs/binius-mayo/src/gf16/transpose.rs @@ -182,7 +182,7 @@ mod tests { use super::*; use crate::gf16::scalar; use binius_core::verify::verify_constraints; - use rand::{Rng, SeedableRng, rngs::StdRng}; + use rand::{RngExt, SeedableRng, rngs::StdRng}; /// Round-trip: packed → bitsliced → packed = identity, in-circuit. #[test] @@ -202,7 +202,7 @@ mod tests { let mut w = circuit.new_witness_filler(); let mut lanes = [0u8; 64]; for v in lanes.iter_mut() { - *v = rng.gen_range(0..16); + *v = rng.random_range(0..16); } let pk = scalar::pack_lanes(&lanes); for i in 0..4 { @@ -229,7 +229,7 @@ mod tests { let mut w = circuit.new_witness_filler(); let mut lanes = [0u8; 64]; for v in lanes.iter_mut() { - *v = rng.gen_range(0..16); + *v = rng.random_range(0..16); } let pk = scalar::pack_lanes(&lanes); for i in 0..4 { @@ -256,7 +256,7 @@ mod tests { let mut w = circuit.new_witness_filler(); let mut lanes = [0u8; 64]; for v in lanes.iter_mut() { - *v = rng.gen_range(0..16); + *v = rng.random_range(0..16); } bv.populate(&mut w, &lanes); circuit.populate_wire_witness(&mut w).unwrap(); diff --git a/libs/binius-mayo/src/quadratic.rs b/libs/binius-mayo/src/quadratic.rs index 28bd31e..a8dca00 100644 --- a/libs/binius-mayo/src/quadratic.rs +++ b/libs/binius-mayo/src/quadratic.rs @@ -283,7 +283,7 @@ mod tests { use super::*; use crate::gf16::scalar::{add as gf_add, mul as gf_mul}; use binius_core::verify::verify_constraints; - use rand::{Rng, SeedableRng, rngs::StdRng}; + use rand::{RngExt, SeedableRng, rngs::StdRng}; /// Pure-Rust reference: compute SPS = s · P · s^T from raw lane data. /// This is a direct port of the same two-pass loop the circuit executes, @@ -389,18 +389,18 @@ mod tests { let mut rng = StdRng::seed_from_u64(0xBEAD_CAFE); let mut p1_lanes: Vec<[u8; 64]> = Vec::with_capacity(P1_ENTRIES); for _ in 0..P1_ENTRIES { - p1_lanes.push(core::array::from_fn(|_| rng.gen_range(0..16))); + p1_lanes.push(core::array::from_fn(|_| rng.random_range(0..16))); } let mut p2_lanes: Vec<[u8; 64]> = Vec::with_capacity(P2_ENTRIES); for _ in 0..P2_ENTRIES { - p2_lanes.push(core::array::from_fn(|_| rng.gen_range(0..16))); + p2_lanes.push(core::array::from_fn(|_| rng.random_range(0..16))); } let mut p3_lanes: Vec<[u8; 64]> = Vec::with_capacity(P3_ENTRIES); for _ in 0..P3_ENTRIES { - p3_lanes.push(core::array::from_fn(|_| rng.gen_range(0..16))); + p3_lanes.push(core::array::from_fn(|_| rng.random_range(0..16))); } let s: [[u8; N]; K] = - core::array::from_fn(|_col| core::array::from_fn(|_r| rng.gen_range(0..16))); + core::array::from_fn(|_col| core::array::from_fn(|_r| rng.random_range(0..16))); let want = scalar_compute_sps(&p1_lanes, &p2_lanes, &p3_lanes, &s); diff --git a/libs/binius-mayo/src/shake256.rs b/libs/binius-mayo/src/shake256.rs index cbd577d..300cebf 100644 --- a/libs/binius-mayo/src/shake256.rs +++ b/libs/binius-mayo/src/shake256.rs @@ -90,7 +90,7 @@ pub(crate) fn shake256_56_to_32( mod tests { use binius_core::verify::verify_constraints; use binius_frontend::CircuitBuilder; - use rand::{RngCore, SeedableRng, rngs::StdRng}; + use rand::{Rng, SeedableRng, rngs::StdRng}; use sha3::{ Shake256, digest::{ExtendableOutput, Update, XofReader}, diff --git a/libs/binius-mayo/src/whipping.rs b/libs/binius-mayo/src/whipping.rs index 7fbbb9f..f7b548b 100644 --- a/libs/binius-mayo/src/whipping.rs +++ b/libs/binius-mayo/src/whipping.rs @@ -165,7 +165,7 @@ mod tests { use super::*; use crate::gf16::scalar; use binius_core::verify::verify_constraints; - use rand::{Rng, SeedableRng, rngs::StdRng}; + use rand::{RngExt, SeedableRng, rngs::StdRng}; /// Pure-Rust reference for the whipping loop. Mirrors MAYO-C /// `compute_rhs` exactly using the in-crate scalar GF(16) helpers. @@ -246,7 +246,7 @@ mod tests { let mut sps_lanes = [[0u8; M]; K * K]; for r in sps_lanes.iter_mut() { for v in r.iter_mut() { - *v = rng.gen_range(0..16); + *v = rng.random_range(0..16); } } for i in 0..K * K { diff --git a/libs/binius-mayo/tests/api_tests.rs b/libs/binius-mayo/tests/api_tests.rs index cf9134b..d8f55ff 100644 --- a/libs/binius-mayo/tests/api_tests.rs +++ b/libs/binius-mayo/tests/api_tests.rs @@ -49,6 +49,35 @@ fn given_first_kat_when_prove_then_verify_succeeds() { verifier.verify(&bundle).expect("verify"); } +#[test] +fn given_same_input_when_proved_twice_then_zk_proofs_differ() { + // Given: one KAT entry and a compiled prover/verifier. + let (cpk, sig, msg) = first_kat(); + let prover = Prover::compile().expect("prover compile"); + let verifier = Verifier::compile().expect("verifier compile"); + let signed = SignedMessage { + payload: &msg, + cpk: &cpk, + sig: &sig, + }; + + // When: we prove the same statement twice with independent blinding. + let a = prover.prove(&signed).expect("prove a"); + let b = prover.prove(&signed).expect("prove b"); + + // Then: both verify, the public commitments match, but the ZK proof bytes + // differ because each call draws fresh blinding randomness. + verifier.verify(&a).expect("verify a"); + verifier.verify(&b).expect("verify b"); + assert_eq!(a.c, b.c); + assert_eq!(a.pk_id, b.pk_id); + assert_ne!( + a.proof.as_slice(), + b.proof.as_slice(), + "ZK proofs over identical input must not be byte-identical" + ); +} + #[test] fn given_proof_when_proof_byte_flipped_then_verify_rejects() { // Given: a valid proof bundle.