From c64367e166ecbebb77c3b339e3398a947e0c7687 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Fri, 28 Aug 2026 15:35:53 +0200 Subject: [PATCH 1/4] Update World ID Protocol dependencies to 0.14 --- Cargo.lock | 84 ++++++++++++++----- Cargo.toml | 4 +- crates/walletkit-cli/src/commands/proof.rs | 62 ++++++++++---- .../walletkit-core/src/authenticator/mod.rs | 6 +- crates/walletkit-core/src/error.rs | 11 ++- ...of_request_credential_constraints_check.rs | 5 +- crates/walletkit-core/src/requests.rs | 5 +- .../tests/proof_generation_integration.rs | 9 +- crates/walletkit-testkit/src/lib.rs | 17 ++-- crates/walletkit-testkit/src/proof.rs | 14 ++-- crates/walletkit-testkit/tests/e2e.rs | 2 +- 11 files changed, 145 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1767498a..916838ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2311,6 +2311,16 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "coset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eb98d5e9155e2cf7cd942c8b3033097d4563b6fb0a00b9caecb74669555c058" +dependencies = [ + "ciborium", + "ciborium-io", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -7461,17 +7471,26 @@ name = "taceo-oprf" version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c10bf82ba41bbc8a6693362d67738145c77bdcec36345d85d4a86d2fb7dc44dc" +dependencies = [ + "taceo-oprf-types 0.15.0", +] + +[[package]] +name = "taceo-oprf" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50935dca161ff8ec1a0405b023639f2e6c181e2271ef41443abca1fe4be55444" dependencies = [ "taceo-oprf-client", "taceo-oprf-core", - "taceo-oprf-types", + "taceo-oprf-types 0.16.0", ] [[package]] name = "taceo-oprf-client" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc6179c5bad58f1210bd8872963960145227e8488dfedb4893538acecc5f8ae" +checksum = "ef8c7fbd38a4c78cbd172f71e3de826cafccae51c1a93c2777d87da73c055ded" dependencies = [ "ark-ec", "ciborium", @@ -7479,23 +7498,25 @@ dependencies = [ "getrandom 0.2.17", "gloo-net", "http", + "reqwest 0.13.4", "serde", "taceo-ark-babyjubjub", "taceo-oprf-core", - "taceo-oprf-types", + "taceo-oprf-types 0.16.0", "taceo-poseidon2", "thiserror 2.0.18", "tokio", "tokio-tungstenite", "tracing", + "url", "uuid", ] [[package]] name = "taceo-oprf-core" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be7f117e2bff79209ce40cdf4af6d566501cb1e63d2e1f9be6134a3bd3a3a2a3" +checksum = "e5627044f0bba8551bda54b0496010a3f1267297333ca70eb39491e767ff2ad9" dependencies = [ "ark-ec", "ark-ff 0.5.0", @@ -7532,6 +7553,25 @@ dependencies = [ "uuid", ] +[[package]] +name = "taceo-oprf-types" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a58191080b4456f5659722dd0abb14fa1edc739d52108858bda861c35dcb95" +dependencies = [ + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "async-trait", + "eyre", + "http", + "ruint", + "serde", + "taceo-ark-babyjubjub", + "taceo-ark-serde-compat", + "taceo-oprf-core", + "uuid", +] + [[package]] name = "taceo-poseidon2" version = "0.2.1" @@ -8496,7 +8536,7 @@ dependencies = [ "sha2 0.10.9", "strum 0.27.2", "subtle", - "taceo-oprf", + "taceo-oprf 0.17.2", "tempfile", "test-case", "thiserror 2.0.18", @@ -9060,9 +9100,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "world-id-authenticator" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc05e2d364f3613e562aef520913a0044b71e504c1d19e8c6b9d80e61bc5af8b" +checksum = "3a65b6afa935d2d538ef7eb816abd660cb7b5b6e70094019955880b75fd9c918" dependencies = [ "alloy", "anyhow", @@ -9084,8 +9124,7 @@ dependencies = [ "taceo-ark-babyjubjub", "taceo-eddsa-babyjubjub", "taceo-groth16-material", - "taceo-oprf", - "taceo-poseidon2", + "taceo-oprf 0.18.1", "thiserror 2.0.18", "tokio", "webpki-roots 1.0.8", @@ -9096,9 +9135,9 @@ dependencies = [ [[package]] name = "world-id-core" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e741ad4aa64d9a681ad4b325b0f49235a84af78af1f359dcbbbb66312286c43" +checksum = "db00ee9ca15e60998adb093170c34703ad41ef7e5df314e22c18f8dd6d6bd6ca" dependencies = [ "taceo-eddsa-babyjubjub", "world-id-authenticator", @@ -9109,9 +9148,9 @@ dependencies = [ [[package]] name = "world-id-primitives" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7430d4229c914b7136a028ad478dacc7983a8bfb926af9f5a4e5e31550d4f1cf" +checksum = "d76ac44fcbb959d6460462b29ee8798ef28baa13cea47ac8e2e9ea4edb22be3b" dependencies = [ "alloy", "alloy-primitives", @@ -9135,7 +9174,7 @@ dependencies = [ "taceo-ark-serde-compat", "taceo-circom-types", "taceo-eddsa-babyjubjub", - "taceo-oprf", + "taceo-oprf 0.18.1", "taceo-poseidon2", "thiserror 2.0.18", "url", @@ -9144,17 +9183,19 @@ dependencies = [ [[package]] name = "world-id-proof" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0530a43963153b34ba8a9f91a781c50771c8baef3a69bddfa230b75d2c84b3ff" +checksum = "2acca04a42f14cf1a5f3662de82218f5293013196ef6f464480e47172aeb3bad" dependencies = [ "ark-bn254", "ark-ec", "ark-ff 0.5.0", "ark-groth16", "ark-serialize 0.5.0", + "coset", "eyre", "once_cell", + "p256", "provekit-common", "provekit-prover", "provekit-r1cs-compiler", @@ -9169,8 +9210,7 @@ dependencies = [ "taceo-eddsa-babyjubjub", "taceo-groth16-material", "taceo-groth16-sol", - "taceo-oprf", - "taceo-poseidon2", + "taceo-oprf 0.18.1", "tar", "thiserror 2.0.18", "tracing", @@ -9181,9 +9221,9 @@ dependencies = [ [[package]] name = "world-id-registries" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47e1d0889ef5c5ee541621bb12cb4dfa64e3f0e3730c8fae08c075dfec6d67e" +checksum = "a3da86a790df7e1962dbba8f05b32c52e2c3fa27bbf5841ccc8d31338b9e67bb" dependencies = [ "alloy", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 5cd5f510..b0f948da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,8 +78,8 @@ zeroize = "1" zip = { version = "2", default-features = false } # world-id-protocol crates -world-id-core = { version = "0.13", default-features = false } -world-id-proof = { version = "0.13", default-features = false } +world-id-core = { version = "0.14", default-features = false } +world-id-proof = { version = "0.14", default-features = false } # internal walletkit-core = { version = "0.21.2", path = "crates/walletkit-core", default-features = false } diff --git a/crates/walletkit-cli/src/commands/proof.rs b/crates/walletkit-cli/src/commands/proof.rs index da8e9aff..557e04fb 100644 --- a/crates/walletkit-cli/src/commands/proof.rs +++ b/crates/walletkit-cli/src/commands/proof.rs @@ -13,7 +13,7 @@ use walletkit_testkit::proof::{ }; use walletkit_testkit::storage::create_artifact_source; use walletkit_testkit::utils::now_secs; -use world_id_core::primitives::{FieldElement, OwnershipProof, SessionId}; +use world_id_core::primitives::{FieldElement, OwnershipProof, SessionId, SessionRef}; use world_id_core::requests::{ ProofRequest as CoreProofRequest, ProofResponse as CoreProofResponse, ProofType, }; @@ -68,7 +68,7 @@ pub enum ProofCommand { expires_in: u64, /// Proof type to generate. #[arg(long, value_parser = parse_proof_type_arg, default_value = "uniqueness")] - proof_type: ProofType, + proof_type: TestProofType, /// Existing session ID for `--proof-type session`. #[arg(long, value_parser = parse_session_id_arg)] session_id: Option, @@ -107,6 +107,9 @@ pub enum ProofCommand { /// Credential `sub` (commitment) the proof claims ownership of, as a 32-byte hex field element. #[arg(long)] sub: String, + /// Context bound to the ownership proof, as a 32-byte hex field element. + #[arg(long)] + context: String, }, } @@ -128,11 +131,18 @@ fn read_file_or_stdin(path: &str) -> eyre::Result { } } -fn parse_proof_type_arg(value: &str) -> Result { +#[derive(Debug, Clone, Copy)] +pub enum TestProofType { + Uniqueness, + CreateSession, + Session, +} + +fn parse_proof_type_arg(value: &str) -> Result { match value.trim().to_ascii_lowercase().as_str() { - "uniqueness" => Ok(ProofType::Uniqueness), - "create-session" | "create_session" => Ok(ProofType::CreateSession), - "session" => Ok(ProofType::Session), + "uniqueness" => Ok(TestProofType::Uniqueness), + "create-session" | "create_session" => Ok(TestProofType::CreateSession), + "session" => Ok(TestProofType::Session), _ => Err("expected one of: uniqueness, create-session, session".to_string()), } } @@ -248,18 +258,23 @@ fn run_generate_test_request( issuer_schema_id: u64, signal: &str, expires_in: u64, - proof_type: ProofType, + proof_type: TestProofType, session_id: Option, ) -> eyre::Result<()> { - let session_id = match (proof_type, session_id) { - (ProofType::Uniqueness | ProofType::CreateSession, Some(_)) => { + let (proof_type, session_ref) = match (proof_type, session_id) { + (TestProofType::Uniqueness | TestProofType::CreateSession, Some(_)) => { eyre::bail!("--session-id is only valid with --proof-type session"); } - (ProofType::Session, None) => { + (TestProofType::Session, None) => { eyre::bail!("--session-id is required with --proof-type session"); } - (ProofType::Session, Some(session_id)) => Some(session_id), - (_, None) => None, + (TestProofType::Uniqueness, None) => (ProofType::Uniqueness, SessionRef::None), + (TestProofType::CreateSession, None) => { + (ProofType::Session, SessionRef::Create) + } + (TestProofType::Session, Some(session_id)) => { + (ProofType::Session, SessionRef::Existing(session_id)) + } }; let request = build_test_request( &TestEnv::default_staging(), @@ -267,7 +282,7 @@ fn run_generate_test_request( signal, expires_in, proof_type, - session_id, + session_ref, )?; let json = serde_json::to_string_pretty(&request)?; @@ -305,7 +320,7 @@ async fn run_test( signal, 300, ProofType::Uniqueness, - None, + SessionRef::None, )?; if !cli.json { @@ -361,6 +376,7 @@ fn run_verify_ownership( proof_path: &str, nonce: &str, sub: &str, + context: &str, ) -> eyre::Result<()> { let b64 = read_file_or_stdin(proof_path)?; let bytes = BASE64_URL_SAFE_NO_PAD @@ -371,11 +387,18 @@ fn run_verify_ownership( let nonce_fe = parse_field_element(nonce, "--nonce")?; let sub_fe = parse_field_element(sub, "--sub")?; + let context_fe = parse_field_element(context, "--context")?; let root = resolve_root(cli)?; let artifacts = create_artifact_source(&root); - let result = verify_ownership_proof(&proof, nonce_fe, sub_fe, artifacts.as_ref()); + let result = verify_ownership_proof( + &proof, + nonce_fe, + sub_fe, + context_fe, + artifacts.as_ref(), + ); let merkle_root = proof.merkle_root.to_string(); if cli.json { @@ -432,8 +455,11 @@ pub async fn run(cli: &Cli, action: &ProofCommand) -> eyre::Result<()> { signal, verifier_address, } => run_test(cli, signal, verifier_address.as_deref()).await, - ProofCommand::VerifyOwnership { proof, nonce, sub } => { - run_verify_ownership(cli, proof, nonce, sub) - } + ProofCommand::VerifyOwnership { + proof, + nonce, + sub, + context, + } => run_verify_ownership(cli, proof, nonce, sub, context), } } diff --git a/crates/walletkit-core/src/authenticator/mod.rs b/crates/walletkit-core/src/authenticator/mod.rs index 3773f233..31645086 100644 --- a/crates/walletkit-core/src/authenticator/mod.rs +++ b/crates/walletkit-core/src/authenticator/mod.rs @@ -646,6 +646,7 @@ impl Authenticator { proof_request .0 .session_id + .existing() .and_then(|session_id| { match self.store.get_session_seed(session_id.oprf_seed, now) { Ok(seed) => seed, @@ -698,6 +699,7 @@ impl Authenticator { /// /// # Arguments /// * `nonce` - A field element provided by the Issuer to prevent replay. + /// * `context` - A field element identifying the issuer operation being authorized. /// * `blinding_factor` - The credential blinding factor previously used to /// derive the credential `sub`. /// * `sub` - The credential `sub` (commitment) to prove ownership of. @@ -712,12 +714,13 @@ impl Authenticator { pub async fn prove_credential_sub( &self, nonce: &FieldElement, + context: &FieldElement, blinding_factor: &FieldElement, sub: &FieldElement, ) -> Result { #[cfg(target_arch = "wasm32")] { - let _ = (nonce, blinding_factor, sub); + let _ = (nonce, context, blinding_factor, sub); return Err(WalletKitError::Generic { error: "credential ownership proofs are not supported on wasm32" .to_string(), @@ -738,6 +741,7 @@ impl Authenticator { .inner .prove_credential_sub( nonce.0, + context.0, blinding_factor.0, sub.0, Some(inclusion_proof), diff --git a/crates/walletkit-core/src/error.rs b/crates/walletkit-core/src/error.rs index bb2b8cb8..f2df2278 100644 --- a/crates/walletkit-core/src/error.rs +++ b/crates/walletkit-core/src/error.rs @@ -226,6 +226,7 @@ impl From for WalletKitError { attribute: "index".to_string(), reason: "Provided index is out of bounds".to_string(), }, + PrimitiveError::SessionIdCommitmentMismatch => Self::SessionIdMismatch, } } } @@ -237,8 +238,8 @@ impl From for WalletKitError { WorldIdRequestAuthError::DuplicateNonce => Self::DuplicateNonce, WorldIdRequestAuthError::UnknownRp => Self::UnknownRp, WorldIdRequestAuthError::InactiveRp => Self::InactiveRp, - WorldIdRequestAuthError::TimestampTooOld => Self::TimestampTooOld, - WorldIdRequestAuthError::TimestampTooFarInFuture => { + WorldIdRequestAuthError::CreatedAtTooOld => Self::TimestampTooOld, + WorldIdRequestAuthError::CreatedAtTooFarInFuture => { Self::TimestampTooFarInFuture } WorldIdRequestAuthError::InvalidTimestamp => Self::InvalidTimestamp, @@ -311,8 +312,6 @@ impl From for WalletKitError { AuthenticatorError::ResponseValidationError(err) => { Self::ResponseValidation(err.to_string()) } - AuthenticatorError::SessionIdMismatch => Self::SessionIdMismatch, - AuthenticatorError::OhttpEncapsulationError(_) | AuthenticatorError::BhttpError(_) | AuthenticatorError::OhttpRelayError { .. } @@ -365,11 +364,11 @@ mod tests { (WorldIdRequestAuthError::UnknownRp, "unknown_rp"), (WorldIdRequestAuthError::InactiveRp, "inactive_rp"), ( - WorldIdRequestAuthError::TimestampTooOld, + WorldIdRequestAuthError::CreatedAtTooOld, "timestamp_too_old", ), ( - WorldIdRequestAuthError::TimestampTooFarInFuture, + WorldIdRequestAuthError::CreatedAtTooFarInFuture, "timestamp_too_far_in_future", ), ( diff --git a/crates/walletkit-core/src/proof_request_credential_constraints_check.rs b/crates/walletkit-core/src/proof_request_credential_constraints_check.rs index 895d1758..8667f611 100644 --- a/crates/walletkit-core/src/proof_request_credential_constraints_check.rs +++ b/crates/walletkit-core/src/proof_request_credential_constraints_check.rs @@ -186,9 +186,8 @@ mod tests { use super::*; use alloy_core::primitives::{Signature, U160}; - use taceo_oprf::types::OprfKeyId; use world_id_core::{ - primitives::rp::RpId, + primitives::{rp::RpId, OprfKeyId, SessionRef}, requests::{ ConstraintExpr, ConstraintNode, ProofRequest as CoreProofRequest, ProofType, RequestItem, RequestVersion, @@ -216,7 +215,7 @@ mod tests { expires_at: u64::MAX, rp_id: RpId::new(1), oprf_key_id: OprfKeyId::new(U160::from(1u64)), - session_id: None, + session_id: SessionRef::None, action: None, signature: Signature::test_signature(), nonce: CoreFieldElement::ZERO, diff --git a/crates/walletkit-core/src/requests.rs b/crates/walletkit-core/src/requests.rs index bfe90a87..2b3794f7 100644 --- a/crates/walletkit-core/src/requests.rs +++ b/crates/walletkit-core/src/requests.rs @@ -111,9 +111,8 @@ mod tests { use alloy::signers::{local::PrivateKeySigner, SignerSync}; use alloy_core::primitives::U160; use serde_json::Value; - use taceo_oprf::types::OprfKeyId; use world_id_core::{ - primitives::{rp::RpId, FieldElement}, + primitives::{rp::RpId, FieldElement, OprfKeyId, SessionRef}, requests::{ProofType, RequestItem, RequestVersion}, }; @@ -136,7 +135,7 @@ mod tests { expires_at: 1_700_000_300, rp_id: RpId::new(1), oprf_key_id: OprfKeyId::new(U160::from(1)), - session_id: None, + session_id: SessionRef::None, action: Some(FieldElement::from(1u64)), signature: test_signature(), nonce: FieldElement::from(2u64), diff --git a/crates/walletkit-core/tests/proof_generation_integration.rs b/crates/walletkit-core/tests/proof_generation_integration.rs index 7d08fbef..325321c8 100644 --- a/crates/walletkit-core/tests/proof_generation_integration.rs +++ b/crates/walletkit-core/tests/proof_generation_integration.rs @@ -122,8 +122,8 @@ async fn e2e_session_proof() -> Result<()> { schema_id, SIGNAL, REQUEST_TTL_SECS, - ProofType::CreateSession, - None, + ProofType::Session, + world_id_core::primitives::SessionRef::Create, ) .wrap_err("failed to build create-session request")?; let create_response = authenticator @@ -164,7 +164,7 @@ async fn e2e_session_proof() -> Result<()> { SIGNAL, REQUEST_TTL_SECS, ProofType::Session, - Some(session_id), + world_id_core::primitives::SessionRef::Existing(session_id), ) .wrap_err("failed to build session request")?; let session_response = authenticator @@ -197,8 +197,9 @@ async fn e2e_session_proof() -> Result<()> { .ok_or_else(|| eyre::eyre!("issued credential missing from store"))?; let sub = credential.sub(); let nonce = FieldElement::random(&mut OsRng).into(); + let context = FieldElement::random(&mut OsRng).into(); let ownership_proof = authenticator - .prove_credential_sub(&nonce, &blinding_factor, &sub) + .prove_credential_sub(&nonce, &context, &blinding_factor, &sub) .await .wrap_err("ownership proof generation failed")?; assert_eq!( diff --git a/crates/walletkit-testkit/src/lib.rs b/crates/walletkit-testkit/src/lib.rs index 0a714f76..d8da3502 100644 --- a/crates/walletkit-testkit/src/lib.rs +++ b/crates/walletkit-testkit/src/lib.rs @@ -21,7 +21,7 @@ use eyre::Context; use walletkit_core::{ storage::CredentialStore, Authenticator, Credential, FieldElement, }; -pub use world_id_core::primitives::SessionId; +pub use world_id_core::primitives::{SessionId, SessionRef}; pub use world_id_core::requests::ProofType; use crate::{ @@ -107,8 +107,8 @@ pub struct TestProofOutcome { pub verification: VerifyItemResult, /// Session ID from the proof response (`None` for uniqueness proofs). /// - /// For `ProofType::CreateSession` this is the newly created session, which - /// can be passed to a follow-up `ProofType::Session` request. + /// For a `ProofType::Session` request without an existing session ID, this + /// is the newly created session and can be passed to a follow-up request. pub session_id: Option, } @@ -156,9 +156,8 @@ pub async fn issue_credential( /// Registers an account, issues a credential of this type, generates a proof /// of `proof_type` for `signal`, and verifies it on-chain. /// -/// For `ProofType::Session`, pass the `session_id` of an existing session -/// (e.g. from a prior `ProofType::CreateSession` outcome); otherwise pass -/// `None`. +/// For `ProofType::Session`, pass an existing `session_id` to prove that +/// session, or `None` to create a new session. /// /// # Errors /// @@ -192,7 +191,11 @@ pub async fn generate_and_verify_test_proof( signal, REQUEST_TTL_SECS, proof_type, - session_id, + match (proof_type, session_id) { + (ProofType::Session, Some(session_id)) => SessionRef::Existing(session_id), + (ProofType::Session, None) => SessionRef::Create, + (ProofType::Uniqueness, _) => SessionRef::None, + }, ) .wrap_err("failed to build proof request")?; diff --git a/crates/walletkit-testkit/src/proof.rs b/crates/walletkit-testkit/src/proof.rs index 7cde7f52..6c6fe727 100644 --- a/crates/walletkit-testkit/src/proof.rs +++ b/crates/walletkit-testkit/src/proof.rs @@ -7,7 +7,7 @@ use alloy_core::primitives::U160; use eyre::WrapErr as _; use rand::rngs::OsRng; use uuid::Uuid; -use world_id_core::primitives::{rp::RpId, FieldElement, OprfKeyId, SessionId}; +use world_id_core::primitives::{rp::RpId, FieldElement, OprfKeyId, SessionRef}; use world_id_core::requests::{ ProofRequest, ProofResponse, ProofType, RequestItem, RequestVersion, }; @@ -48,20 +48,20 @@ sol!( /// Builds a proof [`ProofRequest`] signed by the RP key configured in `env`. /// /// The request expires at `created_at + expires_in`. For uniqueness proofs an `action` of `1` is set and -/// included in the RP signature. Pass an existing `session_id` for `ProofType::Session` proofs. +/// included in the RP signature. Use [`SessionRef::Create`] to create a session +/// or [`SessionRef::Existing`] to prove an existing session. /// /// # Errors /// /// Returns an error if the RP signer cannot be constructed from the configured -/// key, if signing the RP message fails, or if `proof_type` and `session_id` -/// are inconsistent (e.g. `ProofType::Session` without a `session_id`). +/// key or if signing the RP message fails. pub fn build_test_request( env: &TestEnv, issuer_schema_id: u64, signal: &str, expires_in: u64, proof_type: ProofType, - session_id: Option, + session_ref: SessionRef, ) -> eyre::Result { let nonce = FieldElement::random(&mut OsRng); let created_at = now_secs(); @@ -100,7 +100,7 @@ pub fn build_test_request( expires_at, rp_id: RpId::new(env.rp_id), oprf_key_id: OprfKeyId::new(U160::from(env.rp_id)), - session_id, + session_id: session_ref, action, signature, nonce, @@ -193,7 +193,7 @@ pub async fn verify_proof_onchain( .await .map(|_| ()) } - ProofType::CreateSession | ProofType::Session => { + ProofType::Session => { let session_nullifier = response_item.session_nullifier.ok_or_else(|| { eyre::eyre!("response item missing session_nullifier") diff --git a/crates/walletkit-testkit/tests/e2e.rs b/crates/walletkit-testkit/tests/e2e.rs index 46c78b61..ac898025 100644 --- a/crates/walletkit-testkit/tests/e2e.rs +++ b/crates/walletkit-testkit/tests/e2e.rs @@ -114,7 +114,7 @@ async fn e2e_session_proof() { &SESSION_TEST_SEED, root.path(), SIGNAL, - ProofType::CreateSession, + ProofType::Session, None, ) .await From b01bf13a4edfda83eae284c71a1bb276edc409e5 Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Fri, 28 Aug 2026 15:39:37 +0200 Subject: [PATCH 2/4] Align Taceo OPRF with World ID 0.14 --- Cargo.lock | 56 ++++++++++++++---------------------------------------- Cargo.toml | 3 ++- 2 files changed, 16 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 916838ad..9a5328e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2206,7 +2206,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2878,7 +2878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3796,7 +3796,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5713,7 +5713,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6241,7 +6241,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6321,7 +6321,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs 1.0.8", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7466,15 +7466,6 @@ dependencies = [ "ruint", ] -[[package]] -name = "taceo-oprf" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10bf82ba41bbc8a6693362d67738145c77bdcec36345d85d4a86d2fb7dc44dc" -dependencies = [ - "taceo-oprf-types 0.15.0", -] - [[package]] name = "taceo-oprf" version = "0.18.1" @@ -7483,7 +7474,7 @@ checksum = "50935dca161ff8ec1a0405b023639f2e6c181e2271ef41443abca1fe4be55444" dependencies = [ "taceo-oprf-client", "taceo-oprf-core", - "taceo-oprf-types 0.16.0", + "taceo-oprf-types", ] [[package]] @@ -7502,7 +7493,7 @@ dependencies = [ "serde", "taceo-ark-babyjubjub", "taceo-oprf-core", - "taceo-oprf-types 0.16.0", + "taceo-oprf-types", "taceo-poseidon2", "thiserror 2.0.18", "tokio", @@ -7534,25 +7525,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "taceo-oprf-types" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b3645c7a7592e8aacdb4ca7270e75da3cca6061ae012521f3cb0dd01ff0b16" -dependencies = [ - "ark-ff 0.5.0", - "ark-serialize 0.5.0", - "async-trait", - "eyre", - "http", - "ruint", - "serde", - "taceo-ark-babyjubjub", - "taceo-ark-serde-compat", - "taceo-oprf-core", - "uuid", -] - [[package]] name = "taceo-oprf-types" version = "0.16.0" @@ -7612,7 +7584,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8536,7 +8508,7 @@ dependencies = [ "sha2 0.10.9", "strum 0.27.2", "subtle", - "taceo-oprf 0.17.2", + "taceo-oprf", "tempfile", "test-case", "thiserror 2.0.18", @@ -8777,7 +8749,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -9124,7 +9096,7 @@ dependencies = [ "taceo-ark-babyjubjub", "taceo-eddsa-babyjubjub", "taceo-groth16-material", - "taceo-oprf 0.18.1", + "taceo-oprf", "thiserror 2.0.18", "tokio", "webpki-roots 1.0.8", @@ -9174,7 +9146,7 @@ dependencies = [ "taceo-ark-serde-compat", "taceo-circom-types", "taceo-eddsa-babyjubjub", - "taceo-oprf 0.18.1", + "taceo-oprf", "taceo-poseidon2", "thiserror 2.0.18", "url", @@ -9210,7 +9182,7 @@ dependencies = [ "taceo-eddsa-babyjubjub", "taceo-groth16-material", "taceo-groth16-sol", - "taceo-oprf 0.18.1", + "taceo-oprf", "tar", "thiserror 2.0.18", "tracing", diff --git a/Cargo.toml b/Cargo.toml index b0f948da..612ac373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,8 @@ sha2 = "0.10" sqlite-wasm-rs = "0.5" strum = "0.27" subtle = "2" -taceo-oprf = { version = "0.17", default-features = false } +# world-id-proof 0.14 uses Arkworks 0.5; taceo-oprf 0.18.2 moved to Arkworks 0.6. +taceo-oprf = { version = "=0.18.1", default-features = false } tempfile = "3" test-case = "3.3" thiserror = "2" From 4e851b68c96a261c80b672ffde6769973a34128c Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Fri, 28 Aug 2026 16:03:33 +0200 Subject: [PATCH 3/4] Complete World ID 0.14 API migration --- Cargo.lock | 1 + crates/walletkit-cli/src/commands/proof.rs | 35 ++++++------------- crates/walletkit-cli/tests/cli_tests.rs | 21 +++++------ .../walletkit-core/src/authenticator/mod.rs | 1 + 4 files changed, 21 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a5328e0..deb50575 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9083,6 +9083,7 @@ dependencies = [ "base64 0.22.1", "bhttp", "eyre", + "getrandom 0.2.17", "getrandom 0.3.4", "hex", "ohttp", diff --git a/crates/walletkit-cli/src/commands/proof.rs b/crates/walletkit-cli/src/commands/proof.rs index 557e04fb..abded586 100644 --- a/crates/walletkit-cli/src/commands/proof.rs +++ b/crates/walletkit-cli/src/commands/proof.rs @@ -68,8 +68,8 @@ pub enum ProofCommand { expires_in: u64, /// Proof type to generate. #[arg(long, value_parser = parse_proof_type_arg, default_value = "uniqueness")] - proof_type: TestProofType, - /// Existing session ID for `--proof-type session`. + proof_type: ProofType, + /// Existing session ID for `--proof-type session`; omit to create a session. #[arg(long, value_parser = parse_session_id_arg)] session_id: Option, }, @@ -131,19 +131,11 @@ fn read_file_or_stdin(path: &str) -> eyre::Result { } } -#[derive(Debug, Clone, Copy)] -pub enum TestProofType { - Uniqueness, - CreateSession, - Session, -} - -fn parse_proof_type_arg(value: &str) -> Result { +fn parse_proof_type_arg(value: &str) -> Result { match value.trim().to_ascii_lowercase().as_str() { - "uniqueness" => Ok(TestProofType::Uniqueness), - "create-session" | "create_session" => Ok(TestProofType::CreateSession), - "session" => Ok(TestProofType::Session), - _ => Err("expected one of: uniqueness, create-session, session".to_string()), + "uniqueness" => Ok(ProofType::Uniqueness), + "session" => Ok(ProofType::Session), + _ => Err("expected one of: uniqueness, session".to_string()), } } @@ -258,21 +250,16 @@ fn run_generate_test_request( issuer_schema_id: u64, signal: &str, expires_in: u64, - proof_type: TestProofType, + proof_type: ProofType, session_id: Option, ) -> eyre::Result<()> { let (proof_type, session_ref) = match (proof_type, session_id) { - (TestProofType::Uniqueness | TestProofType::CreateSession, Some(_)) => { + (ProofType::Uniqueness, Some(_)) => { eyre::bail!("--session-id is only valid with --proof-type session"); } - (TestProofType::Session, None) => { - eyre::bail!("--session-id is required with --proof-type session"); - } - (TestProofType::Uniqueness, None) => (ProofType::Uniqueness, SessionRef::None), - (TestProofType::CreateSession, None) => { - (ProofType::Session, SessionRef::Create) - } - (TestProofType::Session, Some(session_id)) => { + (ProofType::Uniqueness, None) => (ProofType::Uniqueness, SessionRef::None), + (ProofType::Session, None) => (ProofType::Session, SessionRef::Create), + (ProofType::Session, Some(session_id)) => { (ProofType::Session, SessionRef::Existing(session_id)) } }; diff --git a/crates/walletkit-cli/tests/cli_tests.rs b/crates/walletkit-cli/tests/cli_tests.rs index a11cd03d..6e4e4ea6 100644 --- a/crates/walletkit-cli/tests/cli_tests.rs +++ b/crates/walletkit-cli/tests/cli_tests.rs @@ -318,7 +318,7 @@ fn proof_generate_test_request_defaults_to_uniqueness() { } #[test] -fn proof_generate_test_request_supports_create_session() { +fn proof_generate_test_request_creates_session_without_id() { let output = Command::new(walletkit_bin()) .args([ "--json", @@ -327,7 +327,7 @@ fn proof_generate_test_request_supports_create_session() { "--issuer-schema-id", "47", "--proof-type", - "create-session", + "session", ]) .output() .expect("failed to run"); @@ -341,9 +341,9 @@ fn proof_generate_test_request_supports_create_session() { let parsed: serde_json::Value = serde_json::from_str(&stdout).expect("invalid json"); let data = &parsed["data"]; - assert_eq!(data["proof_type"], "create_session"); + assert_eq!(data["proof_type"], "session"); assert!(data["action"].is_null()); - assert!(data["session_id"].is_null()); + assert_eq!(data["session_id"], "create"); } #[test] @@ -383,7 +383,7 @@ fn proof_generate_test_request_supports_session() { } #[test] -fn proof_generate_test_request_requires_session_id_for_session() { +fn proof_generate_test_request_rejects_legacy_create_session_type() { let output = Command::new(walletkit_bin()) .args([ "--json", @@ -392,21 +392,16 @@ fn proof_generate_test_request_requires_session_id_for_session() { "--issuer-schema-id", "47", "--proof-type", - "session", + "create-session", ]) .output() .expect("failed to run"); assert!(!output.status.success()); let stderr = String::from_utf8_lossy(&output.stderr); - let parsed: serde_json::Value = - serde_json::from_str(&stderr).expect("invalid json"); assert!( - parsed["error"]["message"] - .as_str() - .unwrap() - .contains("--session-id is required"), - "expected missing session id error, got: {stderr}" + stderr.contains("expected one of: uniqueness, session"), + "expected invalid proof type error, got: {stderr}" ); } diff --git a/crates/walletkit-core/src/authenticator/mod.rs b/crates/walletkit-core/src/authenticator/mod.rs index 31645086..742e77ac 100644 --- a/crates/walletkit-core/src/authenticator/mod.rs +++ b/crates/walletkit-core/src/authenticator/mod.rs @@ -630,6 +630,7 @@ impl Authenticator { // Box::pin to heap-allocate the large upstream futures and keep this future below clippy::large_futures threshold let nullifier = Box::pin(self.inner.generate_nullifier( &proof_request.0, + now, Some(account_inclusion_proof.clone()), )) .await?; From 3da02731062c64c2d6ffbbef81bc1e0cfb304b5f Mon Sep 17 00:00:00 2001 From: Dzejkop Date: Fri, 28 Aug 2026 16:52:40 +0200 Subject: [PATCH 4/4] pin foundry tools to 1.7.1 --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c0dd9f3..5aec8d38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,8 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1.9.0 + with: + version: 1.7.1 # Install nargo - uses: noir-lang/noirup@7dbe69ccc78877f0200ffa5a40836c953d2cfd8f # v0.1.4 @@ -252,6 +254,8 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1.9.0 + with: + version: 1.7.1 # Install nargo - uses: noir-lang/noirup@7dbe69ccc78877f0200ffa5a40836c953d2cfd8f # v0.1.4