From a6756b2f0e7cb50020a6a77a2666bbbaae74b631 Mon Sep 17 00:00:00 2001 From: Paolo D'Amico Date: Wed, 5 Nov 2025 13:23:08 -0800 Subject: [PATCH 1/2] feat: introduce World ID Authenticator (#114) --- .env.example | 3 +- .github/workflows/ci.yml | 1 + Cargo.lock | 1008 +++++++++++++++-- Cargo.toml | 2 + walletkit-core/Cargo.toml | 14 +- walletkit-core/src/authenticator.rs | 174 +++ walletkit-core/src/common_apps.rs | 13 +- walletkit-core/src/credential_type.rs | 13 +- walletkit-core/src/defaults.rs | 36 + walletkit-core/src/error.rs | 141 ++- walletkit-core/src/lib.rs | 24 +- walletkit-core/src/logger.rs | 7 +- walletkit-core/src/merkle_tree.rs | 41 +- walletkit-core/src/primitives.rs | 47 + walletkit-core/src/proof.rs | 28 +- walletkit-core/src/request.rs | 28 +- walletkit-core/src/u256.rs | 19 +- walletkit-core/src/world_id.rs | 7 +- .../tests/authenticator_integration.rs | 75 ++ walletkit/Cargo.toml | 5 +- walletkit/src/lib.rs | 2 - 21 files changed, 1480 insertions(+), 208 deletions(-) create mode 100644 walletkit-core/src/authenticator.rs create mode 100644 walletkit-core/src/defaults.rs create mode 100644 walletkit-core/src/primitives.rs create mode 100644 walletkit-core/tests/authenticator_integration.rs diff --git a/.env.example b/.env.example index 2c1114532..900d56989 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ -WORLDCHAIN_SEPOLIA_RPC_URL=https://worldchain-sepolia.g.alchemy.com/public # substitute with your own RPC in case of rate limits \ No newline at end of file +WORLDCHAIN_SEPOLIA_RPC_URL=https://worldchain-sepolia.g.alchemy.com/public # substitute with your own RPC in case of rate limits +WORLDCHAIN_RPC_URL=https://worldchain-mainnet.g.alchemy.com/public \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e70976fb2..47ff06597 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,6 +75,7 @@ jobs: - name: Run tests env: WORLDCHAIN_SEPOLIA_RPC_URL: ${{ secrets.WORLDCHAIN_SEPOLIA_RPC_URL || 'https://worldchain-sepolia.g.alchemy.com/public' }} + WORLDCHAIN_RPC_URL: ${{ secrets.WORLDCHAIN_RPC_URL || 'https://worldchain-mainnet.g.alchemy.com/public' }} run: | cargo test --all --all-features diff --git a/Cargo.lock b/Cargo.lock index b40592126..ebf280277 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,9 +61,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.0.30" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e2a5d689ccd182f1d138a61f081841b905034e0089f5278f6c200f2bcdab00a" +checksum = "ae62e633fa48b4190af5e841eb05179841bb8b713945103291e2c0867037c0d1" dependencies = [ "alloy-consensus", "alloy-contract", @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59094911f05dbff1cf5b29046a00ef26452eccc8d47136d50a47c0cf22f00c85" +checksum = "b9b151e38e42f1586a01369ec52a6934702731d07e8509a7307331b09f6c46dc" dependencies = [ "alloy-eips", "alloy-primitives", @@ -118,9 +118,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903cb8f728107ca27c816546f15be38c688df3c381d7bd1a4a9f215effc1ddb4" +checksum = "6e2d5e8668ef6215efdb7dcca6f22277b4e483a5650e05f5de22b2350971f4b8" dependencies = [ "alloy-consensus", "alloy-eips", @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03df5cb3b428ac96b386ad64c11d5c6e87a5505682cf1fbd6f8f773e9eda04f6" +checksum = "630288cf4f3a34a8c6bc75c03dce1dbd47833138f65f37d53a1661eafc96b83f" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "alloy-core" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575053cea24ea8cb7e775e39d5c53c33b19cfd0ca1cf6c0fd653f3d8c682095f" +checksum = "5ca96214615ec8cf3fa2a54b32f486eb49100ca7fe7eb0b8c1137cd316e7250a" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6c2905bafc2df7ccd32ca3af13f0b0d82f2e2ff9dfbeb12196c0d978d5c0deb" +checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -218,9 +218,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac7f1c9a1ccc7f3e03c36976455751a6166a4f0d2d2c530c3f87dfe7d0cdc836" +checksum = "e5434834adaf64fa20a6fb90877bc1d33214c41b055cc49f82189c98614368cc" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -240,9 +240,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1421f6c9d15e5b86afbfe5865ca84dea3b9f77173a0963c1a2ee4e626320ada9" +checksum = "919a8471cfbed7bcd8cf1197a57dda583ce0e10c6385f6ff4e8b41304b223392" dependencies = [ "alloy-eips", "alloy-primitives", @@ -266,9 +266,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2acb6637a9c0e1cdf8971e0ced8f3fa34c04c5e9dccf6bb184f6a64fe0e37d8" +checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -278,9 +278,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f763621707fa09cece30b73ecc607eb43fd7a72451fe3b46f645b905086926" +checksum = "d7c69f6c9c68a1287c9d5ff903d0010726934de0dac10989be37b75a29190d55" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -293,9 +293,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f59a869fa4b4c3a7f08b1c8cb79aec61c29febe6e24a24fe0fcfded8a9b5703" +checksum = "8eaf2ae05219e73e0979cb2cf55612aafbab191d130f203079805eaf881cca58" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -319,9 +319,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e9374c667c95c41177602ebe6f6a2edd455193844f011d973d374b65501b38" +checksum = "e58f4f345cef483eab7374f2b6056973c7419ffe8ad35e994b7a7f5d8e0c7ba4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -332,9 +332,9 @@ dependencies = [ [[package]] name = "alloy-node-bindings" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d392c130f3d4a325c913348351395efb16d197da1d07c2de3a2f7876d9d981ee" +checksum = "61321a0dbc084c2c9f2b07aa34f10db7ac80065c01721e567e5426d882c73de6" dependencies = [ "alloy-genesis", "alloy-hardforks", @@ -353,9 +353,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b77f7d5e60ad8ae6bd2200b8097919712a07a6db622a4b201e7ead6166f02e5" +checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" dependencies = [ "alloy-rlp", "bytes", @@ -381,9 +381,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77818b7348bd5486491a5297579dbfe5f706a81f8e1f5976393025f1e22a7c7d" +checksum = "de2597751539b1cc8fe4204e5325f9a9ed83fcacfb212018dfcfa7877e76de21" dependencies = [ "alloy-chains", "alloy-consensus", @@ -444,9 +444,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2430d5623e428dd012c6c2156ae40b7fe638d6fca255e3244e0fba51fa698e93" +checksum = "edf8eb8be597cfa8c312934d2566ec4516f066d69164f9212d7a148979fdcfd8" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -467,9 +467,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65e3266095e6d8e8028aab5f439c6b8736c5147314f7e606c61597e014cb8a0" +checksum = "83d98fb386a462e143f5efa64350860af39950c49e7c0cbdba419c16793116ef" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -479,9 +479,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07429a1099cd17227abcddb91b5e38c960aaeb02a6967467f5bb561fbe716ac6" +checksum = "fbde0801a32d21c5f111f037bee7e22874836fba7add34ed4a6919932dd7cf23" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -490,9 +490,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db46b0901ee16bbb68d986003c66dcb74a12f9d9b3c44f8e85d51974f2458f0f" +checksum = "361cd87ead4ba7659bda8127902eda92d17fa7ceb18aba1676f7be10f7222487" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -502,7 +502,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", - "itertools 0.13.0", + "itertools 0.14.0", "serde", "serde_json", "serde_with", @@ -511,9 +511,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5413814be7a22fbc81e0f04a2401fcc3eb25e56fd53b04683e8acecc6e1fe01b" +checksum = "64600fc6c312b7e0ba76f73a381059af044f4f21f43e07f51f1fa76c868fe302" dependencies = [ "alloy-primitives", "serde", @@ -522,9 +522,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53410a18a61916e2c073a6519499514e027b01e77eeaf96acd1df7cf96ef6bb2" +checksum = "5772858492b26f780468ae693405f895d6a27dea6e3eab2c36b6217de47c2647" dependencies = [ "alloy-primitives", "async-trait", @@ -537,9 +537,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6006c4cbfa5d08cadec1fcabea6cb56dc585a30a9fce40bcf81e307d6a71c8e" +checksum = "f4195b803d0a992d8dbaab2ca1986fc86533d4bc80967c0cce7668b26ad99ef9" dependencies = [ "alloy-consensus", "alloy-network", @@ -553,9 +553,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c84c3637bee9b5c4a4d2b93360ee16553d299c3b932712353caf1cea76d0e6" +checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a882aa4e1790063362434b9b40d358942b188477ac1c44cfb8a52816ffc0cc17" +checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -586,9 +586,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5772107f9bb265d8d8c86e0733937bb20d0857ea5425b1b6ddf51a9804042" +checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "alloy-json-abi", "const-hex", @@ -604,9 +604,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e188b939aa4793edfaaa099cb1be4e620036a775b4bdf24fdc56f1cd6fd45890" +checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" dependencies = [ "serde", "winnow", @@ -614,9 +614,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c8a9a909872097caffc05df134e5ef2253a1cdb56d3a9cf0052a042ac763f9" +checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -626,9 +626,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d94ee404368a3d9910dfe61b203e888c6b0e151a50e147f95da8baff9f9c7763" +checksum = "025a940182bddaeb594c26fe3728525ae262d0806fe6a4befdf5d7bc13d54bce" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.37" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f8a6338d594f6c6481292215ee8f2fd7b986c80aba23f3f44e761a8658de78" +checksum = "e3b5064d1e1e1aabc918b5954e7fb8154c39e77ec6903a581b973198b26628fa" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -681,11 +681,10 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.37" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64c09ec565a90ed8390d82aa08cd3b22e492321b96cb4a3d4f58414683c9e2f" +checksum = "ab54221eccefa254ce9f65b079c097b1796e48c21c7ce358230f8988d75392fb" dependencies = [ - "alloy-primitives", "darling 0.21.3", "proc-macro2", "quote", @@ -719,22 +718,34 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" dependencies = [ - "ark-ec", + "ark-ec 0.4.2", "ark-ff 0.4.2", "ark-std 0.4.0", ] +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-r1cs-std", + "ark-std 0.5.0", +] + [[package]] name = "ark-crypto-primitives" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3a13b34da09176a8baba701233fdffbaa7c1b1192ce031a3da4e55ce1f1a56" dependencies = [ - "ark-ec", + "ark-ec 0.4.2", "ark-ff 0.4.2", - "ark-relations", + "ark-relations 0.4.0", "ark-serialize 0.4.2", - "ark-snark", + "ark-snark 0.4.0", "ark-std 0.4.0", "blake2", "derivative", @@ -743,6 +754,40 @@ dependencies = [ "sha2", ] +[[package]] +name = "ark-crypto-primitives" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0c292754729c8a190e50414fd1a37093c786c709899f29c9f7daccecfa855e" +dependencies = [ + "ahash", + "ark-crypto-primitives-macros", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-relations 0.5.1", + "ark-serialize 0.5.0", + "ark-snark 0.5.1", + "ark-std 0.5.0", + "blake2", + "derivative", + "digest 0.10.7", + "fnv", + "merlin", + "rayon", + "sha2", +] + +[[package]] +name = "ark-crypto-primitives-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "ark-ec" version = "0.4.2" @@ -750,7 +795,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ "ark-ff 0.4.2", - "ark-poly", + "ark-poly 0.4.2", "ark-serialize 0.4.2", "ark-std 0.4.0", "derivative", @@ -761,6 +806,28 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.3", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "rayon", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.3.0" @@ -800,6 +867,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +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", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "rayon", + "zeroize", +] + [[package]] name = "ark-ff-asm" version = "0.3.0" @@ -820,6 +908,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.101", +] + [[package]] name = "ark-ff-macros" version = "0.3.0" @@ -845,22 +943,51 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "ark-groth16" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20ceafa83848c3e390f1cbf124bc3193b3e639b3f02009e0e290809a501b95fc" dependencies = [ - "ark-crypto-primitives", - "ark-ec", + "ark-crypto-primitives 0.4.0", + "ark-ec 0.4.2", "ark-ff 0.4.2", - "ark-poly", - "ark-relations", + "ark-poly 0.4.2", + "ark-relations 0.4.0", "ark-serialize 0.4.2", "ark-std 0.4.0", "rayon", ] +[[package]] +name = "ark-groth16" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" +dependencies = [ + "ark-crypto-primitives 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-relations 0.5.1", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "rayon", +] + [[package]] name = "ark-poly" version = "0.4.2" @@ -875,6 +1002,39 @@ dependencies = [ "rayon", ] +[[package]] +name = "ark-poly" +version = "0.5.0" +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", + "educe", + "fnv", + "hashbrown 0.15.3", + "rayon", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-relations 0.5.1", + "ark-std 0.5.0", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + [[package]] name = "ark-relations" version = "0.4.0" @@ -887,6 +1047,18 @@ dependencies = [ "tracing-subscriber 0.2.25", ] +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff 0.5.0", + "ark-std 0.5.0", + "tracing", + "tracing-subscriber 0.2.25", +] + [[package]] name = "ark-serialize" version = "0.3.0" @@ -903,12 +1075,26 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "ark-serialize-derive", + "ark-serialize-derive 0.4.2", "ark-std 0.4.0", "digest 0.10.7", "num-bigint", ] +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", + "rayon", +] + [[package]] name = "ark-serialize-derive" version = "0.4.2" @@ -920,6 +1106,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "ark-snark" version = "0.4.0" @@ -927,11 +1124,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84d3cc6833a335bb8a600241889ead68ee89a3cf8448081fb7694c0fe503da63" dependencies = [ "ark-ff 0.4.2", - "ark-relations", + "ark-relations 0.4.0", "ark-serialize 0.4.2", "ark-std 0.4.0", ] +[[package]] +name = "ark-snark" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" +dependencies = [ + "ark-ff 0.5.0", + "ark-relations 0.5.1", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] + [[package]] name = "ark-std" version = "0.3.0" @@ -953,6 +1162,23 @@ dependencies = [ "rayon", ] +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", + "rayon", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + [[package]] name = "arrayvec" version = "0.7.6" @@ -1226,6 +1452,19 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "blake3" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -1383,6 +1622,78 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "circom-types" +version = "0.9.0" +source = "git+https://github.com/TaceoLabs/co-snarks.git#e636308efdf115149d53e05e70b157cfe5babb6c" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "ark-poly 0.5.0", + "ark-relations 0.5.1", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "byteorder", + "num-traits", + "rayon", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "circom-witness-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffb423ecdfea516ad77c12a0a4b6e7a52b42656fe5b31df151ca2abc44545f" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "byteorder", + "cxx", + "cxx-build", + "eyre", + "hex", + "num-bigint", + "num-traits", + "postcard", + "rand 0.8.5", + "ruint", + "serde", + "serde_json", +] + [[package]] name = "clap" version = "4.5.37" @@ -1472,7 +1783,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -1524,6 +1835,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + [[package]] name = "core-foundation" version = "0.9.4" @@ -1623,6 +1940,20 @@ dependencies = [ "typenum", ] +[[package]] +name = "cxx" +version = "1.0.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ecd70e33fb57b5fec1608d572bf8dc382f5385a19529056b32307a29ac329be" +dependencies = [ + "cc", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash 0.2.0", + "link-cplusplus", +] + [[package]] name = "cxx-build" version = "1.0.158" @@ -1637,6 +1968,39 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "cxxbridge-cmd" +version = "1.0.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64320fd0856fdf2421f8404b67d41e91291cbcfa3d57457b390f0a2618ee9a68" +dependencies = [ + "clap", + "codespan-reporting", + "indexmap 2.9.0", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e40964f209961217b972415a8e3a0c23299076a0b2dfe79fa8366b5e5c833e" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51afdec15d8072d1b69f54f645edaf54250088a7e54c4fe493016781278136bd" +dependencies = [ + "indexmap 2.9.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.101", +] + [[package]] name = "darling" version = "0.20.11" @@ -1850,6 +2214,18 @@ dependencies = [ "spki", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "either" version = "1.15.0" @@ -1895,18 +2271,38 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" name = "encoding_rs" version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" dependencies = [ - "cfg-if", + "enum-ordinalize-derive", ] [[package]] -name = "enum-as-inner" -version = "0.6.1" +name = "enum-ordinalize-derive" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ - "heck", "proc-macro2", "quote", "syn 2.0.101", @@ -1925,7 +2321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2186,6 +2582,22 @@ dependencies = [ "scroll", ] +[[package]] +name = "groth16" +version = "0.1.0" +source = "git+https://github.com/TaceoLabs/groth16.git#6529e47b7a9a792cf92425f2a9682ab4d4c433df" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "ark-poly 0.5.0", + "ark-relations 0.5.1", + "eyre", + "num-traits", + "rayon", + "tracing", +] + [[package]] name = "group" version = "0.13.0" @@ -2235,6 +2647,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hash32" version = "0.2.1" @@ -2776,6 +3198,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -2804,6 +3235,7 @@ dependencies = [ "once_cell", "serdect", "sha2", + "signature", ] [[package]] @@ -2843,6 +3275,15 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "link-cplusplus" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82" +dependencies = [ + "cc", +] + [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -2906,6 +3347,15 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.7.4" @@ -2930,6 +3380,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -3026,6 +3488,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -3121,6 +3592,135 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "oprf-client" +version = "0.1.0" +source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +dependencies = [ + "ark-ec 0.5.0", + "eyre", + "futures", + "groth16", + "k256", + "oprf-core", + "oprf-types", + "oprf-world-types", + "oprf-zk 0.1.0 (git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3)", + "rand 0.8.5", + "reqwest 0.12.22", + "serde_json", + "taceo-ark-babyjubjub", + "thiserror 1.0.69", + "tokio", + "tracing", + "uuid", +] + +[[package]] +name = "oprf-core" +version = "0.1.0" +source = "git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c#f71a91c84f3108eaa41dd2fa1bad5411c7323088" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "blake3", + "itertools 0.14.0", + "num-bigint", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "subtle", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "taceo-eddsa-babyjubjub", + "taceo-poseidon2", + "thiserror 2.0.17", + "uuid", + "zeroize", +] + +[[package]] +name = "oprf-types" +version = "0.1.0" +source = "git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c#f71a91c84f3108eaa41dd2fa1bad5411c7323088" +dependencies = [ + "k256", + "oprf-core", + "oprf-zk 0.1.0 (git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c)", + "serde", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "uuid", +] + +[[package]] +name = "oprf-world-types" +version = "0.1.0" +source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +dependencies = [ + "alloy", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "k256", + "oprf-core", + "oprf-zk 0.1.0 (git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3)", + "serde", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "taceo-eddsa-babyjubjub", + "uuid", +] + +[[package]] +name = "oprf-zk" +version = "0.1.0" +source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "circom-types", + "circom-witness-rs", + "eyre", + "groth16", + "hex", + "k256", + "rand 0.8.5", + "reqwest 0.12.22", + "ruint", + "serde", + "serde_json", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "oprf-zk" +version = "0.1.0" +source = "git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c#f71a91c84f3108eaa41dd2fa1bad5411c7323088" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "circom-types", + "eyre", + "groth16", + "hex", + "k256", + "rand 0.8.5", + "reqwest 0.12.22", + "serde", + "serde_json", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "thiserror 2.0.17", + "tracing", + "witness", +] + [[package]] name = "owo-colors" version = "4.2.0" @@ -3406,7 +4006,7 @@ dependencies = [ "once_cell", "socket2 0.5.9", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3677,13 +4277,14 @@ dependencies = [ [[package]] name = "ruint" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecb38f82477f20c5c3d62ef52d7c4e536e38ea9b73fb570a20c5cae0e14bcf6" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", + "ark-ff 0.5.0", "bytemuck", "bytes", "fastrlp 0.3.1", @@ -3698,7 +4299,7 @@ dependencies = [ "rand 0.9.1", "rlp", "ruint-macro", - "serde", + "serde_core", "valuable", "zeroize", ] @@ -3755,7 +4356,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3950,11 +4551,11 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229ccd18b673765be01fcbbef510f03ba35f1a0cad95f286760cdf9a5264cf40" dependencies = [ - "ark-bn254", - "ark-ec", + "ark-bn254 0.4.0", + "ark-ec 0.4.2", "ark-ff 0.4.2", - "ark-groth16", - "ark-relations", + "ark-groth16 0.4.0", + "ark-relations 0.4.0", "ark-std 0.4.0", "bincode", "bytemuck", @@ -3995,12 +4596,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fc71326fe22d96143be74b4bdd4b5dec4f71337243fb15e1f53fd708e4e8c84" dependencies = [ - "ark-bn254", - "ark-crypto-primitives", + "ark-bn254 0.4.0", + "ark-crypto-primitives 0.4.0", "ark-ff 0.4.2", - "ark-groth16", - "ark-poly", - "ark-relations", + "ark-groth16 0.4.0", + "ark-poly 0.4.2", + "ark-relations 0.4.0", "ark-serialize 0.4.2", "ark-std 0.4.0", "byteorder", @@ -4017,11 +4618,11 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a5e446f0ed250f82e84023a30da133a1ffcd7449d7e04e4396e916c5348a63" dependencies = [ - "ark-bn254", - "ark-ec", + "ark-bn254 0.4.0", + "ark-ec 0.4.2", "ark-ff 0.4.2", - "ark-groth16", - "ark-relations", + "ark-groth16 0.4.0", + "ark-relations 0.4.0", "ark-serialize 0.4.2", "color-eyre", "memmap2", @@ -4072,7 +4673,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c50cfcfd95e3df5ecf7cf61df9e8269582c1810db5c2c77259c7d715df1bcfbc" dependencies = [ - "ark-bn254", + "ark-bn254 0.4.0", "ark-ff 0.4.2", "once_cell", "ruint", @@ -4086,9 +4687,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6706eb0b3603d5860d1177c41712d9d384168bd7dc73145b0703f415a3b9dd07" dependencies = [ "alloy-core", - "ark-bn254", - "ark-ec", - "ark-groth16", + "ark-bn254 0.4.0", + "ark-ec 0.4.2", + "ark-groth16 0.4.0", "getrandom 0.2.16", "hex", "lazy_static", @@ -4117,11 +4718,11 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da92fdc680fe3f6dfd7ce46235e65a43005abf0919386d406989a520994d007e" dependencies = [ - "ark-bn254", - "ark-ec", + "ark-bn254 0.4.0", + "ark-ec 0.4.2", "ark-ff 0.4.2", - "ark-groth16", - "ark-relations", + "ark-groth16 0.4.0", + "ark-relations 0.4.0", "ark-std 0.4.0", "bytemuck", "color-eyre", @@ -4158,7 +4759,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b0addf1911b1def31c498ebd53c1a93a556f84e7b2c3eaf2bbee58d1069219" dependencies = [ - "ark-bn254", + "ark-bn254 0.4.0", "ark-ff 0.4.2", "ark-serialize 0.4.2", "byteorder", @@ -4339,6 +4940,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "2.2.0" @@ -4494,9 +5104,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2375c17f6067adc651d8c2c51658019cef32edfff4a982adaf1d7fd1c039f08b" +checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" dependencies = [ "paste", "proc-macro2", @@ -4565,6 +5175,64 @@ dependencies = [ "libc", ] +[[package]] +name = "taceo-ark-babyjubjub" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f404332979db17b044cb8eb92bd471d993ed8713ffb08dc9b3f459414123a499" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "taceo-ark-serde-compat" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "070074111809a0c9344738814302f6271bd79bb38cc1427e889c2b063e66e5e0" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "serde", + "taceo-ark-babyjubjub", + "thiserror 2.0.17", +] + +[[package]] +name = "taceo-eddsa-babyjubjub" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791e41273cc025e07fbca9fcd1d143a3d8cbe3515de8aa6dab91549c9a0af245" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "blake3", + "eyre", + "num-bigint", + "rand 0.8.5", + "serde", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "taceo-poseidon2", + "zeroize", +] + +[[package]] +name = "taceo-poseidon2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5f09fc2f1c68aafd3f544313fe7e34d33b35aa666bc9e6b7a22e94b9833140" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", + "num-bigint", + "num-traits", +] + [[package]] name = "tap" version = "1.0.1" @@ -4581,7 +5249,7 @@ dependencies = [ "getrandom 0.3.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4739,6 +5407,7 @@ dependencies = [ "mio", "parking_lot", "pin-project-lite", + "signal-hook-registry", "slab", "socket2 0.6.0", "tokio-macros", @@ -4927,6 +5596,17 @@ dependencies = [ "tracing-subscriber 0.3.20", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.2.25" @@ -4942,9 +5622,16 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] @@ -5171,6 +5858,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.2", + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -5216,11 +5915,13 @@ version = "0.1.8" dependencies = [ "alloy", "alloy-core", + "alloy-primitives", "chrono", "dotenvy", "hex", "log", "mockito", + "rand 0.8.5", "regex", "reqwest 0.12.22", "ruint", @@ -5234,6 +5935,7 @@ dependencies = [ "tokio", "tokio-test", "uniffi", + "world-id-core", ] [[package]] @@ -5410,7 +6112,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -5663,6 +6365,88 @@ dependencies = [ "bitflags 2.9.0", ] +[[package]] +name = "witness" +version = "0.2.0" +source = "git+https://github.com/TaceoLabs/circom-witness-rs.git?rev=c8ce390#c8ce39065c158a7d58414212e3cc2ac671b1c088" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "byteorder", + "cxx", + "cxx-build", + "eyre", + "hex", + "num-bigint", + "num-traits", + "postcard", + "rand 0.8.5", + "ruint", + "serde", + "serde_json", +] + +[[package]] +name = "world-id-core" +version = "0.1.0" +source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +dependencies = [ + "alloy", + "anyhow", + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "chrono", + "ciborium", + "circom-types", + "eyre", + "groth16", + "hex", + "oprf-client", + "oprf-types", + "oprf-world-types", + "oprf-zk 0.1.0 (git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3)", + "rand 0.8.5", + "reqwest 0.12.22", + "ruint", + "secrecy", + "serde", + "serde_json", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "taceo-eddsa-babyjubjub", + "taceo-poseidon2", + "thiserror 1.0.69", + "tokio", + "tracing", + "tracing-subscriber 0.3.20", + "uuid", + "world-id-primitives", +] + +[[package]] +name = "world-id-primitives" +version = "0.1.0" +source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +dependencies = [ + "alloy-primitives", + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "ark-serialize 0.5.0", + "hex", + "k256", + "ruint", + "serde", + "serde_json", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "taceo-eddsa-babyjubjub", + "thiserror 1.0.69", +] + [[package]] name = "write16" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 328a7ee6c..953d855f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,10 @@ categories = ["api-bindings", "cryptography::cryptocurrencies"] [workspace.dependencies] alloy-core = { version = "1", default-features = false, features = ["sol-types"] } +alloy-primitives = { version = "1", default-features = false } walletkit-core = { version = "0.1.8", path = "walletkit-core", default-features = false } uniffi = { version = "0.29", features = ["build", "tokio"] } +world-id-core = { git = "https://github.com/worldcoin/world-id-protocol", rev = "8041ac3", default-features = false, features = ["authenticator"] } [profile.release] opt-level = 'z' # Optimize for size. diff --git a/walletkit-core/Cargo.toml b/walletkit-core/Cargo.toml index a8a2066d7..afe51674d 100644 --- a/walletkit-core/Cargo.toml +++ b/walletkit-core/Cargo.toml @@ -22,6 +22,7 @@ name = "walletkit_core" [dependencies] alloy-core = { workspace = true } +alloy-primitives = { workspace = true } hex = "0.4" log = "0.4" reqwest = { version = "0.12", default-features = false, features = [ @@ -29,7 +30,7 @@ reqwest = { version = "0.12", default-features = false, features = [ "brotli", "rustls-tls", ] } -ruint = { version = "1", default-features = false, features = [ +ruint = { version = "1.17", default-features = false, features = [ "alloc", "ark-ff-04", ] } @@ -40,7 +41,9 @@ serde_json = "1" strum = { version = "0.27", features = ["derive"] } subtle = "2" thiserror = "2" -uniffi = { workspace = true, optional = true, features = ["build", "tokio"] } +tokio = { version = "1", features = ["sync"] } +uniffi = { workspace = true, features = ["build", "tokio"] } +world-id-core = { workspace = true, optional = true } [dev-dependencies] alloy = { version = "1", default-features = false, features = ["getrandom", "json", "contract", "node-bindings", "signer-local"] } @@ -48,15 +51,16 @@ chrono = "0.4.41" dotenvy = "0.15.7" mockito = "1.6" regex = "1.11" -tokio = "1.47" tokio-test = "0.4" +world-id-core = { workspace = true } +rand = "0.8" [features] -default = ["common-apps", "ffi", "semaphore"] +default = ["common-apps", "semaphore", "v4"] common-apps = [] -ffi = ["dep:uniffi", "semaphore"] http-tests = [] semaphore = ["semaphore-rs/depth_30"] +v4 = ["world-id-core"] # Before conventions were introduced for external nullifiers with `app_id` & `action`, raw field elements were used. # This feature flag adds support to operate with such external nullifiers. diff --git a/walletkit-core/src/authenticator.rs b/walletkit-core/src/authenticator.rs new file mode 100644 index 000000000..6ac83bae8 --- /dev/null +++ b/walletkit-core/src/authenticator.rs @@ -0,0 +1,174 @@ +//! The Authenticator is the main component with which users interact with the World ID Protocol. + +use alloy_primitives::Address; +use world_id_core::{primitives::Config, Authenticator as CoreAuthenticator}; + +use crate::{ + defaults::DefaultConfig, error::WalletKitError, + primitives::ParseFromForeignBinding, Environment, U256Wrapper, +}; + +/// The Authenticator is the main component with which users interact with the World ID Protocol. +#[derive(Debug, uniffi::Object)] +pub struct Authenticator(CoreAuthenticator); + +#[uniffi::export(async_runtime = "tokio")] +impl Authenticator { + /// Initializes a new Authenticator from a seed and with SDK defaults. + /// + /// # Errors + /// See `CoreAuthenticator::init` for potential errors. + #[uniffi::constructor] + pub async fn init_with_defaults( + seed: &[u8], + rpc_url: String, + environment: &Environment, + ) -> Result { + let config = Config::from_environment(environment, rpc_url); + let authenticator = CoreAuthenticator::init(seed, config).await?; + Ok(Self(authenticator)) + } + + /// Initializes a new Authenticator from a seed and config. + /// + /// # Errors + /// Will error if the provided seed is not valid or if the config is not valid. + #[uniffi::constructor] + pub async fn init(seed: &[u8], config: &str) -> Result { + let config = + Config::from_json(config).map_err(|_| WalletKitError::InvalidInput { + attribute: "config".to_string(), + reason: "Invalid config".to_string(), + })?; + let authenticator = CoreAuthenticator::init(seed, config).await?; + Ok(Self(authenticator)) + } + + /// Initializes a new Authenticator from a seed and with SDK defaults. + /// + /// It will create a new account if it doesn't exist. See `CoreAuthenticator::init_or_create_blocking` for more details. + /// + /// # Errors + /// See `CoreAuthenticator::init_or_create_blocking` for potential errors. + #[uniffi::constructor] + pub async fn init_or_create_blocking_with_defaults( + seed: &[u8], + rpc_url: String, + environment: &Environment, + recovery_address: Option, + ) -> Result { + let recovery_address = + Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; + + let config = Config::from_environment(environment, rpc_url); + + let authenticator = + CoreAuthenticator::init_or_create_blocking(seed, config, recovery_address) + .await?; + + Ok(Self(authenticator)) + } + + /// Initializes a new Authenticator from a seed and config and creates a new account with the specified recovery address. + /// + /// It will create a new account if it doesn't exist. See `CoreAuthenticator::init_or_create_blocking` for more details. + /// + /// # Errors + /// See `CoreAuthenticator::init_or_create_blocking` for potential errors. + #[uniffi::constructor] + pub async fn init_or_create_blocking( + seed: &[u8], + config: &str, + recovery_address: Option, + ) -> Result { + let recovery_address = + Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; + + let config = + Config::from_json(config).map_err(|_| WalletKitError::InvalidInput { + attribute: "config".to_string(), + reason: "Invalid config".to_string(), + })?; + + let authenticator = + CoreAuthenticator::init_or_create_blocking(seed, config, recovery_address) + .await?; + + Ok(Self(authenticator)) + } + + /// Returns the full account index for the holder's World ID. + /// + /// The packed account index is a 256 bit integer which includes the user's account index, their recovery counter, + /// and their pubkey id/commitment. + /// + /// # Errors + /// Will error if the provided RPC URL is not valid or if there are RPC call failures. + #[must_use] + pub fn account_id(&self) -> U256Wrapper { + self.0.account_id().into() + } + + /// Returns the Authenticator's `onchain_address`. + /// + /// See `world_id_core::Authenticator::onchain_address` for more details. + #[must_use] + pub fn onchain_address(&self) -> String { + self.0.onchain_address().to_string() + } + + /// Returns the packed account index for the holder's World ID fetching it from the on-chain registry. + /// + /// # Errors + /// Will error if the provided RPC URL is not valid or if there are RPC call failures. + pub async fn get_packed_account_index_remote( + &self, + ) -> Result { + let packed_account_index = CoreAuthenticator::get_packed_account_index( + self.0.onchain_address(), + &self.0.registry(), + ) + .await?; + Ok(packed_account_index.into()) + } +} + +#[cfg(test)] +mod tests { + use alloy::primitives::address; + + use super::*; + + #[tokio::test] + async fn test_init_with_config() { + let mut mock_server = mockito::Server::new_async().await; + + // Mock eth_call to return account data indicating account exists + mock_server + .mock("POST", "/") + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::json!({ + "jsonrpc": "2.0", + "id": 1, + "result": "0x0000000000000000000000000000000000000000000000000000000000000001" + }) + .to_string(), + ) + .create_async() + .await; + + let seed = [2u8; 32]; + let config = Config::new( + mock_server.url(), + address!("0xd66aFbf92d684B4404B1ed3e9aDA85353c178dE2"), + "https://world-id-indexer.stage-crypto.worldcoin.org".to_string(), + "https://world-id-gateway.stage-crypto.worldcoin.org".to_string(), + vec![], + ); + let config = serde_json::to_string(&config).unwrap(); + Authenticator::init(&seed, &config).await.unwrap(); + drop(mock_server); + } +} diff --git a/walletkit-core/src/common_apps.rs b/walletkit-core/src/common_apps.rs index dac2f1d0b..737117302 100644 --- a/walletkit-core/src/common_apps.rs +++ b/walletkit-core/src/common_apps.rs @@ -4,7 +4,6 @@ use { alloy_core::primitives::{Address, U256}, alloy_core::sol_types::SolValue, ruint::uint, - std::str::FromStr, }; /// Allows interacting with the `WorldIDAddressBook` contract. @@ -15,7 +14,7 @@ use { /// /// The contract of the address book can be found at: `0x57b930d551e677cc36e2fa036ae2fe8fdae0330d` #[cfg(feature = "legacy-nullifiers")] -#[cfg_attr(feature = "ffi", derive(uniffi::Object))] +#[derive(uniffi::Object)] pub struct AddressBook {} /// The external nullifier used in the `WorldIDAddressBook` contract. @@ -35,10 +34,10 @@ impl Default for AddressBook { } #[cfg(feature = "legacy-nullifiers")] -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] impl AddressBook { /// Initializes a new `AddressBook` instance. - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] #[must_use] pub const fn new() -> Self { Self {} @@ -55,8 +54,10 @@ impl AddressBook { address_to_verify: &str, timestamp: u64, ) -> Result { - let address_to_verify = Address::from_str(address_to_verify) - .map_err(|_| WalletKitError::InvalidInput)?; + use crate::primitives::ParseFromForeignBinding; + + let address_to_verify = + Address::parse_from_ffi(address_to_verify, "address_to_verify")?; let timestamp = U256::from(timestamp); diff --git a/walletkit-core/src/credential_type.rs b/walletkit-core/src/credential_type.rs index ccb1fefeb..556bcadf6 100644 --- a/walletkit-core/src/credential_type.rs +++ b/walletkit-core/src/credential_type.rs @@ -10,9 +10,18 @@ use crate::Environment; /// /// More details in `https://docs.world.org/world-id/concepts#proof-of-personhood` #[derive( - Debug, Clone, Copy, PartialEq, Eq, EnumString, Hash, Display, Serialize, Deserialize, + Debug, + Clone, + Copy, + PartialEq, + Eq, + EnumString, + Hash, + Display, + Serialize, + Deserialize, + uniffi::Enum, )] -#[cfg_attr(feature = "ffi", derive(uniffi::Enum))] #[strum(serialize_all = "snake_case")] #[serde(rename_all = "snake_case")] pub enum CredentialType { diff --git a/walletkit-core/src/defaults.rs b/walletkit-core/src/defaults.rs new file mode 100644 index 000000000..b521ae72d --- /dev/null +++ b/walletkit-core/src/defaults.rs @@ -0,0 +1,36 @@ +use alloy_primitives::{address, Address}; +use world_id_core::primitives::Config; + +use crate::Environment; + +pub static ACCOUNT_REGISTRY: Address = + address!("0xd66aFbf92d684B4404B1ed3e9aDA85353c178dE2"); + +pub trait DefaultConfig { + fn from_environment(environment: &Environment, rpc_url: String) -> Self; +} + +impl DefaultConfig for Config { + fn from_environment(environment: &Environment, rpc_url: String) -> Self { + // TODO: Add all correct values + match environment { + Environment::Staging => Self::new( + // This always needs to be provided. There is no default. + rpc_url, + ACCOUNT_REGISTRY, + "https://world-id-indexer.stage-crypto.worldcoin.org".to_string(), + "https://world-id-gateway.stage-crypto.worldcoin.org".to_string(), + vec![], + ), + + Environment::Production => Self::new( + // This always needs to be provided. There is no default. + rpc_url, + ACCOUNT_REGISTRY, + "https://world-id-indexer.crypto.worldcoin.org".to_string(), + "https://world-id-gateway.crypto.worldcoin.org".to_string(), + vec![], + ), + } + } +} diff --git a/walletkit-core/src/error.rs b/walletkit-core/src/error.rs index 8438b8d78..bd08db5c2 100644 --- a/walletkit-core/src/error.rs +++ b/walletkit-core/src/error.rs @@ -1,35 +1,148 @@ use thiserror::Error; +#[cfg(feature = "v4")] +use world_id_core::AuthenticatorError; + /// Error outputs from `WalletKit` -#[derive(Debug, Error)] -#[cfg_attr(feature = "ffi", derive(uniffi::Error))] -#[cfg_attr(feature = "ffi", uniffi(flat_error))] +#[derive(Debug, Error, uniffi::Error)] pub enum WalletKitError { - /// The presented input is not valid for the requested operation - #[error("invalid_input")] - InvalidInput, + /// Invalid input provided (e.g., incorrect length, format, etc.) + #[error("invalid_input_{attribute}")] + InvalidInput { + /// The attribute that is invalid + attribute: String, + /// The reason the input is invalid + reason: String, + }, + /// The presented data is not a valid U256 integer #[error("invalid_number")] InvalidNumber, + /// Unexpected error serializing information - #[error("serialization_error: {0}")] - SerializationError(String), + #[error("serialization_error")] + SerializationError { + /// The error message from the serialization + error: String, + }, + /// Network connection error with details - #[error("network_error: {0}")] - NetworkError(String), + #[error("network_error at {url}: {error}")] + NetworkError { + /// The URL of the request + url: String, + /// The error message from the request + error: String, + /// The HTTP status code of the request, if available + status: Option, + }, + /// HTTP request failure - #[error(transparent)] - Reqwest(#[from] reqwest::Error), + #[error("request_error")] + Reqwest { + /// The error message from the request + error: String, + }, + /// Unhandled error generating a Zero-Knowledge Proof - #[error(transparent)] - ProofGeneration(#[from] semaphore_rs::protocol::ProofError), + #[error("proof_generation_error")] + ProofGeneration { + /// The error message from the proof generation + error: String, + }, + /// The `semaphore` feature flag is not enabled #[error("semaphore_not_enabled")] SemaphoreNotEnabled, + /// The requested credential is not issued for this World ID #[error("credential_not_issued")] CredentialNotIssued, + /// The requested credential has not been submitted on-chain #[error("credential_not_mined")] CredentialNotMined, + + /// This operation requires a registered account and an account is not registered + /// for this authenticator. Call `create_account` first to register it. + #[error("Account is not registered for this authenticator.")] + AccountDoesNotExist, + + /// The account already exists for this authenticator. Call `account_index` to get the account index. + #[error("Account already exists for this authenticator.")] + AccountAlreadyExists, + + /// The public key was not found in the batch, i.e. the authenticator is not authorized to sign for this action + #[error("unauthorized_authenticator")] + UnauthorizedAuthenticator, + + /// An unexpected error occurred with the Authenticator + #[error("unexpected_authenticator_error")] + AuthenticatorError { + /// The error message from the authenticator + error: String, + }, + + /// An unexpected error occurred + #[error("unexpected_error: {error}")] + Generic { + /// The details of the error + error: String, + }, +} + +impl From for WalletKitError { + fn from(error: reqwest::Error) -> Self { + Self::Reqwest { + error: error.to_string(), + } + } +} + +impl From for WalletKitError { + fn from(error: semaphore_rs::protocol::ProofError) -> Self { + Self::ProofGeneration { + error: error.to_string(), + } + } +} + +#[cfg(feature = "v4")] +impl From for WalletKitError { + fn from(error: AuthenticatorError) -> Self { + match error { + AuthenticatorError::AccountDoesNotExist => Self::AccountDoesNotExist, + AuthenticatorError::AccountAlreadyExists => Self::AccountAlreadyExists, + + AuthenticatorError::NetworkError(error) => Self::NetworkError { + url: error + .url() + .map(std::string::ToString::to_string) + .unwrap_or_default(), + error: error.to_string(), + status: None, + }, + AuthenticatorError::PublicKeyNotFound => Self::UnauthorizedAuthenticator, + AuthenticatorError::GatewayError { status, body } => Self::NetworkError { + url: "gateway".to_string(), + error: body, + status: Some(status), + }, + AuthenticatorError::PrimitiveError(error) => { + use world_id_core::primitives::PrimitiveError; + match error { + PrimitiveError::InvalidInput { attribute, reason } => { + Self::InvalidInput { attribute, reason } + } + _ => Self::Generic { + error: error.to_string(), + }, + } + } + + _ => Self::AuthenticatorError { + error: error.to_string(), + }, + } + } } diff --git a/walletkit-core/src/lib.rs b/walletkit-core/src/lib.rs index ebbf593c0..759a97d59 100644 --- a/walletkit-core/src/lib.rs +++ b/walletkit-core/src/lib.rs @@ -26,8 +26,7 @@ use strum::EnumString; /// Each environment uses different sources of truth for the World ID credentials. /// /// More information on testing for the World ID Protocol can be found in: `https://docs.world.org/world-id/quick-start/testing` -#[derive(Debug, Clone, PartialEq, Eq, EnumString)] -#[cfg_attr(feature = "ffi", derive(uniffi::Enum))] +#[derive(Debug, Clone, PartialEq, Eq, EnumString, uniffi::Enum)] #[strum(serialize_all = "lowercase")] pub enum Environment { /// For testing purposes ONLY. @@ -36,6 +35,8 @@ pub enum Environment { Production, } +pub(crate) mod primitives; + mod credential_type; pub use credential_type::CredentialType; @@ -45,6 +46,21 @@ pub mod error; /// Contains logging functionality that can be integrated with foreign language bindings. pub mod logger; +mod u256; +pub use u256::U256Wrapper; + +#[cfg(feature = "v4")] +mod authenticator; +#[cfg(feature = "v4")] +pub use authenticator::Authenticator; + +#[cfg(feature = "v4")] +pub(crate) mod defaults; + +//////////////////////////////////////////////////////////////////////////////// +// Legacy modules +//////////////////////////////////////////////////////////////////////////////// + /// Contains all components to interact and use a World ID pub mod world_id; @@ -55,9 +71,6 @@ pub mod proof; #[cfg(feature = "common-apps")] pub mod common_apps; -mod u256; -pub use u256::U256Wrapper; - //////////////////////////////////////////////////////////////////////////////// // Private modules //////////////////////////////////////////////////////////////////////////////// @@ -65,5 +78,4 @@ pub use u256::U256Wrapper; mod merkle_tree; mod request; -#[cfg(feature = "ffi")] uniffi::setup_scaffolding!("walletkit_core"); diff --git a/walletkit-core/src/logger.rs b/walletkit-core/src/logger.rs index 8066c20e2..45d3e1883 100644 --- a/walletkit-core/src/logger.rs +++ b/walletkit-core/src/logger.rs @@ -42,7 +42,7 @@ use std::sync::{Arc, OnceLock}; /// ```swift /// setupWalletKitLogger() // Call this only once!!! /// ``` -#[cfg_attr(feature = "ffi", uniffi::export(with_foreign))] +#[uniffi::export(with_foreign)] pub trait Logger: Sync + Send { /// Logs a message at the specified log level. /// @@ -56,8 +56,7 @@ pub trait Logger: Sync + Send { /// Enumeration of possible log levels. /// /// This enum represents the severity levels that can be used when logging messages. -#[derive(Debug, Clone)] -#[cfg_attr(feature = "ffi", derive(uniffi::Enum))] +#[derive(Debug, Clone, uniffi::Enum)] pub enum LogLevel { /// Designates very low priority, often extremely detailed messages. Trace, @@ -171,7 +170,7 @@ static LOGGER_INSTANCE: OnceLock> = OnceLock::new(); /// # Note /// /// If the logger has already been set, this function will print a message and do nothing. -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] pub fn set_logger(logger: Arc) { match LOGGER_INSTANCE.set(logger) { Ok(()) => (), diff --git a/walletkit-core/src/merkle_tree.rs b/walletkit-core/src/merkle_tree.rs index ff50b022c..510dc74d5 100644 --- a/walletkit-core/src/merkle_tree.rs +++ b/walletkit-core/src/merkle_tree.rs @@ -20,8 +20,7 @@ struct InclusionProofResponse { const CREDENTIAL_NOT_ISSUED_RESPONSE: &str = "provided identity commitment not found"; const MINED_STATUS: &str = "mined"; // https://github.com/worldcoin/signup-sequencer/blob/f6050fbb3131ee6a61b2f44db3813f9150a045f5/schemas/openapi.yaml#L163 -#[derive(Debug)] -#[cfg_attr(feature = "ffi", derive(uniffi::Object))] +#[derive(Debug, uniffi::Object)] #[allow(clippy::module_name_repetitions)] pub struct MerkleTreeProof { poseidon_proof: Proof, @@ -36,14 +35,14 @@ impl MerkleTreeProof { } } -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] impl MerkleTreeProof { /// Retrieves a Merkle inclusion proof from the sign up sequencer for a given identity commitment. /// Each credential/environment pair uses a different sign up sequencer. /// /// # Errors /// Will throw an error if the request fails or parsing the response fails. - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub async fn from_identity_commitment( identity_commitment: &U256Wrapper, sequencer_host: &str, @@ -65,9 +64,9 @@ impl MerkleTreeProof { let response_text = match http_response.text().await { Ok(text) => text, Err(err) => { - return Err(WalletKitError::SerializationError( - format!("[MerkleTreeProof] Failed to read response body from {url} with status {status}: {err}") - )); + return Err(WalletKitError::SerializationError { error: format!( + "[MerkleTreeProof] Failed to read response body from {url} with status {status}: {err}" + ) }); } }; @@ -88,26 +87,34 @@ impl MerkleTreeProof { } Err(parse_err) => { // Return a more detailed error with first 20 characters of the response (only 20 to avoid logging something sensitive) - Err(WalletKitError::SerializationError(format!( - "[MerkleTreeProof] Failed to parse response from {url} with status {status}: {parse_err}, received: {}", - response_text.chars().take(20).collect::() - ))) + Err(WalletKitError::SerializationError { error: format!( + "[MerkleTreeProof] Failed to parse response from {url} with status {status}: {parse_err}, received: {}", + response_text.chars().take(20).collect::() + ), + }) } } } - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn from_json_proof( json_proof: &str, merkle_root: &str, ) -> Result { - let proof: Proof = serde_json::from_str(json_proof) - .map_err(|_| WalletKitError::InvalidInput)?; + let proof: Proof = serde_json::from_str(json_proof).map_err(|_| { + WalletKitError::SerializationError { + error: "Failed to parse JSON proof".to_string(), + } + })?; Ok(Self { poseidon_proof: proof, - merkle_root: U256Wrapper::try_from_hex_string(merkle_root) - .map_err(|_| WalletKitError::InvalidInput)?, + merkle_root: U256Wrapper::try_from_hex_string(merkle_root).map_err( + |_| WalletKitError::InvalidInput { + attribute: "merkle_root".to_string(), + reason: "Invalid hex encoded number".to_string(), + }, + )?, }) } } @@ -181,7 +188,7 @@ mod tests { assert!(result.is_err()); if let Err(err) = result { match err { - WalletKitError::SerializationError(msg) => { + WalletKitError::SerializationError { error: msg } => { assert!(msg.contains("with status 404")); assert!(msg.contains(&url)); } diff --git a/walletkit-core/src/primitives.rs b/walletkit-core/src/primitives.rs new file mode 100644 index 000000000..a5e2cb24d --- /dev/null +++ b/walletkit-core/src/primitives.rs @@ -0,0 +1,47 @@ +use alloy_primitives::Address; +use std::str::FromStr; + +use crate::error::WalletKitError; + +/// A trait for parsing primitive types from foreign bindings. +/// +/// This trait is used to parse primitive types from foreign provided values. For example, parsing +/// a stringified address into an `Address` type. +/// +/// # Examples +/// ```rust,ignore +/// let address = Address::parse_from_ffi("0x1234567890abcdef", "address"); +/// ``` +/// +/// # Errors +/// - `PrimitiveError::InvalidInput` if the provided string is not a valid address. +#[allow(dead_code)] +pub trait ParseFromForeignBinding { + fn parse_from_ffi(s: &str, attr: &'static str) -> Result + where + Self: Sized; + fn parse_from_ffi_optional( + s: Option, + attr: &'static str, + ) -> Result, WalletKitError> + where + Self: Sized; +} + +impl ParseFromForeignBinding for Address { + fn parse_from_ffi(s: &str, attr: &'static str) -> Result { + Self::from_str(s).map_err(|e| WalletKitError::InvalidInput { + attribute: attr.to_string(), + reason: e.to_string(), + }) + } + fn parse_from_ffi_optional( + s: Option, + attr: &'static str, + ) -> Result, WalletKitError> { + if let Some(s) = s { + return Self::parse_from_ffi(s.as_str(), attr).map(Some); + } + Ok(None) + } +} diff --git a/walletkit-core/src/proof.rs b/walletkit-core/src/proof.rs index 0b5c0aabb..1199b05cc 100644 --- a/walletkit-core/src/proof.rs +++ b/walletkit-core/src/proof.rs @@ -20,8 +20,7 @@ use crate::{ /// It is required to generate a `Proof` and will generally be initialized from an `app_id` and `action`. /// /// Note on naming: `ProofContext` is used to make it clear in FFIs which may not respect the module structure. -#[derive(Clone, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "ffi", derive(uniffi::Object))] +#[derive(Clone, PartialEq, Eq, Debug, uniffi::Object)] pub struct ProofContext { /// The `external_nullifier` is the computed result of a specific context for which a World ID Proof is generated. /// It is used in the Sempahore ZK circuit and in the computation of the `nullifier_hash` to guarantee uniqueness in a privacy-preserving way. @@ -35,7 +34,7 @@ pub struct ProofContext { pub require_mined_proof: bool, } -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] impl ProofContext { /// Initializes a `ProofContext`. /// @@ -53,7 +52,7 @@ impl ProofContext { /// * `credential_type` - The type of credential being requested. /// #[must_use] - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn new( app_id: &str, action: Option, @@ -79,7 +78,7 @@ impl ProofContext { /// See `ProofContext::new` for reference. The `action` and `signal` need to be provided as raw bytes. /// #[must_use] - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] #[allow(clippy::needless_pass_by_value)] pub fn new_from_bytes( app_id: &str, @@ -117,7 +116,7 @@ impl ProofContext { /// # Errors /// /// - Returns an error if the signal is not a valid number in the field. - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn new_from_signal_hash( app_id: &str, action: Option>, @@ -180,7 +179,7 @@ impl ProofContext { } } -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] #[cfg(feature = "legacy-nullifiers")] impl ProofContext { /// LEGACY AND ADVANCED USE ONLY. @@ -200,7 +199,7 @@ impl ProofContext { /// * `credential_type` - The type of credential being requested. /// * `signal` - Optional. The signal is included in the ZKP and is committed to in the proof. #[must_use] - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn legacy_new_from_pre_image_external_nullifier( external_nullifier: &[u8], credential_type: CredentialType, @@ -236,7 +235,7 @@ impl ProofContext { /// # Errors /// /// - Returns an error if the external nullifier is not a valid number in the field. - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn legacy_new_from_raw_external_nullifier( external_nullifier: &U256Wrapper, credential_type: CredentialType, @@ -262,8 +261,7 @@ impl ProofContext { /// For on-chain verification, the `proof` (which is packed) should generally be deserialized into `uint256[8]`. /// /// More information on: [On-Chain Verification](https://docs.world.org/world-id/id/on-chain) -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -#[cfg_attr(feature = "ffi", derive(uniffi::Object))] +#[derive(Clone, PartialEq, Eq, Debug, Serialize, uniffi::Object)] #[allow(clippy::module_name_repetitions)] pub struct ProofOutput { /// The root hash of the Merkle tree used to prove membership. This root hash should match published hashes in the World ID @@ -282,17 +280,15 @@ pub struct ProofOutput { pub credential_type: CredentialType, } -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] impl ProofOutput { /// Converts the entire proof output to a JSON string with standard attribute names. /// /// # Errors /// Will error if serialization fails. pub fn to_json(&self) -> Result { - serde_json::to_string(self).map_err(|e| { - WalletKitError::SerializationError(format!( - "Failed to serialize proof: {e}" - )) + serde_json::to_string(self).map_err(|e| WalletKitError::SerializationError { + error: format!("Failed to serialize proof: {e}"), }) } diff --git a/walletkit-core/src/request.rs b/walletkit-core/src/request.rs index 7d1034e50..94a19cf14 100644 --- a/walletkit-core/src/request.rs +++ b/walletkit-core/src/request.rs @@ -59,9 +59,13 @@ impl Request { // Retry on 429 and 5xx if status == 429 || (500..600).contains(&status) { if attempt >= self.max_retries { - return Err(WalletKitError::NetworkError(format!( - "request to {url} failed with status {status} after retries" - ))); + return Err(WalletKitError::NetworkError { + url, + status: Some(status), + error: format!( + "request error with bad status code {status}" + ), + }); } attempt += 1; // No sleep to keep runtime-agnostic @@ -74,16 +78,22 @@ impl Request { // Retry on timeouts/connect errors if err.is_timeout() || err.is_connect() { if attempt >= self.max_retries { - return Err(WalletKitError::NetworkError(format!( - "request to {url} failed after retries: {err}" - ))); + return Err(WalletKitError::NetworkError { + url, + status: None, + error: format!( + "request timeout/connect error after all retries: {err}" + ), + }); } attempt += 1; continue; } - return Err(WalletKitError::NetworkError(format!( - "request to {url} failed: {err}" - ))); + return Err(WalletKitError::NetworkError { + url, + status: None, + error: format!("request failed after all retries: {err}"), + }); } } } diff --git a/walletkit-core/src/u256.rs b/walletkit-core/src/u256.rs index 55861cfc0..7293a91d9 100644 --- a/walletkit-core/src/u256.rs +++ b/walletkit-core/src/u256.rs @@ -13,11 +13,10 @@ use serde::{Deserialize, Serialize}; /// Particularly, when sending proof inputs/outputs as JSON on HTTP requests, the values SHOULD /// be represented as padded hex strings from Big Endian bytes. #[allow(clippy::module_name_repetitions)] -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "ffi", derive(uniffi::Object))] +#[derive(Debug, PartialEq, Eq, Clone, Copy, uniffi::Object)] pub struct U256Wrapper(pub U256); -#[cfg_attr(feature = "ffi", uniffi::export)] +#[uniffi::export] impl U256Wrapper { /// Outputs a hex string representation of the `U256` value padded to 32 bytes (plus two bytes for the `0x` prefix). #[must_use] @@ -25,11 +24,17 @@ impl U256Wrapper { format!("{:#066x}", self.0) } + /// Outputs the decimal string representation of the `U256` value. + #[must_use] + pub fn to_decimal_string(&self) -> String { + self.0.to_string() + } + /// Attempts to parse a hex string as a `U256` value (wrapped). /// /// # Errors /// Will return an `Error::InvalidNumber` if the input is not a valid hex-string-presented number up to 256 bits. - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn try_from_hex_string(hex_string: &str) -> Result { let hex_string = hex_string.trim().trim_start_matches("0x"); @@ -43,7 +48,7 @@ impl U256Wrapper { /// /// Logically this will only support values up to 64 bits. For larger values a different initialization should be used. #[must_use] - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn from_u64(value: u64) -> Self { Self(U256::from(value)) } @@ -52,7 +57,7 @@ impl U256Wrapper { /// /// Logically this will only support values up to 32 bits. For larger values a different initialization should be used. #[must_use] - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn from_u32(value: u32) -> Self { Self(U256::from(value)) } @@ -64,7 +69,7 @@ impl U256Wrapper { /// # Errors /// /// Will return an `Error::InvalidNumber` if the input is not a valid `U256` value. - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn from_limbs(limbs: Vec) -> Result { let limbs = limbs .try_into() diff --git a/walletkit-core/src/world_id.rs b/walletkit-core/src/world_id.rs index 0f409e909..f6a694c91 100644 --- a/walletkit-core/src/world_id.rs +++ b/walletkit-core/src/world_id.rs @@ -15,8 +15,7 @@ use crate::{ /// A base World ID identity which can be used to generate World ID Proofs for different credentials. /// /// Most essential primitive for World ID. -#[derive(Debug)] -#[cfg_attr(feature = "ffi", derive(uniffi::Object))] +#[derive(Debug, uniffi::Object)] pub struct WorldId { /// The hashed hex-encoded World ID secret (32 byte secret -> 64 byte hex-encoded) /// Note: we need to store this hex-encoded because `semaphore-rs` performs operations on it hex-encoded. Can be improved in the future. @@ -25,11 +24,11 @@ pub struct WorldId { environment: Environment, } -#[cfg_attr(feature = "ffi", uniffi::export(async_runtime = "tokio"))] +#[uniffi::export(async_runtime = "tokio")] impl WorldId { /// Initializes a new `Identity` from a World ID secret. The identity is initialized for a specific environment. #[must_use] - #[cfg_attr(feature = "ffi", uniffi::constructor)] + #[uniffi::constructor] pub fn new(secret: &[u8], environment: &Environment) -> Self { let hashed_secret_hex: SecretBox<[u8; 64]> = SecretBox::init_with(|| seed_hex(secret)); diff --git a/walletkit-core/tests/authenticator_integration.rs b/walletkit-core/tests/authenticator_integration.rs new file mode 100644 index 000000000..3e9749583 --- /dev/null +++ b/walletkit-core/tests/authenticator_integration.rs @@ -0,0 +1,75 @@ +use alloy::node_bindings::AnvilInstance; +use alloy::primitives::{address, U256}; +use alloy::providers::ProviderBuilder; +use alloy::signers::local::PrivateKeySigner; +use walletkit_core::error::WalletKitError; +use walletkit_core::{Authenticator, Environment}; +use world_id_core::account_registry::AccountRegistry; + +const ACCOUNT_REGISTRY: alloy::primitives::Address = + address!("0xd66aFbf92d684B4404B1ed3e9aDA85353c178dE2"); + +fn setup_anvil() -> AnvilInstance { + dotenvy::dotenv().ok(); + let rpc_url = std::env::var("WORLDCHAIN_RPC_URL").expect( + "WORLDCHAIN_RPC_URL not set. Copy .env.example to .env and add your RPC URL", + ); + + let anvil = alloy::node_bindings::Anvil::new().fork(rpc_url).spawn(); + println!( + "✓ Anvil started for World Chain Mainnet at: {}", + anvil.endpoint() + ); + anvil +} + +#[tokio::test] +async fn test_authenticator_integration() { + let anvil = setup_anvil(); + + let authenticator_seeder = PrivateKeySigner::random(); + + // When account doesn't exist, this should fail + let authenticator = Authenticator::init_with_defaults( + authenticator_seeder.to_bytes().as_slice(), + anvil.endpoint(), + &Environment::Staging, + ) + .await + .unwrap_err(); + assert!(matches!(authenticator, WalletKitError::AccountDoesNotExist)); + + // We don't create the account with the internal to avoid having to mock the gateway, + // we simply call the createAccount function directly on the AccountRegistry + + let signer: PrivateKeySigner = anvil.keys()[0].clone().into(); + let provider = ProviderBuilder::new() + .wallet(signer) + .connect_http(anvil.endpoint_url()); + + let registry = AccountRegistry::new(ACCOUNT_REGISTRY, &provider); + + let tx = registry + .createAccount( + address!("0x0000000000000000000000000000000000000001"), // recovery address + vec![authenticator_seeder.address()], + vec![U256::from(1)], // pubkeys + U256::from(1), // commitment + ) + .send() + .await + .unwrap(); + + tx.get_receipt().await.unwrap(); + + // now the authenticator exists + let authenticator = Authenticator::init_with_defaults( + authenticator_seeder.to_bytes().as_slice(), + anvil.endpoint(), + &Environment::Staging, + ) + .await + .unwrap(); + let account_id = authenticator.account_id(); + println!("Created World ID with account ID: {account_id:?}",); +} diff --git a/walletkit/Cargo.toml b/walletkit/Cargo.toml index d77487c2c..f26a66f8d 100644 --- a/walletkit/Cargo.toml +++ b/walletkit/Cargo.toml @@ -20,14 +20,13 @@ crate-type = ["lib", "staticlib", "cdylib"] name = "walletkit" [dependencies] -uniffi = { workspace = true, features = ["build", "tokio"], optional = true } +uniffi = { workspace = true, features = ["build", "tokio"] } walletkit-core = { workspace = true } [features] -default = ["ffi", "semaphore"] +default = ["semaphore"] semaphore = ["walletkit-core/semaphore"] -ffi = ["dep:uniffi", "semaphore", "walletkit-core/ffi"] [package.metadata.docs.rs] no-default-features = true \ No newline at end of file diff --git a/walletkit/src/lib.rs b/walletkit/src/lib.rs index 9442bf867..ac11e2805 100644 --- a/walletkit/src/lib.rs +++ b/walletkit/src/lib.rs @@ -8,10 +8,8 @@ #![doc = include_str!("../README.md")] extern crate walletkit_core; -#[cfg(feature = "ffi")] walletkit_core::uniffi_reexport_scaffolding!(); pub use walletkit_core::*; -#[cfg(feature = "ffi")] uniffi::setup_scaffolding!("walletkit"); From 8a9ceb2cd889c7fb1c477aef291db502173623f4 Mon Sep 17 00:00:00 2001 From: Paolo D'Amico Date: Sun, 23 Nov 2025 23:06:10 -0800 Subject: [PATCH 2/2] feat: use world-id-core from crates.io (#119) --- Cargo.lock | 395 ++++++++---------- Cargo.toml | 2 +- walletkit-core/src/authenticator.rs | 20 +- walletkit-core/src/defaults.rs | 37 +- .../tests/authenticator_integration.rs | 4 +- 5 files changed, 218 insertions(+), 240 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebf280277..790bf946d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1649,33 +1649,11 @@ dependencies = [ "half", ] -[[package]] -name = "circom-types" -version = "0.9.0" -source = "git+https://github.com/TaceoLabs/co-snarks.git#e636308efdf115149d53e05e70b157cfe5babb6c" -dependencies = [ - "ark-bn254 0.5.0", - "ark-ec 0.5.0", - "ark-ff 0.5.0", - "ark-groth16 0.5.0", - "ark-poly 0.5.0", - "ark-relations 0.5.1", - "ark-serialize 0.5.0", - "ark-std 0.5.0", - "byteorder", - "num-traits", - "rayon", - "serde", - "serde_json", - "thiserror 2.0.17", - "tracing", -] - [[package]] name = "circom-witness-rs" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ffb423ecdfea516ad77c12a0a4b6e7a52b42656fe5b31df151ca2abc44545f" +checksum = "ef3c1ad2fd98272ce36f3db32543dbeec6497e04c5e71640602e1cda1698c318" dependencies = [ "ark-bn254 0.5.0", "ark-ff 0.5.0", @@ -1783,7 +1761,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -2093,6 +2071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] @@ -2247,6 +2226,7 @@ dependencies = [ "ff", "generic-array", "group", + "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", @@ -2321,7 +2301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2582,22 +2562,6 @@ dependencies = [ "scroll", ] -[[package]] -name = "groth16" -version = "0.1.0" -source = "git+https://github.com/TaceoLabs/groth16.git#6529e47b7a9a792cf92425f2a9682ab4d4c433df" -dependencies = [ - "ark-ec 0.5.0", - "ark-ff 0.5.0", - "ark-groth16 0.5.0", - "ark-poly 0.5.0", - "ark-relations 0.5.1", - "eyre", - "num-traits", - "rayon", - "tracing", -] - [[package]] name = "group" version = "0.13.0" @@ -3592,135 +3556,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "oprf-client" -version = "0.1.0" -source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" -dependencies = [ - "ark-ec 0.5.0", - "eyre", - "futures", - "groth16", - "k256", - "oprf-core", - "oprf-types", - "oprf-world-types", - "oprf-zk 0.1.0 (git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3)", - "rand 0.8.5", - "reqwest 0.12.22", - "serde_json", - "taceo-ark-babyjubjub", - "thiserror 1.0.69", - "tokio", - "tracing", - "uuid", -] - -[[package]] -name = "oprf-core" -version = "0.1.0" -source = "git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c#f71a91c84f3108eaa41dd2fa1bad5411c7323088" -dependencies = [ - "ark-ec 0.5.0", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "blake3", - "itertools 0.14.0", - "num-bigint", - "rand 0.8.5", - "rand_chacha 0.3.1", - "serde", - "subtle", - "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "taceo-eddsa-babyjubjub", - "taceo-poseidon2", - "thiserror 2.0.17", - "uuid", - "zeroize", -] - -[[package]] -name = "oprf-types" -version = "0.1.0" -source = "git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c#f71a91c84f3108eaa41dd2fa1bad5411c7323088" -dependencies = [ - "k256", - "oprf-core", - "oprf-zk 0.1.0 (git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c)", - "serde", - "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "uuid", -] - -[[package]] -name = "oprf-world-types" -version = "0.1.0" -source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" -dependencies = [ - "alloy", - "ark-ec 0.5.0", - "ark-ff 0.5.0", - "k256", - "oprf-core", - "oprf-zk 0.1.0 (git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3)", - "serde", - "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "taceo-eddsa-babyjubjub", - "uuid", -] - -[[package]] -name = "oprf-zk" -version = "0.1.0" -source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" -dependencies = [ - "ark-bn254 0.5.0", - "ark-ff 0.5.0", - "ark-groth16 0.5.0", - "circom-types", - "circom-witness-rs", - "eyre", - "groth16", - "hex", - "k256", - "rand 0.8.5", - "reqwest 0.12.22", - "ruint", - "serde", - "serde_json", - "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "oprf-zk" -version = "0.1.0" -source = "git+https://github.com/TaceoLabs/nullifier-oracle-service?rev=f71a91c#f71a91c84f3108eaa41dd2fa1bad5411c7323088" -dependencies = [ - "ark-bn254 0.5.0", - "ark-ff 0.5.0", - "ark-groth16 0.5.0", - "circom-types", - "eyre", - "groth16", - "hex", - "k256", - "rand 0.8.5", - "reqwest 0.12.22", - "serde", - "serde_json", - "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "thiserror 2.0.17", - "tracing", - "witness", -] - [[package]] name = "owo-colors" version = "4.2.0" @@ -3784,6 +3619,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4006,7 +3850,7 @@ dependencies = [ "once_cell", "socket2 0.5.9", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4209,6 +4053,7 @@ dependencies = [ "async-compression", "base64 0.22.1", "bytes", + "futures-channel", "futures-core", "futures-util", "http 1.3.1", @@ -4356,7 +4201,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4940,15 +4785,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook-registry" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" -dependencies = [ - "libc", -] - [[package]] name = "signature" version = "2.2.0" @@ -5200,6 +5036,43 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "taceo-ark-serde-compat" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9085f4762d38839ca1ab55c7eab2a24961b8eb1fdb639fabd1d015703a389f13" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "serde", + "taceo-ark-babyjubjub", +] + +[[package]] +name = "taceo-circom-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3561b87890d0e3f4787fd08fc07d96c7457139b22b64fa22b6a61e8d8e16cd4" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "ark-poly 0.5.0", + "ark-relations 0.5.1", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "byteorder", + "num-traits", + "rayon", + "serde", + "serde_json", + "taceo-ark-serde-compat 0.2.1", + "thiserror 2.0.17", + "tracing", +] + [[package]] name = "taceo-eddsa-babyjubjub" version = "0.5.0" @@ -5215,11 +5088,90 @@ dependencies = [ "rand 0.8.5", "serde", "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "taceo-poseidon2", + "taceo-ark-serde-compat 0.1.0", + "taceo-poseidon2 0.1.0", "zeroize", ] +[[package]] +name = "taceo-groth16" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3efa0cf1b7e336c54092e291fbc8403cccc89947737a6fb6f97398882bef9c6" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "ark-poly 0.5.0", + "ark-relations 0.5.1", + "eyre", + "num-traits", + "rayon", + "tracing", +] + +[[package]] +name = "taceo-groth16-material" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e2e97f306dc2aa157c36ce4da3812ee0310ee41686b38a6d199f3bdaeff219" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-groth16 0.5.0", + "ark-relations 0.5.1", + "ark-serialize 0.5.0", + "circom-witness-rs", + "eyre", + "hex", + "rand 0.8.5", + "ruint", + "sha2", + "taceo-circom-types", + "taceo-groth16", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "taceo-oprf-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77bf208b50749b78ae23664585e5cbbfc3265c467074613acae084e8b38730a8" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "blake3", + "itertools 0.14.0", + "num-bigint", + "rand 0.8.5", + "serde", + "subtle", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat 0.2.1", + "taceo-poseidon2 0.2.0", + "uuid", + "zeroize", +] + +[[package]] +name = "taceo-oprf-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f5b2e1829c5ac61f5540735b297bdd7d4d2f8974b7ccf74f7fa4dfaa37f5bf2" +dependencies = [ + "eyre", + "k256", + "serde", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat 0.2.1", + "taceo-circom-types", + "taceo-oprf-core", + "uuid", +] + [[package]] name = "taceo-poseidon2" version = "0.1.0" @@ -5233,6 +5185,19 @@ dependencies = [ "num-traits", ] +[[package]] +name = "taceo-poseidon2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbf106fb8682ee4e057872a18f431828bd467c28d2ead469e4c84dbf6ce5ec6" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", + "num-bigint", + "num-traits", +] + [[package]] name = "tap" version = "1.0.1" @@ -5249,7 +5214,7 @@ dependencies = [ "getrandom 0.3.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5407,7 +5372,6 @@ dependencies = [ "mio", "parking_lot", "pin-project-lite", - "signal-hook-registry", "slab", "socket2 0.6.0", "tokio-macros", @@ -5844,6 +5808,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -6112,7 +6077,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -6365,32 +6330,11 @@ dependencies = [ "bitflags 2.9.0", ] -[[package]] -name = "witness" -version = "0.2.0" -source = "git+https://github.com/TaceoLabs/circom-witness-rs.git?rev=c8ce390#c8ce39065c158a7d58414212e3cc2ac671b1c088" -dependencies = [ - "ark-bn254 0.5.0", - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "byteorder", - "cxx", - "cxx-build", - "eyre", - "hex", - "num-bigint", - "num-traits", - "postcard", - "rand 0.8.5", - "ruint", - "serde", - "serde_json", -] - [[package]] name = "world-id-core" -version = "0.1.0" -source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dc77736dbbe81622ec3bfcb140c47175acb59eb9196872e5ec72c1bb1fccc6c" dependencies = [ "alloy", "anyhow", @@ -6400,24 +6344,24 @@ dependencies = [ "ark-serialize 0.5.0", "chrono", "ciborium", - "circom-types", "eyre", - "groth16", + "futures", "hex", - "oprf-client", - "oprf-types", - "oprf-world-types", - "oprf-zk 0.1.0 (git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3)", "rand 0.8.5", "reqwest 0.12.22", "ruint", "secrecy", "serde", "serde_json", + "strum", "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", + "taceo-ark-serde-compat 0.2.1", + "taceo-circom-types", "taceo-eddsa-babyjubjub", - "taceo-poseidon2", + "taceo-groth16-material", + "taceo-oprf-core", + "taceo-oprf-types", + "taceo-poseidon2 0.1.0", "thiserror 1.0.69", "tokio", "tracing", @@ -6428,23 +6372,30 @@ dependencies = [ [[package]] name = "world-id-primitives" -version = "0.1.0" -source = "git+https://github.com/worldcoin/world-id-protocol?rev=8041ac3#8041ac3403eaf3f751b0d0f1871f37b73d1b4207" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f92efa1c8054bb56b13a4169d55022739591d73b10e3b4222eab705f6db669e" dependencies = [ "alloy-primitives", "ark-bn254 0.5.0", "ark-ff 0.5.0", "ark-groth16 0.5.0", "ark-serialize 0.5.0", + "arrayvec", "hex", "k256", "ruint", "serde", "serde_json", "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", + "taceo-ark-serde-compat 0.2.1", + "taceo-circom-types", "taceo-eddsa-babyjubjub", + "taceo-groth16-material", + "taceo-oprf-core", + "taceo-poseidon2 0.1.0", "thiserror 1.0.69", + "url", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 953d855f5..b05aea816 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ alloy-core = { version = "1", default-features = false, features = ["sol-types"] alloy-primitives = { version = "1", default-features = false } walletkit-core = { version = "0.1.8", path = "walletkit-core", default-features = false } uniffi = { version = "0.29", features = ["build", "tokio"] } -world-id-core = { git = "https://github.com/worldcoin/world-id-protocol", rev = "8041ac3", default-features = false, features = ["authenticator"] } +world-id-core = { version = "0.1", default-features = false, features = ["authenticator", "embed-zkeys"] } [profile.release] opt-level = 'z' # Optimize for size. diff --git a/walletkit-core/src/authenticator.rs b/walletkit-core/src/authenticator.rs index 6ac83bae8..cfaa90e58 100644 --- a/walletkit-core/src/authenticator.rs +++ b/walletkit-core/src/authenticator.rs @@ -21,10 +21,10 @@ impl Authenticator { #[uniffi::constructor] pub async fn init_with_defaults( seed: &[u8], - rpc_url: String, + rpc_url: Option, environment: &Environment, ) -> Result { - let config = Config::from_environment(environment, rpc_url); + let config = Config::from_environment(environment, rpc_url)?; let authenticator = CoreAuthenticator::init(seed, config).await?; Ok(Self(authenticator)) } @@ -53,14 +53,14 @@ impl Authenticator { #[uniffi::constructor] pub async fn init_or_create_blocking_with_defaults( seed: &[u8], - rpc_url: String, + rpc_url: Option, environment: &Environment, recovery_address: Option, ) -> Result { let recovery_address = Address::parse_from_ffi_optional(recovery_address, "recovery_address")?; - let config = Config::from_environment(environment, rpc_url); + let config = Config::from_environment(environment, rpc_url)?; let authenticator = CoreAuthenticator::init_or_create_blocking(seed, config, recovery_address) @@ -124,9 +124,12 @@ impl Authenticator { pub async fn get_packed_account_index_remote( &self, ) -> Result { + let client = reqwest::Client::new(); // TODO: reuse client let packed_account_index = CoreAuthenticator::get_packed_account_index( self.0.onchain_address(), - &self.0.registry(), + self.0.registry().as_deref(), + &self.0.config, + &client, ) .await?; Ok(packed_account_index.into()) @@ -161,12 +164,15 @@ mod tests { let seed = [2u8; 32]; let config = Config::new( - mock_server.url(), + Some(mock_server.url()), + 480, address!("0xd66aFbf92d684B4404B1ed3e9aDA85353c178dE2"), "https://world-id-indexer.stage-crypto.worldcoin.org".to_string(), "https://world-id-gateway.stage-crypto.worldcoin.org".to_string(), vec![], - ); + 2, + ) + .unwrap(); let config = serde_json::to_string(&config).unwrap(); Authenticator::init(&seed, &config).await.unwrap(); drop(mock_server); diff --git a/walletkit-core/src/defaults.rs b/walletkit-core/src/defaults.rs index b521ae72d..627a81de8 100644 --- a/walletkit-core/src/defaults.rs +++ b/walletkit-core/src/defaults.rs @@ -1,36 +1,57 @@ use alloy_primitives::{address, Address}; -use world_id_core::primitives::Config; +use world_id_core::primitives::{Config, PrimitiveError}; -use crate::Environment; +use crate::{error::WalletKitError, Environment}; pub static ACCOUNT_REGISTRY: Address = address!("0xd66aFbf92d684B4404B1ed3e9aDA85353c178dE2"); pub trait DefaultConfig { - fn from_environment(environment: &Environment, rpc_url: String) -> Self; + fn from_environment( + environment: &Environment, + rpc_url: Option, + ) -> Result + where + Self: Sized; +} + +fn map_config_error(e: PrimitiveError) -> WalletKitError { + if let PrimitiveError::InvalidInput { attribute, reason } = e { + return WalletKitError::InvalidInput { attribute, reason }; + } + WalletKitError::Generic { + error: format!("Config initialization error: {e}"), + } } impl DefaultConfig for Config { - fn from_environment(environment: &Environment, rpc_url: String) -> Self { + fn from_environment( + environment: &Environment, + rpc_url: Option, + ) -> Result { // TODO: Add all correct values match environment { Environment::Staging => Self::new( - // This always needs to be provided. There is no default. rpc_url, + 480, // Staging also runs on World Chain Mainnet by default ACCOUNT_REGISTRY, "https://world-id-indexer.stage-crypto.worldcoin.org".to_string(), "https://world-id-gateway.stage-crypto.worldcoin.org".to_string(), vec![], - ), + 2, + ) + .map_err(map_config_error), Environment::Production => Self::new( - // This always needs to be provided. There is no default. rpc_url, + 480, ACCOUNT_REGISTRY, "https://world-id-indexer.crypto.worldcoin.org".to_string(), "https://world-id-gateway.crypto.worldcoin.org".to_string(), vec![], - ), + 2, + ) + .map_err(map_config_error), } } } diff --git a/walletkit-core/tests/authenticator_integration.rs b/walletkit-core/tests/authenticator_integration.rs index 3e9749583..24c37746c 100644 --- a/walletkit-core/tests/authenticator_integration.rs +++ b/walletkit-core/tests/authenticator_integration.rs @@ -32,7 +32,7 @@ async fn test_authenticator_integration() { // When account doesn't exist, this should fail let authenticator = Authenticator::init_with_defaults( authenticator_seeder.to_bytes().as_slice(), - anvil.endpoint(), + Some(anvil.endpoint()), &Environment::Staging, ) .await @@ -65,7 +65,7 @@ async fn test_authenticator_integration() { // now the authenticator exists let authenticator = Authenticator::init_with_defaults( authenticator_seeder.to_bytes().as_slice(), - anvil.endpoint(), + Some(anvil.endpoint()), &Environment::Staging, ) .await