From b0849c511c41637182c7085c7b1f4e1506657f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Mon, 29 Sep 2025 13:56:22 +0200 Subject: [PATCH 1/9] add instrument tracing for submissions --- Cargo.lock | 142 +++++++++++++++++++++++++- Cargo.toml | 1 + ooniauth-core/Cargo.toml | 4 + ooniauth-core/examples/basic_usage.rs | 14 +++ ooniauth-core/src/submit.rs | 30 +++++- 5 files changed, 185 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53945ab..698ac07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -807,12 +807,30 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +[[package]] +name = "nu-ansi-term" +version = "0.50.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "num-bigint" version = "0.3.3" @@ -892,6 +910,9 @@ dependencies = [ "syn 2.0.106", "thiserror 2.0.16", "time", + "tracing", + "tracing-forest", + "tracing-subscriber", ] [[package]] @@ -900,6 +921,12 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "plotters" version = "0.3.7" @@ -1242,6 +1269,15 @@ dependencies = [ "keccak", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1285,8 +1321,6 @@ dependencies = [ [[package]] name = "sigma-proofs" version = "0.1.0-sigma" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe0d134228911458aa039f90582b9e512b06d193aa8fc460c78135367a18388" dependencies = [ "ahash", "ff", @@ -1300,10 +1334,17 @@ dependencies = [ "sha3", "subtle", "thiserror 1.0.69", + "tracing", "zerocopy", "zeroize", ] +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "strsim" version = "0.11.1" @@ -1384,6 +1425,15 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "time" version = "0.3.44" @@ -1425,6 +1475,79 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-forest" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" +dependencies = [ + "smallvec", + "thiserror 1.0.69", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "typenum" version = "1.18.0" @@ -1443,6 +1566,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.5" @@ -1608,6 +1737,15 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 0033d50..67b5a8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ resolver = "2" [patch.crates-io] cmz = { path = "include/cmz" } sigma-compiler-core = { path = "include/sigma-compiler/sigma-compiler-core" } +sigma-proofs = { path = "include/sigma-proofs" } \ No newline at end of file diff --git a/ooniauth-core/Cargo.toml b/ooniauth-core/Cargo.toml index 02e4107..31beeb0 100644 --- a/ooniauth-core/Cargo.toml +++ b/ooniauth-core/Cargo.toml @@ -20,9 +20,12 @@ subtle = "2.6.1" thiserror = "2.0.12" syn = "2.0.103" hex = "0.4" +tracing = "0.1" [dev-dependencies] criterion = { version = "0.5"} +tracing-subscriber = { version = "0.3", features = ["env-filter", "registry"] } +tracing-forest = "0.1" [[example]] name = "basic_usage" @@ -32,3 +35,4 @@ test = true [[bench]] name = "bench_server" harness = false + diff --git a/ooniauth-core/examples/basic_usage.rs b/ooniauth-core/examples/basic_usage.rs index 69220d9..040f00a 100644 --- a/ooniauth-core/examples/basic_usage.rs +++ b/ooniauth-core/examples/basic_usage.rs @@ -2,8 +2,22 @@ use std::time::Instant; use hex; use ooniauth_core::{scalar_u32, ServerState, UserState}; +use tracing_forest::ForestLayer; +use tracing_forest::util::LevelFilter; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::{EnvFilter, Registry}; fn main() -> Result<(), Box> { + // Initialize tracing with forest layer for runtime display + let env_filter = EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env_lossy(); + + Registry::default() + .with(env_filter) + .with(ForestLayer::default()) + .init(); let mut rng = rand::thread_rng(); println!("=== Anonymous Credential Example ===\n"); diff --git a/ooniauth-core/src/submit.rs b/ooniauth-core/src/submit.rs index 55f8cdd..452f8d8 100644 --- a/ooniauth-core/src/submit.rs +++ b/ooniauth-core/src/submit.rs @@ -8,6 +8,7 @@ use curve25519_dalek::RistrettoPoint; use group::{Group, GroupEncoding}; use rand::{CryptoRng, RngCore}; use sha2::Sha512; +use tracing::{instrument, trace, debug}; const SESSION_ID: &[u8] = b"submit"; @@ -24,6 +25,7 @@ muCMZProtocol!(submit, measurement_count_range: std::ops::Range, ) -> Result<((submit::Request, submit::ClientState), [u8; 32]), CredentialError> { + trace!("Starting submit request"); + debug!("Age range: {:?}, Measurement count range: {:?}", age_range, measurement_count_range); cmz_group_init(G::hash_from_bytes::(b"CMZ Generator A")); // Get the current credential @@ -45,8 +49,10 @@ impl UserState { // Domain-specific generator and NYM computation let domain_str = format!("ooni.org/{}/{}", probe_cc, probe_asn); + trace!("Computing DOMAIN for: {}", domain_str); let DOMAIN = G::hash_from_bytes::(domain_str.as_bytes()); let NYM = Old.nym_id.unwrap() * DOMAIN; + debug!("NYM computed successfully"); // Ensure the credential timestamp is within the allowed range let age: u32 = match scalar_u32(&Old.age.unwrap()) { @@ -115,9 +121,16 @@ impl UserState { NYM, }; + trace!("Preparing submit proof with params"); match submit::prepare(rng, SESSION_ID, &Old, New, ¶ms) { - Ok(req_state) => Ok((req_state, NYM.compress().to_bytes())), - Err(_) => Err(CredentialError::CMZError(CMZError::CliProofFailed)), + Ok(req_state) => { + debug!("Submit request prepared successfully"); + Ok((req_state, NYM.compress().to_bytes())) + } + Err(_) => { + debug!("Failed to prepare submit request"); + Err(CredentialError::CMZError(CMZError::CliProofFailed)) + } } } @@ -139,6 +152,7 @@ impl UserState { } impl ServerState { + #[instrument(skip(self, rng, req))] pub fn handle_submit( &mut self, rng: &mut (impl RngCore + CryptoRng), @@ -149,6 +163,8 @@ impl ServerState { age_range: std::ops::Range, measurement_count_range: std::ops::Range, ) -> Result { + trace!("Server handling submit request"); + debug!("Age range: {:?}, Measurement count range: {:?}", age_range, measurement_count_range); let reqbytes = req.as_bytes(); let recvreq = submit::Request::try_from(&reqbytes[..]).unwrap(); @@ -189,8 +205,14 @@ impl ServerState { Ok(()) }, ) { - Ok((response, (_old_cred, _new_cred))) => Ok(response), - Err(e) => Err(e), + Ok((response, (_old_cred, _new_cred))) => { + debug!("Submit request verified successfully"); + Ok(response) + } + Err(e) => { + debug!("Submit request verification failed: {:?}", e); + Err(e) + } } } } From 16db81d13ba17e7f48abe694961187c87ef61b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Mon, 19 Jan 2026 11:44:28 -0800 Subject: [PATCH 2/9] create ios test --- Cargo.lock | 10 +- Cargo.toml | 5 +- ios/OoniAuthApp.xcodeproj/project.pbxproj | 642 ++++++++++++++++++ .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 35 + ios/OoniAuthApp/Assets.xcassets/Contents.json | 6 + ios/OoniAuthApp/ContentView.swift | 51 ++ ios/OoniAuthApp/OoniAuthAppApp.swift | 10 + .../Preview Assets.xcassets/Contents.json | 6 + ios/OoniAuthAppTests/OoniAuthAppTests.swift | 8 + .../OoniAuthAppUITests.swift | 13 + .../OoniAuthAppUITestsLaunchTests.swift | 12 + ios/OoniAuthBindings/.gitignore | 1 + ios/OoniAuthBindings/OoniAuthFFI.swift | 17 + ios/OoniAuthBindings/README.md | 7 + ios/README.md | 20 + ios/build-ffi.sh | 37 + ios/noir_multiplier2.json | 1 + ios/noir_multiplier2.srs | 0 ios/noir_multiplier2.vk | 0 ios/plonk_fibonacci_pk.bin | 0 ios/plonk_fibonacci_srs.bin | 0 ios/plonk_fibonacci_vk.bin | 0 ooniauth-ffi/Cargo.toml | 12 + ooniauth-ffi/include/ooniauth_ffi.h | 15 + ooniauth-ffi/src/lib.rs | 127 ++++ 26 files changed, 1043 insertions(+), 3 deletions(-) create mode 100644 ios/OoniAuthApp.xcodeproj/project.pbxproj create mode 100644 ios/OoniAuthApp/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 ios/OoniAuthApp/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/OoniAuthApp/Assets.xcassets/Contents.json create mode 100644 ios/OoniAuthApp/ContentView.swift create mode 100644 ios/OoniAuthApp/OoniAuthAppApp.swift create mode 100644 ios/OoniAuthApp/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 ios/OoniAuthAppTests/OoniAuthAppTests.swift create mode 100644 ios/OoniAuthAppUITests/OoniAuthAppUITests.swift create mode 100644 ios/OoniAuthAppUITests/OoniAuthAppUITestsLaunchTests.swift create mode 100644 ios/OoniAuthBindings/.gitignore create mode 100644 ios/OoniAuthBindings/OoniAuthFFI.swift create mode 100644 ios/OoniAuthBindings/README.md create mode 100644 ios/README.md create mode 100755 ios/build-ffi.sh create mode 100644 ios/noir_multiplier2.json create mode 100644 ios/noir_multiplier2.srs create mode 100644 ios/noir_multiplier2.vk create mode 100644 ios/plonk_fibonacci_pk.bin create mode 100644 ios/plonk_fibonacci_srs.bin create mode 100644 ios/plonk_fibonacci_vk.bin create mode 100644 ooniauth-ffi/Cargo.toml create mode 100644 ooniauth-ffi/include/ooniauth_ffi.h create mode 100644 ooniauth-ffi/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 698ac07..ce1163a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,6 +915,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "ooniauth-ffi" +version = "0.1.0" +dependencies = [ + "hex", + "ooniauth-core", + "rand", +] + [[package]] name = "oorandom" version = "11.1.5" @@ -1334,7 +1343,6 @@ dependencies = [ "sha3", "subtle", "thiserror 1.0.69", - "tracing", "zerocopy", "zeroize", ] diff --git a/Cargo.toml b/Cargo.toml index 67b5a8c..11a1de4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [workspace] members = [ - "ooniauth-core" + "ooniauth-core", + "ooniauth-ffi" ] resolver = "2" [patch.crates-io] cmz = { path = "include/cmz" } sigma-compiler-core = { path = "include/sigma-compiler/sigma-compiler-core" } -sigma-proofs = { path = "include/sigma-proofs" } \ No newline at end of file +sigma-proofs = { path = "include/sigma-proofs" } diff --git a/ios/OoniAuthApp.xcodeproj/project.pbxproj b/ios/OoniAuthApp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..73511e8 --- /dev/null +++ b/ios/OoniAuthApp.xcodeproj/project.pbxproj @@ -0,0 +1,642 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 2A4190692DF1CCE6004F1A4F /* noir_multiplier2.json in Resources */ = {isa = PBXBuildFile; fileRef = 2A4190682DF1CCE6004F1A4F /* noir_multiplier2.json */; }; + 2A41906B2DF1CCED004F1A4F /* noir_multiplier2.srs in Resources */ = {isa = PBXBuildFile; fileRef = 2A41906A2DF1CCED004F1A4F /* noir_multiplier2.srs */; }; + 2A5992332CC7750C00135402 /* plonk_fibonacci_vk.bin in Resources */ = {isa = PBXBuildFile; fileRef = 2A5992322CC7750C00135402 /* plonk_fibonacci_vk.bin */; }; + 2A5992342CC7750C00135402 /* plonk_fibonacci_srs.bin in Resources */ = {isa = PBXBuildFile; fileRef = 2A5992312CC7750C00135402 /* plonk_fibonacci_srs.bin */; }; + 2A5992352CC7750C00135402 /* plonk_fibonacci_pk.bin in Resources */ = {isa = PBXBuildFile; fileRef = 2A5992302CC7750C00135402 /* plonk_fibonacci_pk.bin */; }; + 2A59923A2CC77A7E00135402 /* OoniAuthFFI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5992362CC77A7E00135402 /* OoniAuthFFI.swift */; }; + 37AB9B142EB3AEE700EDF5DE /* OoniAuthFFI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */; settings = {ATTRIBUTES = (Required, ); }; }; + 37AB9B152EB3AEE700EDF5DE /* OoniAuthFFI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + E11808962E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */ = {isa = PBXBuildFile; fileRef = E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */; }; + E11808972E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */ = {isa = PBXBuildFile; fileRef = E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */; }; + E11808982E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */ = {isa = PBXBuildFile; fileRef = E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2A5991FD2CC7722A00135402 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2A5991E42CC7722900135402 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2A5991EB2CC7722900135402; + remoteInfo = OoniAuthApp; + }; + 2A5992072CC7722A00135402 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2A5991E42CC7722900135402 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2A5991EB2CC7722900135402; + remoteInfo = OoniAuthApp; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 37AB9B162EB3AEE700EDF5DE /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 37AB9B152EB3AEE700EDF5DE /* OoniAuthFFI.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2A4190682DF1CCE6004F1A4F /* noir_multiplier2.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = noir_multiplier2.json; sourceTree = ""; }; + 2A41906A2DF1CCED004F1A4F /* noir_multiplier2.srs */ = {isa = PBXFileReference; lastKnownFileType = file; path = noir_multiplier2.srs; sourceTree = ""; }; + 2A5991EC2CC7722900135402 /* OoniAuthApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OoniAuthApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2A5991FC2CC7722A00135402 /* OoniAuthAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OoniAuthAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 2A5992062CC7722A00135402 /* OoniAuthAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OoniAuthAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 2A5992302CC7750C00135402 /* plonk_fibonacci_pk.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = plonk_fibonacci_pk.bin; sourceTree = ""; }; + 2A5992312CC7750C00135402 /* plonk_fibonacci_srs.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = plonk_fibonacci_srs.bin; sourceTree = ""; }; + 2A5992322CC7750C00135402 /* plonk_fibonacci_vk.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = plonk_fibonacci_vk.bin; sourceTree = ""; }; + 2A5992362CC77A7E00135402 /* OoniAuthFFI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OoniAuthFFI.swift; sourceTree = ""; }; + 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = OoniAuthFFI.xcframework; sourceTree = ""; }; + E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */ = {isa = PBXFileReference; lastKnownFileType = file; path = noir_multiplier2.vk; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 2A5991EE2CC7722900135402 /* OoniAuthApp */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = OoniAuthApp; + sourceTree = ""; + }; + 2A5991FF2CC7722A00135402 /* OoniAuthAppTests */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = OoniAuthAppTests; + sourceTree = ""; + }; + 2A5992092CC7722A00135402 /* OoniAuthAppUITests */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = OoniAuthAppUITests; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2A5991E92CC7722900135402 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 37AB9B142EB3AEE700EDF5DE /* OoniAuthFFI.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A5991F92CC7722A00135402 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A5992032CC7722A00135402 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2A5991E32CC7722900135402 = { + isa = PBXGroup; + children = ( + 2A5991EE2CC7722900135402 /* OoniAuthApp */, + 2A5991FF2CC7722A00135402 /* OoniAuthAppTests */, + 2A5992092CC7722A00135402 /* OoniAuthAppUITests */, + 2A5991ED2CC7722900135402 /* Products */, + 2A5992382CC77A7E00135402 /* OoniAuthBindings */, + 2A5992302CC7750C00135402 /* plonk_fibonacci_pk.bin */, + 2A5992312CC7750C00135402 /* plonk_fibonacci_srs.bin */, + 2A5992322CC7750C00135402 /* plonk_fibonacci_vk.bin */, + 2A4190682DF1CCE6004F1A4F /* noir_multiplier2.json */, + 2A41906A2DF1CCED004F1A4F /* noir_multiplier2.srs */, + E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */, + ); + sourceTree = ""; + }; + 2A5991ED2CC7722900135402 /* Products */ = { + isa = PBXGroup; + children = ( + 2A5991EC2CC7722900135402 /* OoniAuthApp.app */, + 2A5991FC2CC7722A00135402 /* OoniAuthAppTests.xctest */, + 2A5992062CC7722A00135402 /* OoniAuthAppUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 2A5992382CC77A7E00135402 /* OoniAuthBindings */ = { + isa = PBXGroup; + children = ( + 2A5992362CC77A7E00135402 /* OoniAuthFFI.swift */, + 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */, + ); + path = OoniAuthBindings; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2A5991EB2CC7722900135402 /* OoniAuthApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2A5992102CC7722A00135402 /* Build configuration list for PBXNativeTarget "OoniAuthApp" */; + buildPhases = ( + 2A5991E82CC7722900135402 /* Sources */, + 2A5991E92CC7722900135402 /* Frameworks */, + 2A5991EA2CC7722900135402 /* Resources */, + 37AB9B162EB3AEE700EDF5DE /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 2A5991EE2CC7722900135402 /* OoniAuthApp */, + ); + name = OoniAuthApp; + packageProductDependencies = ( + ); + productName = OoniAuthApp; + productReference = 2A5991EC2CC7722900135402 /* OoniAuthApp.app */; + productType = "com.apple.product-type.application"; + }; + 2A5991FB2CC7722A00135402 /* OoniAuthAppTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2A5992132CC7722A00135402 /* Build configuration list for PBXNativeTarget "OoniAuthAppTests" */; + buildPhases = ( + 2A5991F82CC7722A00135402 /* Sources */, + 2A5991F92CC7722A00135402 /* Frameworks */, + 2A5991FA2CC7722A00135402 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 2A5991FE2CC7722A00135402 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 2A5991FF2CC7722A00135402 /* OoniAuthAppTests */, + ); + name = OoniAuthAppTests; + packageProductDependencies = ( + ); + productName = OoniAuthAppTests; + productReference = 2A5991FC2CC7722A00135402 /* OoniAuthAppTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 2A5992052CC7722A00135402 /* OoniAuthAppUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2A5992162CC7722A00135402 /* Build configuration list for PBXNativeTarget "OoniAuthAppUITests" */; + buildPhases = ( + 2A5992022CC7722A00135402 /* Sources */, + 2A5992032CC7722A00135402 /* Frameworks */, + 2A5992042CC7722A00135402 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 2A5992082CC7722A00135402 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 2A5992092CC7722A00135402 /* OoniAuthAppUITests */, + ); + name = OoniAuthAppUITests; + packageProductDependencies = ( + ); + productName = OoniAuthAppUITests; + productReference = 2A5992062CC7722A00135402 /* OoniAuthAppUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2A5991E42CC7722900135402 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1600; + LastUpgradeCheck = 2600; + TargetAttributes = { + 2A5991EB2CC7722900135402 = { + CreatedOnToolsVersion = 16.0; + }; + 2A5991FB2CC7722A00135402 = { + CreatedOnToolsVersion = 16.0; + TestTargetID = 2A5991EB2CC7722900135402; + }; + 2A5992052CC7722A00135402 = { + CreatedOnToolsVersion = 16.0; + TestTargetID = 2A5991EB2CC7722900135402; + }; + }; + }; + buildConfigurationList = 2A5991E72CC7722900135402 /* Build configuration list for PBXProject "OoniAuthApp" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2A5991E32CC7722900135402; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 2A5991ED2CC7722900135402 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2A5991EB2CC7722900135402 /* OoniAuthApp */, + 2A5991FB2CC7722A00135402 /* OoniAuthAppTests */, + 2A5992052CC7722A00135402 /* OoniAuthAppUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2A5991EA2CC7722900135402 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A5992332CC7750C00135402 /* plonk_fibonacci_vk.bin in Resources */, + E11808972E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */, + 2A5992342CC7750C00135402 /* plonk_fibonacci_srs.bin in Resources */, + 2A41906B2DF1CCED004F1A4F /* noir_multiplier2.srs in Resources */, + 2A5992352CC7750C00135402 /* plonk_fibonacci_pk.bin in Resources */, + 2A4190692DF1CCE6004F1A4F /* noir_multiplier2.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A5991FA2CC7722A00135402 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E11808982E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A5992042CC7722A00135402 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E11808962E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2A5991E82CC7722900135402 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A59923A2CC77A7E00135402 /* OoniAuthFFI.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A5991F82CC7722A00135402 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A5992022CC7722A00135402 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2A5991FE2CC7722A00135402 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2A5991EB2CC7722900135402 /* OoniAuthApp */; + targetProxy = 2A5991FD2CC7722A00135402 /* PBXContainerItemProxy */; + }; + 2A5992082CC7722A00135402 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2A5991EB2CC7722900135402 /* OoniAuthApp */; + targetProxy = 2A5992072CC7722A00135402 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 2A59920E2CC7722A00135402 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-lc++"; + SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2A59920F2CC7722A00135402 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = "-lc++"; + SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2A5992112CC7722A00135402 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"OoniAuthApp/Preview Content\""; + DEVELOPMENT_TEAM = 8DN4QDS23Z; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ooni.OoniAuthApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2A5992122CC7722A00135402 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"OoniAuthApp/Preview Content\""; + DEVELOPMENT_TEAM = 8DN4QDS23Z; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ooni.OoniAuthApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 2A5992142CC7722A00135402 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 8DN4QDS23Z; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ooni.OoniAuthAppTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OoniAuthApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/OoniAuthApp"; + }; + name = Debug; + }; + 2A5992152CC7722A00135402 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 8DN4QDS23Z; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ooni.OoniAuthAppTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OoniAuthApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/OoniAuthApp"; + }; + name = Release; + }; + 2A5992172CC7722A00135402 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 8DN4QDS23Z; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ooni.OoniAuthAppUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = OoniAuthApp; + }; + name = Debug; + }; + 2A5992182CC7722A00135402 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 8DN4QDS23Z; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ooni.OoniAuthAppUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = OoniAuthApp; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2A5991E72CC7722900135402 /* Build configuration list for PBXProject "OoniAuthApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A59920E2CC7722A00135402 /* Debug */, + 2A59920F2CC7722A00135402 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2A5992102CC7722A00135402 /* Build configuration list for PBXNativeTarget "OoniAuthApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A5992112CC7722A00135402 /* Debug */, + 2A5992122CC7722A00135402 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2A5992132CC7722A00135402 /* Build configuration list for PBXNativeTarget "OoniAuthAppTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A5992142CC7722A00135402 /* Debug */, + 2A5992152CC7722A00135402 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2A5992162CC7722A00135402 /* Build configuration list for PBXNativeTarget "OoniAuthAppUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A5992172CC7722A00135402 /* Debug */, + 2A5992182CC7722A00135402 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2A5991E42CC7722900135402 /* Project object */; +} diff --git a/ios/OoniAuthApp/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/OoniAuthApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/ios/OoniAuthApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/OoniAuthApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/OoniAuthApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2305880 --- /dev/null +++ b/ios/OoniAuthApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/OoniAuthApp/Assets.xcassets/Contents.json b/ios/OoniAuthApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ios/OoniAuthApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/OoniAuthApp/ContentView.swift b/ios/OoniAuthApp/ContentView.swift new file mode 100644 index 0000000..c1563c8 --- /dev/null +++ b/ios/OoniAuthApp/ContentView.swift @@ -0,0 +1,51 @@ +import SwiftUI + +struct ContentView: View { + @State private var log = "Tap Run Demo to execute the Rust flow via FFI." + @State private var isRunning = false + + var body: some View { + VStack(alignment: .leading, spacing: 12) { + Text("OONI Auth Demo") + .font(.title2) + .fontWeight(.semibold) + + Text("Runs the basic_usage flow from Rust and prints the result below.") + .font(.subheadline) + .foregroundStyle(.secondary) + + Button(action: runDemo) { + HStack { + if isRunning { + ProgressView() + } + Text(isRunning ? "Running..." : "Run Demo") + } + } + .disabled(isRunning) + + Divider() + + ScrollView { + Text(log) + .frame(maxWidth: .infinity, alignment: .leading) + .textSelection(.enabled) + .padding(.vertical, 4) + } + } + .padding() + } + + private func runDemo() { + isRunning = true + log = "Running..." + + DispatchQueue.global(qos: .userInitiated).async { + let output = OoniAuthFFI.runBasicUsage() + DispatchQueue.main.async { + log = output + isRunning = false + } + } + } +} diff --git a/ios/OoniAuthApp/OoniAuthAppApp.swift b/ios/OoniAuthApp/OoniAuthAppApp.swift new file mode 100644 index 0000000..44a9dce --- /dev/null +++ b/ios/OoniAuthApp/OoniAuthAppApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct OoniAuthAppApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/ios/OoniAuthApp/Preview Content/Preview Assets.xcassets/Contents.json b/ios/OoniAuthApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ios/OoniAuthApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/OoniAuthAppTests/OoniAuthAppTests.swift b/ios/OoniAuthAppTests/OoniAuthAppTests.swift new file mode 100644 index 0000000..5e13f8a --- /dev/null +++ b/ios/OoniAuthAppTests/OoniAuthAppTests.swift @@ -0,0 +1,8 @@ +import Testing +@testable import OoniAuthApp + +struct OoniAuthAppTests { + @Test func example() async throws { + // Placeholder test for the app target. + } +} diff --git a/ios/OoniAuthAppUITests/OoniAuthAppUITests.swift b/ios/OoniAuthAppUITests/OoniAuthAppUITests.swift new file mode 100644 index 0000000..ad248f3 --- /dev/null +++ b/ios/OoniAuthAppUITests/OoniAuthAppUITests.swift @@ -0,0 +1,13 @@ +import XCTest + +final class OoniAuthAppUITests: XCTestCase { + override func setUpWithError() throws { + continueAfterFailure = false + } + + @MainActor + func testExample() throws { + let app = XCUIApplication() + app.launch() + } +} diff --git a/ios/OoniAuthAppUITests/OoniAuthAppUITestsLaunchTests.swift b/ios/OoniAuthAppUITests/OoniAuthAppUITestsLaunchTests.swift new file mode 100644 index 0000000..69fdc7a --- /dev/null +++ b/ios/OoniAuthAppUITests/OoniAuthAppUITestsLaunchTests.swift @@ -0,0 +1,12 @@ +import XCTest + +final class OoniAuthAppUITestsLaunchTests: XCTestCase { + @MainActor + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/ios/OoniAuthBindings/.gitignore b/ios/OoniAuthBindings/.gitignore new file mode 100644 index 0000000..b7b7aa2 --- /dev/null +++ b/ios/OoniAuthBindings/.gitignore @@ -0,0 +1 @@ +OoniAuthFFI.xcframework/ diff --git a/ios/OoniAuthBindings/OoniAuthFFI.swift b/ios/OoniAuthBindings/OoniAuthFFI.swift new file mode 100644 index 0000000..cff8689 --- /dev/null +++ b/ios/OoniAuthBindings/OoniAuthFFI.swift @@ -0,0 +1,17 @@ +import Foundation + +@_silgen_name("ooniauth_run_basic_usage") +private func ooniauth_run_basic_usage() -> UnsafeMutablePointer? + +@_silgen_name("ooniauth_string_free") +private func ooniauth_string_free(_ ptr: UnsafeMutablePointer?) + +enum OoniAuthFFI { + static func runBasicUsage() -> String { + guard let raw = ooniauth_run_basic_usage() else { + return "error: FFI returned null pointer" + } + defer { ooniauth_string_free(raw) } + return String(cString: raw) + } +} diff --git a/ios/OoniAuthBindings/README.md b/ios/OoniAuthBindings/README.md new file mode 100644 index 0000000..a47a6b6 --- /dev/null +++ b/ios/OoniAuthBindings/README.md @@ -0,0 +1,7 @@ +This folder is the home for the generated iOS xcframework produced from the Rust FFI crate. + +Generate it with: + + ./ios/build-ffi.sh + +The script will place `OoniAuthFFI.xcframework` in this directory. diff --git a/ios/README.md b/ios/README.md new file mode 100644 index 0000000..15ab00f --- /dev/null +++ b/ios/README.md @@ -0,0 +1,20 @@ +# iOS app + +This folder contains a SwiftUI app that calls the Rust demo flow through a C ABI FFI. + +## Build the FFI framework + +1. Install the iOS Rust targets (once): + + rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios + +2. Build the xcframework: + + ./ios/build-ffi.sh + +This writes `ios/OoniAuthBindings/OoniAuthFFI.xcframework`. + +## Run the app + +Open `ios/OoniAuthApp.xcodeproj` in Xcode and run the `OoniAuthApp` target. +The app has a single "Run Demo" button that executes the Rust `basic_usage` flow via FFI. diff --git a/ios/build-ffi.sh b/ios/build-ffi.sh new file mode 100755 index 0000000..dda145e --- /dev/null +++ b/ios/build-ffi.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT_DIR="$ROOT/ios/OoniAuthBindings" +HEADER_DIR="$ROOT/ooniauth-ffi/include" + +build_target() { + local target="$1" + cargo build -p ooniauth-ffi --release --target "$target" +} + +build_target aarch64-apple-ios +build_target aarch64-apple-ios-sim +build_target x86_64-apple-ios + +LIB_DEVICE="$ROOT/target/aarch64-apple-ios/release/libooniauth_ffi.a" +LIB_SIM="$ROOT/target/aarch64-apple-ios-sim/release/libooniauth_ffi.a" +LIB_SIM_X86="$ROOT/target/x86_64-apple-ios/release/libooniauth_ffi.a" +LIB_SIM_UNIVERSAL="$ROOT/target/ios-sim-universal/libooniauth_ffi.a" + +mkdir -p "$(dirname "$LIB_SIM_UNIVERSAL")" +if command -v lipo >/dev/null 2>&1; then + lipo -create "$LIB_SIM" "$LIB_SIM_X86" -output "$LIB_SIM_UNIVERSAL" +else + echo "error: lipo not found; cannot create universal simulator library" >&2 + exit 1 +fi + +rm -rf "$OUT_DIR/OoniAuthFFI.xcframework" + +xcodebuild -create-xcframework \ + -library "$LIB_DEVICE" -headers "$HEADER_DIR" \ + -library "$LIB_SIM_UNIVERSAL" -headers "$HEADER_DIR" \ + -output "$OUT_DIR/OoniAuthFFI.xcframework" + +echo "Generated $OUT_DIR/OoniAuthFFI.xcframework" diff --git a/ios/noir_multiplier2.json b/ios/noir_multiplier2.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/ios/noir_multiplier2.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/ios/noir_multiplier2.srs b/ios/noir_multiplier2.srs new file mode 100644 index 0000000..e69de29 diff --git a/ios/noir_multiplier2.vk b/ios/noir_multiplier2.vk new file mode 100644 index 0000000..e69de29 diff --git a/ios/plonk_fibonacci_pk.bin b/ios/plonk_fibonacci_pk.bin new file mode 100644 index 0000000..e69de29 diff --git a/ios/plonk_fibonacci_srs.bin b/ios/plonk_fibonacci_srs.bin new file mode 100644 index 0000000..e69de29 diff --git a/ios/plonk_fibonacci_vk.bin b/ios/plonk_fibonacci_vk.bin new file mode 100644 index 0000000..e69de29 diff --git a/ooniauth-ffi/Cargo.toml b/ooniauth-ffi/Cargo.toml new file mode 100644 index 0000000..11b7c70 --- /dev/null +++ b/ooniauth-ffi/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "ooniauth-ffi" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "staticlib"] + +[dependencies] +hex = "0.4" +ooniauth-core = { path = "../ooniauth-core" } +rand = "0.8.5" diff --git a/ooniauth-ffi/include/ooniauth_ffi.h b/ooniauth-ffi/include/ooniauth_ffi.h new file mode 100644 index 0000000..e381dcc --- /dev/null +++ b/ooniauth-ffi/include/ooniauth_ffi.h @@ -0,0 +1,15 @@ +#ifndef OONIAUTH_FFI_H +#define OONIAUTH_FFI_H + +#ifdef __cplusplus +extern "C" { +#endif + +char *ooniauth_run_basic_usage(void); +void ooniauth_string_free(char *ptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OONIAUTH_FFI_H diff --git a/ooniauth-ffi/src/lib.rs b/ooniauth-ffi/src/lib.rs new file mode 100644 index 0000000..deef4b2 --- /dev/null +++ b/ooniauth-ffi/src/lib.rs @@ -0,0 +1,127 @@ +use std::ffi::{c_char, CString}; + +use ooniauth_core::registration::UserAuthCredential; +use ooniauth_core::{scalar_u32, ServerState, UserState}; + +fn push_line(log: &mut String, line: &str) { + log.push_str(line); + log.push('\n'); +} + +fn log_credential( + log: &mut String, + label: &str, + cred: &UserAuthCredential, +) -> Result<(), String> { + push_line(log, ""); + push_line(log, label); + + let nym_id = cred + .nym_id + .ok_or_else(|| "missing nym_id in credential".to_string())?; + let age = cred + .age + .ok_or_else(|| "missing age in credential".to_string())?; + let measurement_count = cred + .measurement_count + .ok_or_else(|| "missing measurement_count in credential".to_string())?; + + push_line(log, &format!("nym_id: {}", hex::encode(nym_id.to_bytes()))); + + let age_value = scalar_u32(&age).ok_or_else(|| "age is not a u32".to_string())?; + push_line(log, &format!("age: {}", age_value)); + + let measurement_value = scalar_u32(&measurement_count) + .ok_or_else(|| "measurement_count is not a u32".to_string())?; + push_line(log, &format!("measurement_count: {}", measurement_value)); + + Ok(()) +} + +fn run_basic_usage_demo() -> Result { + let mut log = String::new(); + push_line(&mut log, "=== OONI Auth Demo ==="); + + let mut rng = rand::thread_rng(); + let mut server = ServerState::new(&mut rng); + let public_params = server.public_parameters(); + push_line(&mut log, "Initialized server"); + + let mut user = UserState::new(public_params); + push_line(&mut log, "Initialized user"); + + let (reg_request, reg_state) = user + .request(&mut rng) + .map_err(|e| format!("registration request failed: {e:?}"))?; + let reg_response = server + .open_registration(reg_request) + .map_err(|e| format!("registration response failed: {e:?}"))?; + user.handle_response(reg_state, reg_response) + .map_err(|e| format!("registration finalize failed: {e:?}"))?; + push_line(&mut log, "Registration complete"); + + match user.get_credential() { + Some(cred) => log_credential(&mut log, "Initial credential", cred)?, + None => return Err("credential missing after registration".to_string()), + } + + let probe_cc = "US".to_string(); + let probe_asn = "AS1234".to_string(); + let today = server.today(); + let age_range = (today - 30)..(today + 1); + let measurement_count_range = 0..100; + + let ((submit_request, submit_state), nym) = user + .submit_request( + &mut rng, + probe_cc.clone(), + probe_asn.clone(), + age_range.clone(), + measurement_count_range.clone(), + ) + .map_err(|e| format!("submit request failed: {e:?}"))?; + push_line(&mut log, "Submit request created"); + + let submit_response = server + .handle_submit( + &mut rng, + submit_request, + &nym, + &probe_cc, + &probe_asn, + age_range, + measurement_count_range, + ) + .map_err(|e| format!("submit handling failed: {e:?}"))?; + user.handle_submit_response(submit_state, submit_response) + .map_err(|e| format!("submit finalize failed: {e:?}"))?; + push_line(&mut log, "Submit complete"); + + match user.get_credential() { + Some(cred) => log_credential(&mut log, "Updated credential", cred)?, + None => return Err("credential missing after submit".to_string()), + } + + Ok(log) +} + +#[no_mangle] +pub extern "C" fn ooniauth_run_basic_usage() -> *mut c_char { + let output = match run_basic_usage_demo() { + Ok(log) => log, + Err(err) => format!("error: {err}"), + }; + + CString::new(output) + .unwrap_or_else(|_| CString::new("error: output contained nul byte").unwrap()) + .into_raw() +} + +/// Caller must pass the pointer returned by `ooniauth_run_basic_usage`. +#[no_mangle] +pub unsafe extern "C" fn ooniauth_string_free(ptr: *mut c_char) { + if ptr.is_null() { + return; + } + drop(CString::from_raw(ptr)); +} From d348c9d8e469a2b5ec9ff72ecd7f9b466699c581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Mon, 19 Jan 2026 11:52:35 -0800 Subject: [PATCH 3/9] remove old files --- ios/OoniAuthApp.xcodeproj/project.pbxproj | 28 ----------------------- ios/noir_multiplier2.json | 1 - ios/noir_multiplier2.srs | 0 ios/noir_multiplier2.vk | 0 ios/plonk_fibonacci_pk.bin | 0 ios/plonk_fibonacci_srs.bin | 0 ios/plonk_fibonacci_vk.bin | 0 7 files changed, 29 deletions(-) delete mode 100644 ios/noir_multiplier2.json delete mode 100644 ios/noir_multiplier2.srs delete mode 100644 ios/noir_multiplier2.vk delete mode 100644 ios/plonk_fibonacci_pk.bin delete mode 100644 ios/plonk_fibonacci_srs.bin delete mode 100644 ios/plonk_fibonacci_vk.bin diff --git a/ios/OoniAuthApp.xcodeproj/project.pbxproj b/ios/OoniAuthApp.xcodeproj/project.pbxproj index 73511e8..c791b15 100644 --- a/ios/OoniAuthApp.xcodeproj/project.pbxproj +++ b/ios/OoniAuthApp.xcodeproj/project.pbxproj @@ -7,17 +7,9 @@ objects = { /* Begin PBXBuildFile section */ - 2A4190692DF1CCE6004F1A4F /* noir_multiplier2.json in Resources */ = {isa = PBXBuildFile; fileRef = 2A4190682DF1CCE6004F1A4F /* noir_multiplier2.json */; }; - 2A41906B2DF1CCED004F1A4F /* noir_multiplier2.srs in Resources */ = {isa = PBXBuildFile; fileRef = 2A41906A2DF1CCED004F1A4F /* noir_multiplier2.srs */; }; - 2A5992332CC7750C00135402 /* plonk_fibonacci_vk.bin in Resources */ = {isa = PBXBuildFile; fileRef = 2A5992322CC7750C00135402 /* plonk_fibonacci_vk.bin */; }; - 2A5992342CC7750C00135402 /* plonk_fibonacci_srs.bin in Resources */ = {isa = PBXBuildFile; fileRef = 2A5992312CC7750C00135402 /* plonk_fibonacci_srs.bin */; }; - 2A5992352CC7750C00135402 /* plonk_fibonacci_pk.bin in Resources */ = {isa = PBXBuildFile; fileRef = 2A5992302CC7750C00135402 /* plonk_fibonacci_pk.bin */; }; 2A59923A2CC77A7E00135402 /* OoniAuthFFI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5992362CC77A7E00135402 /* OoniAuthFFI.swift */; }; 37AB9B142EB3AEE700EDF5DE /* OoniAuthFFI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */; settings = {ATTRIBUTES = (Required, ); }; }; 37AB9B152EB3AEE700EDF5DE /* OoniAuthFFI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - E11808962E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */ = {isa = PBXBuildFile; fileRef = E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */; }; - E11808972E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */ = {isa = PBXBuildFile; fileRef = E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */; }; - E11808982E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */ = {isa = PBXBuildFile; fileRef = E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,17 +44,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 2A4190682DF1CCE6004F1A4F /* noir_multiplier2.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = noir_multiplier2.json; sourceTree = ""; }; - 2A41906A2DF1CCED004F1A4F /* noir_multiplier2.srs */ = {isa = PBXFileReference; lastKnownFileType = file; path = noir_multiplier2.srs; sourceTree = ""; }; 2A5991EC2CC7722900135402 /* OoniAuthApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OoniAuthApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2A5991FC2CC7722A00135402 /* OoniAuthAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OoniAuthAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 2A5992062CC7722A00135402 /* OoniAuthAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OoniAuthAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 2A5992302CC7750C00135402 /* plonk_fibonacci_pk.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = plonk_fibonacci_pk.bin; sourceTree = ""; }; - 2A5992312CC7750C00135402 /* plonk_fibonacci_srs.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = plonk_fibonacci_srs.bin; sourceTree = ""; }; - 2A5992322CC7750C00135402 /* plonk_fibonacci_vk.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = plonk_fibonacci_vk.bin; sourceTree = ""; }; 2A5992362CC77A7E00135402 /* OoniAuthFFI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OoniAuthFFI.swift; sourceTree = ""; }; 2A5992372CC77A7E00135402 /* OoniAuthFFI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = OoniAuthFFI.xcframework; sourceTree = ""; }; - E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */ = {isa = PBXFileReference; lastKnownFileType = file; path = noir_multiplier2.vk; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ @@ -117,12 +103,6 @@ 2A5992092CC7722A00135402 /* OoniAuthAppUITests */, 2A5991ED2CC7722900135402 /* Products */, 2A5992382CC77A7E00135402 /* OoniAuthBindings */, - 2A5992302CC7750C00135402 /* plonk_fibonacci_pk.bin */, - 2A5992312CC7750C00135402 /* plonk_fibonacci_srs.bin */, - 2A5992322CC7750C00135402 /* plonk_fibonacci_vk.bin */, - 2A4190682DF1CCE6004F1A4F /* noir_multiplier2.json */, - 2A41906A2DF1CCED004F1A4F /* noir_multiplier2.srs */, - E11808952E5CBDB000B8B284 /* noir_multiplier2.vk */, ); sourceTree = ""; }; @@ -266,12 +246,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2A5992332CC7750C00135402 /* plonk_fibonacci_vk.bin in Resources */, - E11808972E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */, - 2A5992342CC7750C00135402 /* plonk_fibonacci_srs.bin in Resources */, - 2A41906B2DF1CCED004F1A4F /* noir_multiplier2.srs in Resources */, - 2A5992352CC7750C00135402 /* plonk_fibonacci_pk.bin in Resources */, - 2A4190692DF1CCE6004F1A4F /* noir_multiplier2.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -279,7 +253,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - E11808982E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -287,7 +260,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - E11808962E5CBDB000B8B284 /* noir_multiplier2.vk in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/noir_multiplier2.json b/ios/noir_multiplier2.json deleted file mode 100644 index 9e26dfe..0000000 --- a/ios/noir_multiplier2.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/ios/noir_multiplier2.srs b/ios/noir_multiplier2.srs deleted file mode 100644 index e69de29..0000000 diff --git a/ios/noir_multiplier2.vk b/ios/noir_multiplier2.vk deleted file mode 100644 index e69de29..0000000 diff --git a/ios/plonk_fibonacci_pk.bin b/ios/plonk_fibonacci_pk.bin deleted file mode 100644 index e69de29..0000000 diff --git a/ios/plonk_fibonacci_srs.bin b/ios/plonk_fibonacci_srs.bin deleted file mode 100644 index e69de29..0000000 diff --git a/ios/plonk_fibonacci_vk.bin b/ios/plonk_fibonacci_vk.bin deleted file mode 100644 index e69de29..0000000 From e9ba0e36a7c1053211d237af3c31c8765c6a8717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Fri, 19 Sep 2025 16:38:51 +0200 Subject: [PATCH 4/9] fix pointers to local copies of cmz. --- Cargo.lock | 141 ++++++++++----------------------------- ooniauth-core/Cargo.toml | 10 ++- 2 files changed, 45 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3369877..cfc463a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,6 +25,18 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -264,10 +276,11 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cmz" -version = "0.1.0-rc2" -source = "git+https://github.com/sigma-rs/cmz#de6781d47f94dd58934bebf1a8a30b0b05e85e16" +version = "0.1.0-rc1" dependencies = [ + "bincode", "cmz-derive", + "curve25519-dalek", "ff", "generic_static", "group", @@ -277,15 +290,16 @@ dependencies = [ "serde", "serde_bytes", "serde_with", + "sha2", "sigma-compiler", - "thiserror 2.0.17", + "thiserror 2.0.12", ] [[package]] name = "cmz-core" -version = "0.1.0-rc2" +version = "0.1.0-rc1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4a2a2128f7d96b1f9fec3f985079f0ca7799b8fb2f270139916a0e4a7412cd" +checksum = "974f6d2467d3e238ddb63c9b49426352719ac4feeb15a5ada06b80b53102fa17" dependencies = [ "clap", "darling 0.20.11", @@ -297,12 +311,12 @@ dependencies = [ [[package]] name = "cmz-derive" -version = "0.1.0-rc2" +version = "0.1.0-rc1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9382d9aa6d7e68453df90df78d2719674f8faa78c524131c4e8b9d0361e55bc6" +checksum = "28731764e311044c05e270c6970756b8a7a6d060742a433b91e1e7c8e1d9ffff" dependencies = [ "cmz-core", - "darling 0.20.11", + "darling", "proc-macro2", "quote", "syn 2.0.106", @@ -832,6 +846,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "log" version = "0.4.28" @@ -939,22 +959,6 @@ dependencies = [ "libm", ] -[[package]] -name = "numpy" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2dba356160b54f5371b550575b78130a54718b4c6e46b3f33a6da74a27e78b" -dependencies = [ - "libc", - "ndarray", - "num-complex", - "num-integer", - "num-traits", - "pyo3", - "pyo3-build-config", - "rustc-hash", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -990,79 +994,6 @@ dependencies = [ "time", ] -[[package]] -name = "ooniauth_py" -version = "0.1.0" -dependencies = [ - "base64", - "bincode", - "cmz", - "ooniauth-core", - "pyo3", - "pyo3-stub-gen", - "rand", - "serde", - "thiserror 2.0.17", -] - -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "ordered-float" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" -dependencies = [ - "num-traits", -] - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - [[package]] name = "powerfmt" version = "0.2.0" @@ -1502,9 +1433,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "sigma-compiler" -version = "0.1.0-rc2" +version = "0.1.0-rc1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5916890ed39d5bb79e0c9f21043fd44fadd9387b58d52c033ffe61108ca5332" +checksum = "c8ba895a9c1e72f3303fe7a371a0eb8b86ba50b00431faafc2a8909698af196c" dependencies = [ "group", "rand", @@ -1515,9 +1446,9 @@ dependencies = [ [[package]] name = "sigma-compiler-core" -version = "0.1.0-rc2" +version = "0.1.0-rc1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc19242949b28e1efafe2bbd5f55c9db8b9cd7aaadbb797868aa7864bd405a97" +checksum = "d4ea72a5142e1f78fdc1be3cef3e5124d01266eb223317008f5af7fe86ab3b70" dependencies = [ "clap", "prettyplease", @@ -1528,12 +1459,12 @@ dependencies = [ [[package]] name = "sigma-compiler-derive" -version = "0.1.0-rc2" +version = "0.1.0-rc1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6df1acaaf98084f800ba3583880bf708428c71a959a492664a1a1ff0f83af59" +checksum = "d3ff778120ecfe50f6d997c5f5bcac6bef74f6234e28a01966df6e501b1f1b19" dependencies = [ "sigma-compiler-core", - "syn 2.0.106", + "syn 2.0.103", ] [[package]] @@ -1545,7 +1476,7 @@ dependencies = [ "ahash", "ff", "group", - "hashbrown 0.15.5", + "hashbrown 0.15.4", "keccak", "num-bigint 0.4.6", "num-traits", diff --git a/ooniauth-core/Cargo.toml b/ooniauth-core/Cargo.toml index 84cbb41..aecaea9 100644 --- a/ooniauth-core/Cargo.toml +++ b/ooniauth-core/Cargo.toml @@ -3,8 +3,16 @@ name = "ooniauth-core" version = "0.1.0" edition = "2021" +[patch.crates-io] +cmz = { path = "../cmz" } +cmz-derive = { path = "include/cmz" } +cmz-core = { path = "include/cmz" } +sigma-compiler = { path = "include/sigma-compiler" } +sigma-compiler-derive = { path = "include/sigma-compiler" } +sigma-compiler-core = { path = "include/sigma-compiler" } + [dependencies] -cmz = {workspace = true} +cmz = { version = "0.1.0-rc1", path = "../include/cmz" } curve25519-dalek = { version = "4", features = ["digest", "group", "rand_core", "serde"] } ff = "0.13.1" group = "0.13.0" From 28536b5841d669bfb319973e7d5848124891e0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Mon, 19 Jan 2026 12:09:12 -0800 Subject: [PATCH 5/9] fix --- Cargo.lock | 25 ++----------------------- ooniauth-core/Cargo.toml | 11 +---------- ooniauth-ffi/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a434773..f226b54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,27 +262,6 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" -[[package]] -name = "cmz" -version = "0.1.0-rc1" -dependencies = [ - "bincode", - "cmz-derive", - "curve25519-dalek", - "ff", - "generic_static", - "group", - "hex", - "lazy_static", - "rand", - "serde", - "serde_bytes", - "serde_with", - "sha2", - "sigma-compiler", - "thiserror 2.0.18", -] - [[package]] name = "cmz" version = "0.1.0-rc2" @@ -1016,7 +995,7 @@ version = "0.1.0" dependencies = [ "bincode", "chrono", - "cmz 0.1.0-rc1", + "cmz", "criterion", "curve25519-dalek", "ff", @@ -1051,7 +1030,7 @@ version = "0.1.0" dependencies = [ "base64", "bincode", - "cmz 0.1.0-rc2", + "cmz", "ooniauth-core", "pyo3", "pyo3-stub-gen", diff --git a/ooniauth-core/Cargo.toml b/ooniauth-core/Cargo.toml index 6d6bf37..f8ae3d4 100644 --- a/ooniauth-core/Cargo.toml +++ b/ooniauth-core/Cargo.toml @@ -3,16 +3,8 @@ name = "ooniauth-core" version = "0.1.0" edition = "2021" -[patch.crates-io] -cmz = { path = "../cmz" } -cmz-derive = { path = "include/cmz" } -cmz-core = { path = "include/cmz" } -sigma-compiler = { path = "include/sigma-compiler" } -sigma-compiler-derive = { path = "include/sigma-compiler" } -sigma-compiler-core = { path = "include/sigma-compiler" } - [dependencies] -cmz = { version = "0.1.0-rc1", path = "../include/cmz" } +cmz = { workspace = true } curve25519-dalek = { version = "4", features = ["digest", "group", "rand_core", "serde"] } ff = "0.13.1" group = "0.13.0" @@ -42,4 +34,3 @@ test = true [[bench]] name = "bench_server" harness = false - diff --git a/ooniauth-ffi/src/lib.rs b/ooniauth-ffi/src/lib.rs index deef4b2..b5ddb8a 100644 --- a/ooniauth-ffi/src/lib.rs +++ b/ooniauth-ffi/src/lib.rs @@ -67,7 +67,7 @@ fn run_basic_usage_demo() -> Result { let probe_cc = "US".to_string(); let probe_asn = "AS1234".to_string(); - let today = server.today(); + let today = ServerState::today(); let age_range = (today - 30)..(today + 1); let measurement_count_range = 0..100; From 1f77607eb7388173734dc44726b791f50b95798d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Mon, 19 Jan 2026 12:32:55 -0800 Subject: [PATCH 6/9] trace info --- Cargo.lock | 2 + ooniauth-ffi/Cargo.toml | 2 + ooniauth-ffi/src/lib.rs | 88 ++++++++++++++++++++++++++++++++++++++--- ooniauth-py/Cargo.toml | 2 +- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f226b54..18bc1fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1022,6 +1022,8 @@ dependencies = [ "hex", "ooniauth-core", "rand", + "tracing-forest", + "tracing-subscriber", ] [[package]] diff --git a/ooniauth-ffi/Cargo.toml b/ooniauth-ffi/Cargo.toml index 11b7c70..ab1d257 100644 --- a/ooniauth-ffi/Cargo.toml +++ b/ooniauth-ffi/Cargo.toml @@ -10,3 +10,5 @@ crate-type = ["cdylib", "staticlib"] hex = "0.4" ooniauth-core = { path = "../ooniauth-core" } rand = "0.8.5" +tracing-forest = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter", "registry"] } diff --git a/ooniauth-ffi/src/lib.rs b/ooniauth-ffi/src/lib.rs index b5ddb8a..52c0ba5 100644 --- a/ooniauth-ffi/src/lib.rs +++ b/ooniauth-ffi/src/lib.rs @@ -1,7 +1,29 @@ use std::ffi::{c_char, CString}; +use std::sync::Once; +use std::time::Instant; use ooniauth_core::registration::UserAuthCredential; use ooniauth_core::{scalar_u32, ServerState, UserState}; +use tracing_forest::util::LevelFilter; +use tracing_forest::ForestLayer; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::{EnvFilter, Registry}; + +static TRACING_INIT: Once = Once::new(); + +fn init_tracing() { + TRACING_INIT.call_once(|| { + let env_filter = EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env_lossy(); + + Registry::default() + .with(env_filter) + .with(ForestLayer::default()) + .init(); + }); +} fn push_line(log: &mut String, line: &str) { log.push_str(line); @@ -39,25 +61,58 @@ fn log_credential( } fn run_basic_usage_demo() -> Result { + init_tracing(); let mut log = String::new(); push_line(&mut log, "=== OONI Auth Demo ==="); let mut rng = rand::thread_rng(); - let mut server = ServerState::new(&mut rng); + let now = Instant::now(); + let server = ServerState::new(&mut rng); let public_params = server.public_parameters(); - push_line(&mut log, "Initialized server"); + push_line( + &mut log, + &format!("Initialized server in {} ms", now.elapsed().as_millis()), + ); + let now = Instant::now(); let mut user = UserState::new(public_params); - push_line(&mut log, "Initialized user"); + push_line( + &mut log, + &format!("Initialized user in {} ms", now.elapsed().as_millis()), + ); + let now = Instant::now(); let (reg_request, reg_state) = user .request(&mut rng) .map_err(|e| format!("registration request failed: {e:?}"))?; + push_line( + &mut log, + &format!( + "Registration request created in {} ms", + now.elapsed().as_millis() + ), + ); + let now = Instant::now(); let reg_response = server .open_registration(reg_request) .map_err(|e| format!("registration response failed: {e:?}"))?; + push_line( + &mut log, + &format!( + "Registration response created in {} ms", + now.elapsed().as_millis() + ), + ); + let now = Instant::now(); user.handle_response(reg_state, reg_response) .map_err(|e| format!("registration finalize failed: {e:?}"))?; + push_line( + &mut log, + &format!( + "Registration finalized in {} ms", + now.elapsed().as_millis() + ), + ); push_line(&mut log, "Registration complete"); match user.get_credential() { @@ -71,6 +126,7 @@ fn run_basic_usage_demo() -> Result { let age_range = (today - 30)..(today + 1); let measurement_count_range = 0..100; + let now = Instant::now(); let ((submit_request, submit_state), nym) = user .submit_request( &mut rng, @@ -80,8 +136,15 @@ fn run_basic_usage_demo() -> Result { measurement_count_range.clone(), ) .map_err(|e| format!("submit request failed: {e:?}"))?; - push_line(&mut log, "Submit request created"); - + push_line( + &mut log, + &format!( + "Submit request created in {} ms", + now.elapsed().as_millis() + ), + ); + + let now = Instant::now(); let submit_response = server .handle_submit( &mut rng, @@ -93,8 +156,23 @@ fn run_basic_usage_demo() -> Result { measurement_count_range, ) .map_err(|e| format!("submit handling failed: {e:?}"))?; + push_line( + &mut log, + &format!( + "Submit handled in {} ms", + now.elapsed().as_millis() + ), + ); + let now = Instant::now(); user.handle_submit_response(submit_state, submit_response) .map_err(|e| format!("submit finalize failed: {e:?}"))?; + push_line( + &mut log, + &format!( + "Submit finalized in {} ms", + now.elapsed().as_millis() + ), + ); push_line(&mut log, "Submit complete"); match user.get_credential() { diff --git a/ooniauth-py/Cargo.toml b/ooniauth-py/Cargo.toml index ccded4e..a80772a 100644 --- a/ooniauth-py/Cargo.toml +++ b/ooniauth-py/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ooniauth_py" version = "0.1.0" -edition = "2024" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] From 1711bd7378e72e2ef04ef8db28f6537fe478f58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Mon, 19 Jan 2026 12:47:24 -0800 Subject: [PATCH 7/9] tracing --- ooniauth-core/src/registration.rs | 7 +++++++ ooniauth-core/src/user_registration.rs | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/ooniauth-core/src/registration.rs b/ooniauth-core/src/registration.rs index ee3cab8..b240bea 100644 --- a/ooniauth-core/src/registration.rs +++ b/ooniauth-core/src/registration.rs @@ -12,6 +12,7 @@ use cmz::*; use group::Group; use rand::{CryptoRng, RngCore}; use sha2::Sha512; +use tracing::{instrument, trace}; const SESSION_ID: &[u8] = b"registration"; @@ -40,10 +41,12 @@ muCMZProtocol! {open_registration, } impl UserState { + #[instrument(skip(self, rng))] pub fn request( &self, rng: &mut (impl RngCore + CryptoRng), ) -> Result<(open_registration::Request, open_registration::ClientState), CMZError> { + trace!("Starting registration request"); cmz_group_init(G::hash_from_bytes::(b"CMZ Generator A")); let mut UAC = UserAuthCredential::using_pubkey(&self.pp); @@ -58,11 +61,13 @@ impl UserState { } impl UserState { + #[instrument(skip(self, state, rep))] pub fn handle_response( &mut self, state: open_registration::ClientState, rep: open_registration::Reply, ) -> Result<(), CMZError> { + trace!("Handling registration response"); let replybytes = rep.as_bytes(); let recvreply = open_registration::Reply::try_from(&replybytes[..]).unwrap(); match state.finalize(recvreply) { @@ -76,10 +81,12 @@ impl UserState { } impl ServerState { + #[instrument(skip(self, req))] pub fn open_registration( &self, req: open_registration::Request, ) -> Result { + trace!("Server opening registration"); let mut rng = rand::thread_rng(); let reqbytes = req.as_bytes(); diff --git a/ooniauth-core/src/user_registration.rs b/ooniauth-core/src/user_registration.rs index 8301464..9b53815 100644 --- a/ooniauth-core/src/user_registration.rs +++ b/ooniauth-core/src/user_registration.rs @@ -4,13 +4,16 @@ use curve25519_dalek::RistrettoPoint; use cmz::*; use rand::{CryptoRng, RngCore}; use sha2::Sha512; +use tracing::{instrument, trace}; const SESSION_ID: &[u8] = b"registration"; +#[instrument(skip(pp, rng))] pub fn request( pp: &CMZPubkey, rng: &mut (impl RngCore + CryptoRng), ) -> Result<(open_registration::Request, open_registration::ClientState), CMZError> { + trace!("Starting registration request (standalone)"); cmz_group_init(G::hash_from_bytes::(b"CMZ Generator A")); let mut UAC = UserAuthCredential::using_pubkey(pp); @@ -24,6 +27,7 @@ pub fn handle_request_response( state: open_registration::ClientState, rep: open_registration::Reply ) -> Result { + trace!("Handling registration response (standalone)"); let replybytes = rep.as_bytes(); let recvreply = open_registration::Reply::try_from(&replybytes[..]).unwrap(); state.finalize(recvreply).map_err(|_| CMZError::IssProofFailed) From 1052d55917c4581cadb5e8891980ae97cfa888f7 Mon Sep 17 00:00:00 2001 From: Michele Orru Date: Fri, 30 Jan 2026 09:27:44 -0800 Subject: [PATCH 8/9] lint and fix builds --- ios/.DS_Store | Bin 0 -> 6148 bytes .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 13724 bytes .../xcschemes/xcschememanagement.plist | 14 ++ ios/OoniAuthApp/ContentView.swift | 1 + ooniauth-core/examples/basic_usage.rs | 7 +- ooniauth-core/src/lib.rs | 2 +- ooniauth-core/src/submit.rs | 22 ++- ooniauth-core/src/user_registration.rs | 10 +- ooniauth-core/src/user_submit.rs | 17 +- ooniauth-ffi/src/lib.rs | 172 +++++++++++++++--- ooniauth-py/build.rs | 43 +++++ ooniauth-py/src/exceptions.rs | 2 +- ooniauth-py/src/protocol.rs | 55 +++--- ooniauth-py/src/utils.rs | 2 +- 15 files changed, 276 insertions(+), 78 deletions(-) create mode 100644 ios/.DS_Store create mode 100644 ios/OoniAuthApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/OoniAuthApp.xcodeproj/project.xcworkspace/xcuserdata/maker.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ios/OoniAuthApp.xcodeproj/xcuserdata/maker.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ooniauth-py/build.rs diff --git a/ios/.DS_Store b/ios/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..428d5cfd8184e72bb3086e316e3ddbc957938ea3 GIT binary patch literal 6148 zcmeHK!Ab)`41H63Sn<+};Bme{=pXEs_3WWPpzVs)w(cSpJT8KFKSlflPhR{eUnZei zRu4rG(FBq=JCn>XFEH5v2%}Xs1O@;ys$g%I<`a>1(T?!_xv?D#4V;=sc^=8UUPK0I3JFu_0qC?Ki@8TS(oKxQBN3^J>R`P zoj$x2+wM?(bBAX3@dl4P-o+Vk2AqL^#{g@#NVccw)){aHoPjk1@;*eWU~bqdrl*4@ zwE#rv-p+pT0)?x$==X^B3+^|*Da0F{Uf}I?!Lka10?jMso zLayl68E^(R8Q9U!fzOfHZS7o6YHg&RP({SARa}Q~ ikV-Lqr4%1flW;!DfS4P$ikzYNk3gcqjWh7047>p!Peok- literal 0 HcmV?d00001 diff --git a/ios/OoniAuthApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/OoniAuthApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/OoniAuthApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/OoniAuthApp.xcodeproj/project.xcworkspace/xcuserdata/maker.xcuserdatad/UserInterfaceState.xcuserstate b/ios/OoniAuthApp.xcodeproj/project.xcworkspace/xcuserdata/maker.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..9bf12b3c7e7196842dcb47b02ac2498bb492ae56 GIT binary patch literal 13724 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 L$j{K1<){Av7n4RK literal 0 HcmV?d00001 diff --git a/ios/OoniAuthApp.xcodeproj/xcuserdata/maker.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/OoniAuthApp.xcodeproj/xcuserdata/maker.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ece420e --- /dev/null +++ b/ios/OoniAuthApp.xcodeproj/xcuserdata/maker.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + OoniAuthApp.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/ios/OoniAuthApp/ContentView.swift b/ios/OoniAuthApp/ContentView.swift index c1563c8..7e87a55 100644 --- a/ios/OoniAuthApp/ContentView.swift +++ b/ios/OoniAuthApp/ContentView.swift @@ -28,6 +28,7 @@ struct ContentView: View { ScrollView { Text(log) + .font(.system(.body, design: .monospaced)) .frame(maxWidth: .infinity, alignment: .leading) .textSelection(.enabled) .padding(.vertical, 4) diff --git a/ooniauth-core/examples/basic_usage.rs b/ooniauth-core/examples/basic_usage.rs index 9e77d0b..9701edd 100644 --- a/ooniauth-core/examples/basic_usage.rs +++ b/ooniauth-core/examples/basic_usage.rs @@ -1,9 +1,8 @@ use std::time::Instant; -use hex; use ooniauth_core::{scalar_u32, ServerState, UserState}; -use tracing_forest::ForestLayer; use tracing_forest::util::LevelFilter; +use tracing_forest::ForestLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::{EnvFilter, Registry}; @@ -117,7 +116,7 @@ fn main() -> Result<(), Box> { println!(" Domain-specific pseudonym computed"); // Show the NYM as hex - println!(" NYM (hex): {}", hex::encode(&nym)); + println!(" NYM (hex): {}", hex::encode(nym)); // Convert to bytes let submit_request_bytes = submit_request.as_bytes(); @@ -195,7 +194,7 @@ fn main() -> Result<(), Box> { println!(" Different domain produces different pseudonym"); // Show the second NYM as hex - println!(" NYM (hex): {}", hex::encode(&nym2)); + println!(" NYM (hex): {}", hex::encode(nym2)); let now = Instant::now(); let submit_response2 = server.handle_submit( diff --git a/ooniauth-core/src/lib.rs b/ooniauth-core/src/lib.rs index fd7d545..6b2bf9b 100644 --- a/ooniauth-core/src/lib.rs +++ b/ooniauth-core/src/lib.rs @@ -15,8 +15,8 @@ pub mod errors; pub mod registration; pub mod submit; pub mod update; -pub mod user_submit; pub mod user_registration; +pub mod user_submit; #[derive(Debug, Serialize, Deserialize)] pub struct ServerState { diff --git a/ooniauth-core/src/submit.rs b/ooniauth-core/src/submit.rs index c75f3bf..1af7280 100644 --- a/ooniauth-core/src/submit.rs +++ b/ooniauth-core/src/submit.rs @@ -1,5 +1,3 @@ -use std::u32; - use super::{scalar_u32, ServerState, UserState, G}; use crate::errors::CredentialError; use crate::registration::UserAuthCredential; @@ -8,7 +6,7 @@ use curve25519_dalek::RistrettoPoint; use group::{Group, GroupEncoding}; use rand::{CryptoRng, RngCore}; use sha2::Sha512; -use tracing::{instrument, trace, debug}; +use tracing::{debug, instrument, trace}; const SESSION_ID: &[u8] = b"submit"; @@ -35,7 +33,10 @@ impl UserState { measurement_count_range: std::ops::Range, ) -> Result<((submit::Request, submit::ClientState), [u8; 32]), CredentialError> { trace!("Starting submit request"); - debug!("Age range: {:?}, Measurement count range: {:?}", age_range, measurement_count_range); + debug!( + "Age range: {:?}, Measurement count range: {:?}", + age_range, measurement_count_range + ); cmz_group_init(G::hash_from_bytes::(b"CMZ Generator A")); // Get the current credential @@ -122,7 +123,7 @@ impl UserState { }; trace!("Preparing submit proof with params"); - match submit::prepare(rng, SESSION_ID, &Old, New, ¶ms) { + match submit::prepare(rng, SESSION_ID, Old, New, ¶ms) { Ok(req_state) => { debug!("Submit request prepared successfully"); Ok((req_state, NYM.compress().to_bytes())) @@ -153,6 +154,7 @@ impl UserState { impl ServerState { #[instrument(skip(self, rng, req))] + #[allow(clippy::too_many_arguments)] pub fn handle_submit( &self, rng: &mut (impl RngCore + CryptoRng), @@ -164,7 +166,10 @@ impl ServerState { measurement_count_range: std::ops::Range, ) -> Result { trace!("Server handling submit request"); - debug!("Age range: {:?}, Measurement count range: {:?}", age_range, measurement_count_range); + debug!( + "Age range: {:?}, Measurement count range: {:?}", + age_range, measurement_count_range + ); let reqbytes = req.as_bytes(); let recvreq = submit::Request::try_from(&reqbytes[..]).unwrap(); @@ -301,7 +306,10 @@ mod tests { let ((request, client_state), nym) = result.unwrap(); // Verify the request is valid - assert!(request.as_bytes().len() > 0, "Request should have content"); + assert!( + !request.as_bytes().is_empty(), + "Request should have content" + ); // Verify NYM is computed (check it's not all zeros) assert_ne!(&nym, &[0u8; 32], "NYM should not be all zeros"); diff --git a/ooniauth-core/src/user_registration.rs b/ooniauth-core/src/user_registration.rs index 9b53815..42be7b1 100644 --- a/ooniauth-core/src/user_registration.rs +++ b/ooniauth-core/src/user_registration.rs @@ -1,7 +1,7 @@ use super::{Scalar, G}; use crate::registration::{open_registration, UserAuthCredential}; -use curve25519_dalek::RistrettoPoint; use cmz::*; +use curve25519_dalek::RistrettoPoint; use rand::{CryptoRng, RngCore}; use sha2::Sha512; use tracing::{instrument, trace}; @@ -25,18 +25,20 @@ pub fn request( pub fn handle_request_response( state: open_registration::ClientState, - rep: open_registration::Reply + rep: open_registration::Reply, ) -> Result { trace!("Handling registration response (standalone)"); let replybytes = rep.as_bytes(); let recvreply = open_registration::Reply::try_from(&replybytes[..]).unwrap(); - state.finalize(recvreply).map_err(|_| CMZError::IssProofFailed) + state + .finalize(recvreply) + .map_err(|_| CMZError::IssProofFailed) } #[cfg(test)] mod tests { use super::*; - use crate::{ServerState}; + use crate::ServerState; #[test] fn test_registration() { diff --git a/ooniauth-core/src/user_submit.rs b/ooniauth-core/src/user_submit.rs index c425869..dbc6b82 100644 --- a/ooniauth-core/src/user_submit.rs +++ b/ooniauth-core/src/user_submit.rs @@ -1,11 +1,9 @@ -use std::u32; - use super::{scalar_u32, G}; -use crate::{errors::CredentialError}; +use crate::errors::CredentialError; use crate::registration::UserAuthCredential; +use crate::submit::submit; use cmz::*; use curve25519_dalek::RistrettoPoint; -use crate::submit::submit; use rand::{CryptoRng, RngCore}; use sha2::Sha512; @@ -106,14 +104,16 @@ pub fn handle_submit_response( ) -> Result { let replybytes = rep.as_bytes(); let recvreply = submit::Reply::try_from(&replybytes[..]).unwrap(); - state.finalize(recvreply).map_err(|_| CMZError::IssProofFailed) + state + .finalize(recvreply) + .map_err(|_| CMZError::IssProofFailed) } #[cfg(test)] mod tests { use super::*; + use crate::user_registration::{handle_request_response, request}; use crate::{Scalar, ServerState, G}; - use crate::user_registration::{request, handle_request_response}; use sha2::Sha512; #[test] @@ -192,7 +192,10 @@ mod tests { let ((request, client_state), nym) = result.unwrap(); // Verify the request is valid - assert!(request.as_bytes().len() > 0, "Request should have content"); + assert!( + !request.as_bytes().is_empty(), + "Request should have content" + ); // Verify NYM is computed (check it's not all zeros) assert_ne!(&nym, &[0u8; 32], "NYM should not be all zeros"); diff --git a/ooniauth-ffi/src/lib.rs b/ooniauth-ffi/src/lib.rs index 52c0ba5..ced4525 100644 --- a/ooniauth-ffi/src/lib.rs +++ b/ooniauth-ffi/src/lib.rs @@ -30,13 +30,9 @@ fn push_line(log: &mut String, line: &str) { log.push('\n'); } -fn log_credential( - log: &mut String, - label: &str, - cred: &UserAuthCredential, -) -> Result<(), String> { +fn log_credential(log: &mut String, label: &str, cred: &UserAuthCredential) -> Result<(), String> { push_line(log, ""); - push_line(log, label); + push_line(log, &format!(" === {label} ===")); let nym_id = cred .nym_id @@ -48,14 +44,20 @@ fn log_credential( .measurement_count .ok_or_else(|| "missing measurement_count in credential".to_string())?; - push_line(log, &format!("nym_id: {}", hex::encode(nym_id.to_bytes()))); + push_line( + log, + &format!(" - nym_id: {}", hex::encode(nym_id.to_bytes())), + ); let age_value = scalar_u32(&age).ok_or_else(|| "age is not a u32".to_string())?; - push_line(log, &format!("age: {}", age_value)); + push_line(log, &format!(" - age: {}", age_value)); let measurement_value = scalar_u32(&measurement_count) .ok_or_else(|| "measurement_count is not a u32".to_string())?; - push_line(log, &format!("measurement_count: {}", measurement_value)); + push_line( + log, + &format!(" - measurement_count: {}", measurement_value), + ); Ok(()) } @@ -63,24 +65,35 @@ fn log_credential( fn run_basic_usage_demo() -> Result { init_tracing(); let mut log = String::new(); - push_line(&mut log, "=== OONI Auth Demo ==="); + push_line(&mut log, "=== Anonymous Credential Example ==="); + push_line(&mut log, ""); + // Match the flow in ooniauth-core/examples/basic_usage.rs so the iOS app + // surfaces identical outputs and timings. let mut rng = rand::thread_rng(); + push_line(&mut log, "1. Initializing server..."); let now = Instant::now(); let server = ServerState::new(&mut rng); let public_params = server.public_parameters(); push_line( &mut log, - &format!("Initialized server in {} ms", now.elapsed().as_millis()), + &format!( + " Key generation completed in {} ms", + now.elapsed().as_millis() + ), ); + push_line(&mut log, ""); + push_line(&mut log, "2. Initializing user..."); let now = Instant::now(); let mut user = UserState::new(public_params); push_line( &mut log, - &format!("Initialized user in {} ms", now.elapsed().as_millis()), + &format!(" User initialized in {} ms", now.elapsed().as_millis()), ); + push_line(&mut log, ""); + push_line(&mut log, "3. User registration..."); let now = Instant::now(); let (reg_request, reg_state) = user .request(&mut rng) @@ -88,10 +101,21 @@ fn run_basic_usage_demo() -> Result { push_line( &mut log, &format!( - "Registration request created in {} ms", + " Registration request created in {} ms", now.elapsed().as_millis() ), ); + + let request_bytes = reg_request.as_bytes(); + push_line( + &mut log, + &format!(" Request size: {} bytes", request_bytes.len()), + ); + push_line( + &mut log, + &format!(" Request payload (hex): {}", hex::encode(&request_bytes)), + ); + let now = Instant::now(); let reg_response = server .open_registration(reg_request) @@ -99,27 +123,37 @@ fn run_basic_usage_demo() -> Result { push_line( &mut log, &format!( - "Registration response created in {} ms", + " Server processed registration in {} ms", now.elapsed().as_millis() ), ); + + let response_bytes = reg_response.as_bytes(); + push_line( + &mut log, + &format!(" Response size: {} bytes", response_bytes.len()), + ); + let now = Instant::now(); user.handle_response(reg_state, reg_response) .map_err(|e| format!("registration finalize failed: {e:?}"))?; push_line( &mut log, &format!( - "Registration finalized in {} ms", + " User handled response in {} ms", now.elapsed().as_millis() ), ); - push_line(&mut log, "Registration complete"); - match user.get_credential() { - Some(cred) => log_credential(&mut log, "Initial credential", cred)?, - None => return Err("credential missing after registration".to_string()), - } + log_credential( + &mut log, + "Initial Credential Attributes", + user.get_credential() + .ok_or_else(|| "credential missing after registration".to_string())?, + )?; + push_line(&mut log, ""); + push_line(&mut log, "4. Creating anonymous report submission..."); let probe_cc = "US".to_string(); let probe_asn = "AS1234".to_string(); let today = ServerState::today(); @@ -139,10 +173,17 @@ fn run_basic_usage_demo() -> Result { push_line( &mut log, &format!( - "Submit request created in {} ms", + " Submit request created for {probe_cc}/{probe_asn} in {} ms", now.elapsed().as_millis() ), ); + push_line(&mut log, " Domain-specific pseudonym computed"); + push_line(&mut log, &format!(" NYM (hex): {}", hex::encode(nym))); + let submit_request_bytes = submit_request.as_bytes(); + push_line( + &mut log, + &format!(" Request size: {} bytes", submit_request_bytes.len()), + ); let now = Instant::now(); let submit_response = server @@ -159,26 +200,99 @@ fn run_basic_usage_demo() -> Result { push_line( &mut log, &format!( - "Submit handled in {} ms", + " Server validated submission and issued updated credential in {} ms", now.elapsed().as_millis() ), ); + let submit_response_bytes = submit_response.as_bytes(); + push_line( + &mut log, + &format!(" Response size: {} bytes", submit_response_bytes.len()), + ); let now = Instant::now(); user.handle_submit_response(submit_state, submit_response) .map_err(|e| format!("submit finalize failed: {e:?}"))?; push_line( &mut log, &format!( - "Submit finalized in {} ms", + " User handled submit response in {} ms", now.elapsed().as_millis() ), ); - push_line(&mut log, "Submit complete"); - match user.get_credential() { - Some(cred) => log_credential(&mut log, "Updated credential", cred)?, - None => return Err("credential missing after submit".to_string()), - } + log_credential( + &mut log, + "Updated Credential Attributes", + user.get_credential() + .ok_or_else(|| "credential missing after submit".to_string())?, + )?; + + push_line(&mut log, ""); + push_line(&mut log, "5. Creating second submission..."); + let probe_cc2 = "UK".to_string(); + let probe_asn2 = "AS5678".to_string(); + + let age_range2 = (today - 30)..(today + 1); + let measurement_count_range2 = 0..100; + + let now = Instant::now(); + let ((submit_request2, submit_state2), nym2) = user + .submit_request( + &mut rng, + probe_cc2.clone(), + probe_asn2.clone(), + age_range2.clone(), + measurement_count_range2.clone(), + ) + .map_err(|e| format!("submit request 2 failed: {e:?}"))?; + + push_line( + &mut log, + &format!( + " Submit request created for {probe_cc2}/{probe_asn2} in {} ms", + now.elapsed().as_millis() + ), + ); + push_line(&mut log, " Different domain produces different pseudonym"); + push_line(&mut log, &format!(" NYM (hex): {}", hex::encode(nym2))); + + let now = Instant::now(); + let submit_response2 = server + .handle_submit( + &mut rng, + submit_request2, + &nym2, + &probe_cc2, + &probe_asn2, + age_range2, + measurement_count_range2, + ) + .map_err(|e| format!("submit handling 2 failed: {e:?}"))?; + push_line( + &mut log, + &format!( + " Second submit request handled by server in {} ms", + now.elapsed().as_millis() + ), + ); + + let now = Instant::now(); + user.handle_submit_response(submit_state2, submit_response2) + .map_err(|e| format!("submit finalize 2 failed: {e:?}"))?; + push_line( + &mut log, + &format!( + " Second submit response handled by user in {} ms", + now.elapsed().as_millis() + ), + ); + + log_credential( + &mut log, + "Final Credential Attributes", + user.get_credential() + .ok_or_else(|| "credential missing after second submit".to_string())?, + )?; Ok(log) } @@ -195,7 +309,9 @@ pub extern "C" fn ooniauth_run_basic_usage() -> *mut c_char { .into_raw() } +/// # Safety /// Caller must pass the pointer returned by `ooniauth_run_basic_usage`. +/// The pointer must be valid, non-null, and freed exactly once. #[no_mangle] pub unsafe extern "C" fn ooniauth_string_free(ptr: *mut c_char) { if ptr.is_null() { diff --git a/ooniauth-py/build.rs b/ooniauth-py/build.rs new file mode 100644 index 0000000..ac2d936 --- /dev/null +++ b/ooniauth-py/build.rs @@ -0,0 +1,43 @@ +use std::process::Command; + +fn main() { + println!("cargo:rerun-if-env-changed=PYO3_PYTHON"); + println!("cargo:rerun-if-env-changed=PYTHON_SYS_EXECUTABLE"); + + let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); + if target_os != "macos" && target_os != "linux" { + return; + } + + let flags = python3_config_ldflags(); + if let Some(flags) = flags { + emit_link_flags(&flags); + } +} + +fn python3_config_ldflags() -> Option { + run_python3_config(&["--embed", "--ldflags"]).or_else(|| run_python3_config(&["--ldflags"])) +} + +fn run_python3_config(args: &[&str]) -> Option { + let output = Command::new("python3-config").args(args).output().ok()?; + if !output.status.success() { + return None; + } + String::from_utf8(output.stdout).ok() +} + +fn emit_link_flags(flags: &str) { + let mut iter = flags.split_whitespace().peekable(); + while let Some(flag) = iter.next() { + if let Some(path) = flag.strip_prefix("-L") { + println!("cargo:rustc-link-search=native={path}"); + } else if let Some(lib) = flag.strip_prefix("-l") { + println!("cargo:rustc-link-lib={lib}"); + } else if flag == "-framework" { + if let Some(name) = iter.next() { + println!("cargo:rustc-link-lib=framework={name}"); + } + } + } +} diff --git a/ooniauth-py/src/exceptions.rs b/ooniauth-py/src/exceptions.rs index bd1de76..4aaea9d 100644 --- a/ooniauth-py/src/exceptions.rs +++ b/ooniauth-py/src/exceptions.rs @@ -1,7 +1,7 @@ use cmz::CMZError; use ooniauth_core::errors; -use pyo3::PyErr; use pyo3::exceptions::PyException; +use pyo3::PyErr; use pyo3_stub_gen::create_exception; use thiserror::Error; diff --git a/ooniauth-py/src/protocol.rs b/ooniauth-py/src/protocol.rs index c1f46b3..75f01ad 100644 --- a/ooniauth-py/src/protocol.rs +++ b/ooniauth-py/src/protocol.rs @@ -11,7 +11,7 @@ use pyo3::{ use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods}; use crate::utils::{from_pystring, to_pystring}; -use crate::{OoniErr, exceptions::OoniResult}; +use crate::{exceptions::OoniResult, OoniErr}; #[gen_stub_pyclass] #[pyclass] @@ -72,6 +72,7 @@ impl ServerState { ooni::ServerState::today() } + #[allow(clippy::too_many_arguments)] fn handle_submit_request( &self, py: Python<'_>, @@ -174,7 +175,11 @@ impl UserState { self.state.get_credential().map(|c| to_pystring(py, c)) } - pub fn set_public_params(&mut self, py: Python<'_>, new_public_params : Py) -> OoniResult<()>{ + pub fn set_public_params( + &mut self, + py: Python<'_>, + new_public_params: Py, + ) -> OoniResult<()> { let params = from_pystring(py, &new_public_params)?; self.state.pp = params; Ok(()) @@ -301,11 +306,11 @@ pub struct SubmitRequest { #[cfg(test)] mod tests { - use base64::{Engine, prelude::BASE64_STANDARD}; - use ooniauth_core::{ServerState, UserState, registration::open_registration::Request}; + use base64::{prelude::BASE64_STANDARD, Engine}; + use ooniauth_core::{registration::open_registration::Request, ServerState, UserState}; use pyo3::{ - Py, Python, types::{PyList, PyString}, + Py, Python, }; use rand::{rngs::ThreadRng, thread_rng}; @@ -337,11 +342,9 @@ mod tests { let mut client = crate::UserState::new(py, server.get_public_parameters(py)).unwrap(); let req = client.make_registration_request(py).unwrap(); let reg_response = server.handle_registration_request(py, req).unwrap(); - assert!( - client - .handle_registration_response(py, reg_response) - .is_ok() - ); + assert!(client + .handle_registration_response(py, reg_response) + .is_ok()); // Test submit let cc = PyString::new(py, "VE"); @@ -353,19 +356,17 @@ mod tests { let age_range = PyList::new(py, vec![today - 30, today + 1]).unwrap(); let msm_range = PyList::new(py, vec![0, 100]).unwrap(); - assert!( - server - .handle_submit_request( - py, - submit_req.nym, - submit_req.request, - cc.into(), - asn.into(), - age_range.into(), - msm_range.into() - ) - .is_ok() - ); + assert!(server + .handle_submit_request( + py, + submit_req.nym, + submit_req.request, + cc.into(), + asn.into(), + age_range.into(), + msm_range.into() + ) + .is_ok()); }); } @@ -395,7 +396,9 @@ mod tests { .expect("Unable to handle registration response"); // Update credential - client.set_public_params(py, new_state.get_public_parameters(py)).expect("Unable to change public params"); + client + .set_public_params(py, new_state.get_public_parameters(py)) + .expect("Unable to change public params"); let update_req = client .make_credential_update_request(py) .expect("Unable to make credential update request"); @@ -467,7 +470,9 @@ mod tests { // Create new server state and update credentials let new_state = crate::ServerState::new(); - client.set_public_params(py, new_state.get_public_parameters(py)).expect("Unable to change public params"); + client + .set_public_params(py, new_state.get_public_parameters(py)) + .expect("Unable to change public params"); let update_req = client .make_credential_update_request(py) diff --git a/ooniauth-py/src/utils.rs b/ooniauth-py/src/utils.rs index 319af15..5628050 100644 --- a/ooniauth-py/src/utils.rs +++ b/ooniauth-py/src/utils.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::{OoniResult, exceptions::OoniErr}; +use crate::{exceptions::OoniErr, OoniResult}; use base64::prelude::*; use pyo3::{prelude::*, types::PyString}; From 7ebfeae9ee534197c62ab78885f70d820d5e703c Mon Sep 17 00:00:00 2001 From: Michele Orru Date: Tue, 3 Feb 2026 10:50:22 -0800 Subject: [PATCH 9/9] Add benchmark + readme instructions --- Readme.md | 16 ++--- ios/.DS_Store | Bin 6148 -> 0 bytes ooniauth-core/Cargo.toml | 4 ++ ooniauth-core/benches/bench_basic_usage.rs | 79 +++++++++++++++++++++ 4 files changed, 91 insertions(+), 8 deletions(-) delete mode 100644 ios/.DS_Store create mode 100644 ooniauth-core/benches/bench_basic_usage.rs diff --git a/Readme.md b/Readme.md index 87bb7fb..2490885 100644 --- a/Readme.md +++ b/Readme.md @@ -1,14 +1,14 @@ # OONI User Auth -To set this up you should run: -``` -make include +Run example: +```bash +cargo run -p ooniauth-core --example basic_usage ``` -Make sure you have setup ssh keys to clone the repositories listed in the -Makefile. +iOS build: +Open `ios/OoniAuthApp.xcodeproj` in Xcode. -You can then build it as usual with: -``` -cargo build +Criterion benchmark (same flow): +```bash +cargo bench -p ooniauth-core --bench bench_basic_usage ``` diff --git a/ios/.DS_Store b/ios/.DS_Store deleted file mode 100644 index 428d5cfd8184e72bb3086e316e3ddbc957938ea3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!Ab)`41H63Sn<+};Bme{=pXEs_3WWPpzVs)w(cSpJT8KFKSlflPhR{eUnZei zRu4rG(FBq=JCn>XFEH5v2%}Xs1O@;ys$g%I<`a>1(T?!_xv?D#4V;=sc^=8UUPK0I3JFu_0qC?Ki@8TS(oKxQBN3^J>R`P zoj$x2+wM?(bBAX3@dl4P-o+Vk2AqL^#{g@#NVccw)){aHoPjk1@;*eWU~bqdrl*4@ zwE#rv-p+pT0)?x$==X^B3+^|*Da0F{Uf}I?!Lka10?jMso zLayl68E^(R8Q9U!fzOfHZS7o6YHg&RP({SARa}Q~ ikV-Lqr4%1flW;!DfS4P$ikzYNk3gcqjWh7047>p!Peok- diff --git a/ooniauth-core/Cargo.toml b/ooniauth-core/Cargo.toml index f8ae3d4..98dda43 100644 --- a/ooniauth-core/Cargo.toml +++ b/ooniauth-core/Cargo.toml @@ -34,3 +34,7 @@ test = true [[bench]] name = "bench_server" harness = false + +[[bench]] +name = "bench_basic_usage" +harness = false diff --git a/ooniauth-core/benches/bench_basic_usage.rs b/ooniauth-core/benches/bench_basic_usage.rs new file mode 100644 index 0000000..d45e0a7 --- /dev/null +++ b/ooniauth-core/benches/bench_basic_usage.rs @@ -0,0 +1,79 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use ooniauth_core::{ServerState, UserState}; +use rand::thread_rng; +use std::hint::black_box; + +fn run_basic_usage_flow() { + let mut rng = thread_rng(); + let server = ServerState::new(&mut rng); + let public_params = server.public_parameters(); + let mut user = UserState::new(public_params); + + let (reg_request, reg_state) = user.request(&mut rng).unwrap(); + let reg_response = server.open_registration(reg_request).unwrap(); + user.handle_response(reg_state, reg_response).unwrap(); + + let today = ServerState::today(); + let age_range = (today - 30)..(today + 1); + let measurement_count_range = 0..100; + + let ((submit_request, submit_state), nym) = user + .submit_request( + &mut rng, + "US".to_string(), + "AS1234".to_string(), + age_range.clone(), + measurement_count_range.clone(), + ) + .unwrap(); + + let submit_response = server + .handle_submit( + &mut rng, + submit_request, + &nym, + "US", + "AS1234", + age_range, + measurement_count_range, + ) + .unwrap(); + user.handle_submit_response(submit_state, submit_response) + .unwrap(); + + let age_range2 = (today - 30)..(today + 1); + let measurement_count_range2 = 0..100; + + let ((submit_request2, submit_state2), nym2) = user + .submit_request( + &mut rng, + "UK".to_string(), + "AS5678".to_string(), + age_range2.clone(), + measurement_count_range2.clone(), + ) + .unwrap(); + + let submit_response2 = server + .handle_submit( + &mut rng, + submit_request2, + &nym2, + "UK", + "AS5678", + age_range2, + measurement_count_range2, + ) + .unwrap(); + user.handle_submit_response(submit_state2, submit_response2) + .unwrap(); + + black_box(user.get_credential().is_some()); +} + +fn bench_basic_usage(c: &mut Criterion) { + c.bench_function("basic_usage_flow", |b| b.iter(run_basic_usage_flow)); +} + +criterion_group!(benches, bench_basic_usage); +criterion_main!(benches);