Skip to content

Commit

Permalink
proof context / external nullifier generation
Browse files Browse the repository at this point in the history
  • Loading branch information
pdtfh committed Nov 21, 2024
1 parent 78b15bc commit 9ae6e7d
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions walletkit-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
4 changes: 2 additions & 2 deletions walletkit-core/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Identity {
/// [Protocol Reference](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#nullifier-hash).
#[must_use]
pub fn generate_nullifier_hash(&self, context: &Context) -> U256Wrapper {
generate_nullifier_hash(&self.0, context.external_nullifier).into()
generate_nullifier_hash(&self.0, context.external_nullifier.into()).into()
}
}

Expand All @@ -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());
}
Expand Down
100 changes: 94 additions & 6 deletions walletkit-core/src/proof.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,107 @@
use ruint::aliases::U256;
use alloy_core::sol_types::SolValue;
use semaphore::hash_to_field;

use crate::u256::U256Wrapper;

#[derive(Clone, PartialEq, Eq, Debug, uniffi::Object)]
pub struct Context {
pub external_nullifier: U256,
pub external_nullifier: U256Wrapper,
}

#[uniffi::export]
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
pub fn new(app_id: &[u8], action: Option<Vec<u8>>) -> 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: <https://github.com/worldcoin/world-id-docs/blob/main/src/pages/world-id/try.tsx>
#[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"
);
}
}
2 changes: 1 addition & 1 deletion walletkit-core/src/u256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,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]
Expand Down

0 comments on commit 9ae6e7d

Please sign in to comment.