From 5f72869523f4f0c710ecd62c2454c09a054e1c36 Mon Sep 17 00:00:00 2001 From: pdtfh <149602456+pdtfh@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:02:25 +0100 Subject: [PATCH 1/5] proof context / external nullifier generation --- Cargo.lock | 1 + walletkit-core/Cargo.toml | 1 + walletkit-core/src/identity.rs | 2 +- walletkit-core/src/proof.rs | 97 +++++++++++++++++++++++++++++++--- walletkit-core/src/u256.rs | 2 +- 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a20bb4a1..5857ced3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5087,6 +5087,7 @@ dependencies = [ name = "walletkit-core" version = "0.0.6" dependencies = [ + "alloy-core", "hex", "ruint", "semaphore", diff --git a/walletkit-core/Cargo.toml b/walletkit-core/Cargo.toml index ac40014d..6e104b0a 100644 --- a/walletkit-core/Cargo.toml +++ b/walletkit-core/Cargo.toml @@ -15,6 +15,7 @@ crate-type = ["lib", "staticlib", "cdylib"] name = "walletkit_core" [dependencies] +alloy-core = { version = "0.8.12", default-features = false, features = ["sol-types"] } hex = "0.4.3" ruint = { version = "1.12.3", default-features = false, features = ["alloc"] } semaphore = { git = "https://github.com/worldcoin/semaphore-rs", rev = "accb14b", features = ["depth_30"] } diff --git a/walletkit-core/src/identity.rs b/walletkit-core/src/identity.rs index a2f32c7d..6b843453 100644 --- a/walletkit-core/src/identity.rs +++ b/walletkit-core/src/identity.rs @@ -39,7 +39,7 @@ mod tests { #[test] fn test() { let identity = Identity::new(b"not_a_real_secret"); - let context = Context::new(b"app_id", b"action"); + let context = Context::new(b"app_id", None); let nullifier_hash = identity.generate_nullifier_hash(&context); println!("{}", nullifier_hash.to_hex_string()); } diff --git a/walletkit-core/src/proof.rs b/walletkit-core/src/proof.rs index e69f757e..33422aef 100644 --- a/walletkit-core/src/proof.rs +++ b/walletkit-core/src/proof.rs @@ -1,3 +1,4 @@ +use alloy_core::sol_types::SolValue; use semaphore::hash_to_field; use crate::u256::U256Wrapper; @@ -11,12 +12,96 @@ pub struct Context { impl Context { #[must_use] #[uniffi::constructor] - pub fn new(app_id: &[u8], action: &[u8]) -> Self { - let external_nullifier = hash_to_field(app_id); - dbg!(&action); - // TODO: handle action properly - Self { - external_nullifier: external_nullifier.into(), + pub fn new(app_id: &[u8], action: Option>) -> Self { + let mut pre_image = hash_to_field(app_id).abi_encode_packed(); + + if let Some(action) = action { + pre_image.extend_from_slice(&action); } + + let external_nullifier = hash_to_field(&pre_image).into(); + + Self { external_nullifier } + } +} + +#[cfg(test)] +mod tests { + use alloy_core::primitives::address; + use ruint::{aliases::U256, uint}; + + use super::*; + + #[test] + fn test_external_nullifier_hash_generation_no_action() { + let context = Context::new(b"app_369183bd38f1641b6964ab51d7a20434", None); + assert_eq!( + context.external_nullifier.to_hex_string(), + "0x0073e4a6b670e81dc619b1f8703aa7491dc5aaadf75409aba0ac2414014c0227" + ); + + let context = Context::new(b"app_369183bd38f1641b6964ab51d7a20434", Some(b"".to_vec())); + assert_eq!( + context.external_nullifier.to_hex_string(), + "0x0073e4a6b670e81dc619b1f8703aa7491dc5aaadf75409aba0ac2414014c0227" + ); + } + + /// This test case comes from the real example in the docs. + /// Reference: + #[test] + fn test_external_nullifier_hash_generation_string_action_staging() { + let context = Context::new( + b"app_staging_45068dca85829d2fd90e2dd6f0bff997", + Some(b"test-action-qli8g".to_vec()), + ); + assert_eq!( + context.external_nullifier.to_hex_string(), + "0x00d8b157e767dc59faa533120ed0ce34fc51a71937292ea8baed6ee6f4fda866" + ); + } + + #[test] + fn test_external_nullifier_hash_generation_string_action() { + let context = Context::new(b"app_10eb12bd96d8f7202892ff25f094c803", Some(b"test-123123".to_vec())); + assert_eq!( + context.external_nullifier.0, + // cspell:disable-next-line + uint!(0x0065ebab05692ff2e0816cc4c3b83216c33eaa4d906c6495add6323fe0e2dc89_U256) + ); + } + + #[test] + fn test_external_nullifier_hash_generation_with_complex_abi_encoded_values() { + let custom_action = [ + address!("541f3cc5772a64f2ba0a47e83236CcE2F089b188").abi_encode_packed(), + U256::from(1).abi_encode_packed(), + "hello".abi_encode_packed(), + ] + .concat(); + + let context = Context::new(b"app_10eb12bd96d8f7202892ff25f094c803", Some(custom_action)); + assert_eq!( + context.external_nullifier.to_hex_string(), + // expected output obtained from Solidity + "0x00f974ff06219e8ca992073d8bbe05084f81250dbd8f37cae733f24fcc0c5ffd" + ); + } + + #[test] + fn test_external_nullifier_hash_generation_with_complex_abi_encoded_values_staging() { + let custom_action = [ + "world".abi_encode_packed(), + U256::from(1).abi_encode_packed(), + "hello".abi_encode_packed(), + ] + .concat(); + + let context = Context::new(b"app_staging_45068dca85829d2fd90e2dd6f0bff997", Some(custom_action)); + assert_eq!( + context.external_nullifier.to_hex_string(), + // expected output obtained from Solidity + "0x005b49f95e822c7c37f4f043421689b11f880e617faa5cd0391803bc9bcc63c0" + ); } } diff --git a/walletkit-core/src/u256.rs b/walletkit-core/src/u256.rs index f5feba65..b0b32561 100644 --- a/walletkit-core/src/u256.rs +++ b/walletkit-core/src/u256.rs @@ -11,7 +11,7 @@ use ruint::aliases::U256; /// 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(uniffi::Object, Debug, PartialEq, Eq, Clone)] +#[derive(uniffi::Object, Debug, PartialEq, Eq, Clone, Copy)] pub struct U256Wrapper(pub U256); #[uniffi::export] From 95b6459b29d25aebbae08f8298003858a553ccdf Mon Sep 17 00:00:00 2001 From: pdtfh <149602456+pdtfh@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:12:00 +0100 Subject: [PATCH 2/5] solidity full tests --- .gitignore | 6 +- Cargo.lock | 885 +++++++++++++++++- rustfmt.toml | 5 +- walletkit-core/Cargo.toml | 4 + walletkit-core/src/identity.rs | 3 +- walletkit-core/src/proof.rs | 37 +- walletkit-core/tests/README.md | 15 + .../tests/contracts/external_nullifier.sol | 43 + .../external_nullifier.sol/ByteHasher.json | 1 + .../ExternalNullifier.json | 1 + walletkit-core/tests/solidity.rs | 45 + 11 files changed, 1029 insertions(+), 16 deletions(-) create mode 100644 walletkit-core/tests/README.md create mode 100644 walletkit-core/tests/contracts/external_nullifier.sol create mode 100644 walletkit-core/tests/out/external_nullifier.sol/ByteHasher.json create mode 100644 walletkit-core/tests/out/external_nullifier.sol/ExternalNullifier.json create mode 100644 walletkit-core/tests/solidity.rs diff --git a/.gitignore b/.gitignore index 3c56df93..471f9c00 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,8 @@ target/ # Swift build outputs are not commited to this repo. WalletKitCore.xcframework/ -Sources/ \ No newline at end of file +Sources/ + +# forge +cache/ +**/out/build-info \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5857ced3..6b6f8718 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,14 +56,235 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" + +[[package]] +name = "alloy" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b524b8c28a7145d1fe4950f84360b5de3e307601679ff0558ddc20ea229399" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-network", + "alloy-node-bindings", + "alloy-provider", + "alloy-rpc-client", + "alloy-transport", + "alloy-transport-http", +] + +[[package]] +name = "alloy-chains" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18c5c520273946ecf715c0010b4e3503d7eba9893cd9ce6b7fff5654c4a3c470" +dependencies = [ + "alloy-primitives", + "num_enum 0.7.3", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae09ffd7c29062431dd86061deefe4e3c6f07fa0d674930095f8dcedb0baf02c" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66430a72d5bf5edead101c8c2f0a24bada5ec9f3cf9909b3e08b6d6899b4803e" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "thiserror 1.0.69", +] + [[package]] name = "alloy-core" version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8316d83e590f4163b221b8180008f302bda5cf5451202855cdd323e588849c" dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2364c782a245cf8725ea6dbfca5f530162702b5d685992ea03ce64529136cc" +dependencies = [ + "alloy-json-abi", "alloy-primitives", + "alloy-sol-type-parser", "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.20", +] + +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6cee6a35793f3db8a5ffe60e86c695f321d081a567211245f503e8c498fce8" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "serde", +] + +[[package]] +name = "alloy-eips" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b6aa3961694b30ba53d41006131a2fca3bdab22e4c344e46db2c639e7c2dfdd" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "derive_more", + "once_cell", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53f7877ded3921d18a0a9556d55bedf84535567198c9edab2aa23106da91855" +dependencies = [ + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84c506bf264110fa7e90d9924f742f40ef53c6572ea56a0b0bd714a567ed389" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3694b7e480728c0b3e228384f223937f14c10caef5a4c766021190fc8f283d35" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea94b8ceb5c75d7df0a93ba0acc53b55a22b47b532b600a800a87ef04eb5b0b4" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9f3e281005943944d15ee8491534a1c7b3cbf7a7de26f8c433b842b93eb5f9" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-node-bindings" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9805d126f24be459b958973c0569c73e1aadd27d4535eee82b2b6764aa03616" +dependencies = [ + "alloy-genesis", + "alloy-primitives", + "k256", + "rand", + "serde_json", + "tempfile", + "thiserror 1.0.69", + "tracing", + "url", ] [[package]] @@ -72,27 +293,186 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fce5dbd6a4f118eecc4719eaa9c7ffc31c315e6c5ccde3642db927802312425" dependencies = [ + "alloy-rlp", "bytes", "cfg-if", "const-hex", "derive_more", + "foldhash", + "hashbrown 0.15.1", "hex-literal", + "indexmap 2.6.0", "itoa", + "k256", + "keccak-asm", "paste", + "proptest", + "rand", "ruint", + "rustc-hash", + "serde", + "sha3", "tiny-keccak", ] +[[package]] +name = "alloy-provider" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c1f9eede27bf4c13c099e8e64d54efd7ce80ef6ea47478aa75d5d74e2dba3b" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-node-bindings", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-anvil", + "alloy-rpc-types-eth", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "futures-utils-wasm", + "lru", + "parking_lot", + "pin-project", + "reqwest 0.12.9", + "schnellru", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "alloy-rlp" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0822426598f95e45dd1ea32a738dac057529a709ee645fcc516ffa4cbde08f" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] +[[package]] +name = "alloy-rlp-derive" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b09cae092c27b6f1bde952653a22708691802e57bfef4a2973b80bea21efd3f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374dbe0dc3abdc2c964f36b3d3edf9cdb3db29d16bda34aa123f03d810bec1dd" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest 0.12.9", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types-anvil" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca97963132f78ddfc60e43a017348e6d52eea983925c23652f5b330e8e02291" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a477281940d82d29315846c7216db45b15e90bcd52309da9f54bcf7ad94a11" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "derive_more", + "itertools 0.13.0", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dfa4a7ccf15b2492bb68088692481fd6b2604ccbee1d0d6c44c21427ae4df83" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e10aec39d60dc27edcac447302c7803d2371946fb737245320a05b78eb2fafd" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror 1.0.69", +] + +[[package]] +name = "alloy-signer-local" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8396f6dff60700bc1d215ee03d86ff56de268af96e2bf833a14d0bafcab9882" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand", + "thiserror 1.0.69", +] + [[package]] name = "alloy-sol-macro" version = "0.8.12" @@ -113,6 +493,7 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4222d70bec485ceccc5d8fd4f2909edd65b5d5e43d4aca0b5dcee65d519ae98f" dependencies = [ + "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck 0.5.0", @@ -131,24 +512,73 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e17f2677369571b976e51ea1430eb41c3690d344fef567b840bfc0b01b6f83a" dependencies = [ + "alloy-json-abi", "const-hex", "dunce", "heck 0.5.0", "proc-macro2", "quote", + "serde_json", "syn 2.0.87", "syn-solidity", ] +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa64d80ae58ffaafdff9d5d84f58d03775f66c84433916dc9a64ed16af5755da" +dependencies = [ + "serde", + "winnow 0.6.20", +] + [[package]] name = "alloy-sol-types" version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6520d427d4a8eb7aa803d852d7a52ceb0c519e784c292f64bb339e636918cf27" dependencies = [ + "alloy-json-abi", "alloy-primitives", "alloy-sol-macro", "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f99acddb34000d104961897dbb0240298e8b775a7efffb9fda2a1a3efedd65b3" +dependencies = [ + "alloy-json-rpc", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc013132e34eeadaa0add7e74164c1503988bfba8bae885b32e0918ba85a8a6" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest 0.12.9", + "serde_json", + "tower", + "tracing", + "url", ] [[package]] @@ -551,6 +981,28 @@ dependencies = [ "nom", ] +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "async-trait" version = "0.1.83" @@ -603,6 +1055,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.21.7" @@ -615,6 +1073,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "basic-toml" version = "0.1.9" @@ -633,6 +1097,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -688,6 +1167,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bstr" version = "1.11.0" @@ -762,6 +1253,21 @@ dependencies = [ "serde", ] +[[package]] +name = "c-kzg" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + [[package]] name = "camino" version = "1.1.9" @@ -954,6 +1460,12 @@ dependencies = [ "serde", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "constant_time_eq" version = "0.3.1" @@ -1151,6 +1663,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1288,6 +1812,16 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1387,6 +1921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1423,12 +1958,45 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embedded-io" version = "0.4.0" @@ -1552,6 +2120,16 @@ dependencies = [ "bytes", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "filetime" version = "0.2.25" @@ -1622,6 +2200,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1756,6 +2340,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1773,6 +2363,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1835,6 +2426,17 @@ dependencies = [ "scroll", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "h2" version = "0.3.26" @@ -1902,6 +2504,12 @@ name = "hashbrown" version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "serde", +] [[package]] name = "hasher" @@ -1950,6 +2558,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-literal" @@ -1957,6 +2568,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "http" version = "0.2.12" @@ -2394,6 +3014,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", +] + [[package]] name = "keccak" version = "0.1.0" @@ -2403,6 +3036,25 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lazy_static" version = "0.2.11" @@ -2511,6 +3163,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.1", +] + [[package]] name = "lz4_flex" version = "0.11.3" @@ -2790,7 +3451,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive 0.7.3", ] [[package]] @@ -2805,6 +3475,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "object" version = "0.32.2" @@ -2897,6 +3578,16 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + [[package]] name = "parking_lot_core" version = "0.9.10" @@ -2981,6 +3672,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.31" @@ -3123,6 +3824,8 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ + "bit-set", + "bit-vec", "bitflags 2.6.0", "lazy_static 1.5.0", "num-traits", @@ -3130,6 +3833,8 @@ dependencies = [ "rand_chacha", "rand_xorshift", "regex-syntax", + "rusty-fork", + "tempfile", "unarray", ] @@ -3164,6 +3869,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quinn" version = "0.11.6" @@ -3240,6 +3951,7 @@ dependencies = [ "libc", "rand_chacha", "rand_core", + "serde", ] [[package]] @@ -3450,6 +4162,16 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.8" @@ -3643,6 +4365,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "rusty_pool" version = "0.7.0" @@ -3705,6 +4439,17 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash 0.8.11", + "cfg-if", + "hashbrown 0.13.2", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3743,6 +4488,20 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -3793,7 +4552,7 @@ dependencies = [ "hex", "hex-literal", "itertools 0.13.0", - "keccak", + "keccak 0.1.0", "mmap-rs", "num-bigint", "once_cell", @@ -3958,6 +4717,26 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak 0.1.5", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -3992,6 +4771,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + [[package]] name = "simdutf8" version = "0.1.5" @@ -4061,6 +4850,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4096,6 +4895,28 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.87", +] + [[package]] name = "subtle" version = "2.6.1" @@ -4331,6 +5152,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.36" @@ -4536,6 +5366,26 @@ dependencies = [ "winnow 0.6.20", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -5067,6 +5917,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.2.0" @@ -5087,12 +5946,14 @@ dependencies = [ name = "walletkit-core" version = "0.0.6" dependencies = [ + "alloy", "alloy-core", "hex", "ruint", "semaphore", "serde_json", "thiserror 2.0.3", + "tokio", "uniffi", ] @@ -5347,7 +6208,7 @@ dependencies = [ "bytes", "derivative", "lz4_flex", - "num_enum", + "num_enum 0.5.11", "rkyv", "serde", "serde_json", @@ -5436,7 +6297,7 @@ dependencies = [ "libc", "linked_hash_set", "lz4_flex", - "num_enum", + "num_enum 0.5.11", "once_cell", "petgraph", "pin-project", @@ -5487,7 +6348,7 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "cfg-if", - "num_enum", + "num_enum 0.5.11", "serde", "time", "tracing", @@ -5512,6 +6373,20 @@ dependencies = [ "semver 1.0.23", ] +[[package]] +name = "wasmtimer" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "wast" version = "64.0.0" diff --git a/rustfmt.toml b/rustfmt.toml index 0a3643e3..07b24489 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,2 @@ -max_width = 120 -edition = "2021" -condense_wildcard_suffixes = true \ No newline at end of file +max_width = 88 +edition = "2021" \ No newline at end of file diff --git a/walletkit-core/Cargo.toml b/walletkit-core/Cargo.toml index 6e104b0a..dc3e8315 100644 --- a/walletkit-core/Cargo.toml +++ b/walletkit-core/Cargo.toml @@ -22,3 +22,7 @@ semaphore = { git = "https://github.com/worldcoin/semaphore-rs", rev = "accb14b" serde_json = "1.0.133" thiserror = "2.0.3" uniffi = { workspace = true, features = ["build"] } + +[dev-dependencies] +alloy = { version = "0.6.4", default-features = false, features = ["json", "contract", "node-bindings"] } +tokio = "1.41.1" diff --git a/walletkit-core/src/identity.rs b/walletkit-core/src/identity.rs index 6b843453..809c6361 100644 --- a/walletkit-core/src/identity.rs +++ b/walletkit-core/src/identity.rs @@ -17,7 +17,8 @@ impl Identity { #[uniffi::constructor] pub fn new(secret: &[u8]) -> Self { let mut secret_key = secret.to_vec(); - let identity = semaphore::identity::Identity::from_secret(&mut secret_key, None); + let identity = + semaphore::identity::Identity::from_secret(&mut secret_key, None); Self(identity) } diff --git a/walletkit-core/src/proof.rs b/walletkit-core/src/proof.rs index 33422aef..ff15b9c8 100644 --- a/walletkit-core/src/proof.rs +++ b/walletkit-core/src/proof.rs @@ -3,6 +3,9 @@ use semaphore::hash_to_field; use crate::u256::U256Wrapper; +/// A `Proof::Context` contains the basic information on the verifier and the specific action a user will be proving. +/// +/// A `Proof::Context` is required to generate a `Proof` and will generally be initialized from an `app_id` and `action`. #[derive(Clone, PartialEq, Eq, Debug, uniffi::Object)] pub struct Context { pub external_nullifier: U256Wrapper, @@ -10,6 +13,17 @@ pub struct Context { #[uniffi::export] impl Context { + /// Initializes a `Proof::Context`. + /// + /// Will compute the relevant external nullifier from the provided `app_id` and `action` as defined by the + /// World ID Protocol. The external nullifier generation matches the logic in the + /// [Developer Portal](https://github.com/worldcoin/developer-portal/blob/main/web/lib/hashing.ts). + /// + /// # Arguments + /// + /// * `app_id` - The ID of the application requesting proofs. This can be obtained from the Developer Portal. + /// * `action` - Optional. Custom incognito action being requested. + /// #[must_use] #[uniffi::constructor] pub fn new(app_id: &[u8], action: Option>) -> Self { @@ -40,7 +54,8 @@ mod tests { "0x0073e4a6b670e81dc619b1f8703aa7491dc5aaadf75409aba0ac2414014c0227" ); - let context = Context::new(b"app_369183bd38f1641b6964ab51d7a20434", Some(b"".to_vec())); + let context = + Context::new(b"app_369183bd38f1641b6964ab51d7a20434", Some(b"".to_vec())); assert_eq!( context.external_nullifier.to_hex_string(), "0x0073e4a6b670e81dc619b1f8703aa7491dc5aaadf75409aba0ac2414014c0227" @@ -63,11 +78,16 @@ mod tests { #[test] fn test_external_nullifier_hash_generation_string_action() { - let context = Context::new(b"app_10eb12bd96d8f7202892ff25f094c803", Some(b"test-123123".to_vec())); + let context = Context::new( + b"app_10eb12bd96d8f7202892ff25f094c803", + Some(b"test-123123".to_vec()), + ); assert_eq!( context.external_nullifier.0, // cspell:disable-next-line - uint!(0x0065ebab05692ff2e0816cc4c3b83216c33eaa4d906c6495add6323fe0e2dc89_U256) + uint!( + 0x0065ebab05692ff2e0816cc4c3b83216c33eaa4d906c6495add6323fe0e2dc89_U256 + ) ); } @@ -80,7 +100,8 @@ mod tests { ] .concat(); - let context = Context::new(b"app_10eb12bd96d8f7202892ff25f094c803", Some(custom_action)); + let context = + Context::new(b"app_10eb12bd96d8f7202892ff25f094c803", Some(custom_action)); assert_eq!( context.external_nullifier.to_hex_string(), // expected output obtained from Solidity @@ -89,7 +110,8 @@ mod tests { } #[test] - fn test_external_nullifier_hash_generation_with_complex_abi_encoded_values_staging() { + fn test_external_nullifier_hash_generation_with_complex_abi_encoded_values_staging() + { let custom_action = [ "world".abi_encode_packed(), U256::from(1).abi_encode_packed(), @@ -97,7 +119,10 @@ mod tests { ] .concat(); - let context = Context::new(b"app_staging_45068dca85829d2fd90e2dd6f0bff997", Some(custom_action)); + let context = Context::new( + b"app_staging_45068dca85829d2fd90e2dd6f0bff997", + Some(custom_action), + ); assert_eq!( context.external_nullifier.to_hex_string(), // expected output obtained from Solidity diff --git a/walletkit-core/tests/README.md b/walletkit-core/tests/README.md new file mode 100644 index 00000000..cd1fee83 --- /dev/null +++ b/walletkit-core/tests/README.md @@ -0,0 +1,15 @@ +# Integration Tests + +These tests are used to verify the correct functionality of the World ID SDK beyond the basic Rust interactions. + +### Test scenarios + +- Solidity compatibility. Key functionality is tested against the Solidity implementation. + +### Updating the Solidity contracts + +When updating the Solidity contracts, make sure to run `forge` to rebuild the JSON artifacts. + +```bash +forge build -C walletkit-core/tests/contracts -o walletkit-core/tests/out +``` diff --git a/walletkit-core/tests/contracts/external_nullifier.sol b/walletkit-core/tests/contracts/external_nullifier.sol new file mode 100644 index 00000000..7bdc5b1a --- /dev/null +++ b/walletkit-core/tests/contracts/external_nullifier.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +library ByteHasher { + /// @dev Creates a keccak256 hash of a bytestring. + /// @param value The bytestring to hash + /// @return The hash of the specified value + /// @dev `>> 8` makes sure that the result is included in our field + function hashToField(bytes memory value) internal pure returns (uint256) { + return uint256(keccak256(abi.encodePacked(value))) >> 8; + } +} + +/// @title ExternalNullifier +/// @author World +/// @notice A contract to test external nullifier generation. REMINDER TO UPDATE THE JSON ARTIFACTS WHEN UPDATING THIS CONTRACT. +contract ExternalNullifier { + using ByteHasher for bytes; + + string appId; + + /// @notice Constructs the contract + constructor(string memory _appId) { + appId = _appId; + } + + /// @notice Generate an external nullifier to be used in tests + /// @param someText A random string to be included + /// @return The external nullifier + function generateExternalNullifier( + string memory someText + ) external view returns (uint256) { + uint256 externalNullifier = abi + .encodePacked( + abi.encodePacked(appId).hashToField(), + abi.encodePacked(msg.sender), // Note how this could be used to validate a more advanced context + abi.encodePacked(someText) + ) + .hashToField(); + + return externalNullifier; + } +} diff --git a/walletkit-core/tests/out/external_nullifier.sol/ByteHasher.json b/walletkit-core/tests/out/external_nullifier.sol/ByteHasher.json new file mode 100644 index 00000000..d39ed8ec --- /dev/null +++ b/walletkit-core/tests/out/external_nullifier.sol/ByteHasher.json @@ -0,0 +1 @@ +{"abi":[],"bytecode":{"object":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220fefdc0eed757a40c487429f00c5157f6120185065757feac54151ea6afbf30f464736f6c634300081c0033","sourceMap":"58:391:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;58:391:0;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220fefdc0eed757a40c487429f00c5157f6120185065757feac54151ea6afbf30f464736f6c634300081c0033","sourceMap":"58:391:0:-:0;;;;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"walletkit-core/tests/contracts/external_nullifier.sol\":\"ByteHasher\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"walletkit-core/tests/contracts/external_nullifier.sol\":{\"keccak256\":\"0xe7f8ab9597a80e72184d32f25eaf76c488906d5bff6b66e54a8a75e54f56e075\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bf2426ea1b9a5f8caf4651f298344632a01ee36e0f37850d85e7c049ed3a1b46\",\"dweb:/ipfs/QmSXNFpCqW9QMwWgrA1sXADH8GKTpbePD3ispHqqVBMcjT\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"walletkit-core/tests/contracts/external_nullifier.sol":"ByteHasher"},"evmVersion":"paris","libraries":{}},"sources":{"walletkit-core/tests/contracts/external_nullifier.sol":{"keccak256":"0xe7f8ab9597a80e72184d32f25eaf76c488906d5bff6b66e54a8a75e54f56e075","urls":["bzz-raw://bf2426ea1b9a5f8caf4651f298344632a01ee36e0f37850d85e7c049ed3a1b46","dweb:/ipfs/QmSXNFpCqW9QMwWgrA1sXADH8GKTpbePD3ispHqqVBMcjT"],"license":"MIT"}},"version":1},"id":0} \ No newline at end of file diff --git a/walletkit-core/tests/out/external_nullifier.sol/ExternalNullifier.json b/walletkit-core/tests/out/external_nullifier.sol/ExternalNullifier.json new file mode 100644 index 00000000..0d3f3a44 --- /dev/null +++ b/walletkit-core/tests/out/external_nullifier.sol/ExternalNullifier.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"_appId","type":"string","internalType":"string"}],"stateMutability":"nonpayable"},{"type":"function","name":"generateExternalNullifier","inputs":[{"name":"someText","type":"string","internalType":"string"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b506040516105b83803806105b883398101604081905261002f91610058565b600061003b82826101ad565b505061026b565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561006a57600080fd5b81516001600160401b0381111561008057600080fd5b8201601f8101841361009157600080fd5b80516001600160401b038111156100aa576100aa610042565b604051601f8201601f19908116603f011681016001600160401b03811182821017156100d8576100d8610042565b6040528181528282016020018610156100f057600080fd5b60005b8281101561010f576020818501810151838301820152016100f3565b50600091810160200191909152949350505050565b600181811c9082168061013857607f821691505b60208210810361015857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156101a857806000526020600020601f840160051c810160208510156101855750805b601f840160051c820191505b818110156101a55760008155600101610191565b50505b505050565b81516001600160401b038111156101c6576101c6610042565b6101da816101d48454610124565b8461015e565b6020601f82116001811461020e57600083156101f65750848201515b600019600385901b1c1916600184901b1784556101a5565b600084815260208120601f198516915b8281101561023e578785015182556020948501946001909201910161021e565b508482101561025c5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b61033e8061027a6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a099132114610030575b600080fd5b61004361003e366004610133565b610055565b60405190815260200160405180910390f35b6000806100e1610084600060405160200161007091906101ec565b6040516020818303038152906040526100e8565b6040516bffffffffffffffffffffffff193360601b166020820152603401604051602081830303815290604052856040516020016100c291906102af565b60408051601f19818403018152908290526100709392916020016102cb565b9392505050565b60006008826040516020016100fd91906102af565b60408051601f198184030181529190528051602090910120901c92915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561014557600080fd5b813567ffffffffffffffff81111561015c57600080fd5b8201601f8101841361016d57600080fd5b803567ffffffffffffffff8111156101875761018761011d565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156101b6576101b661011d565b6040528181528282016020018610156101ce57600080fd5b81602084016020830137600091810160200191909152949350505050565b6000808354818160011c9050600182168061020857607f821691505b60208210810361022657634e487b7160e01b84526022600452602484fd5b80801561023a576001811461024f5761027f565b60ff198416875282151583028701945061027f565b60008881526020902060005b848110156102775781548982015260019091019060200161025b565b505082870194505b50929695505050505050565b60005b838110156102a657818101518382015260200161028e565b50506000910152565b600082516102c181846020870161028b565b9190910192915050565b838152600083516102e381602085016020880161028b565b808301905083516102fb81602084016020880161028b565b016020019594505050505056fea2646970667358221220ae92ee61ed080bbe411c58f9ecdc7150f51b1825718ffd2a35204bfa893c23c564736f6c634300081c0033","sourceMap":"627:826:0:-:0;;;752:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;796:5;:14;804:6;796:5;:14;:::i;:::-;;752:65;627:826;;14:127:1;75:10;70:3;66:20;63:1;56:31;106:4;103:1;96:15;130:4;127:1;120:15;146:1044;226:6;279:2;267:9;258:7;254:23;250:32;247:52;;;295:1;292;285:12;247:52;322:16;;-1:-1:-1;;;;;350:30:1;;347:50;;;393:1;390;383:12;347:50;416:22;;469:4;461:13;;457:27;-1:-1:-1;447:55:1;;498:1;495;488:12;447:55;525:9;;-1:-1:-1;;;;;546:30:1;;543:56;;;579:18;;:::i;:::-;628:2;622:9;720:2;682:17;;-1:-1:-1;;678:31:1;;;711:2;674:40;670:54;658:67;;-1:-1:-1;;;;;740:34:1;;776:22;;;737:62;734:88;;;802:18;;:::i;:::-;838:2;831:22;862;;;903:15;;;920:2;899:24;896:37;-1:-1:-1;893:57:1;;;946:1;943;936:12;893:57;968:1;978:133;992:6;989:1;986:13;978:133;;;1096:2;1084:10;;;1080:19;;1074:26;1053:14;;;1049:23;;1042:59;1007:10;978:133;;;-1:-1:-1;1157:1:1;1131:19;;;1152:2;1127:28;1120:39;;;;1135:6;146:1044;-1:-1:-1;;;;146:1044:1:o;1195:380::-;1274:1;1270:12;;;;1317;;;1338:61;;1392:4;1384:6;1380:17;1370:27;;1338:61;1445:2;1437:6;1434:14;1414:18;1411:38;1408:161;;1491:10;1486:3;1482:20;1479:1;1472:31;1526:4;1523:1;1516:15;1554:4;1551:1;1544:15;1408:161;;1195:380;;;:::o;1706:518::-;1808:2;1803:3;1800:11;1797:421;;;1844:5;1841:1;1834:16;1888:4;1885:1;1875:18;1958:2;1946:10;1942:19;1939:1;1935:27;1929:4;1925:38;1994:4;1982:10;1979:20;1976:47;;;-1:-1:-1;2017:4:1;1976:47;2072:2;2067:3;2063:12;2060:1;2056:20;2050:4;2046:31;2036:41;;2127:81;2145:2;2138:5;2135:13;2127:81;;;2204:1;2190:16;;2171:1;2160:13;2127:81;;;2131:3;;1797:421;1706:518;;;:::o;2400:1299::-;2520:10;;-1:-1:-1;;;;;2542:30:1;;2539:56;;;2575:18;;:::i;:::-;2604:97;2694:6;2654:38;2686:4;2680:11;2654:38;:::i;:::-;2648:4;2604:97;:::i;:::-;2750:4;2781:2;2770:14;;2798:1;2793:649;;;;3486:1;3503:6;3500:89;;;-1:-1:-1;3555:19:1;;;3549:26;3500:89;-1:-1:-1;;2357:1:1;2353:11;;;2349:24;2345:29;2335:40;2381:1;2377:11;;;2332:57;3602:81;;2763:930;;2793:649;1653:1;1646:14;;;1690:4;1677:18;;-1:-1:-1;;2829:20:1;;;2947:222;2961:7;2958:1;2955:14;2947:222;;;3043:19;;;3037:26;3022:42;;3150:4;3135:20;;;;3103:1;3091:14;;;;2977:12;2947:222;;;2951:3;3197:6;3188:7;3185:19;3182:201;;;3258:19;;;3252:26;-1:-1:-1;;3341:1:1;3337:14;;;3353:3;3333:24;3329:37;3325:42;3310:58;3295:74;;3182:201;-1:-1:-1;;;;3429:1:1;3413:14;;;3409:22;3396:36;;-1:-1:-1;2400:1299:1:o;:::-;627:826:0;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a099132114610030575b600080fd5b61004361003e366004610133565b610055565b60405190815260200160405180910390f35b6000806100e1610084600060405160200161007091906101ec565b6040516020818303038152906040526100e8565b6040516bffffffffffffffffffffffff193360601b166020820152603401604051602081830303815290604052856040516020016100c291906102af565b60408051601f19818403018152908290526100709392916020016102cb565b9392505050565b60006008826040516020016100fd91906102af565b60408051601f198184030181529190528051602090910120901c92915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561014557600080fd5b813567ffffffffffffffff81111561015c57600080fd5b8201601f8101841361016d57600080fd5b803567ffffffffffffffff8111156101875761018761011d565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156101b6576101b661011d565b6040528181528282016020018610156101ce57600080fd5b81602084016020830137600091810160200191909152949350505050565b6000808354818160011c9050600182168061020857607f821691505b60208210810361022657634e487b7160e01b84526022600452602484fd5b80801561023a576001811461024f5761027f565b60ff198416875282151583028701945061027f565b60008881526020902060005b848110156102775781548982015260019091019060200161025b565b505082870194505b50929695505050505050565b60005b838110156102a657818101518382015260200161028e565b50506000910152565b600082516102c181846020870161028b565b9190910192915050565b838152600083516102e381602085016020880161028b565b808301905083516102fb81602084016020880161028b565b016020019594505050505056fea2646970667358221220ae92ee61ed080bbe411c58f9ecdc7150f51b1825718ffd2a35204bfa893c23c564736f6c634300081c0033","sourceMap":"627:826:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;984:467;;;;;;:::i;:::-;;:::i;:::-;;;1242:25:1;;;1230:2;1215:18;984:467:0;;;;;;;;1080:7;1099:25;1127:282;1174:37;1191:5;1174:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;:35;:37::i;:::-;1229:28;;-1:-1:-1;;1246:10:0;2642:2:1;2638:15;2634:53;1229:28:0;;;2622:66:1;2704:12;;1229:28:0;;;;;;;;;;;;1359:8;1342:26;;;;;;;;:::i;:::-;;;;-1:-1:-1;;1342:26:0;;;;;;;;;;1127:255;;;;1342:26;1127:255;;:::i;:282::-;1099:310;984:467;-1:-1:-1;;;984:467:0:o;302:145::-;366:7;439:1;427:5;410:23;;;;;;;;:::i;:::-;;;;-1:-1:-1;;410:23:0;;;;;;;;;400:34;;410:23;400:34;;;;392:48;;;302:145;-1:-1:-1;;302:145:0:o;14:127:1:-;75:10;70:3;66:20;63:1;56:31;106:4;103:1;96:15;130:4;127:1;120:15;146:945;215:6;268:2;256:9;247:7;243:23;239:32;236:52;;;284:1;281;274:12;236:52;324:9;311:23;357:18;349:6;346:30;343:50;;;389:1;386;379:12;343:50;412:22;;465:4;457:13;;453:27;-1:-1:-1;443:55:1;;494:1;491;484:12;443:55;534:2;521:16;560:18;552:6;549:30;546:56;;;582:18;;:::i;:::-;631:2;625:9;723:2;685:17;;-1:-1:-1;;681:31:1;;;714:2;677:40;673:54;661:67;;758:18;743:34;;779:22;;;740:62;737:88;;;805:18;;:::i;:::-;841:2;834:22;865;;;906:15;;;923:2;902:24;899:37;-1:-1:-1;896:57:1;;;949:1;946;939:12;896:57;1005:6;1000:2;996;992:11;987:2;979:6;975:15;962:50;1058:1;1032:19;;;1053:2;1028:28;1021:39;;;;1036:6;146:945;-1:-1:-1;;;;146:945:1:o;1404:1084::-;1532:3;1561:1;1594:6;1588:13;1624:3;1653:9;1650:1;1646:17;1636:27;;1713:1;1702:9;1698:17;1734:18;1724:61;;1778:4;1770:6;1766:17;1756:27;;1724:61;1831:2;1823:6;1820:14;1800:18;1797:38;1794:165;;-1:-1:-1;;;1858:33:1;;1914:4;1911:1;1904:15;1944:4;1865:3;1932:17;1794:165;1975:18;2002:133;;;;2149:1;2144:319;;;;1968:495;;2002:133;-1:-1:-1;;2035:24:1;;2023:37;;2108:14;;2101:22;2089:35;;2080:45;;;-1:-1:-1;2002:133:1;;2144:319;1351:1;1344:14;;;1388:4;1375:18;;2239:1;2253:164;2267:6;2264:1;2261:13;2253:164;;;2345:14;;2332:11;;;2325:35;2401:1;2388:15;;;;2289:2;2282:10;2253:164;;;2257:3;;2446:6;2441:3;2437:16;2430:23;;1968:495;-1:-1:-1;2479:3:1;;1404:1084;-1:-1:-1;;;;;;1404:1084:1:o;2727:250::-;2812:1;2822:113;2836:6;2833:1;2830:13;2822:113;;;2912:11;;;2906:18;2893:11;;;2886:39;2858:2;2851:10;2822:113;;;-1:-1:-1;;2969:1:1;2951:16;;2944:27;2727:250::o;2982:289::-;3113:3;3151:6;3145:13;3167:66;3226:6;3221:3;3214:4;3206:6;3202:17;3167:66;:::i;:::-;3249:16;;;;;2982:289;-1:-1:-1;;2982:289:1:o;3276:562::-;3509:6;3504:3;3497:19;3479:3;3545:6;3539:13;3561:73;3627:6;3622:2;3617:3;3613:12;3608:2;3600:6;3596:15;3561:73;:::i;:::-;3662:6;3657:3;3653:16;3643:26;;3700:6;3694:13;3716:74;3781:8;3776:2;3772;3768:11;3763:2;3755:6;3751:15;3716:74;:::i;:::-;3810:17;3829:2;3806:26;;3276:562;-1:-1:-1;;;;;3276:562:1:o","linkReferences":{}},"methodIdentifiers":{"generateExternalNullifier(string)":"a0991321"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_appId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"someText\",\"type\":\"string\"}],\"name\":\"generateExternalNullifier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"World\",\"kind\":\"dev\",\"methods\":{\"generateExternalNullifier(string)\":{\"params\":{\"someText\":\"A random string to be included\"},\"returns\":{\"_0\":\"The external nullifier\"}}},\"title\":\"ExternalNullifier\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructs the contract\"},\"generateExternalNullifier(string)\":{\"notice\":\"Generate an external nullifier to be used in tests\"}},\"notice\":\"A contract to test external nullifier generation. REMINDER TO UPDATE THE JSON ARTIFACTS WHEN UPDATING THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"walletkit-core/tests/contracts/external_nullifier.sol\":\"ExternalNullifier\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"walletkit-core/tests/contracts/external_nullifier.sol\":{\"keccak256\":\"0xe7f8ab9597a80e72184d32f25eaf76c488906d5bff6b66e54a8a75e54f56e075\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bf2426ea1b9a5f8caf4651f298344632a01ee36e0f37850d85e7c049ed3a1b46\",\"dweb:/ipfs/QmSXNFpCqW9QMwWgrA1sXADH8GKTpbePD3ispHqqVBMcjT\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_appId","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"someText","type":"string"}],"stateMutability":"view","type":"function","name":"generateExternalNullifier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]}],"devdoc":{"kind":"dev","methods":{"generateExternalNullifier(string)":{"params":{"someText":"A random string to be included"},"returns":{"_0":"The external nullifier"}}},"version":1},"userdoc":{"kind":"user","methods":{"constructor":{"notice":"Constructs the contract"},"generateExternalNullifier(string)":{"notice":"Generate an external nullifier to be used in tests"}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"walletkit-core/tests/contracts/external_nullifier.sol":"ExternalNullifier"},"evmVersion":"paris","libraries":{}},"sources":{"walletkit-core/tests/contracts/external_nullifier.sol":{"keccak256":"0xe7f8ab9597a80e72184d32f25eaf76c488906d5bff6b66e54a8a75e54f56e075","urls":["bzz-raw://bf2426ea1b9a5f8caf4651f298344632a01ee36e0f37850d85e7c049ed3a1b46","dweb:/ipfs/QmSXNFpCqW9QMwWgrA1sXADH8GKTpbePD3ispHqqVBMcjT"],"license":"MIT"}},"version":1},"id":0} \ No newline at end of file diff --git a/walletkit-core/tests/solidity.rs b/walletkit-core/tests/solidity.rs new file mode 100644 index 00000000..cc95e90e --- /dev/null +++ b/walletkit-core/tests/solidity.rs @@ -0,0 +1,45 @@ +use alloy::{ + providers::{ProviderBuilder, WalletProvider}, + sol, + sol_types::SolValue, +}; +use walletkit_core::proof::Context; + +sol!( + #[allow(missing_docs)] + #[sol(rpc)] + ExternalNullifier, + "tests/out/external_nullifier.sol/ExternalNullifier.json" +); + +#[tokio::test] +async fn test_compile_contracts() { + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .on_anvil_with_wallet(); + + let app_id = "app_10eb12bd96d8f7202892ff25f094c803".to_string(); + + let addr = provider.default_signer_address(); + + let contract = ExternalNullifier::deploy(&provider, app_id.clone()) + .await + .unwrap(); + + let contract = contract.clone(); + + let custom_action = + [addr.abi_encode_packed(), "test_text".abi_encode_packed()].concat(); + + let context = Context::new(app_id.as_bytes(), Some(custom_action)); + + let nullifier = contract + .generateExternalNullifier("test_text".to_string()) + .from(addr) + .call() + .await + .unwrap() + ._0; + + assert_eq!(nullifier, context.external_nullifier.as_inner()); +} From 4c2fe45b6dd6fb813e32eb398746b83274274c50 Mon Sep 17 00:00:00 2001 From: pdtfh <149602456+pdtfh@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:15:08 +0100 Subject: [PATCH 3/5] add foundry to CI --- .github/workflows/ci.yml | 3 +++ README.md | 10 ++++++++++ cspell.json | 2 ++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4dd943a4..e86943f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,6 +113,9 @@ jobs: run: | rustup update stable && rustup default stable + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + - name: Cache Cargo registry uses: actions/cache@v4 with: diff --git a/README.md b/README.md index ed50e1aa..65405eca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ # walletkit + WalletKit enables wallets to use World ID. + +## Tests + +To run all tests Foundry is required. Anvil is used for functional tests with Solidity. + +```bash +curl -L https://foundry.paradigm.xyz | bash +foundryup +``` diff --git a/cspell.json b/cspell.json index 65c46efe..0d89a06c 100644 --- a/cspell.json +++ b/cspell.json @@ -5,6 +5,8 @@ "ignorePaths": ["Cargo.toml"], "words": [ "aarch", + "clippy", + "foundryup", "ruint", "Uniffi", "WalletKit", From f4f54d0955ccd0a4bca73d78b19ebbdd5e595d25 Mon Sep 17 00:00:00 2001 From: pdtfh <149602456+pdtfh@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:34:20 +0100 Subject: [PATCH 4/5] branch merge post fix --- walletkit-core/tests/solidity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/walletkit-core/tests/solidity.rs b/walletkit-core/tests/solidity.rs index cc95e90e..1940c8a8 100644 --- a/walletkit-core/tests/solidity.rs +++ b/walletkit-core/tests/solidity.rs @@ -41,5 +41,5 @@ async fn test_compile_contracts() { .unwrap() ._0; - assert_eq!(nullifier, context.external_nullifier.as_inner()); + assert_eq!(nullifier, *context.external_nullifier); } From 2202bbbd00b735132e13d298afa39a36a9357365 Mon Sep 17 00:00:00 2001 From: pdtfh <149602456+pdtfh@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:14:10 +0100 Subject: [PATCH 5/5] improve the api --- walletkit-core/src/identity.rs | 2 +- walletkit-core/src/proof.rs | 54 ++++++++++++++++++++++---------- walletkit-core/tests/solidity.rs | 4 +-- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/walletkit-core/src/identity.rs b/walletkit-core/src/identity.rs index 809c6361..47e84368 100644 --- a/walletkit-core/src/identity.rs +++ b/walletkit-core/src/identity.rs @@ -40,7 +40,7 @@ mod tests { #[test] fn test() { let identity = Identity::new(b"not_a_real_secret"); - let context = Context::new(b"app_id", None); + let context = Context::new("app_id", None); let nullifier_hash = identity.generate_nullifier_hash(&context); println!("{}", nullifier_hash.to_hex_string()); } diff --git a/walletkit-core/src/proof.rs b/walletkit-core/src/proof.rs index ff15b9c8..e2e7487f 100644 --- a/walletkit-core/src/proof.rs +++ b/walletkit-core/src/proof.rs @@ -26,8 +26,25 @@ impl Context { /// #[must_use] #[uniffi::constructor] - pub fn new(app_id: &[u8], action: Option>) -> Self { - let mut pre_image = hash_to_field(app_id).abi_encode_packed(); + pub fn new(app_id: &str, action: Option) -> Self { + Self::new_from_bytes(app_id, action.map(std::string::String::into_bytes)) + } + + /// Initializes a `Proof::Context` where the `action` is provided as raw bytes. This is useful for advanced cases + /// where the `action` is an already ABI encoded value for on-chain usage. + /// See _walletkit-core/tests/solidity.rs_ for an example. + /// + /// Will compute the relevant external nullifier from the provided `app_id` and `action`. + /// + /// # Arguments + /// + /// * `app_id` - The ID of the application requesting proofs. This can be obtained from the Developer Portal. + /// * `action` - Optional. Custom incognito action being requested as raw bytes (*must be UTF-8*). + /// + #[must_use] + #[uniffi::constructor] + pub fn new_from_bytes(app_id: &str, action: Option>) -> Self { + let mut pre_image = hash_to_field(app_id.as_bytes()).abi_encode_packed(); if let Some(action) = action { pre_image.extend_from_slice(&action); @@ -47,15 +64,16 @@ mod tests { use super::*; #[test] - fn test_external_nullifier_hash_generation_no_action() { - let context = Context::new(b"app_369183bd38f1641b6964ab51d7a20434", None); + fn test_context_and_external_nullifier_hash_generation() { + let context = Context::new("app_369183bd38f1641b6964ab51d7a20434", None); assert_eq!( context.external_nullifier.to_hex_string(), "0x0073e4a6b670e81dc619b1f8703aa7491dc5aaadf75409aba0ac2414014c0227" ); + // note the same external nullifier hash is generated for an empty string action let context = - Context::new(b"app_369183bd38f1641b6964ab51d7a20434", Some(b"".to_vec())); + Context::new("app_369183bd38f1641b6964ab51d7a20434", Some(String::new())); assert_eq!( context.external_nullifier.to_hex_string(), "0x0073e4a6b670e81dc619b1f8703aa7491dc5aaadf75409aba0ac2414014c0227" @@ -67,8 +85,8 @@ mod tests { #[test] fn test_external_nullifier_hash_generation_string_action_staging() { let context = Context::new( - b"app_staging_45068dca85829d2fd90e2dd6f0bff997", - Some(b"test-action-qli8g".to_vec()), + "app_staging_45068dca85829d2fd90e2dd6f0bff997", + Some("test-action-qli8g".to_string()), ); assert_eq!( context.external_nullifier.to_hex_string(), @@ -79,20 +97,20 @@ mod tests { #[test] fn test_external_nullifier_hash_generation_string_action() { let context = Context::new( - b"app_10eb12bd96d8f7202892ff25f094c803", - Some(b"test-123123".to_vec()), + "app_10eb12bd96d8f7202892ff25f094c803", + Some("test-123123".to_string()), ); assert_eq!( context.external_nullifier.0, - // cspell:disable-next-line uint!( + // cspell:disable-next-line 0x0065ebab05692ff2e0816cc4c3b83216c33eaa4d906c6495add6323fe0e2dc89_U256 ) ); } #[test] - fn test_external_nullifier_hash_generation_with_complex_abi_encoded_values() { + fn test_external_nullifier_hash_generation_with_advanced_abi_encoded_values() { let custom_action = [ address!("541f3cc5772a64f2ba0a47e83236CcE2F089b188").abi_encode_packed(), U256::from(1).abi_encode_packed(), @@ -100,8 +118,10 @@ mod tests { ] .concat(); - let context = - Context::new(b"app_10eb12bd96d8f7202892ff25f094c803", Some(custom_action)); + let context = Context::new_from_bytes( + "app_10eb12bd96d8f7202892ff25f094c803", + Some(custom_action), + ); assert_eq!( context.external_nullifier.to_hex_string(), // expected output obtained from Solidity @@ -110,8 +130,8 @@ mod tests { } #[test] - fn test_external_nullifier_hash_generation_with_complex_abi_encoded_values_staging() - { + fn test_external_nullifier_hash_generation_with_advanced_abi_encoded_values_staging( + ) { let custom_action = [ "world".abi_encode_packed(), U256::from(1).abi_encode_packed(), @@ -119,8 +139,8 @@ mod tests { ] .concat(); - let context = Context::new( - b"app_staging_45068dca85829d2fd90e2dd6f0bff997", + let context = Context::new_from_bytes( + "app_staging_45068dca85829d2fd90e2dd6f0bff997", Some(custom_action), ); assert_eq!( diff --git a/walletkit-core/tests/solidity.rs b/walletkit-core/tests/solidity.rs index 1940c8a8..6b8125ba 100644 --- a/walletkit-core/tests/solidity.rs +++ b/walletkit-core/tests/solidity.rs @@ -13,7 +13,7 @@ sol!( ); #[tokio::test] -async fn test_compile_contracts() { +async fn test_advanced_external_nullifier_generation_on_chain() { let provider = ProviderBuilder::new() .with_recommended_fillers() .on_anvil_with_wallet(); @@ -31,7 +31,7 @@ async fn test_compile_contracts() { let custom_action = [addr.abi_encode_packed(), "test_text".abi_encode_packed()].concat(); - let context = Context::new(app_id.as_bytes(), Some(custom_action)); + let context = Context::new_from_bytes(&app_id, Some(custom_action)); let nullifier = contract .generateExternalNullifier("test_text".to_string())