diff --git a/Cargo.lock b/Cargo.lock index d7a8424..3da65fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -11,16 +11,7 @@ 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", + "zerocopy 0.7.35", ] [[package]] @@ -29,22 +20,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "alloy-rlp" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6c1d995bff8d011f7cd6c81820d51825e6e06d6db73914c1630ecf544d83d6" -dependencies = [ - "arrayvec", - "bytes", -] - -[[package]] -name = "anyhow" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" - [[package]] name = "ark-bn254" version = "0.5.0" @@ -52,8 +27,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" dependencies = [ "ark-ec", - "ark-ff 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-std", ] [[package]] @@ -63,14 +38,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" dependencies = [ "ahash", - "ark-ff 0.5.0", + "ark-ff", "ark-poly", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-serialize", + "ark-std", "educe", "fnv", "hashbrown", - "itertools 0.13.0", + "itertools", "num-bigint", "num-integer", "num-traits", @@ -78,41 +53,15 @@ dependencies = [ ] [[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" +name = "ark-ed-on-bn254" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +checksum = "962e24e25cbdcaabe619c281a62bccc885f778b188129d6a02875c2671666219" dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.1", - "zeroize", + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-std", ] [[package]] @@ -121,40 +70,20 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" dependencies = [ - "ark-ff-asm 0.5.0", - "ark-ff-macros 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", "arrayvec", - "digest 0.10.7", + "digest", "educe", - "itertools 0.13.0", + "itertools", "num-bigint", "num-traits", "paste", "zeroize", ] -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[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-asm" version = "0.5.0" @@ -162,32 +91,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.98", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "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", + "syn", ] [[package]] @@ -200,7 +104,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.98", + "syn", ] [[package]] @@ -210,35 +114,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" dependencies = [ "ahash", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", + "ark-ff", + "ark-serialize", + "ark-std", "educe", "fnv", "hashbrown", ] -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - [[package]] name = "ark-serialize" version = "0.5.0" @@ -246,9 +129,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ "ark-serialize-derive", - "ark-std 0.5.0", + "ark-std", "arrayvec", - "digest 0.10.7", + "digest", "num-bigint", ] @@ -260,27 +143,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand", + "syn", ] [[package]] @@ -299,17 +162,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "auto_impl" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -317,1125 +169,291 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] -name = "base16ct" -version = "0.2.0" +name = "blake" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "ee55e9ca33be1f257d8356cfb29b10b1c8f86dc38cf1344ca01525464356cd0c" +dependencies = [ + "cc", + "libc", +] [[package]] -name = "base64ct" -version = "1.6.0" +name = "cc" +version = "1.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +dependencies = [ + "shlex", +] [[package]] -name = "bitflags" -version = "2.8.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "bitvec" -version = "1.0.1" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "funty", - "radium", - "tap", - "wyz", + "generic-array", + "typenum", ] [[package]] -name = "block-buffer" -version = "0.10.4" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "generic-array", + "crypto-common", ] [[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.0" +name = "educe" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" dependencies = [ - "serde", + "enum-ordinalize", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "chrono" -version = "0.4.39" +name = "enum-ordinalize" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" dependencies = [ - "num-traits", + "enum-ordinalize-derive", ] [[package]] -name = "const-hex" -version = "1.14.0" +name = "enum-ordinalize-derive" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "const-oid" -version = "0.9.6" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "cpufeatures" -version = "0.2.17" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "libc", + "typenum", + "version_check", ] [[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" +name = "hashbrown" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", + "allocator-api2", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "itertools" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ - "generic-array", - "typenum", + "either", ] [[package]] -name = "der" -version = "0.7.9" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "derivative" -version = "2.2.0" +name = "libc" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] -name = "derive_more" -version = "1.0.0" +name = "light-poseidon" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +checksum = "39e3d87542063daaccbfecd78b60f988079b6ec4e089249658b9455075c78d42" dependencies = [ - "derive_more-impl", + "ark-bn254", + "ark-ff", + "num-bigint", + "thiserror 1.0.69", ] [[package]] -name = "derive_more-impl" -version = "1.0.0" +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "digest" -version = "0.9.0" +name = "num-bigint" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "generic-array", + "num-integer", + "num-traits", ] [[package]] -name = "digest" -version = "0.10.7" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", + "num-traits", ] [[package]] -name = "ecdsa" -version = "0.16.9" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", + "autocfg", ] [[package]] -name = "educe" -version = "0.6.0" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" -dependencies = [ - "enum-ordinalize", - "proc-macro2", - "quote", - "syn 2.0.98", -] +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "either" -version = "1.13.0" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "elliptic-curve" -version = "0.13.8" +name = "ppv-lite86" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", + "zerocopy 0.8.24", ] [[package]] -name = "enum-ordinalize" -version = "4.3.0" +name = "proc-macro2" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ - "enum-ordinalize-derive", + "unicode-ident", ] [[package]] -name = "enum-ordinalize-derive" -version = "4.3.1" +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", - "quote", - "syn 2.0.98", ] [[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror 1.0.69", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "chrono", - "const-hex", - "elliptic-curve", - "ethabi", - "generic-array", - "k256", - "num_enum", - "open-fastrlp", - "rand", - "rlp", - "serde", - "serde_json", - "strum", - "tempfile", - "thiserror 1.0.69", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "fastrlp" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "allocator-api2", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "indexmap" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "leanimt-rs" -version = "0.1.0" -source = "git+https://github.com/vplasencia/leanimt-rs#a34db7c1b7b04b42e8c266b930088ae52a10cc33" - -[[package]] -name = "libc" -version = "0.2.169" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "light-poseidon" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3d87542063daaccbfecd78b60f988079b6ec4e089249658b9455075c78d42" -dependencies = [ - "ark-bn254", - "ark-ff 0.5.0", - "num-bigint", - "thiserror 1.0.69", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[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", - "libm", -] - -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "once_cell" -version = "1.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" - -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pest" -version = "2.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" -dependencies = [ - "memchr", - "thiserror 2.0.11", - "ucd-trie", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[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.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" -dependencies = [ - "bitflags", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", - "unarray", -] - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[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 0.2.15", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[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", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" +name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ruint" -version = "1.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ef8fb1dd8de3870cb8400d51b4c2023854bbafd5431a3ac7e7317243e22d2f" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp 0.3.1", - "fastrlp 0.4.0", - "num-bigint", - "num-integer", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "semver 1.0.25", + "rand_chacha", + "rand_core", ] [[package]] -name = "rustix" -version = "0.38.44" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", + "ppv-lite86", + "rand_core", ] [[package]] -name = "rustversion" -version = "1.0.19" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "ryu" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" - -[[package]] -name = "scale-info" -version = "2.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[package]] -name = "sec1" -version = "0.7.3" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "semaphore-rs" version = "0.1.0" dependencies = [ - "anyhow", - "ark-bn254", - "ethers-core", - "leanimt-rs", + "ark-ec", + "ark-ed-on-bn254", + "ark-ff", + "blake", "light-poseidon", "num-bigint", - "ruint", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" - -[[package]] -name = "semver-parser" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" -dependencies = [ - "pest", + "serde", + "serde_json", + "thiserror 2.0.12", + "zk-kit-lean-imt", ] [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn", ] [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -1444,122 +462,22 @@ dependencies = [ ] [[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.98", -] - -[[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" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "2.0.98" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" -dependencies = [ - "cfg-if", - "fastrand", - "getrandom 0.3.1", - "once_cell", - "rustix", - "windows-sys", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -1571,11 +489,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -1586,93 +504,31 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[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.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", + "syn", ] [[package]] name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "version_check" @@ -1681,139 +537,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - -[[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.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "bitflags", + "zerocopy-derive 0.7.35", ] [[package]] -name = "wyz" -version = "0.5.1" +name = "zerocopy" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "tap", + "zerocopy-derive 0.8.24", ] [[package]] -name = "zerocopy" +name = "zerocopy-derive" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "byteorder", - "zerocopy-derive", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn", ] [[package]] @@ -1833,5 +593,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn", +] + +[[package]] +name = "zk-kit-lean-imt" +version = "0.1.0" +source = "git+https://github.com/brech1/zk-kit.rust?branch=feat%2Fgeneric-tree#fd9d98bd29bbbfc48d89df2db9beae78aff85e7a" +dependencies = [ + "serde", + "thiserror 2.0.12", ] diff --git a/Cargo.toml b/Cargo.toml index 5d8c01f..6cc6d48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,30 @@ [package] name = "semaphore-rs" version = "0.1.0" -edition = "2021" +edition = "2024" [dependencies] -anyhow = "1.0.95" -ethers-core = "2.0.14" +blake = "2.0.2" light-poseidon = "0.3.0" num-bigint = "0.4.6" -ruint = "1.12.4" -leanimt-rs = { git = "https://github.com/vplasencia/leanimt-rs" } -ark-bn254 = "0.5.0" +thiserror = "2.0.12" + +# arkworks +ark-ec = { version = "=0.5.0", default-features = false } +ark-ed-on-bn254 = { version = "=0.5.0", default-features = false } +ark-ff = { version = "=0.5.0", default-features = false } + +# zk-kit +zk-kit-lean-imt = { git = "https://github.com/brech1/zk-kit.rust", package = "zk-kit-lean-imt", branch = "feat/generic-tree" } + +# serde +serde = { version = "1", features = ["derive"], optional = true } +serde_json = { version = "1", optional = true } + +[features] +default = [] +serde = [ + "dep:serde", + "serde_json", + "zk-kit-lean-imt/serde" +] diff --git a/src/baby_jubjub.rs b/src/baby_jubjub.rs new file mode 100644 index 0000000..3693565 --- /dev/null +++ b/src/baby_jubjub.rs @@ -0,0 +1,201 @@ +//! EIP-2494 Baby Jubjub Curve +//! +//! This is an append to the the `ark-ed-on-bn254` crate to use the EIP-2494 defined Baby Jubjub curve parameters. +//! +//! - https://eips.ethereum.org/EIPS/eip-2494 +//! +//! - Base field: q = 21888242871839275222246405745257275088548364400416034343698204186575808495617 +//! - Scalar field: r = 2736030358979909402780800718157159386076813972158567259200215660948447373041 +//! - Order: n = l * cofactor = 21888242871839275222246405745257275088614511777268538073601725287587578984328 +//! - Cofactor: 8 +//! - Subgroup order: l = 2736030358979909402780800718157159386076813972158567259200215660948447373041 +//! - Curve equation: ax² + y² = 1 + d·x²y², where +//! - a = 168700 +//! - d = 168696 +//! - Generator point: +//! (995203441582195749578291179787384436505546430278305826713579947235728471134, +//! 5472060717959818805561601436314318772137091100104008585924551046643952123905) +//! - Base point: +//! (5299619240641551281634865583518297030282874472190772894086521144482721001553, +//! 16950150798460657717958625567821834550301663161624707787222815936182638968203) + +use ark_ec::{ + models::CurveConfig, + twisted_edwards::{Affine, MontCurveConfig, Projective, TECurveConfig}, +}; +use ark_ed_on_bn254::{Fq, Fr}; +use ark_ff::{Field, MontFp}; + +pub type EdwardsAffine = Affine; +pub type EdwardsProjective = Projective; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct BabyJubjubConfig; + +impl CurveConfig for BabyJubjubConfig { + type BaseField = Fq; + type ScalarField = Fr; + + // h = 8 + const COFACTOR: &'static [u64] = &[8]; + + // h^(-1) (mod r) + const COFACTOR_INV: Fr = + MontFp!("2394026564107420727433200628387514462817212225638746351800188703329891451411"); +} + +// Twisted Edwards form +// ax^2 + y^2 = 1 + dx^2y^2 +impl TECurveConfig for BabyJubjubConfig { + // a = 168700 + const COEFF_A: Fq = MontFp!("168700"); + + #[inline(always)] + fn mul_by_a(elem: Self::BaseField) -> Self::BaseField { + elem * ::COEFF_A + } + + // d = 168696 + const COEFF_D: Fq = MontFp!("168696"); + + // Base point is used as generator to operate in subgroup + const GENERATOR: EdwardsAffine = EdwardsAffine::new_unchecked(BASE_X, BASE_Y); + + type MontCurveConfig = BabyJubjubConfig; +} + +// Montgomery form +// By^2 = x^3 + A x^2 + x +impl MontCurveConfig for BabyJubjubConfig { + // A = 168698 + const COEFF_A: Fq = MontFp!("168698"); + // B = 1 + const COEFF_B: Fq = Fq::ONE; + + type TECurveConfig = BabyJubjubConfig; +} + +/// Generator point x-coordinate +pub const GENERATOR_X: Fq = + MontFp!("995203441582195749578291179787384436505546430278305826713579947235728471134"); +/// Generator point y-coordinate +pub const GENERATOR_Y: Fq = + MontFp!("5472060717959818805561601436314318772137091100104008585924551046643952123905"); + +/// Subgroup order `l` +pub const SUBGROUP_ORDER: Fr = + MontFp!("2736030358979909402780800718157159386076813972158567259200215660948447373041"); + +// Subgroup generator +// Generates subgroup l * P = O + +/// Base point x-coordinate +pub const BASE_X: Fq = + MontFp!("5299619240641551281634865583518297030282874472190772894086521144482721001553"); +/// Base point y-coordinate +pub const BASE_Y: Fq = + MontFp!("16950150798460657717958625567821834550301663161624707787222815936182638968203"); + +#[cfg(test)] +mod tests { + //! Implementation of the tests presented in the EIP-2494 + + use super::*; + use ark_ec::CurveGroup; + use ark_ff::{PrimeField, Zero}; + + #[test] + fn test_addition() { + let p1 = EdwardsAffine::new_unchecked( + MontFp!( + "17777552123799933955779906779655732241715742912184938656739573121738514868268" + ), + MontFp!("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ); + + let p2 = EdwardsAffine::new_unchecked( + MontFp!( + "16540640123574156134436876038791482806971768689494387082833631921987005038935" + ), + MontFp!( + "20819045374670962167435360035096875258406992893633759881276124905556507972311" + ), + ); + + let result = (p1 + p2).into_affine(); + + assert_eq!( + result, + EdwardsAffine::new_unchecked( + MontFp!( + "7916061937171219682591368294088513039687205273691143098332585753343424131937" + ), + MontFp!( + "14035240266687799601661095864649209771790948434046947201833777492504781204499" + ) + ) + ); + } + + #[test] + fn test_doubling() { + let p1 = EdwardsAffine::new_unchecked( + MontFp!( + "17777552123799933955779906779655732241715742912184938656739573121738514868268" + ), + MontFp!("2626589144620713026669568689430873010625803728049924121243784502389097019475"), + ); + + let result = (p1 + p1).into_affine(); + + assert_eq!( + result, + EdwardsAffine::new_unchecked( + MontFp!( + "6890855772600357754907169075114257697580319025794532037257385534741338397365" + ), + MontFp!( + "4338620300185947561074059802482547481416142213883829469920100239455078257889" + ) + ) + ); + } + + #[test] + fn test_doubling_identity() { + let identity = EdwardsAffine::new_unchecked(Fq::zero(), Fq::ONE); + let result = (identity + identity).into_affine(); + + assert_eq!(result, identity); + } + + #[test] + fn test_curve_membership() { + let valid_point = EdwardsAffine::new_unchecked(Fq::zero(), Fq::ONE); + assert!(valid_point.is_on_curve()); + + let invalid_point = EdwardsAffine::new_unchecked(Fq::ONE, Fq::zero()); + assert!(!invalid_point.is_on_curve()); + } + + #[test] + fn test_base_point_choice() { + let g = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y); + + let expected_base_point = EdwardsAffine::new_unchecked(BASE_X, BASE_Y); + let cofactor = Fr::from_be_bytes_mod_order(&[BabyJubjubConfig::COFACTOR[0] as u8]); + let calculated_base_point = (g * cofactor).into_affine(); + + assert_eq!(calculated_base_point, expected_base_point); + } + + #[test] + fn test_base_point_order() { + let base_point = EdwardsAffine::new_unchecked(GENERATOR_X, GENERATOR_Y); + + let result = (base_point * SUBGROUP_ORDER).into_affine(); + let identity = EdwardsAffine::new_unchecked(Fq::zero(), Fq::ONE); + + assert_eq!(result, identity); + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..0d18412 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,34 @@ +//! Error Module + +use thiserror::Error; +use zk_kit_lean_imt::lean_imt::LeanIMTError; + +#[derive(Error, Debug, PartialEq, Eq)] +pub enum SemaphoreError { + #[error("Member already removed")] + AlreadyRemovedMember, + #[error("Member value is empty")] + EmptyLeaf, + #[error("Input array of size {0} exceeds maximum allowed length of 32 bytes")] + InputSizeExceeded(usize), + #[error("LeanIMT error: {0}")] + LeanIMTError(LeanIMTError), + #[error("Message of size {0} exceeds maximum allowed length of 32 bytes")] + MessageSizeExceeded(usize), + #[error("Public key validation failed: point is not on curve")] + PublicKeyNotOnCurve, + #[error("Member has been removed")] + RemovedMember, + #[error("Signature point R is not on curve")] + SignaturePointNotOnCurve, + #[error("Signature verification failed")] + SignatureVerificationFailed, + #[error("Serialization error: {0}")] + SerializationError(String), +} + +impl From for SemaphoreError { + fn from(error: LeanIMTError) -> Self { + SemaphoreError::LeanIMTError(error) + } +} diff --git a/src/group.rs b/src/group.rs index 4921a90..a39c958 100644 --- a/src/group.rs +++ b/src/group.rs @@ -1,328 +1,421 @@ -use anyhow::{Ok, Result}; - -use ark_bn254::Fr; -use leanimt_rs::*; +//! Group module +//! +//! This module is a wrapper around the `HashedLeanIMT` struct with some utility methods. +//! +//! Leaves and nodes are the same size, 32 bytes. + +use crate::error::SemaphoreError; +use ark_ed_on_bn254::Fq; +use ark_ff::{BigInteger, PrimeField}; use light_poseidon::{Poseidon, PoseidonHasher}; +use zk_kit_lean_imt::{ + hashed_tree::{HashedLeanIMT, LeanIMTHasher}, + lean_imt::MerkleProof, +}; + +/// Size of nodes and leaves in bytes +pub const ELEMENT_SIZE: usize = 32; +/// Empty element +pub const EMPTY_ELEMENT: Element = [0u8; ELEMENT_SIZE]; + +/// Element type alias +pub type Element = [u8; ELEMENT_SIZE]; + +/// Poseidon LeanIMT hasher +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct PoseidonHash; + +impl LeanIMTHasher for PoseidonHash { + fn hash(input: &[u8]) -> [u8; ELEMENT_SIZE] { + let hash = Poseidon::::new_circom(2) + .expect("Failed to initialize Poseidon") + .hash(&[ + Fq::from_le_bytes_mod_order(&input[..ELEMENT_SIZE]), + Fq::from_le_bytes_mod_order(&input[ELEMENT_SIZE..]), + ]) + .expect("Poseidon hash failed"); + + let mut hash_bytes = [0u8; ELEMENT_SIZE]; + hash_bytes.copy_from_slice(&hash.into_bigint().to_bytes_le()); + + hash_bytes + } +} -use crate::utils::string_to_biguint; - +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Group { - lean_imt: LeanIMT, + /// Hashed LeanIMT + pub tree: HashedLeanIMT, } impl Group { - pub fn new(leaves: Vec) -> Self { - if !leaves.is_empty() { - leaves.iter().for_each(|m| { - assert!( - Group::is_valid_leaf(m.clone()), - "Failed to add member: value can't be 0" - ); + /// Creates a new instance of the Group with optional initial members + pub fn new(members: &[Element]) -> Result { + if members.is_empty() { + return Ok(Group { + tree: HashedLeanIMT::::new(&[], PoseidonHash)?, }); } - Group { - lean_imt: LeanIMT::new(Group::hash, leaves).unwrap(), + for &member in members { + if member == EMPTY_ELEMENT { + return Err(SemaphoreError::EmptyLeaf); + } } + + Ok(Group { + tree: HashedLeanIMT::::new(members, PoseidonHash)?, + }) } - fn hash(nodes: Vec) -> String { - let mut poseidon = Poseidon::::new_circom(2).unwrap(); + /// Returns the root hash of the tree, or None if the tree is empty + pub fn root(&self) -> Option { + self.tree.root() + } - let input1 = Fr::from(string_to_biguint(&nodes[0])); - let input2 = Fr::from(string_to_biguint(&nodes[1])); - let hash = poseidon.hash(&[input1, input2]).unwrap(); + /// Returns the depth of the tree + pub fn depth(&self) -> usize { + self.tree.depth() + } - hash.to_string() + /// Returns the size of the tree (number of leaves) + pub fn size(&self) -> usize { + self.tree.size() } - pub fn add_member(&mut self, member: LeanIMTNode) -> Result<()> { - assert!( - Group::is_valid_leaf(member.clone()), - "Failed to add member: value can't be empty" - ); - self.lean_imt.insert(member.to_string()).unwrap(); - Ok(()) + /// Returns the group members + pub fn members(&self) -> Vec { + self.tree + .leaves() + .iter() + .map(|v| v.as_slice().try_into().unwrap()) + .collect() } - pub fn add_members(&mut self, members: Vec) -> Result<()> { - members.iter().for_each(|m| { - assert!( - Group::is_valid_leaf(m.clone()), - "Failed to add member: value can't be 0" - ); - }); - self.lean_imt.insert_many(members).unwrap(); - Ok(()) + /// Returns the index of a member if it exists + pub fn index_of(&self, member: Element) -> Option { + self.tree.index_of(&member) } - pub fn update_member(&mut self, index: usize, member: LeanIMTNode) -> Result<()> { - let members = self.lean_imt.leaves(); - assert!( - Group::is_valid_leaf(members[index].clone()), - "Failed to update member: it has been removed" - ); + /// Adds a new member to the group + pub fn add_member(&mut self, member: Element) -> Result<(), SemaphoreError> { + if member == EMPTY_ELEMENT { + return Err(SemaphoreError::EmptyLeaf); + } - self.lean_imt.update(index, member.to_string()).unwrap(); + self.tree.insert(&member); Ok(()) } - pub fn remove_member(&mut self, index: usize) -> Result<()> { - let members = self.lean_imt.leaves(); - assert!( - Group::is_valid_leaf(members[index].clone()), - "Failed to remove member: it has been removed" - ); + /// Adds a set of members to the group + pub fn add_members(&mut self, members: Vec) -> Result<(), SemaphoreError> { + for member in &members { + if *member == EMPTY_ELEMENT { + return Err(SemaphoreError::EmptyLeaf); + } + } - self.lean_imt.update(index, "0".to_string()).unwrap(); + self.tree.insert_many(&members)?; Ok(()) } - pub fn generate_merkle_proof(&self, index: usize) -> Result { - Ok(self.lean_imt.generate_proof(index).unwrap()) - } + /// Updates a group member + pub fn update_member(&mut self, index: usize, member: Element) -> Result<(), SemaphoreError> { + if self.members()[index] == EMPTY_ELEMENT { + return Err(SemaphoreError::RemovedMember); + } - pub fn root(&mut self) -> Option { - self.lean_imt.root() + self.tree.update(index, &member)?; + Ok(()) } - pub fn depth(&self) -> usize { - self.lean_imt.depth() + /// Removes a member from the group + pub fn remove_member(&mut self, index: usize) -> Result<(), SemaphoreError> { + if self.members()[index] == EMPTY_ELEMENT { + return Err(SemaphoreError::AlreadyRemovedMember); + } + + self.tree.update(index, &EMPTY_ELEMENT)?; + Ok(()) } - pub fn members(&self) -> Vec { - self.lean_imt.leaves() + /// Creates a proof of membership for a member + pub fn generate_proof( + &self, + index: usize, + ) -> Result, SemaphoreError> { + self.tree + .generate_proof(index) + .map_err(SemaphoreError::LeanIMTError) } - pub fn size(&self) -> usize { - self.lean_imt.size() + /// Verifies a proof of membership for a member + pub fn verify_proof(proof: &MerkleProof) -> bool { + HashedLeanIMT::::verify_proof(proof) } +} - fn is_valid_leaf(leaf: LeanIMTNode) -> bool { - !leaf.is_empty() && leaf.ne("0") +#[cfg(feature = "serde")] +impl Group { + /// Exports the LeanIMT tree to a JSON. + pub fn export(&self) -> Result { + serde_json::to_string(&self.tree.tree()) + .map_err(|e| SemaphoreError::SerializationError(e.to_string())) } - // TODO wait for LeanIMT support - pub fn export(&self) -> String { - unimplemented!("Unsupported."); + /// Imports a Group from a JSON string representing a LeanIMT tree. + pub fn import(json: &str) -> Result { + let lean_imt_tree: zk_kit_lean_imt::lean_imt::LeanIMT = + serde_json::from_str(json) + .map_err(|e| SemaphoreError::SerializationError(e.to_string()))?; + + Ok(Group { + tree: zk_kit_lean_imt::hashed_tree::HashedLeanIMT::new_from_tree( + lean_imt_tree, + PoseidonHash, + ), + }) } +} - // TODO wait for LeanIMT support - pub fn import(_json: &str) -> Self { - unimplemented!("Unsupported."); +/// Converts a byte array to an element +pub fn bytes_to_element(bytes: &[u8]) -> Result { + if bytes.len() > ELEMENT_SIZE { + return Err(SemaphoreError::InputSizeExceeded(bytes.len())); } + + let mut element = EMPTY_ELEMENT; + element[..bytes.len()].copy_from_slice(bytes); + + Ok(element) +} + +/// Converts a scalar to an element +pub fn fq_to_element(fq: &Fq) -> Element { + let mut element = EMPTY_ELEMENT; + let bytes = fq.into_bigint().to_bytes_le(); + element[..bytes.len()].copy_from_slice(&bytes); + element +} + +/// Converts an element to a scalar +pub fn element_to_fq(element: &Element) -> Fq { + Fq::from_le_bytes_mod_order(element) } #[cfg(test)] mod tests { - use super::Group; + use super::*; - #[cfg(test)] - mod group { - use crate::group::Group; - use std::panic; + #[test] + fn test_conversions() { + let test_bytes = [ + 59, 227, 30, 252, 212, 244, 251, 255, 228, 174, 31, 212, 161, 61, 184, 169, 200, 50, 7, + 84, 65, 96, + ]; + let element = bytes_to_element(&test_bytes).unwrap(); + let fq = element_to_fq(&element); + let element_back = fq_to_element(&fq); + + assert_eq!(element, element_back); + assert_eq!(fq, Fq::from_le_bytes_mod_order(&test_bytes)); + assert_eq!( + bytes_to_element(&[0; 33]), + Err(SemaphoreError::InputSizeExceeded(33)) + ); + } - #[test] - fn test_empty() { - let mut group = Group::new(vec![]); + #[test] + fn test_create_empty_group() { + let group = Group::default(); - assert_eq!(group.root(), None); - assert_eq!(group.depth(), 0); - assert_eq!(group.size(), 0); - } + assert_eq!(group.root(), None); + assert_eq!(group.depth(), 0); + assert_eq!(group.size(), 0); + } - #[test] - fn test_with_a_list_members() { - let mut group = Group::new(vec!["1".to_string(), "2".to_string(), "3".to_string()]); + #[test] + fn test_create_group_with_members() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let member3 = [3; 32]; - let mut group2 = Group::new(vec![]); - group2.add_member("1".to_string()).unwrap(); - group2.add_member("2".to_string()).unwrap(); - group2.add_member("3".to_string()).unwrap(); + let group1 = Group::new(&[member1, member2, member3]).unwrap(); - assert_eq!(group.root(), group2.root()); - assert_eq!(group.depth(), group2.depth()); - assert_eq!(group.size(), group2.size()); - } + let mut group2 = Group::default(); + group2.add_member(member1).unwrap(); + group2.add_member(member2).unwrap(); + group2.add_member(member3).unwrap(); + + assert_eq!(group1.root(), group2.root()); + assert_eq!(group1.depth(), 2); + assert_eq!(group1.size(), 3); + } - #[test] - fn test_panic_value_is_zero() { - let err = panic::catch_unwind(|| Group::new(vec!["1".to_string(), "0".to_string()])); + #[test] + fn test_create_group_with_zero_member() { + let member1 = [1; 32]; + let zero = [0u8; ELEMENT_SIZE]; - assert!(err.is_err()); - if let Err(err) = err { - if let Some(msg) = err.downcast_ref::() { - assert_eq!(msg, "Failed to add member: value can't be 0"); - } - } - } + let result = Group::new(&[member1, zero]); + + assert!(result.is_err()); + assert_eq!(result, Err(SemaphoreError::EmptyLeaf)); } - #[cfg(test)] - mod add_member { - use crate::group::Group; - use std::panic::{self, AssertUnwindSafe}; + #[test] + fn test_add_member() { + let mut group = Group::default(); + let member = [1; 32]; + group.add_member(member).unwrap(); - #[test] - fn test_add_members() { - let mut group = Group::new(vec![]); - group.add_member("1".to_string()).unwrap(); - assert_eq!(group.size(), 1); + assert_eq!(group.size(), 1); + } - group.add_member("2".to_string()).unwrap(); - assert_eq!(group.size(), 2); - } + #[test] + fn test_add_zero_member() { + let mut group = Group::default(); + let zero = [0u8; ELEMENT_SIZE]; + let result = group.add_member(zero); - #[test] - fn test_panic_value_is_zero() { - let mut group = Group::new(vec![]); - let err = panic::catch_unwind(AssertUnwindSafe(|| { - group.add_member("0".to_string()).unwrap() - })); - - assert!(err.is_err()); - if let Err(err) = err { - if let Some(msg) = err.downcast_ref::() { - assert_eq!(msg, "Failed to add member: value can't be 0"); - } - } - } + assert!(result.is_err()); + assert_eq!(result, Err(SemaphoreError::EmptyLeaf)); } - #[cfg(test)] - mod add_members { - use crate::group::Group; - use std::panic::{self, AssertUnwindSafe}; + #[test] + fn test_add_members() { + let mut group = Group::default(); + let member1 = [1; 32]; + let member2 = [2; 32]; - #[test] - fn test_add_members() { - let mut group = Group::new(vec![]); - group - .add_members(vec!["1".to_string(), "2".to_string()]) - .unwrap(); - assert_eq!(group.size(), 2); - } + group.add_members(vec![member1, member2]).unwrap(); - #[test] - fn test_add_members_in_existing_group() { - let mut group = Group::new(vec!["1".to_string()]); - group - .add_members(vec!["2".to_string(), "3".to_string()]) - .unwrap(); - assert_eq!(group.size(), 3); - } + assert_eq!(group.size(), 2); + } - #[test] - fn test_panic_value_is_zero() { - let mut group = Group::new(vec![]); - let err = panic::catch_unwind(AssertUnwindSafe(|| { - group - .add_members(vec!["1".to_string(), "0".to_string()]) - .unwrap() - })); - - assert!(err.is_err()); - if let Err(err) = err { - if let Some(msg) = err.downcast_ref::() { - assert_eq!(msg, "Failed to add member: value can't be 0"); - } - } - } + #[test] + fn test_add_members_with_zero() { + let mut group = Group::default(); + let member1 = [1; 32]; + let zero = [0u8; ELEMENT_SIZE]; + + let result = group.add_members(vec![member1, zero]); + + assert!(result.is_err()); + assert_eq!(result, Err(SemaphoreError::EmptyLeaf)); } - #[cfg(test)] - mod remove_member { - use crate::group::Group; - use std::panic::{self, AssertUnwindSafe}; + #[test] + fn test_index_of() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); - #[test] - fn test_remove_member() { - let mut group = Group::new(vec![]); - group - .add_members(vec!["1".to_string(), "2".to_string()]) - .unwrap(); + group.add_members(vec![member1, member2]).unwrap(); + let index = group.index_of(member2); - group.remove_member(0).unwrap(); - assert_eq!(group.size(), 2); - assert_eq!(group.members()[0], "0".to_string()) - } + assert_eq!(index, Some(1)); + } - #[test] - fn test_panic_removed_member() { - let mut group = Group::new(vec![]); - group - .add_members(vec!["1".to_string(), "2".to_string()]) - .unwrap(); - group.remove_member(0).unwrap(); - - let err = panic::catch_unwind(AssertUnwindSafe(|| { - group.remove_member(0).unwrap(); - })); - - assert!(err.is_err()); - if let Err(err) = err { - if let Some(msg) = err.downcast_ref::() { - assert_eq!(msg, "Failed to update member: it has been removed"); - } - } - } + #[test] + fn test_update_member() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); + + group.add_members(vec![member1, member2]).unwrap(); + + group.update_member(0, member1).unwrap(); + assert_eq!(group.size(), 2); + + let members = group.members(); + assert_eq!(members[0], member1); } - #[cfg(test)] - mod update_member { - use crate::group::Group; - use std::panic::{self, AssertUnwindSafe}; + #[test] + fn test_update_removed_member() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); - #[test] - fn test_update_member() { - let mut group = Group::new(vec![]); - group - .add_members(vec!["1".to_string(), "2".to_string()]) - .unwrap(); + group.add_members(vec![member1, member2]).unwrap(); + group.remove_member(0).unwrap(); - group.update_member(0, "3".to_string()).unwrap(); - assert_eq!(group.size(), 2); - assert_eq!(group.members()[0], "3".to_string()) - } + let result = group.update_member(0, member1); + assert!(result.is_err()); + assert_eq!(result, Err(SemaphoreError::RemovedMember)); + } - #[test] - fn test_update_member_with_same_value() { - let mut group = Group::new(vec![]); - group - .add_members(vec!["1".to_string(), "2".to_string()]) - .unwrap(); + #[test] + fn test_remove_member() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); - group.update_member(0, "1".to_string()).unwrap(); - assert_eq!(group.size(), 2); - assert_eq!(group.members()[0], "1".to_string()) - } + group.add_members(vec![member1, member2]).unwrap(); + group.remove_member(0).unwrap(); - #[test] - fn test_panic_removed_member() { - let mut group = Group::new(vec![]); - group - .add_members(vec!["1".to_string(), "2".to_string()]) - .unwrap(); - group.remove_member(0).unwrap(); - - let err = panic::catch_unwind(AssertUnwindSafe(|| { - group.update_member(0, "1".to_string()).unwrap(); - })); - - assert!(err.is_err()); - if let Err(err) = err { - if let Some(msg) = err.downcast_ref::() { - assert_eq!(msg, "Failed to update member: it has been removed"); - } - } - } + let members = group.members(); + assert_eq!(members[0], [0u8; ELEMENT_SIZE]); + assert_eq!(group.size(), 2); + } + + #[test] + fn test_remove_member_already_removed() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); + + group.add_members(vec![member1, member2]).unwrap(); + group.remove_member(0).unwrap(); + + let result = group.remove_member(0); + + assert!(result.is_err()); + assert_eq!(result, Err(SemaphoreError::AlreadyRemovedMember)); } #[test] fn test_generate_merkle_proof() { - let group = Group::new(vec!["1".to_string(), "2".to_string()]); - let proof = group.generate_merkle_proof(0).unwrap(); + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); + + group.add_members(vec![member1, member2]).unwrap(); + + let proof = group.generate_proof(0).unwrap(); + assert_eq!(proof.leaf, member1); + } + + #[test] + fn test_verify_proof() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let mut group = Group::default(); + + group.add_members(vec![member1, member2]).unwrap(); + + let proof_0 = group.generate_proof(0).unwrap(); + assert_eq!(Group::verify_proof(&proof_0), true); + + let mut proof_1 = group.generate_proof(1).unwrap(); + assert_eq!(Group::verify_proof(&proof_1), true); + + proof_1.leaf = member1; + assert_eq!(Group::verify_proof(&proof_1), false); + } + + #[cfg(feature = "serde")] + #[test] + fn test_export_import() { + let member1 = [1; 32]; + let member2 = [2; 32]; + let member3 = [3; 32]; + let group = Group::new(&[member1, member2, member3]).unwrap(); + + let json = group.export().unwrap(); + let imported_group = Group::import(&json).unwrap(); - assert_eq!(proof.leaf, "1".to_string()) + assert_eq!(group, imported_group); } } diff --git a/src/identity.rs b/src/identity.rs index 9aa1968..8698b46 100644 --- a/src/identity.rs +++ b/src/identity.rs @@ -1,25 +1,246 @@ -use anyhow::Result; -use ruint::aliases::U256; +//! Identity Module -#[allow(dead_code)] +use crate::{ + baby_jubjub::{BabyJubjubConfig, EdwardsAffine}, + error::SemaphoreError, +}; +use ark_ec::{CurveConfig, CurveGroup, twisted_edwards::TECurveConfig}; +use ark_ed_on_bn254::{Fq, Fr}; +use ark_ff::{BigInteger, PrimeField}; +use blake::Blake; +use light_poseidon::{Poseidon, PoseidonHasher}; +use num_bigint::{BigInt, Sign}; +use std::ops::Mul; + +/// Semaphore identity +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Identity { + /// Private key private_key: Vec, - secret_scalar: U256, - public_key: Vec, - commitment: U256, + /// Secret scalar + secret_scalar: Fr, + /// Public key + public_key: PublicKey, + /// Identity commitment + commitment: Fq, } -#[allow(dead_code)] impl Identity { - fn sign_message(&self, _message: &[u8]) -> Result<()> { - unimplemented!() + /// Creates a new identity from a private key + pub fn new(private_key: &[u8]) -> Self { + // Hash the private key + let secret_scalar = Self::gen_secret_scalar(private_key); + + // Get the public key by multiplying the secret scalar by the base point + let public_key = PublicKey::from_scalar(&secret_scalar); + + // Generate the identity commitment + let commitment = public_key.commitment(); + + Self { + private_key: private_key.to_vec(), + secret_scalar, + public_key, + commitment, + } + } + + /// Returns the private key + pub fn private_key(&self) -> &[u8] { + &self.private_key + } + + /// Returns the secret scalar + pub fn secret_scalar(&self) -> &Fr { + &self.secret_scalar + } + + /// Returns the public key + pub fn public_key(&self) -> &PublicKey { + &self.public_key + } + + /// Returns the identity commitment + pub fn commitment(&self) -> &Fq { + &self.commitment + } + + /// Signs a message + pub fn sign_message(&self, message: &[u8]) -> Result { + if message.len() > 32 { + return Err(SemaphoreError::MessageSizeExceeded(message.len())); + } + + // Hash the private key and prune + let mut priv_key_hash = blake_512(&self.private_key); + priv_key_hash[0] &= 0xF8; + priv_key_hash[31] &= 0x7F; + priv_key_hash[31] |= 0x40; + + // Prepare the message in little-endian format + let mut message_le = message.to_vec(); + message_le.reverse(); + + // Compute ephemeral nonce scalar + let mut k_input = [0u8; 64]; + k_input[..32].copy_from_slice(&priv_key_hash[32..]); + k_input[32..32 + message.len()].copy_from_slice(&message_le); + let k_fr = Fr::from_le_bytes_mod_order(&blake_512(&k_input)); + + // Calculate ephemeral point r = k * base point + let r = BabyJubjubConfig::GENERATOR.mul(k_fr).into_affine(); + + // Compute challenge scalar + let poseidon_inputs = [ + r.x, + r.y, + self.public_key.x(), + self.public_key.y(), + Fq::from_be_bytes_mod_order(message), + ]; + let c_fq = Poseidon::::new_circom(5) + .unwrap() + .hash(&poseidon_inputs) + .unwrap(); + let c_fr = Fr::from_le_bytes_mod_order(&c_fq.into_bigint().to_bytes_le()); + + // Calculate secret scalar (without dividing by cofactor) + let secret_scalar = Fr::from_le_bytes_mod_order(&priv_key_hash[..32]); + + // s = nonce + challenge * secret + let s = k_fr + c_fr * secret_scalar; + + Ok(Signature::new(r, s)) + } + + /// Generates the secret scalar from the private key + fn gen_secret_scalar(private_key: &[u8]) -> Fr { + // Hash the private key + let mut hash = blake_512(private_key); + + // Prune hash + hash[0] &= 0xF8; + hash[31] &= 0x7F; + hash[31] |= 0x40; + + // Use first half of hash and divide by cofactor (equivalent to shifting right by 3 bits) + let shifted: BigInt = BigInt::from_bytes_le(Sign::Plus, &hash[..32]) >> 3; + + Fr::from_le_bytes_mod_order(&shifted.to_bytes_le().1) + } +} + +/// Semaphore public key +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PublicKey { + point: EdwardsAffine, +} + +impl PublicKey { + /// Creates a new public key instance from a point + pub fn from_point(point: EdwardsAffine) -> Self { + Self { point } + } + + /// Creates a new subgroup public key from a scalar + pub fn from_scalar(secret_scalar: &Fr) -> Self { + let point = BabyJubjubConfig::GENERATOR.mul(secret_scalar).into_affine(); + + Self { point } + } + + /// Generates an identity commitment + pub fn commitment(&self) -> Fq { + Poseidon::::new_circom(2) + .unwrap() + .hash(&[self.point.x, self.point.y]) + .unwrap() } - fn verify_signature(_message: &[u8], _signature: &[u8], _public_key: &[u8]) -> Result<()> { - unimplemented!() + /// Returns the public key point in Affine form + pub fn point(&self) -> EdwardsAffine { + self.point } - fn generate_commitment(_public_key: &[u8]) -> Result<()> { - unimplemented!() + /// Returns the x coordinate of the public key point + pub fn x(&self) -> Fq { + self.point.x + } + + /// Returns the y coordinate of the public key point + pub fn y(&self) -> Fq { + self.point.y + } +} + +/// Signature +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Signature { + /// `r` point + pub r: EdwardsAffine, + /// `s` scalar + pub s: Fr, +} + +impl Signature { + /// Creates a new signature from a point and scalar + pub fn new(r: EdwardsAffine, s: Fr) -> Self { + Self { r, s } } + + /// Verifies against a public key and message + pub fn verify(&self, public_key: &PublicKey, message: &[u8]) -> Result<(), SemaphoreError> { + if message.len() > 32 { + return Err(SemaphoreError::MessageSizeExceeded(message.len())); + } + + if !self.r.is_on_curve() { + return Err(SemaphoreError::SignaturePointNotOnCurve); + } + + if !public_key.point().is_on_curve() { + return Err(SemaphoreError::PublicKeyNotOnCurve); + } + + // Compute challenge scalar + let poseidon_inputs = [ + self.r.x, + self.r.y, + public_key.x(), + public_key.y(), + Fq::from_be_bytes_mod_order(message), + ]; + let c_fq = Poseidon::::new_circom(5) + .unwrap() + .hash(&poseidon_inputs) + .unwrap(); + let mut c_fr = Fr::from_le_bytes_mod_order(&c_fq.into_bigint().to_bytes_le()); + + // Multiply challenge scalar by cofactor + c_fr *= Fr::from_be_bytes_mod_order(&[BabyJubjubConfig::COFACTOR[0] as u8]); + + // s * generator + let left = BabyJubjubConfig::GENERATOR.mul(self.s); + + // nonce + challenge * public_key + let right = self.r + public_key.point().mul(c_fr); + + // s * generator = nonce + challenge * public_key + if left != right { + return Err(SemaphoreError::SignatureVerificationFailed); + } + + Ok(()) + } +} + +/// Computes Blake 512 hash +pub fn blake_512(input: &[u8]) -> [u8; 64] { + let mut output = [0u8; 64]; + let mut hasher = Blake::new(512).unwrap(); + + hasher.update(input); + hasher.finalise(&mut output); + + output } diff --git a/src/lib.rs b/src/lib.rs index 172e2cf..03ff399 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,11 @@ +//! Semaphore Rust Implementation +//! +//! Protocol specifications: +//! - https://github.com/zkspecs/zkspecs/tree/main/specs/3 + +pub mod baby_jubjub; +pub mod error; pub mod group; pub mod identity; pub mod proof; - pub mod utils; diff --git a/src/proof.rs b/src/proof.rs index c08bc76..fdc58ba 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -1,3 +1,4 @@ +/* use anyhow::Result; use ruint::aliases::U256; @@ -48,3 +49,4 @@ impl Proof { unimplemented!() } } +*/ diff --git a/tests/group.rs b/tests/group.rs new file mode 100644 index 0000000..cf1963b --- /dev/null +++ b/tests/group.rs @@ -0,0 +1,241 @@ +//! Group module integration tests +//! +//! The constants were generated using the TypeScript Semaphore V4 implementation. +//! +//! - https://github.com/brech1/sem-test-values +//! +//! All byte values are in big endian format. + +// Initial Members Group +const INITIAL_MEMBERS_ROOT_STR: &str = + "9130007428544271791338115123915220727467361888518863494831750410170124565752"; +const INITIAL_MEMBERS: [&str; 3] = [ + "100000000000000000000000000000", + "200000000000000000000000000000", + "300000000000000000000000000000", +]; + +// Add Members Group +const ADD_MEMBERS_ROOT_STR: &str = + "6982876087413765702847094329357954484405070236699469184558186311499667292397"; +const ADDED_MEMBERS: [&str; 2] = [ + "2000000000000000000000000000000", + "20000000000000000000000000000001", +]; + +// Index Lookup Constants +const INDEX_LOOKUP_EXISTING_MEMBER: &str = "200000000000000000000000000000"; +const INDEX_LOOKUP_EXISTING_INDEX: usize = 1; +const INDEX_LOOKUP_NON_EXISTING_MEMBER: &str = "999999999999999999999999999999"; + +// Merkle Proof Constants +const MERKLE_PROOF_ROOT_STR: &str = + "9130007428544271791338115123915220727467361888518863494831750410170124565752"; +const MERKLE_PROOF_LEAF: &str = "100000000000000000000000000000"; +const MERKLE_PROOF_INDEX: usize = 0; +const MERKLE_PROOF_SIBLINGS: [&str; 2] = [ + "200000000000000000000000000000", + "300000000000000000000000000000", +]; +const MERKLE_PROOF_INVALID_INDEX: usize = 999; + +// Update Member Group +const UPDATE_MEMBER_ROOT_STR: &str = + "11698254358747948552441141621532898036199784096354171759939257930719916843614"; +const UPDATE_MEMBER_BEFORE: [&str; 3] = [ + "100000000000000000000000000000", + "200000000000000000000000000000", + "300000000000000000000000000000", +]; +const UPDATE_MEMBER_INDEX: usize = 1; +const UPDATE_NEW_VALUE: &str = "3000000000000000000000000000000"; + +// Sequential Operations Group +const SEQUENTIAL_OPS_ROOT_STR: &str = + "4382838098257486169531967821059829509336344667844562046304959594145268687258"; +const SEQUENTIAL_OPS_INITIAL: [&str; 3] = [ + "100000000000000000000000000000", + "200000000000000000000000000000", + "300000000000000000000000000000", +]; +const SEQUENTIAL_OPS_MEMBERS: [&str; 4] = [ + "100000000000000000000000000000", + "500000000000000000000000000000", + "0", + "400000000000000000000000000000", +]; + +#[cfg(test)] +mod group { + use super::*; + use ark_ed_on_bn254::Fq; + use ark_ff::{BigInteger, PrimeField}; + use num_bigint::BigInt; + use semaphore_rs::group::{EMPTY_ELEMENT, Element, Group}; + use std::str::FromStr; + + fn str_to_element(s: &str) -> Element { + let big_int = BigInt::from_str(s).unwrap(); + let fq = Fq::from_le_bytes_mod_order(&big_int.to_bytes_le().1); + + let mut element = EMPTY_ELEMENT; + + let bytes = fq.into_bigint().to_bytes_le(); + element[..bytes.len()].copy_from_slice(&bytes); + element + } + + fn leaf_to_str(leaf: &[u8]) -> String { + Fq::from_le_bytes_mod_order(leaf).to_string() + } + + #[test] + fn empty_group() { + let group = Group::default(); + + assert_eq!(group.root(), None); + assert_eq!(group.depth(), 0); + assert_eq!(group.size(), 0); + assert_eq!(group.members(), Vec::::new()); + } + + #[test] + fn initial_members() { + let elements: Vec = INITIAL_MEMBERS.iter().map(|s| str_to_element(s)).collect(); + let group = Group::new(&elements).unwrap(); + + let root = group.root().unwrap(); + assert_eq!(leaf_to_str(&root), INITIAL_MEMBERS_ROOT_STR); + assert_eq!(group.depth(), 2); + assert_eq!(group.size(), 3); + + let group_members: Vec = group.members().iter().map(|l| leaf_to_str(l)).collect(); + assert_eq!( + group_members, + INITIAL_MEMBERS + .iter() + .map(|&s| s.to_string()) + .collect::>() + ); + } + + #[test] + fn add_members() { + let mut group = Group::default(); + let elements: Vec = ADDED_MEMBERS.iter().map(|s| str_to_element(s)).collect(); + group.add_members(elements).unwrap(); + + let root = group.root().unwrap(); + assert_eq!(leaf_to_str(&root), ADD_MEMBERS_ROOT_STR); + assert_eq!(group.depth(), 1); + assert_eq!(group.size(), 2); + + let group_members: Vec = group.members().iter().map(|l| leaf_to_str(l)).collect(); + assert_eq!( + group_members, + ADDED_MEMBERS + .iter() + .map(|&s| s.to_string()) + .collect::>() + ); + } + + #[test] + fn index_lookup() { + let elements: Vec = INITIAL_MEMBERS.iter().map(|s| str_to_element(s)).collect(); + let group = Group::new(&elements).unwrap(); + + assert_eq!( + group.index_of(str_to_element(INDEX_LOOKUP_EXISTING_MEMBER)), + Some(INDEX_LOOKUP_EXISTING_INDEX) + ); + assert_eq!( + group.index_of(str_to_element(INDEX_LOOKUP_NON_EXISTING_MEMBER)), + None + ); + } + + #[test] + fn merkle_proof() { + let elements: Vec = INITIAL_MEMBERS.iter().map(|s| str_to_element(s)).collect(); + let group = Group::new(&elements).unwrap(); + + let proof = group.generate_proof(MERKLE_PROOF_INDEX).unwrap(); + + assert_eq!(leaf_to_str(&proof.root), MERKLE_PROOF_ROOT_STR); + assert_eq!(leaf_to_str(&proof.leaf), MERKLE_PROOF_LEAF); + assert_eq!(proof.index, MERKLE_PROOF_INDEX); + + let sibling_strs: Vec = proof.siblings.iter().map(|s| leaf_to_str(s)).collect(); + assert_eq!( + sibling_strs, + MERKLE_PROOF_SIBLINGS + .iter() + .map(|&s| s.to_string()) + .collect::>() + ); + + assert_eq!(Group::verify_proof(&proof), true); + + let mut invalid_proof = proof.clone(); + invalid_proof.leaf = str_to_element(INDEX_LOOKUP_NON_EXISTING_MEMBER); + assert_eq!(Group::verify_proof(&invalid_proof), false); + + assert!(group.generate_proof(MERKLE_PROOF_INVALID_INDEX).is_err()); + } + + #[test] + fn update_member() { + let elements: Vec = UPDATE_MEMBER_BEFORE + .iter() + .map(|s| str_to_element(s)) + .collect(); + let mut group = Group::new(&elements).unwrap(); + + group + .update_member(UPDATE_MEMBER_INDEX, str_to_element(UPDATE_NEW_VALUE)) + .unwrap(); + + let root = group.root().unwrap(); + + assert_eq!(leaf_to_str(&root), UPDATE_MEMBER_ROOT_STR); + assert_eq!( + leaf_to_str(&group.members()[UPDATE_MEMBER_INDEX]), + UPDATE_NEW_VALUE + ); + assert_eq!(group.depth(), 2); + assert_eq!(group.size(), 3); + } + + #[test] + fn sequential_operations() { + let mut group = Group::default(); + let initial_elements: Vec = SEQUENTIAL_OPS_INITIAL + .iter() + .map(|s| str_to_element(s)) + .collect(); + + group.add_members(initial_elements).unwrap(); + group + .add_member(str_to_element("400000000000000000000000000000")) + .unwrap(); + group + .update_member(1, str_to_element("500000000000000000000000000000")) + .unwrap(); + group.remove_member(2).unwrap(); + + let root = group.root().unwrap(); + assert_eq!(leaf_to_str(&root), SEQUENTIAL_OPS_ROOT_STR); + assert_eq!(group.depth(), 2); + assert_eq!(group.size(), 4); + + let group_members: Vec = group.members().iter().map(|l| leaf_to_str(l)).collect(); + assert_eq!( + group_members, + SEQUENTIAL_OPS_MEMBERS + .iter() + .map(|&s| s.to_string()) + .collect::>() + ); + } +} diff --git a/tests/identity.rs b/tests/identity.rs new file mode 100644 index 0000000..09a5efb --- /dev/null +++ b/tests/identity.rs @@ -0,0 +1,201 @@ +//! Identity module integration tests +//! +//! The constants were generated using the typescript Semaphore V4 implementation. +//! +//! - https://github.com/brech1/sem-test-values +//! +//! All byte values are in big endian format. + +// Inputs +const PRIVATE_KEY_BYTES: [u8; 10] = [112, 114, 105, 118, 97, 116, 101, 75, 101, 121]; +const MESSAGE_BYTES: [u8; 7] = [109, 101, 115, 115, 97, 103, 101]; + +// Secret Scalar +const SECRET_SCALAR_STR: &str = + "1319709833472015827730826418408303647941748850729897255051940662182776719635"; +const SECRET_SCALAR_BYTES: [u8; 32] = [ + 2, 234, 237, 230, 80, 122, 153, 195, 63, 142, 196, 130, 148, 129, 61, 227, 71, 127, 38, 235, + 161, 55, 179, 143, 5, 158, 187, 138, 221, 88, 201, 19, +]; + +// Public Key +const PUBLIC_KEY_STR: &str = "(20191161190634177714856258432742391014210684311546132016070244128804840948064, 15209227963454794938053687888234270810990820964270375245744800564428536818120)"; +const PUBLIC_KEY_X_BYTES: [u8; 32] = [ + 44, 163, 202, 208, 199, 57, 16, 211, 82, 180, 59, 227, 30, 252, 212, 244, 251, 255, 228, 174, + 31, 212, 161, 61, 184, 169, 200, 50, 7, 84, 65, 96, +]; +const PUBLIC_KEY_Y_BYTES: [u8; 32] = [ + 33, 160, 30, 51, 23, 176, 120, 182, 143, 13, 107, 115, 65, 222, 145, 126, 149, 154, 43, 209, + 80, 105, 239, 250, 176, 136, 240, 236, 63, 128, 41, 200, +]; + +// Commitment +const COMMITMENT_STR: &str = + "11372478937056182347300323057848769551333725898578571354328589544822167334484"; +const COMMITMENT_BYTES: [u8; 32] = [ + 25, 36, 152, 80, 56, 11, 26, 2, 17, 243, 115, 82, 175, 106, 167, 84, 119, 125, 231, 4, 147, 4, + 199, 208, 152, 164, 217, 145, 36, 212, 110, 84, +]; + +// Signature +const SIGNATURE_R8_STR: &str = "(15692604209546184713306928546008997717398425098370611740032900661941398951046, 9561160056878562889932140991915362529009920711886027675468824242797436205292)"; +const SIGNATURE_R8_X_BYTES: [u8; 32] = [ + 34, 177, 179, 0, 139, 36, 37, 68, 198, 92, 159, 9, 236, 31, 168, 86, 199, 99, 218, 146, 74, + 170, 134, 26, 114, 113, 31, 133, 13, 204, 84, 134, +]; +const SIGNATURE_R8_Y_BYTES: [u8; 32] = [ + 21, 35, 108, 192, 232, 36, 155, 242, 251, 145, 16, 62, 78, 177, 155, 18, 237, 74, 38, 7, 185, + 83, 80, 124, 252, 124, 125, 15, 187, 139, 248, 236, +]; +const SIGNATURE_S_STR: &str = + "463050405688667311380335008913093928239282429722515841444688860881221420599"; +const SIGNATURE_S_BYTES: [u8; 32] = [ + 1, 6, 19, 198, 32, 235, 21, 163, 223, 208, 109, 6, 140, 118, 120, 45, 10, 180, 61, 58, 2, 39, + 62, 249, 210, 16, 126, 67, 124, 237, 134, 55, +]; + +#[cfg(test)] +mod identity { + use super::*; + use ark_ed_on_bn254::{Fq, Fr}; + use ark_ff::{AdditiveGroup, BigInteger, PrimeField}; + use semaphore_rs::{ + baby_jubjub::EdwardsAffine, + error::SemaphoreError, + identity::{Identity, Signature}, + }; + + #[test] + fn secret_scalar() { + let identity = Identity::new(&PRIVATE_KEY_BYTES); + + // Verify Secret Scalar + assert_eq!(SECRET_SCALAR_STR, identity.secret_scalar().to_string()); + assert_eq!( + SECRET_SCALAR_BYTES, + identity + .secret_scalar() + .into_bigint() + .to_bytes_be() + .to_vec() + .as_slice() + ); + } + + #[test] + fn public_key() { + let identity = Identity::new(&PRIVATE_KEY_BYTES); + + // Verify generated public key + assert_eq!(PUBLIC_KEY_STR, identity.public_key().point().to_string()); + assert_eq!( + PUBLIC_KEY_X_BYTES, + identity + .public_key() + .x() + .into_bigint() + .to_bytes_be() + .to_vec() + .as_slice() + ); + assert_eq!( + PUBLIC_KEY_Y_BYTES, + identity + .public_key() + .y() + .into_bigint() + .to_bytes_be() + .to_vec() + .as_slice() + ); + } + + #[test] + fn commitment() { + let identity = Identity::new(&PRIVATE_KEY_BYTES); + + // Verify generated commitment + assert_eq!(COMMITMENT_STR, identity.commitment().to_string()); + assert_eq!( + COMMITMENT_BYTES, + identity.commitment().into_bigint().to_bytes_be().as_slice() + ); + } + + #[test] + fn sign_message() { + let identity = Identity::new(&PRIVATE_KEY_BYTES); + + let signature = identity.sign_message(&MESSAGE_BYTES).unwrap(); + + assert_eq!(SIGNATURE_R8_STR, signature.r.to_string()); + assert_eq!( + SIGNATURE_R8_X_BYTES, + signature.r.x.into_bigint().to_bytes_be().as_slice() + ); + assert_eq!( + SIGNATURE_R8_Y_BYTES, + signature.r.y.into_bigint().to_bytes_be().as_slice() + ); + + assert_eq!(SIGNATURE_S_STR, signature.s.to_string()); + assert_eq!( + SIGNATURE_S_BYTES, + signature.s.into_bigint().to_bytes_be().as_slice() + ); + } + + #[test] + fn verify_signature() { + let identity = Identity::new(&PRIVATE_KEY_BYTES); + let signature = identity.sign_message(&MESSAGE_BYTES).unwrap(); + + assert_eq!( + signature + .verify(identity.public_key(), &MESSAGE_BYTES) + .unwrap(), + () + ); + + let provided_signature = Signature { + r: EdwardsAffine::new_unchecked( + Fq::from_be_bytes_mod_order(&SIGNATURE_R8_X_BYTES), + Fq::from_be_bytes_mod_order(&SIGNATURE_R8_Y_BYTES), + ), + s: Fr::from_be_bytes_mod_order(&SIGNATURE_S_BYTES), + }; + assert_eq!( + provided_signature + .verify(identity.public_key(), &MESSAGE_BYTES) + .unwrap(), + () + ); + + let invalid_message = [0u8; 7]; + assert_eq!( + provided_signature + .verify(identity.public_key(), &invalid_message) + .unwrap_err(), + SemaphoreError::SignatureVerificationFailed + ); + + let long_message = [0u8; 33]; + assert_eq!( + provided_signature + .verify(identity.public_key(), &long_message) + .unwrap_err(), + SemaphoreError::MessageSizeExceeded(33) + ); + + let invalid_signature = Signature { + r: EdwardsAffine::new_unchecked(Fq::ZERO, Fq::ZERO), + s: signature.s, + }; + assert_eq!( + invalid_signature + .verify(identity.public_key(), &MESSAGE_BYTES) + .unwrap_err(), + SemaphoreError::SignaturePointNotOnCurve + ); + } +}