### Mobile Cross-Compilation Setup for iOS and Android with Rust Source: https://context7.com/zkpassport/noir_rs/llms.txt Provides instructions for setting up Rust toolchains to cross-compile Noir.rs for iOS and Android platforms, including ARM64 optimization. This requires `rustup` and platform-specific build tools like the Android SDK and NDK. ```bash # iOS Build (macOS only) rustup target add aarch64-apple-ios IPHONEOS_DEPLOYMENT_TARGET=15.0 cargo build \ --target aarch64-apple-ios \ --features barretenberg \ --release # Android Build (requires Android SDK/NDK) export ANDROID_HOME=/path/to/android-sdk export NDK_VERSION=26.3.11579264 export HOST_TAG=darwin-x86_64 export TARGET=aarch64-linux-android export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/$NDK_VERSION export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$HOST_TAG export API=33 export AR="$TOOLCHAIN/bin/llvm-ar" export CC="$TOOLCHAIN/bin/$TARGET$API-clang" export CXX="$TOOLCHAIN/bin/$TARGET$API-clang++" rustup target add aarch64-linux-android cargo build \ --target aarch64-linux-android \ --features barretenberg,android-compat \ --release ``` -------------------------------- ### Generate and Verify Noir Circuit Proofs in Rust Source: https://github.com/zkpassport/noir_rs/blob/main/README.md This Rust code demonstrates how to use the noir_rs crate to generate and verify proofs for a Noir circuit. It includes steps for setting up the SRS (Superprintlnary Randomness), preparing the witness data, generating the proof using `prove_ultra_honk`, retrieving the verification key, and finally verifying the proof with `verify_ultra_honk`. The example assumes you have the circuit bytecode available as a string. ```rust use noir_rs::{ barretenberg::{prove::prove_ultra_honk, srs::{setup_srs_from_bytecode, setup_srs}, verify::verify_ultra_honk, utils::get_honk_verification_key}, witness::from_vec_str_to_witness_map, } // The bytecode of the circuit // You can find it in the compiled circuit json file created by running `nargo compile` const BYTECODE: &str = "H4sIAAAAAAAA/62QQQqAMAwErfigpEna5OZXLLb/f4KKLZbiTQdCQg7Dsm66mc9x00O717rhG9ico5cgMOfoMxJu4C2pAEsKioqisnslysoaLVkEQ6aMRYxKFc//ZYQr29L10XfhXv4jB52E+OpMAQAA"; // Setup the SRS // You can provide a path to the SRS transcript file as second argument // Otherwise it will be downloaded automatically from Aztec's servers setup_srs_from_bytecode(BYTECODE, None, false).unwrap(); // Alternatively, if you know the circuit size, you can use the following function // Assuming the circuit size is 40 here setup_srs(40, None).unwrap(); // Set up your witness // a = 5, b = 6, res = a * b = 30 let initial_witness = from_vec_str_to_witness_map(vec!["5", "6", "0x1e"]).unwrap(); // Start timing the proof generation let start = std::time::Instant::now(); // Generate the proof // It returns the proof let proof = prove_ultra_honk(BYTECODE, initial_witness).unwrap(); // Print the time it took to generate the proof info!("Proof generation time: {:?}", start.elapsed()); // Get the verification key let vk = get_honk_verification_key(BYTECODE).unwrap(); // Verify the proof let verdict = verify_ultra_honk(proof, vk).unwrap(); // Print the verdict info!("Proof verification verdict: {}", verdict); ``` -------------------------------- ### Setup Android Environment Variables for Noir.rs Cross-Compilation Source: https://github.com/zkpassport/noir_rs/blob/main/README.md Configures essential environment variables for cross-compiling Noir.rs on a desktop platform to Android. This includes setting paths for the Android SDK and NDK, specifying the NDK version, host tag, and defining compiler/linker paths. ```bash # Set the ANDROID_HOME environment variable to the path to your Android SDK export ANDROID_HOME=/path/to/your/android-sdk # e.g. /Users//Library/Android/sdk # Set the NDK_VERSION environment variable to the version of the Android NDK you have installed export NDK_VERSION=.. # e.g. 26.3.11579264 # Set the HOST_TAG environment variable to the host tag of your platform export HOST_TAG=your-host-tag # e.g. darwin-x86_64 (for macOS) # Then you just copy paste the ones below export TARGET=aarch64-linux-android export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/$NDK_VERSION export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$HOST_TAG export API=33 export AR="$TOOLCHAIN/bin/llvm-ar" export CC="$TOOLCHAIN/bin/$TARGET$API-clang" export AS="$TOOLCHAIN/bin/$TARGET$API-clang" export CXX="$TOOLCHAIN/bin/$TARGET$API-clang++" export LD="$TOOLCHAIN/bin/ld" export RANLIB="$TOOLCHAIN/bin/llvm-ranlib" export STRIP="$TOOLCHAIN/bin/llvm-strip" export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin" export PATH="$PATH:$TOOLCHAIN/bin" export CMAKE_TOOLCHAIN_FILE_aarch64_linux_android="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" export ANDROID_ABI="arm64-v8a" ``` -------------------------------- ### Install Rust Target for Android Source: https://github.com/zkpassport/noir_rs/blob/main/README.md Installs the necessary Rust toolchain target for Android cross-compilation. This command ensures that the Rust compiler can generate code for the specified Android architecture. ```bash rustup target add aarch64-linux-android ``` -------------------------------- ### Install Noir.rs Crate with Barretenberg Feature Source: https://github.com/zkpassport/noir_rs/blob/main/README.md This snippet shows how to add the noir_rs crate to your project's Cargo.toml file, specifically enabling the 'barretenberg' feature flag for backend proving and verification. This is necessary for projects that utilize Barretenberg for proof operations. ```toml [dependencies] noir_rs = { git = "https://github.com/zkpassport/noir_rs.git", tag = "v1.0.0-beta.3-1", features = ["barretenberg"] } ``` -------------------------------- ### Compute Circuit Sizes and Subgroup Dimensions (Rust) Source: https://context7.com/zkpassport/noir_rs/llms.txt Calculates the necessary circuit sizes (number of gates) and subgroup dimensions (next power of 2) required for SRS setup and memory allocation. These computations are crucial for planning resource requirements for proof generation. ```rust use noir_rs::barretenberg::utils::{ get_circuit_size, get_subgroup_size, compute_subgroup_size }; const BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Get circuit size (number of gates) let circuit_size = get_circuit_size(BYTECODE, false); println!("Circuit size: {} gates", circuit_size); // Get subgroup size (next power of 2) let subgroup_size = get_subgroup_size(BYTECODE, false); println!("Subgroup size: {}", subgroup_size); // Compute subgroup size from known circuit size let subgroup = compute_subgroup_size(1000); assert_eq!(subgroup, 1024); // 2^10 let subgroup = compute_subgroup_size(500000); assert_eq!(subgroup, 524288); // 2^19 ``` -------------------------------- ### Generate Low Memory Ultra Honk Proofs with Storage Cap in Rust Source: https://context7.com/zkpassport/noir_rs/llms.txt Generates Ultra Honk proofs on memory-constrained devices by utilizing disk storage for intermediate computations. This function allows for setting a maximum storage cap, with automatic fallback to RAM if the cap is exceeded. It requires setup of SRS, obtaining a verification key with low memory mode enabled, and witness preparation. ```rust use noir_rs::barretenberg::prove::prove_ultra_honk; use noir_rs::barretenberg::verify::get_ultra_honk_verification_key; use noir_rs::barretenberg::srs::setup_srs_from_bytecode; use noir_rs::witness::from_vec_to_witness_map; use std::time::Instant; // Large circuit bytecode const LARGE_BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Setup SRS setup_srs_from_bytecode(LARGE_BYTECODE, None, false).unwrap(); // Get verification key with low memory mode let vk = get_ultra_honk_verification_key( LARGE_BYTECODE, true, // Enable low memory mode None ).expect("VK generation failed"); // Prepare witness let initial_witness = from_vec_to_witness_map(vec![2u128, 5u128, 10u128]) .expect("Failed to create witness"); // Generate proof with 5GB storage cap let start = Instant::now(); let proof = prove_ultra_honk( LARGE_BYTECODE, initial_witness, vk, true, // Enable low memory mode Some(5 * 1024 * 1024 * 1024) // 5GB storage cap ).expect("Low memory proof generation failed"); println!("Low memory proof generated in {:?}", start.elapsed()); // Memory exceeding cap will fallback to RAM automatically ``` -------------------------------- ### Verify Standard and Keccak Ultra Honk Proofs in Rust Source: https://context7.com/zkpassport/noir_rs/llms.txt Verifies Ultra Honk proofs to ensure computational integrity and zero-knowledge properties. This process involves the same setup as proof generation (SRS, verification key, and the proof itself) and then calling the appropriate verification function. It supports both standard and Keccak variants of the Ultra Honk proofs. ```rust use noir_rs::barretenberg::prove::prove_ultra_honk; use noir_rs::barretenberg::verify::{ verify_ultra_honk, verify_ultra_honk_keccak, get_ultra_honk_verification_key }; use noir_rs::barretenberg::srs::setup_srs_from_bytecode; use noir_rs::witness::from_vec_to_witness_map; const BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Setup and generate proof setup_srs_from_bytecode(BYTECODE, None, false).unwrap(); let vk = get_ultra_honk_verification_key(BYTECODE, false, None).unwrap(); let witness = from_vec_to_witness_map(vec![5u128, 6u128, 30u128]).unwrap(); let proof = prove_ultra_honk(BYTECODE, witness, vk.clone(), false, None) .expect("Proof generation failed"); // Verify the proof let verdict = verify_ultra_honk(proof.clone(), vk.clone()) .expect("Verification failed"); assert!(verdict, "Proof verification failed"); println!("Proof verified successfully"); // Verify Keccak variant proof let verdict_keccak = verify_ultra_honk_keccak( proof, vk, false // disable_zk: must match proving parameter ).expect("Keccak verification failed"); assert!(verdict_keccak, "Keccak proof verification failed"); ``` -------------------------------- ### Initialize SRS for Proof Generation (Rust) Source: https://context7.com/zkpassport/noir_rs/llms.txt Initializes the Structured Reference String (SRS) required for proof generation. Supports automatic downloading from network or loading from a local file. The SRS can be set up from circuit bytecode or a specified circuit size. It also provides a method to retrieve the SRS object for manual initialization. ```rust use noir_rs::barretenberg::srs::{ setup_srs, setup_srs_from_bytecode, get_srs }; const BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Setup SRS automatically from circuit bytecode (downloads from Aztec if needed) let num_points = setup_srs_from_bytecode(BYTECODE, None, false) .expect("Failed to setup SRS"); println!("SRS initialized with {} points", num_points); // Setup SRS from known circuit size let num_points = setup_srs(500, None) .expect("Failed to setup SRS"); // Use local SRS file (.local or .dat format) let num_points = setup_srs_from_bytecode( BYTECODE, Some("/path/to/srs.dat"), false ).expect("Failed to setup local SRS"); // Get SRS object for manual initialization let subgroup_size = 64; let srs = get_srs(subgroup_size, None); println!("SRS G1 data size: {} bytes", srs.g1_data.len()); ``` -------------------------------- ### Complete Proof Generation Workflow in Rust Source: https://context7.com/zkpassport/noir_rs/llms.txt Demonstrates the end-to-end workflow for generating and verifying zero-knowledge proofs using Noir.rs. This includes setting up the SRS, generating verification keys, preparing witness data, generating the proof, and verifying its integrity. It relies on the `noir_rs` crate and its `barretenberg` and `witness` modules. ```rust use noir_rs::{ barretenberg::{ srs::setup_srs_from_bytecode, verify::verify_ultra_honk, get_ultra_honk_verification_key, prove::prove_ultra_honk, }, witness::from_vec_str_to_witness_map, }; use tracing::info; use std::time::Instant; const BYTECODE: &str = "H4sIAAAAAAAA/62QQQqAMAwErfigpEma5OZXLLb/f4KKLZbiTQdCQg7Dsm66mc9x00O717rhG9ico5cgMOfoMxJu4C2pAEsKioqisnslysoaLVkEQ6aMRYxKFc//ZYQr29L10XfhXv4jB52E+OpMAQAA"; fn main() -> Result<(), String> { // Initialize logging tracing_subscriber::fmt::init(); // Step 1: Setup SRS (downloads automatically if not cached) info!("Setting up SRS..."); setup_srs_from_bytecode(BYTECODE, None, false)?; // Step 2: Generate verification key info!("Generating verification key..."); let vk = get_ultra_honk_verification_key(BYTECODE, false, None)?; // Step 3: Prepare witness (a=5, b=6, res=30 for a*b circuit) let initial_witness = from_vec_str_to_witness_map(vec!["5", "6", "0x1e"])?; // Step 4: Generate proof info!("Generating proof..."); let start = Instant::now(); let proof = prove_ultra_honk(BYTECODE, initial_witness, vk.clone(), false, None)?; info!("Proof generation time: {:?}", start.elapsed()); // Step 5: Verify proof info!("Verifying proof..."); let verdict = verify_ultra_honk(proof, vk)?; info!("Proof verification verdict: {}", verdict); if verdict { Ok(()) } else { Err("Proof verification failed".to_string()) } } ``` -------------------------------- ### Rust: Execute Noir Circuits Source: https://context7.com/zkpassport/noir_rs/llms.txt Executes Noir circuits with provided initial witness values to compute all intermediate witnesses and public outputs. This step precedes proof generation. Dependencies include `noir_rs::execute` and `noir_rs::witness`. ```rust use noir_rs::execute::execute; use noir_rs::witness::from_vec_to_witness_map; const BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Prepare initial witness: a = 5, b = 6, res = 30 let initial_witness = from_vec_to_witness_map(vec![5u128, 6u128, 30u128]) .expect("Failed to create witness"); // Execute circuit to solve all witnesses let witness_stack = execute(BYTECODE, initial_witness) .expect("Circuit execution failed"); println!("Execution successful, witness stack size: {}", witness_stack.length()); ``` -------------------------------- ### Build Noir.rs for Release with Barretenberg Source: https://github.com/zkpassport/noir_rs/blob/main/README.md This command demonstrates how to build the noir_rs crate in release mode while enabling the 'barretenberg' feature. This is useful for optimizing performance for production environments that require Barretenberg's cryptographic primitives. The `-vvvv` flag is recommended for detailed build output. ```bash cargo build -vvvv --release --features barretenberg ``` -------------------------------- ### Generate Verification Keys (Rust) Source: https://context7.com/zkpassport/noir_rs/llms.txt Generates verification keys essential for both proving and verifying cryptographic proofs. Supports standard Ultra Honk and Keccak variants, the latter being suitable for Ethereum compatibility. Options for low memory mode and storage caps are also available. ```rust use noir_rs::barretenberg::verify::{ get_ultra_honk_verification_key, get_ultra_honk_keccak_verification_key }; use noir_rs::barretenberg::srs::setup_srs_from_bytecode; const BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Setup SRS first setup_srs_from_bytecode(BYTECODE, None, false) .expect("SRS setup failed"); // Generate standard Ultra Honk verification key let vk = get_ultra_honk_verification_key(BYTECODE, false, None) .expect("Failed to generate verification key"); println!("Verification key size: {} bytes", vk.len()); // Generate Keccak variant verification key (for Ethereum compatibility) let vk_keccak = get_ultra_honk_keccak_verification_key( BYTECODE, false, // disable_zk: false for zero-knowledge proofs false, // low_memory_mode: false None // max_storage_usage ).expect("Failed to generate Keccak verification key"); // Generate with low memory mode and storage cap (5GB) let vk_low_mem = get_ultra_honk_verification_key( BYTECODE, true, // low_memory_mode Some(5 * 1024 * 1024 * 1024) // 5GB storage cap ).expect("Failed to generate verification key"); ``` -------------------------------- ### Generate Standard and Keccak Ultra Honk Proofs with noir_rs Source: https://context7.com/zkpassport/noir_rs/llms.txt Generates zero-knowledge proofs using the Ultra Honk proving system, supporting both standard and Keccak variants. This involves setting up the SRS, obtaining a verification key, preparing the witness, and then generating the proofs. The Keccak variant is specifically noted for Ethereum compatibility. ```rust use noir_rs::barretenberg::prove::{prove_ultra_honk, prove_ultra_honk_keccak}; use noir_rs::barretenberg::verify::get_ultra_honk_verification_key; use noir_rs::barretenberg::srs::setup_srs_from_bytecode; use noir_rs::witness::from_vec_to_witness_map; use std::time::Instant; const BYTECODE: &str = "H4sIAAAAAAAA/42NsQmAMBBF74KDWGqnOIIIVmJpYyHYWChiZ5kRxAWcQnScdJY29gZNSAgp8or7x93/fIQfT2jfdAPhiqCQuw9OoBxmLmqLicVbeJTZTmlVB8mVz+e4pOxZb/4n7h2fVy9Ey93kBZmTjiLsAAAA"; // Setup SRS setup_srs_from_bytecode(BYTECODE, None, false).unwrap(); // Get verification key let vk = get_ultra_honk_verification_key(BYTECODE, false, None).unwrap(); // Prepare witness: a = 5, b = 6, res = 30 let initial_witness = from_vec_to_witness_map(vec![5u128, 6u128, 30u128]) .expect("Failed to create witness"); // Generate proof let start = Instant::now(); let proof = prove_ultra_honk( BYTECODE, initial_witness.clone(), vk.clone(), false, // low_memory_mode None // max_storage_usage ).expect("Proof generation failed"); println!("Proof generated in {:?}", start.elapsed()); println!("Proof size: {} bytes", proof.len()); // Generate Keccak variant proof (for Ethereum) let proof_keccak = prove_ultra_honk_keccak( BYTECODE, initial_witness, vk, false, // disable_zk: false for zero-knowledge false, // low_memory_mode None // max_storage_usage ).expect("Keccak proof generation failed"); ``` -------------------------------- ### Rust: Decode Noir Circuit Bytecode to ACIR Source: https://context7.com/zkpassport/noir_rs/llms.txt Decodes base64-encoded, gzip-compressed circuit bytecode into ACIR (Abstract Circuit Intermediate Representation) programs. Supports retrieving compressed, uncompressed, and deserialized program structures. Dependencies include `noir_rs::circuit` and `acvm::acir`. ```rust use noir_rs::circuit::{ get_acir_buffer, get_acir_buffer_uncompressed, decode_circuit, get_program }; // Circuit bytecode from nargo compile output const BYTECODE: &str = "H4sIAAAAAAAA/62QQQqAMAwErfigpEma5OZXLLb/f4KKLZbiTQdCQg7Dsm66mc9x00O717rhG9ico5cgMOfoMxJu4C2pAEsKioqisnslysoaLVkEQ6aMRYxKFc//ZYQr29L10XfhXv4jB52E+OpMAQAA"; // Get compressed ACIR buffer let acir_buffer = get_acir_buffer(BYTECODE) .expect("Failed to decode bytecode"); // Get uncompressed ACIR buffer let acir_buffer_uncompressed = get_acir_buffer_uncompressed(BYTECODE) .expect("Failed to uncompress ACIR"); // Get both compressed and uncompressed buffers let (compressed, uncompressed) = decode_circuit(BYTECODE) .expect("Failed to decode circuit"); // Deserialize into Program structure let program = get_program(BYTECODE) .expect("Failed to get program"); println!("Circuit loaded: {} functions", program.functions.len()); ``` -------------------------------- ### Cross-compile Noir.rs for Android (ARM64) Source: https://github.com/zkpassport/noir_rs/blob/main/README.md Builds the Noir.rs project for the Android ARM64 architecture using Cargo. Includes options for debug, release, and builds with specific features like 'android-compat' and 'barretenberg'. ```bash cargo build -vvvv --target aarch64-linux-android --features android-compat # Release build cargo build -vvvv --target aarch64-linux-android --release --features android-compat # Build with the `barretenberg` feature cargo build -vvvv --target aarch64-linux-android --features barretenberg --features android-compat # Release build with the `barretenberg` feature cargo build -vvvv --target aarch64-linux-android --features barretenberg --features android-compat --release ``` -------------------------------- ### Rust: Create and Manage Witness Maps Source: https://context7.com/zkpassport/noir_rs/llms.txt Converts input values into WitnessMap structures for circuit execution. Supports conversion from numeric vectors and string vectors (hex/decimal). Includes functions for serializing and deserializing witness data. Dependencies include `noir_rs::witness` and `acvm::acir::native_types`. ```rust use noir_rs::witness::{ from_vec_to_witness_map, from_vec_str_to_witness_map, witness_map_to_witness_stack, serialize_witness, deserialize_witness }; use acvm::acir::native_types::{WitnessMap, Witness}; use acvm::FieldElement; // Create witness map from numeric values (u8, u16, u32, u64, u128) let witness_from_nums = from_vec_to_witness_map(vec![5u128, 6u128, 30u128]) .expect("Failed to create witness map"); // Create witness map from hex and decimal strings let witness_from_strs = from_vec_str_to_witness_map(vec!["5", "6", "0x1e"]) .expect("Failed to create witness map from strings"); // Manual witness map creation for complex inputs let mut custom_witness = WitnessMap::new(); custom_witness.insert(Witness(0), FieldElement::from(5u128)); custom_witness.insert(Witness(1), FieldElement::from(6u128)); custom_witness.insert(Witness(2), FieldElement::from(30u128)); // Convert to witness stack let witness_stack = witness_map_to_witness_stack(witness_from_nums) .expect("Failed to convert to stack"); // Serialize for storage or transmission let serialized = serialize_witness(witness_stack) .expect("Failed to serialize"); // Deserialize when needed let deserialized = deserialize_witness(serialized) .expect("Failed to deserialize"); ``` -------------------------------- ### Cross-Compile Noir.rs for iOS ARM64 Source: https://github.com/zkpassport/noir_rs/blob/main/README.md This command shows how to cross-compile the noir_rs crate for iOS ARM64 architecture. It requires setting the IPHONEOS_DEPLOYMENT_TARGET environment variable and can be combined with the 'barretenberg' feature for optimized builds. This is essential for deploying Noir.rs-based applications on iOS devices. ```bash IPHONEOS_DEPLOYMENT_TARGET=15.0 cargo build -vvvv --target aarch64-apple-ios --features barretenberg --release ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.