From 718a54f427d4fd1a6c1abb8a093ef8bf84c3bac1 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 10:02:38 -0400 Subject: [PATCH 01/11] Add ZK email verification example Noir circuit verifies DKIM-signed emails from icloud.com and an Aztec contract verifies the proof on-chain using verify_honk_proof. Includes testnet deployment scripts, integration tests, and proof generation. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/.gitignore | 8 + zkemail_verification/README.md | 186 + zkemail_verification/circuit/Nargo.toml | 9 + zkemail_verification/circuit/src/main.nr | 77 + zkemail_verification/contract/Nargo.toml | 8 + zkemail_verification/contract/src/main.nr | 51 + zkemail_verification/package.json | 34 + zkemail_verification/scripts/generate_data.ts | 244 + zkemail_verification/scripts/run_testnet.ts | 95 + .../scripts/run_verification.ts | 97 + zkemail_verification/scripts/sponsored_fpc.ts | 25 + .../tests/zkemail_verification.test.ts | 132 + zkemail_verification/tsconfig.json | 18 + zkemail_verification/vitest.config.ts | 8 + zkemail_verification/yarn.lock | 4834 +++++++++++++++++ 15 files changed, 5826 insertions(+) create mode 100644 zkemail_verification/.gitignore create mode 100644 zkemail_verification/README.md create mode 100644 zkemail_verification/circuit/Nargo.toml create mode 100644 zkemail_verification/circuit/src/main.nr create mode 100644 zkemail_verification/contract/Nargo.toml create mode 100644 zkemail_verification/contract/src/main.nr create mode 100644 zkemail_verification/package.json create mode 100644 zkemail_verification/scripts/generate_data.ts create mode 100644 zkemail_verification/scripts/run_testnet.ts create mode 100644 zkemail_verification/scripts/run_verification.ts create mode 100644 zkemail_verification/scripts/sponsored_fpc.ts create mode 100644 zkemail_verification/tests/zkemail_verification.test.ts create mode 100644 zkemail_verification/tsconfig.json create mode 100644 zkemail_verification/vitest.config.ts create mode 100644 zkemail_verification/yarn.lock diff --git a/zkemail_verification/.gitignore b/zkemail_verification/.gitignore new file mode 100644 index 0000000..b44bd27 --- /dev/null +++ b/zkemail_verification/.gitignore @@ -0,0 +1,8 @@ +target/ +artifacts/ +node_modules/ +*.log +.DS_Store +codegenCache.json +data.json +store/ diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md new file mode 100644 index 0000000..875afde --- /dev/null +++ b/zkemail_verification/README.md @@ -0,0 +1,186 @@ +# Verify ZK Email Proofs in Aztec Contracts + +Proves that an email was sent from a specific domain (`icloud.com`) using DKIM signature verification in a Noir circuit, then verifies that proof on-chain inside an Aztec private smart contract. + +Built to validate the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library's compatibility with Aztec 4.2.0. + +## Overview + +This project implements: + +- **Noir Circuit** (`circuit/`): Verifies a 2048-bit RSA DKIM signature, checks the body hash, extracts the sender address, and asserts the sender domain is `icloud.com`. Returns three public outputs: two public key hashes (root of trust) and an email nullifier. +- **Aztec Contract** (`contract/`): A private smart contract that verifies the Noir proof on-chain using `verify_honk_proof` and tracks a per-user verification count. +- **Proof Generation** (`scripts/generate_data.ts`): Generates an UltraHonk proof from hardcoded test email data and verifies it off-chain before writing `data.json`. +- **On-chain Verification** (`scripts/run_testnet.ts`): Deploys the contract and submits the proof for verification on the Aztec testnet. + +**Aztec Version**: `4.2.0-aztecnr-rc.2` (compatible with testnet `4.2.0-rc.1`) + +## Testnet Deployment + +Successfully deployed and verified on the Aztec testnet (`https://rpc.testnet.aztec-labs.com`) with real proofs enabled. + +| Step | Transaction Hash | +|------|-----------------| +| Account deployment | `0x190a55042b4a4bd063150c0b1d2a233c07e8b4b7decb3ba57e2527c646acd2be` | +| Contract deployment | `0x258f5c271e67ce681cf7db8641984d78d6e7718268d6cb4b9897d8ac624709bc` | +| Email proof verification | `0x2c053bad6f58bfcdea0b2bc4b918e0e31bb3d38aed740ac836e227cd5b7bca4e` | + +**Contract address**: `0x1bbf99d2acd54c9dc9ef58fd05892fec9d5916fa66949aead6877964879a142b` + +## How It Works + +``` +Raw Email ──> [Noir Circuit] ──> UltraHonk Proof ──> [Aztec Contract] ──> On-chain Verification + │ │ + │ DKIM verify │ verify_honk_proof() + │ Body hash check │ Increment counter + │ Domain = icloud.com │ + │ │ + └──> 3 public outputs: └──> VK hash stored in + pubkey_hash[0] PublicImmutable storage + pubkey_hash[1] + email_nullifier +``` + +1. The **inner circuit** (`circuit/src/main.nr`) uses the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library to: + - Verify the DKIM RSA signature over the email header + - Extract and verify the body hash from the DKIM-Signature header against a SHA256 hash of the body + - Extract the sender email address from the `From:` header + - Assert the sender domain is `icloud.com` + - Output the public key hash (Poseidon), redc parameter hash, and email nullifier (Pedersen) + +2. An **UltraHonk proof** is generated off-chain using Barretenberg (`@aztec/bb.js`), then verified off-chain to confirm validity. + +3. The **Aztec contract** (`contract/src/main.nr`) calls `verify_honk_proof(vk, proof, public_inputs, vk_hash)` inside a private function. The VK hash is stored at deployment to bind the contract to the specific circuit. On successful verification, a public counter is incremented. + +4. With `proverEnabled: true`, the PXE generates real ClientIVC proofs that enforce the `verify_honk_proof` constraint during private kernel execution — the inner proof is cryptographically verified, not skipped. + +## Prerequisites + +- [Node.js](https://nodejs.org/) (v22+) and [Yarn](https://yarnpkg.com/) +- [Aztec CLI](https://docs.aztec.network/getting_started/quickstart) (version 4.2.0-aztecnr-rc.2) + +```bash +# Install Aztec CLI +bash -i <(curl -s https://install.aztec.network) +aztec-up 4.2.0-aztecnr-rc.2 + +# Verify nargo (bundled with Aztec CLI) +nargo --version # 1.0.0-beta.18 +``` + +## Project Structure + +``` +. +├── circuit/ # Inner Noir circuit (vanilla bin, not Aztec contract) +│ ├── src/main.nr # DKIM verify + domain check + public outputs +│ └── Nargo.toml # Depends on zkemail.nr and sha256 +├── contract/ # Aztec smart contract +│ ├── src/main.nr # verify_honk_proof + counter storage +│ ├── artifacts/ # Generated TypeScript bindings +│ └── Nargo.toml # Depends on aztec-nr and bb_proof_verification +├── scripts/ +│ ├── generate_data.ts # Build circuit inputs, generate + verify proof +│ ├── run_verification.ts # Deploy + verify on local network +│ ├── run_testnet.ts # Deploy + verify on Aztec testnet +│ └── sponsored_fpc.ts # SponsoredFPC fee payment utility +├── tests/ +│ └── zkemail_verification.test.ts # Vitest integration tests +├── data.json # Generated proof data (created by yarn data) +├── package.json +├── tsconfig.json +└── vitest.config.ts +``` + +## Quick Start + +```bash +# Install dependencies +yarn install + +# Compile the inner Noir circuit +cd circuit && nargo compile && cd .. + +# Compile the Aztec contract and generate TypeScript bindings +yarn ccc + +# Generate proof data (generates + verifies proof, writes data.json) +yarn data +``` + +### Deploy to Testnet + +```bash +yarn testnet +``` + +### Deploy to Local Network + +```bash +# Start local network in a separate terminal +aztec start --local-network + +# Deploy and verify +yarn verify + +# Or run the full test suite +yarn test +``` + +## Scripts + +| Command | Description | +|---------|-------------| +| `yarn ccc` | Compile Aztec contract + generate TypeScript bindings | +| `yarn data` | Generate UltraHonk proof from test email data, verify off-chain, write `data.json` | +| `yarn testnet` | Deploy contract and verify proof on the Aztec testnet | +| `yarn verify` | Deploy contract and verify proof on local network | +| `yarn test` | Run Vitest integration tests against local network | + +## Circuit Details + +The inner circuit verifies a DKIM-signed email from `icloud.com` using ~222K constraints: + +| Component | Constraints | Description | +|-----------|------------|-------------| +| DKIM signature verification | ~86,500 | RSA-2048 PKCS#1 v1.5 over SHA256 header hash | +| Body hash (SHA256) | ~114,000 | SHA256 over email body, compared to DKIM `bh=` field | +| Address extraction | ~16,000 | Extract and validate `From:` email address | +| Domain check | ~100 | Assert domain bytes match `icloud.com` | +| Key + nullifier hashing | ~10,200 | Poseidon hash of pubkey, Pedersen hash of signature | + +**Public outputs** (3 fields): +- `pubkey_hash[0]` — Poseidon hash of RSA modulus (root of trust) +- `pubkey_hash[1]` — Poseidon hash of RSA redc parameter +- `email_nullifier` — Pedersen hash of DKIM signature (prevents double-use) + +## Contract Details + +The `ZKEmailVerifier` contract stores a verification key hash at deployment and exposes: + +- `verify_email(owner, vk, proof, public_inputs)` — **private function** that verifies the UltraHonk proof and enqueues a public state update +- `get_verification_count(owner)` — **public view** that returns how many emails have been verified for an address + +The contract uses the hybrid private/public execution pattern: proof verification happens privately (the email content is never revealed on-chain), while the verification count is updated publicly. + +## Troubleshooting + +**"Cannot find module '../contract/artifacts/ZKEmailVerifier'"** +Run `yarn ccc` to compile the contract and generate TypeScript bindings. + +**"Cannot find module '../data.json'"** +Run `yarn data` to generate the proof data. + +**"Failed to connect" on testnet** +Check testnet status: `curl https://rpc.testnet.aztec-labs.com/status` + +**Proof verification fails off-chain** +Ensure the circuit was compiled with `nargo compile` after any changes, then re-run `yarn data`. + +## Dependencies + +- [zkemail.nr](https://github.com/zkemail/zkemail.nr) — Noir library for DKIM email verification +- [aztec-nr](https://github.com/AztecProtocol/aztec-nr/) v4.2.0-aztecnr-rc.2 — Aztec smart contract framework +- [bb_proof_verification](https://github.com/AztecProtocol/aztec-packages/) — Barretenberg proof verification for Aztec contracts +- [@aztec/bb.js](https://www.npmjs.com/package/@aztec/bb.js) 4.2.0-aztecnr-rc.2 — UltraHonk proving backend diff --git a/zkemail_verification/circuit/Nargo.toml b/zkemail_verification/circuit/Nargo.toml new file mode 100644 index 0000000..29c4306 --- /dev/null +++ b/zkemail_verification/circuit/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "icloud_email_verifier" +type = "bin" +authors = [""] +compiler_version = ">=1.0.0" + +[dependencies] +zkemail = { path = "/workspaces/sandbox/zkemail.nr/lib" } +sha256 = { git = "https://github.com/noir-lang/sha256", tag = "v0.3.0" } diff --git a/zkemail_verification/circuit/src/main.nr b/zkemail_verification/circuit/src/main.nr new file mode 100644 index 0000000..6c6a75b --- /dev/null +++ b/zkemail_verification/circuit/src/main.nr @@ -0,0 +1,77 @@ +use sha256::sha256_var; +use std::{collections::bounded_vec::BoundedVec, hash::pedersen_hash}; +use zkemail::{ + dkim::RSAPubkey, headers::body_hash::get_body_hash, + headers::email_address::get_email_address, KEY_LIMBS_2048, MAX_EMAIL_ADDRESS_LENGTH, Sequence, +}; + +global MAX_EMAIL_HEADER_LENGTH: u32 = 512; +global MAX_EMAIL_BODY_LENGTH: u32 = 1024; +global EXPECTED_DOMAIN: [u8; 10] = comptime { "icloud.com".as_bytes() }; + +/// Verify a DKIM-signed email from the icloud.com domain +/// +/// Returns: +/// [0]: Poseidon hash of DKIM public key modulus +/// [1]: Poseidon hash of DKIM public key redc parameter +/// [2]: Pedersen hash of DKIM signature (email nullifier) +fn main( + header: BoundedVec, + body: BoundedVec, + pubkey: RSAPubkey, + signature: [Field; KEY_LIMBS_2048], + body_hash_index: u32, + dkim_header_sequence: Sequence, + from_header_sequence: Sequence, + from_address_sequence: Sequence, +) -> pub [Field; 3] { + assert(header.len() <= MAX_EMAIL_HEADER_LENGTH); + assert(body.len() <= MAX_EMAIL_BODY_LENGTH); + + // Verify the DKIM signature over the header + pubkey.verify_dkim_signature(header, signature); + + // Extract the body hash from the DKIM-Signature header and verify against computed body hash + let signed_body_hash = get_body_hash(header, dkim_header_sequence, body_hash_index); + let computed_body_hash: [u8; 32] = sha256_var(body.storage(), body.len() as u32); + assert( + signed_body_hash == computed_body_hash, + "SHA256 hash computed over body does not match body hash found in DKIM-signed header", + ); + + // Extract the from email address + let from_field_name = comptime { "from".as_bytes() }; + let from_address: BoundedVec = + get_email_address(header, from_header_sequence, from_address_sequence, from_field_name); + + // Find the '@' in the from address and verify the domain matches "icloud.com" + let mut at_index: u32 = 0; + let mut found_at = false; + for i in 0..MAX_EMAIL_ADDRESS_LENGTH { + if i < from_address.len() { + if from_address.get_unchecked(i) == 64 { + at_index = i + 1; + found_at = true; + } + } + } + assert(found_at, "No @ symbol found in from address"); + + // Check the domain length matches + let domain_len = from_address.len() - at_index; + assert(domain_len == 10, "Domain length does not match icloud.com"); + + // Check each byte of the domain + for i in 0..10 { + assert( + from_address.get_unchecked(at_index + i) == EXPECTED_DOMAIN[i], + "Email domain does not match icloud.com", + ); + } + + // Compute standard outputs + let email_nullifier = pedersen_hash(signature); + let pubkey_hash = pubkey.hash(); + [pubkey_hash[0], pubkey_hash[1], email_nullifier] +} + diff --git a/zkemail_verification/contract/Nargo.toml b/zkemail_verification/contract/Nargo.toml new file mode 100644 index 0000000..595996c --- /dev/null +++ b/zkemail_verification/contract/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ZKEmailVerifier" +type = "contract" +authors = [""] + +[dependencies] +aztec = { git = "https://github.com/AztecProtocol/aztec-nr/", tag = "v4.2.0-aztecnr-rc.2", directory = "aztec" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.2.0-aztecnr-rc.2", directory = "barretenberg/noir/bb_proof_verification" } diff --git a/zkemail_verification/contract/src/main.nr b/zkemail_verification/contract/src/main.nr new file mode 100644 index 0000000..3000bc3 --- /dev/null +++ b/zkemail_verification/contract/src/main.nr @@ -0,0 +1,51 @@ +use aztec::macros::aztec; + +#[aztec] +pub contract ZKEmailVerifier { + use aztec::{ + macros::{functions::{external, initializer, only_self, view}, storage::storage}, + oracle::logging::debug_log_format, + protocol::{address::AztecAddress, traits::ToField}, + state_vars::{Map, PublicImmutable, PublicMutable}, + }; + use bb_proof_verification::{UltraHonkVerificationKey, UltraHonkZKProof, verify_honk_proof}; + + #[storage] + struct Storage { + verification_count: Map, Context>, + vk_hash: PublicImmutable, + } + + #[initializer] + #[external("public")] + fn constructor(owner: AztecAddress, vk_hash: Field) { + self.storage.verification_count.at(owner).write(0); + self.storage.vk_hash.initialize(vk_hash); + } + + #[external("private")] + fn verify_email( + owner: AztecAddress, + verification_key: UltraHonkVerificationKey, + proof: UltraHonkZKProof, + public_inputs: [Field; 3], + ) { + debug_log_format("Verifying email proof for owner {0}", [owner.to_field()]); + let vk_hash = self.storage.vk_hash.read(); + verify_honk_proof(verification_key, proof, public_inputs, vk_hash); + self.enqueue_self._increment_verification_count(owner); + } + + #[only_self] + #[external("public")] + fn _increment_verification_count(owner: AztecAddress) { + let current = self.storage.verification_count.at(owner).read(); + self.storage.verification_count.at(owner).write(current + 1); + } + + #[view] + #[external("public")] + fn get_verification_count(owner: AztecAddress) -> Field { + self.storage.verification_count.at(owner).read() + } +} diff --git a/zkemail_verification/package.json b/zkemail_verification/package.json new file mode 100644 index 0000000..eb0faad --- /dev/null +++ b/zkemail_verification/package.json @@ -0,0 +1,34 @@ +{ + "name": "zkemail_verification", + "module": "index.ts", + "type": "module", + "scripts": { + "clean": "rm -rf store", + "ccc": "cd contract && aztec compile && aztec codegen target -o artifacts", + "data": "tsx scripts/generate_data.ts", + "verify": "tsx scripts/run_verification.ts", + "testnet": "tsx scripts/run_testnet.ts", + "test": "yarn clean && vitest run", + "test:watch": "vitest" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "vitest": "^3.0.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@aztec/accounts": "4.2.0-aztecnr-rc.2", + "@aztec/aztec.js": "4.2.0-aztecnr-rc.2", + "@aztec/bb.js": "4.2.0-aztecnr-rc.2", + "@aztec/kv-store": "4.2.0-aztecnr-rc.2", + "@aztec/noir-contracts.js": "4.2.0-aztecnr-rc.2", + "@aztec/noir-noir_js": "4.2.0-aztecnr-rc.2", + "@aztec/pxe": "4.2.0-aztecnr-rc.2", + "@aztec/wallets": "4.2.0-aztecnr-rc.2", + "@aztec/stdlib": "4.2.0-aztecnr-rc.2", + "tsx": "^4.20.6" + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" +} diff --git a/zkemail_verification/scripts/generate_data.ts b/zkemail_verification/scripts/generate_data.ts new file mode 100644 index 0000000..422f8ae --- /dev/null +++ b/zkemail_verification/scripts/generate_data.ts @@ -0,0 +1,244 @@ +import { Noir } from '@aztec/noir-noir_js'; +import circuitJson from '../circuit/target/icloud_email_verifier.json' with { type: "json" } +import { Barretenberg, UltraHonkBackend, deflattenFields } from '@aztec/bb.js'; +import fs from 'fs' +import { exit } from 'process'; + +// ============================================================================= +// Test data from zkemail.nr/lib/src/tests/test_inputs.nr (EmailLarge module) +// Email from: runnier.leagues.0j@icloud.com +// ============================================================================= + +const HEADER_BYTES = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, + 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, + 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, + 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 116, 102, 45, 56, 13, 10, 109, 105, + 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, 46, 48, 32, 40, 77, 97, 99, 32, 79, + 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, + 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, 117, 98, 106, 101, 99, 116, 58, 66, 105, + 116, 99, 111, 105, 110, 13, 10, 109, 101, 115, 115, 97, 103, 101, 45, 105, 100, 58, 60, 49, + 50, 56, 48, 48, 65, 57, 48, 45, 52, 69, 67, 67, 45, 52, 53, 49, 51, 45, 57, 50, 57, 56, 45, + 65, 51, 51, 53, 52, 54, 49, 50, 50, 57, 50, 48, 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, + 100, 97, 116, 101, 58, 87, 101, 100, 44, 32, 51, 32, 65, 112, 114, 32, 50, 48, 50, 52, 32, + 49, 54, 58, 50, 51, 58, 52, 56, 32, 43, 48, 53, 51, 48, 13, 10, 116, 111, 58, 122, 107, 101, + 119, 116, 101, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, + 105, 109, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, + 114, 115, 97, 45, 115, 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, + 100, 47, 114, 101, 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, + 99, 111, 109, 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 55, 49, 50, + 49, 52, 49, 54, 52, 52, 59, 32, 98, 104, 61, 50, 74, 115, 100, 75, 52, 66, 77, 122, 122, + 116, 57, 119, 52, 90, 108, 122, 50, 84, 100, 121, 86, 67, 70, 99, 43, 108, 55, 118, 78, 121, + 84, 53, 97, 65, 103, 71, 68, 89, 102, 55, 102, 77, 61, 59, 32, 104, 61, 102, 114, 111, 109, + 58, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, + 101, 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99, 116, 58, 77, 101, 115, 115, 97, + 103, 101, 45, 73, 100, 58, 68, 97, 116, 101, 58, 116, 111, 59, 32, 98, 61, +]; + +const BODY_BYTES = [ + 84, 104, 101, 32, 84, 105, 109, 101, 115, 32, 48, 51, 47, 74, 97, 110, 47, 50, 48, 48, 57, + 32, 67, 104, 97, 110, 99, 101, 108, 108, 111, 114, 32, 111, 110, 32, 98, 114, 105, 110, 107, + 32, 111, 102, 32, 115, 101, 99, 111, 110, 100, 32, 98, 97, 105, 108, 111, 117, 116, 32, 102, + 111, 114, 32, 98, 97, 110, 107, 115, 13, 10, 13, 10, 49, 53, 32, 121, 101, 97, 114, 115, 32, + 97, 103, 111, 44, 32, 83, 97, 116, 111, 115, 104, 105, 32, 109, 105, 110, 101, 100, 32, 116, + 104, 101, 32, 102, 105, 114, 115, 116, 32, 98, 108, 111, 99, 107, 32, 111, 102, 32, 116, + 104, 101, 32, 66, 105, 116, 99, 111, 105, 110, 32, 98, 108, 111, 99, 107, 99, 104, 97, 105, + 110, 32, 61, 13, 10, 65, 102, 116, 101, 114, 32, 116, 104, 101, 32, 66, 105, 116, 99, 111, + 105, 110, 32, 119, 104, 105, 116, 101, 32, 112, 97, 112, 101, 114, 32, 97, 112, 112, 101, + 97, 114, 101, 100, 32, 111, 110, 32, 79, 99, 116, 111, 98, 101, 114, 32, 51, 49, 44, 32, 50, + 48, 48, 56, 44, 32, 111, 110, 32, 97, 32, 61, 13, 10, 99, 114, 121, 112, 116, 111, 103, 114, + 97, 112, 104, 121, 32, 109, 97, 105, 108, 105, 110, 103, 32, 108, 105, 115, 116, 44, 32, + 116, 104, 101, 32, 71, 101, 110, 101, 115, 105, 115, 32, 66, 108, 111, 99, 107, 32, 61, 69, + 50, 61, 56, 48, 61, 57, 52, 32, 116, 104, 101, 32, 102, 105, 114, 115, 116, 32, 98, 105, + 116, 99, 111, 105, 110, 32, 61, 13, 10, 98, 108, 111, 99, 107, 32, 97, 110, 100, 32, 116, + 104, 101, 32, 98, 97, 115, 105, 115, 32, 111, 102, 32, 116, 104, 101, 32, 101, 110, 116, + 105, 114, 101, 32, 66, 105, 116, 99, 111, 105, 110, 32, 116, 114, 97, 100, 105, 110, 103, + 32, 115, 121, 115, 116, 101, 109, 32, 105, 110, 32, 112, 108, 97, 99, 101, 32, 116, 111, 32, + 61, 13, 10, 116, 104, 105, 115, 32, 100, 97, 121, 32, 61, 69, 50, 61, 56, 48, 61, 57, 52, + 32, 119, 97, 115, 32, 109, 105, 110, 101, 100, 32, 111, 110, 32, 74, 97, 110, 117, 97, 114, + 121, 32, 51, 44, 32, 50, 48, 48, 57, 46, 61, 50, 48, 13, 10, 13, 10, 84, 104, 101, 32, 71, + 101, 110, 101, 115, 105, 115, 32, 66, 108, 111, 99, 107, 32, 105, 115, 32, 97, 108, 115, + 111, 32, 107, 110, 111, 119, 110, 32, 97, 115, 32, 66, 108, 111, 99, 107, 32, 48, 32, 111, + 114, 32, 66, 108, 111, 99, 107, 32, 49, 44, 32, 97, 110, 100, 32, 105, 115, 32, 115, 116, + 105, 108, 108, 32, 105, 110, 32, 61, 13, 10, 116, 104, 101, 32, 66, 105, 116, 99, 111, 105, + 110, 32, 110, 101, 116, 119, 111, 114, 107, 44, 32, 119, 104, 101, 114, 101, 32, 105, 116, + 32, 119, 105, 108, 108, 32, 114, 101, 109, 97, 105, 110, 32, 97, 115, 32, 108, 111, 110, + 103, 32, 97, 115, 32, 116, 104, 101, 114, 101, 32, 105, 115, 32, 97, 32, 99, 111, 109, 112, + 117, 116, 101, 114, 32, 61, 13, 10, 114, 117, 110, 110, 105, 110, 103, 32, 116, 104, 101, + 32, 66, 105, 116, 99, 111, 105, 110, 32, 115, 111, 102, 116, 119, 97, 114, 101, 46, 61, 50, + 48, 13, 10, 13, 10, 65, 108, 108, 32, 110, 111, 100, 101, 115, 32, 105, 110, 32, 116, 104, + 101, 32, 66, 105, 116, 99, 111, 105, 110, 32, 110, 101, 116, 119, 111, 114, 107, 32, 99, 97, + 110, 32, 99, 111, 110, 115, 117, 108, 116, 32, 105, 116, 44, 32, 101, 118, 101, 110, 32, + 105, 102, 32, 105, 116, 32, 105, 115, 32, 97, 116, 32, 116, 104, 101, 32, 61, 13, 10, 111, + 116, 104, 101, 114, 32, 101, 110, 100, 32, 111, 102, 32, 116, 104, 101, 32, 110, 101, 116, + 119, 111, 114, 107, 32, 119, 105, 116, 104, 32, 104, 117, 110, 100, 114, 101, 100, 115, 32, + 111, 102, 32, 116, 104, 111, 117, 115, 97, 110, 100, 115, 32, 111, 102, 32, 98, 108, 111, + 99, 107, 115, 46, 13, 10, +]; + +// RSA public key modulus limbs (18 x 120-bit) +const MODULUS_LIMBS = [ + "0xe5cf995b5ef59ce9943d1f4209b6ab", + "0xe0caf03235e91a2db27e9ed214bcc6", + "0xafe1309f87414bd36ed296dacfade2", + "0xbeff3f19046a43adce46c932514988", + "0x324041af8736e87de4358860fff057", + "0xadcc6669dfa346f322717851a8c22a", + "0x8b2a193089e6bf951c553b5a6f71aa", + "0x0a570fe582918c4f731a0002068df2", + "0x39419a433d6bfdd1978356cbca4b60", + "0x550d695a514d38b45c862320a00ea5", + "0x1c56ac1dfbf1beea31e8a613c2a51f", + "0x6a30c9f22d2e5cb6934263d0838809", + "0x0a281f268a44b21a4f77a91a52f960", + "0x5134dc3966c8e91402669a47cc8597", + "0x71590781df114ec072e641cdc5d224", + "0xa1bc0f0937489c806c1944fd029dc9", + "0x911f6e47f84db3b64c3648ebb5a127", + "0xd5", +]; + +// RSA public key redc parameter limbs (Barrett reduction, OVERFLOW_BITS=6) +const REDC_LIMBS = [ + "0x22a09393af1f83c4167cfb3e95f118", + "0x7076c8fcf1f51eb5f9f5f3f6946269", + "0x6edaeef63eb3c047c08bea4146bb01", + "0x3ea933bd1d2fb58e4d8ba9c7de885e", + "0x40ea942ddf892c0c21069f41856049", + "0xefd398a01786182a41303d9a97eb45", + "0x2f492dc910b4b3991f75f42910da16", + "0xd2a20e69118305a7739c4e3bf6bbd7", + "0xc1b8278c646e656c2396d1460bd941", + "0x7eb52a27e0da7f8439752db8526843", + "0x1de2c5660b447afdff88ed3857c414", + "0x27fce9159c1dd44311d392b02886b7", + "0xdf9a7976eddc59edcc1979316b5aa8", + "0x3d1dd388b9ff8e8e190861bdeb9d2c", + "0xb9cad7ad3204e8ecde66020eaae07b", + "0x239c142aa2afb739691705a614dd85", + "0x4ca1794ecc8ac887def3d3e3e2b629", + "0x4cb7", +]; + +// DKIM signature limbs (18 x 120-bit) +const SIGNATURE_LIMBS = [ + "0xf193c3300b7c9902e32861c38d0d2d", + "0x9f6927fdb3df0b84092d8459654327", + "0x8a0bea5e2fa82821e49c27b68d5a7b", + "0xaa8c0acc1190f9fd845ef64f8e7ae9", + "0xa7aeebb37f4395965543e6df69a5a7", + "0x087ecef9921569cfba83331ca11c6b", + "0x4589ed316ed20757e65ad221736011", + "0x0835d8748f11dcc985700c3fea27b1", + "0xe870d2493fb83b4a1d72350e5de926", + "0x268b28eda0aac07625cfab32b60af1", + "0xb41a164eae7ba1602eaec5b5a39fe6", + "0x693cc5ec578422bee48eabe390fc37", + "0xa29504dd504f14423f2ce65b2ac388", + "0x6c3ac6310c084a0b126fcd5225c208", + "0xab0903e48563e5f4a5365ac5cbd888", + "0xf05bf2e5b6266c0ac88dfc733c414f", + "0xf58f9e9669e0f4f3086cce1187fd44", + "0xb9", +]; + +const MAX_HEADER_LENGTH = 512; +const MAX_BODY_LENGTH = 1024; + +// ============================================================================= +// Build circuit inputs +// ============================================================================= + +// Pad arrays to max length with zeros +function padArray(arr: number[], maxLen: number): string[] { + const padded = [...arr.map(b => b.toString()), ...Array(maxLen - arr.length).fill("0")]; + return padded; +} + +const inputs = { + header: { + storage: padArray(HEADER_BYTES, MAX_HEADER_LENGTH), + len: HEADER_BYTES.length.toString(), + }, + body: { + storage: padArray(BODY_BYTES, MAX_BODY_LENGTH), + len: BODY_BYTES.length.toString(), + }, + pubkey: { + modulus: MODULUS_LIMBS, + redc: REDC_LIMBS, + }, + signature: SIGNATURE_LIMBS, + body_hash_index: "361", + dkim_header_sequence: { index: "267", length: "203" }, + from_header_sequence: { index: "0", length: "34" }, + from_address_sequence: { index: "5", length: "29" }, +}; + +// ============================================================================= +// Generate proof +// ============================================================================= + +console.log("Initializing Barretenberg..."); +const barretenbergAPI = await Barretenberg.new({ threads: 1 }); + +const noir = new Noir(circuitJson as any); + +console.log("Executing circuit (generating witness)..."); +const { witness } = await noir.execute(inputs); +console.log("Witness generated successfully"); + +const backend = new UltraHonkBackend(circuitJson.bytecode, barretenbergAPI); + +console.log("Generating UltraHonk proof (this may take several minutes)..."); +const proofData = await backend.generateProof(witness, { + verifierTarget: 'noir-recursive' +}); +console.log("Proof generated successfully"); + +// Verify proof off-chain +console.log("Verifying proof off-chain..."); +const isValid = await backend.verifyProof(proofData, { + verifierTarget: 'noir-recursive' +}); +console.log(`Off-chain proof verification: ${isValid ? 'SUCCESS' : 'FAILED'}`); +if (!isValid) { + console.error("FATAL: Proof verification failed off-chain. Aborting."); + await barretenbergAPI.destroy(); + exit(1); +} + +// Generate recursive proof artifacts +console.log("Generating recursive proof artifacts..."); +const recursiveArtifacts = await backend.generateRecursiveProofArtifacts( + proofData.proof, + proofData.publicInputs.length +); + +// Handle proofAsFields fallback (same as reference) +let proofAsFields = recursiveArtifacts.proofAsFields; +if (proofAsFields.length === 0) { + console.log('Using deflattenFields to convert proof...'); + proofAsFields = deflattenFields(proofData.proof).map(f => f.toString()); +} + +const vkAsFields = recursiveArtifacts.vkAsFields; + +console.log(`VK size: ${vkAsFields.length}`); +console.log(`Proof size: ${proofAsFields.length}`); +console.log(`Public inputs: ${proofData.publicInputs.length}`); + +// Write data.json +const data = { + vkAsFields: vkAsFields, + vkHash: recursiveArtifacts.vkHash, + proofAsFields: proofAsFields, + publicInputs: proofData.publicInputs.map((p: string) => p.toString()), +}; + +fs.writeFileSync('data.json', JSON.stringify(data, null, 2)); +console.log("data.json written successfully"); + +await barretenbergAPI.destroy(); +console.log("Done"); +exit(); diff --git a/zkemail_verification/scripts/run_testnet.ts b/zkemail_verification/scripts/run_testnet.ts new file mode 100644 index 0000000..8903bbd --- /dev/null +++ b/zkemail_verification/scripts/run_testnet.ts @@ -0,0 +1,95 @@ +import { createAztecNodeClient } from "@aztec/aztec.js/node"; +import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee"; +import type { FieldLike } from "@aztec/aztec.js/abi"; +import { getSponsoredFPCInstance } from "./sponsored_fpc.js"; +import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC"; +import { ZKEmailVerifierContract } from "../contract/artifacts/ZKEmailVerifier"; +import data from "../data.json"; +import { EmbeddedWallet } from "@aztec/wallets/embedded"; +import { NO_FROM } from "@aztec/aztec.js/account"; +import { Fr } from "@aztec/aztec.js/fields"; +import assert from "node:assert"; + +const TESTNET_URL = "https://rpc.testnet.aztec-labs.com"; + +const sponsoredFPC = await getSponsoredFPCInstance(); +const sponsoredPaymentMethod = new SponsoredFeePaymentMethod( + sponsoredFPC.address +); + +async function main() { + console.log(`Connecting to Aztec testnet at ${TESTNET_URL}...`); + const aztecNode = await createAztecNodeClient(TESTNET_URL); + + const nodeInfo = await aztecNode.getNodeInfo(); + console.log(`Testnet node version: ${nodeInfo.nodeVersion}`); + console.log(`Real proofs enabled: ${nodeInfo.realProofs}`); + + console.log("Creating EmbeddedWallet..."); + const testWallet = await EmbeddedWallet.create(aztecNode, { + pxeConfig: { proverEnabled: true }, + ephemeral: true, + }); + await testWallet.registerContract(sponsoredFPC, SponsoredFPCContract.artifact); + console.log("EmbeddedWallet configured"); + + console.log("Creating Schnorr account..."); + const account = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); + const manager = await account.getDeployMethod(); + console.log("Deploying account (this will take a while on testnet with real proofs)..."); + await manager.send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + + const accounts = await testWallet.getAccounts(); + const ownerAddress = accounts[0].item; + console.log(`Owner address: ${ownerAddress.toString()}`); + + const sendOpts = { + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + }; + + console.log("Deploying ZKEmailVerifier contract..."); + const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( + testWallet, + ownerAddress, + data.vkHash as unknown as FieldLike + ).send(sendOpts); + + console.log(`Contract deployed at: ${zkEmailVerifier.address.toString()}`); + + // Check initial verification count + let counterValue = (await zkEmailVerifier.methods + .get_verification_count(ownerAddress) + .simulate({ from: ownerAddress })).result; + console.log(`Initial verification count: ${counterValue}`); + + console.log("Submitting ZK email proof for on-chain verification..."); + const { receipt: tx } = await zkEmailVerifier.methods.verify_email( + ownerAddress, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(sendOpts); + + console.log(`Transaction hash: ${tx.txHash.toString()}`); + console.log(`Transaction status: ${tx.status}`); + + // Read verification count + counterValue = (await zkEmailVerifier.methods + .get_verification_count(ownerAddress) + .simulate({ from: ownerAddress })).result; + console.log(`Verification count after proof: ${counterValue}`); + + assert(counterValue === 1n, `Expected verification count 1, got ${counterValue}`); + console.log("SUCCESS: ZK email proof verified on Aztec testnet!"); + + await testWallet.stop(); +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/zkemail_verification/scripts/run_verification.ts b/zkemail_verification/scripts/run_verification.ts new file mode 100644 index 0000000..2c411ba --- /dev/null +++ b/zkemail_verification/scripts/run_verification.ts @@ -0,0 +1,97 @@ +import { createAztecNodeClient } from "@aztec/aztec.js/node"; +import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee"; +import type { FieldLike } from "@aztec/aztec.js/abi"; +import { getSponsoredFPCInstance } from "./sponsored_fpc.js"; +import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC"; +import { ZKEmailVerifierContract } from "../contract/artifacts/ZKEmailVerifier"; +import data from "../data.json"; +import { EmbeddedWallet } from "@aztec/wallets/embedded"; +import { NO_FROM } from "@aztec/aztec.js/account"; +import { Fr } from "@aztec/aztec.js/fields"; +import assert from "node:assert"; + +export const NODE_URL = "http://localhost:8080"; + +const sponsoredFPC = await getSponsoredFPCInstance(); +const sponsoredPaymentMethod = new SponsoredFeePaymentMethod( + sponsoredFPC.address +); + +export const setupWallet = async (): Promise => { + try { + const aztecNode = await createAztecNodeClient(NODE_URL); + let wallet = await EmbeddedWallet.create(aztecNode, { + pxeConfig: { proverEnabled: true }, + ephemeral: true, + }); + await wallet.registerContract(sponsoredFPC, SponsoredFPCContract.artifact); + + return wallet; + } catch (error) { + console.error("Failed to setup local network:", error); + throw error; + } +}; + +async function main() { + console.log("Setting up wallet with proverEnabled: true..."); + const testWallet = await setupWallet(); + + console.log("Creating Schnorr account..."); + const account = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); + const manager = await account.getDeployMethod(); + await manager + .send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + const accounts = await testWallet.getAccounts(); + const ownerAddress = accounts[0].item; + console.info('Owner address:', ownerAddress.toString()); + + console.log("Deploying ZKEmailVerifier contract..."); + const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( + testWallet, + ownerAddress, + data.vkHash as unknown as FieldLike + ) + .send({ + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + + console.log("Contract deployed at:", zkEmailVerifier.address.toString()); + + // Check initial verification count + let counterValue = (await zkEmailVerifier.methods + .get_verification_count(ownerAddress) + .simulate({ from: ownerAddress })).result; + console.log(`Initial verification count: ${counterValue}`); + + console.log("Submitting email proof for on-chain verification (this may take 5-15 minutes with real proofs)..."); + const opts = { + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + }; + + await zkEmailVerifier.methods.verify_email( + ownerAddress, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(opts); + + // Check verification count after + counterValue = (await zkEmailVerifier.methods + .get_verification_count(ownerAddress) + .simulate({ from: ownerAddress })).result; + console.log(`Verification count after proof: ${counterValue}`); + + assert(counterValue === 1n, `Expected verification count to be 1, got ${counterValue}`); + console.log("SUCCESS: Email proof verified on-chain!"); +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/zkemail_verification/scripts/sponsored_fpc.ts b/zkemail_verification/scripts/sponsored_fpc.ts new file mode 100644 index 0000000..30291c8 --- /dev/null +++ b/zkemail_verification/scripts/sponsored_fpc.ts @@ -0,0 +1,25 @@ +import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts'; +import { Fr } from '@aztec/aztec.js/fields'; +import type { Wallet } from '@aztec/aztec.js/wallet'; +import { SponsoredFPCContract } from '@aztec/noir-contracts.js/SponsoredFPC'; + +const SPONSORED_FPC_SALT = new Fr(BigInt(0)); + +export async function getSponsoredFPCInstance(): Promise { + return await getContractInstanceFromInstantiationParams(SponsoredFPCContract.artifact, { + salt: SPONSORED_FPC_SALT, + }); +} + +export async function getSponsoredFPCAddress() { + return (await getSponsoredFPCInstance()).address; +} + +export async function setupSponsoredFPC(wallet: Wallet) { + const instance = await getContractInstanceFromInstantiationParams(SponsoredFPCContract.artifact, { + salt: new Fr(SPONSORED_FPC_SALT), + }); + + await wallet.registerContract(instance, SponsoredFPCContract.artifact); + return instance; +} diff --git a/zkemail_verification/tests/zkemail_verification.test.ts b/zkemail_verification/tests/zkemail_verification.test.ts new file mode 100644 index 0000000..6bacde4 --- /dev/null +++ b/zkemail_verification/tests/zkemail_verification.test.ts @@ -0,0 +1,132 @@ +import { describe, expect, test, beforeAll, afterAll } from "vitest" +import type { FieldLike } from "@aztec/aztec.js/abi" +import { TxExecutionResult } from "@aztec/aztec.js/tx" +import { AztecAddress } from "@aztec/aztec.js/addresses" +import { NO_FROM } from "@aztec/aztec.js/account" +import { Fr } from "@aztec/aztec.js/fields" +import { createAztecNodeClient } from "@aztec/aztec.js/node" +import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee" +import { EmbeddedWallet } from "@aztec/wallets/embedded" +import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC" +import { ZKEmailVerifierContract } from '../contract/artifacts/ZKEmailVerifier' +import { getSponsoredFPCInstance } from '../scripts/sponsored_fpc' +import data from '../data.json' + +const NODE_URL = 'http://localhost:8080' +const TEST_TIMEOUT = 1200000 // 20 minutes + +describe("ZKEmail Verification", () => { + let testWallet: EmbeddedWallet + let ownerAddress: AztecAddress + let zkEmailVerifierContract: ZKEmailVerifierContract + let sponsoredPaymentMethod: SponsoredFeePaymentMethod + + beforeAll(async () => { + console.log(`Connecting to Aztec Node at ${NODE_URL}`) + const aztecNode = await createAztecNodeClient(NODE_URL) + + const sponsoredFPC = await getSponsoredFPCInstance() + sponsoredPaymentMethod = new SponsoredFeePaymentMethod(sponsoredFPC.address) + + // Create EmbeddedWallet with proverEnabled: true for real proof verification + testWallet = await EmbeddedWallet.create(aztecNode, { + pxeConfig: { proverEnabled: true }, + ephemeral: true, + }) + + await testWallet.registerContract(sponsoredFPC, SponsoredFPCContract.artifact) + console.log('EmbeddedWallet configured with proverEnabled: true') + + console.log('Creating owner account...') + const ownerAccountManager = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()) + const ownerDeployMethod = await ownerAccountManager.getDeployMethod() + console.log('Deploying account (this may take a while with real proof generation)...') + await ownerDeployMethod.send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }) + console.log('Account deployed!') + + const accounts = await testWallet.getAccounts() + ownerAddress = accounts[0].item + console.info('Owner address:', ownerAddress.toString()) + }, TEST_TIMEOUT) + + afterAll(async () => { + if (testWallet) { + await testWallet.stop() + } + }) + + test("should deploy ZKEmailVerifier contract", async () => { + const sendOpts = { + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + } + + ;({ contract: zkEmailVerifierContract } = await ZKEmailVerifierContract.deploy( + testWallet, + ownerAddress, + data.vkHash as unknown as FieldLike + ) + .send(sendOpts)) + + expect(zkEmailVerifierContract.address).toBeDefined() + expect(zkEmailVerifierContract.address.toString()).not.toBe("") + + console.log("Contract deployed at address:", zkEmailVerifierContract.address.toString()) + }, TEST_TIMEOUT) + + test("should verify email proof and increment verification count", async () => { + const sendOpts = { + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + } + + console.log("Submitting email proof for on-chain verification...") + const { receipt: tx } = await zkEmailVerifierContract.methods.verify_email( + ownerAddress, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(sendOpts) + expect(tx).toBeDefined() + expect(tx.txHash).toBeDefined() + expect(tx.executionResult).toBe(TxExecutionResult.SUCCESS) + + console.log(`Transaction hash: ${tx.txHash.toString()}`) + console.log(`Transaction status: ${tx.status}`) + }, TEST_TIMEOUT) + + test("should read verification count", async () => { + const { result: counterValue } = await zkEmailVerifierContract.methods.get_verification_count( + ownerAddress + ).simulate({ from: ownerAddress }) + + expect(counterValue).toBe(1n) + console.log(`Verification count: ${counterValue}`) + }, TEST_TIMEOUT) + + test("should verify same proof again and increment count to 2", async () => { + const sendOpts = { + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + } + + const { receipt: tx } = await zkEmailVerifierContract.methods.verify_email( + ownerAddress, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(sendOpts) + expect(tx).toBeDefined() + expect(tx.executionResult).toBe(TxExecutionResult.SUCCESS) + + const { result: counterValue } = await zkEmailVerifierContract.methods.get_verification_count( + ownerAddress + ).simulate({ from: ownerAddress }) + + expect(counterValue).toBe(2n) + console.log(`Verification count after second proof: ${counterValue}`) + }, TEST_TIMEOUT) +}) diff --git a/zkemail_verification/tsconfig.json b/zkemail_verification/tsconfig.json new file mode 100644 index 0000000..d202670 --- /dev/null +++ b/zkemail_verification/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "lib": ["ESNext"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + } +} diff --git a/zkemail_verification/vitest.config.ts b/zkemail_verification/vitest.config.ts new file mode 100644 index 0000000..8e0efbf --- /dev/null +++ b/zkemail_verification/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + testTimeout: 1200000, // 20 minutes - real IVC proof generation can be very slow + hookTimeout: 1200000, // 20 minutes for beforeAll/afterAll hooks + }, +}) diff --git a/zkemail_verification/yarn.lock b/zkemail_verification/yarn.lock new file mode 100644 index 0000000..0c43c42 --- /dev/null +++ b/zkemail_verification/yarn.lock @@ -0,0 +1,4834 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@^1.11.0": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz#6c2d657d4b2dfb37f8ea811dcb3e60843d4ac24a" + integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== + +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@5.2.0", "@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.892.0": + version "3.1030.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.1030.0.tgz#f5c593deb0e32fbd0a174d00feae9c69c0e7cccf" + integrity sha512-sgGb4ub0JXnHaXnok5td7A1KGwENFPwOrwgzvpkeWq9w16Sl7x2KhYtVl+Fdd/7LAvaEtm3HqrYtNmm2d0OXmQ== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/credential-provider-node" "^3.972.30" + "@aws-sdk/middleware-bucket-endpoint" "^3.972.9" + "@aws-sdk/middleware-expect-continue" "^3.972.9" + "@aws-sdk/middleware-flexible-checksums" "^3.974.7" + "@aws-sdk/middleware-host-header" "^3.972.9" + "@aws-sdk/middleware-location-constraint" "^3.972.9" + "@aws-sdk/middleware-logger" "^3.972.9" + "@aws-sdk/middleware-recursion-detection" "^3.972.10" + "@aws-sdk/middleware-sdk-s3" "^3.972.28" + "@aws-sdk/middleware-ssec" "^3.972.9" + "@aws-sdk/middleware-user-agent" "^3.972.29" + "@aws-sdk/region-config-resolver" "^3.972.11" + "@aws-sdk/signature-v4-multi-region" "^3.996.16" + "@aws-sdk/types" "^3.973.7" + "@aws-sdk/util-endpoints" "^3.996.6" + "@aws-sdk/util-user-agent-browser" "^3.972.9" + "@aws-sdk/util-user-agent-node" "^3.973.15" + "@smithy/config-resolver" "^4.4.14" + "@smithy/core" "^3.23.14" + "@smithy/eventstream-serde-browser" "^4.2.13" + "@smithy/eventstream-serde-config-resolver" "^4.3.13" + "@smithy/eventstream-serde-node" "^4.2.13" + "@smithy/fetch-http-handler" "^5.3.16" + "@smithy/hash-blob-browser" "^4.2.14" + "@smithy/hash-node" "^4.2.13" + "@smithy/hash-stream-node" "^4.2.13" + "@smithy/invalid-dependency" "^4.2.13" + "@smithy/md5-js" "^4.2.13" + "@smithy/middleware-content-length" "^4.2.13" + "@smithy/middleware-endpoint" "^4.4.29" + "@smithy/middleware-retry" "^4.5.0" + "@smithy/middleware-serde" "^4.2.17" + "@smithy/middleware-stack" "^4.2.13" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/node-http-handler" "^4.5.2" + "@smithy/protocol-http" "^5.3.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + "@smithy/url-parser" "^4.2.13" + "@smithy/util-base64" "^4.3.2" + "@smithy/util-body-length-browser" "^4.2.2" + "@smithy/util-body-length-node" "^4.2.3" + "@smithy/util-defaults-mode-browser" "^4.3.45" + "@smithy/util-defaults-mode-node" "^4.2.49" + "@smithy/util-endpoints" "^3.3.4" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-retry" "^4.3.0" + "@smithy/util-stream" "^4.5.22" + "@smithy/util-utf8" "^4.2.2" + "@smithy/util-waiter" "^4.2.15" + tslib "^2.6.2" + +"@aws-sdk/core@^3.973.27": + version "3.973.27" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.973.27.tgz#cc2872a8d54357f5bc6d9475400291c653ab5d08" + integrity sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@aws-sdk/xml-builder" "^3.972.17" + "@smithy/core" "^3.23.14" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/property-provider" "^4.2.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/signature-v4" "^5.3.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + "@smithy/util-base64" "^4.3.2" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@aws-sdk/crc64-nvme@^3.972.6": + version "3.972.6" + resolved "https://registry.yarnpkg.com/@aws-sdk/crc64-nvme/-/crc64-nvme-3.972.6.tgz#4e023b3e3b5f67d3129c97c5caa3e18699d3d550" + integrity sha512-NMbiqKdruhwwgI6nzBVe2jWMkXjaoQz2YOs3rFX+2F3gGyrJDkDPwMpV/RsTFeq2vAQ055wZNtOXFK4NYSkM8g== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@^3.972.25": + version "3.972.25" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.25.tgz#6a55730ec56597545119e2013101c5872c7b1602" + integrity sha512-6QfI0wv4jpG5CrdO/AO0JfZ2ux+tKwJPrUwmvxXF50vI5KIypKVGNF6b4vlkYEnKumDTI1NX2zUBi8JoU5QU3A== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/types" "^3.973.7" + "@smithy/property-provider" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@^3.972.27": + version "3.972.27" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.27.tgz#371cca39c19b52012ec2bf025299a233d26445b2" + integrity sha512-3V3Usj9Gs93h865DqN4M2NWJhC5kXU9BvZskfN3+69omuYlE3TZxOEcVQtBGLOloJB7BVfJKXVLqeNhOzHqSlQ== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/types" "^3.973.7" + "@smithy/fetch-http-handler" "^5.3.16" + "@smithy/node-http-handler" "^4.5.2" + "@smithy/property-provider" "^4.2.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + "@smithy/util-stream" "^4.5.22" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@^3.972.29": + version "3.972.29" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.29.tgz#0129911b1ca5e561b4e25d494447457ee7540eaa" + integrity sha512-SiBuAnXecCbT/OpAf3vqyI/AVE3mTaYr9ShXLybxZiPLBiPCCOIWSGAtYYGQWMRvobBTiqOewaB+wcgMMZI2Aw== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/credential-provider-env" "^3.972.25" + "@aws-sdk/credential-provider-http" "^3.972.27" + "@aws-sdk/credential-provider-login" "^3.972.29" + "@aws-sdk/credential-provider-process" "^3.972.25" + "@aws-sdk/credential-provider-sso" "^3.972.29" + "@aws-sdk/credential-provider-web-identity" "^3.972.29" + "@aws-sdk/nested-clients" "^3.996.19" + "@aws-sdk/types" "^3.973.7" + "@smithy/credential-provider-imds" "^4.2.13" + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-login@^3.972.29": + version "3.972.29" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.29.tgz#a861534cc0bdec0ce506c6c7310fdd57a4caacc8" + integrity sha512-OGOslTbOlxXexKMqhxCEbBQbUIfuhGxU5UXw3Fm56ypXHvrXH4aTt/xb5Y884LOoteP1QST1lVZzHfcTnWhiPQ== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/nested-clients" "^3.996.19" + "@aws-sdk/types" "^3.973.7" + "@smithy/property-provider" "^4.2.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@^3.972.30": + version "3.972.30" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.30.tgz#cbf0da21b1fe14108829ed17eaa153fb5fe55c85" + integrity sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw== + dependencies: + "@aws-sdk/credential-provider-env" "^3.972.25" + "@aws-sdk/credential-provider-http" "^3.972.27" + "@aws-sdk/credential-provider-ini" "^3.972.29" + "@aws-sdk/credential-provider-process" "^3.972.25" + "@aws-sdk/credential-provider-sso" "^3.972.29" + "@aws-sdk/credential-provider-web-identity" "^3.972.29" + "@aws-sdk/types" "^3.973.7" + "@smithy/credential-provider-imds" "^4.2.13" + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@^3.972.25": + version "3.972.25" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.25.tgz#631bd69f28600a6ef134a4cb6e0395371814d3f4" + integrity sha512-HR7ynNRdNhNsdVCOCegy1HsfsRzozCOPtD3RzzT1JouuaHobWyRfJzCBue/3jP7gECHt+kQyZUvwg/cYLWurNQ== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/types" "^3.973.7" + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@^3.972.29": + version "3.972.29" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.29.tgz#7410169f97f686eaab33daed7e18789a46de1116" + integrity sha512-HWv4SEq3jZDYPlwryZVef97+U8CxxRos5mK8sgGO1dQaFZpV5giZLzqGE5hkDmh2csYcBO2uf5XHjPTpZcJlig== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/nested-clients" "^3.996.19" + "@aws-sdk/token-providers" "3.1026.0" + "@aws-sdk/types" "^3.973.7" + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@^3.972.29": + version "3.972.29" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.29.tgz#ed3c750076cb9131fd940535ea7e94b846a885dd" + integrity sha512-PdMBza1WEKEUPFEmMGCfnU2RYCz9MskU2e8JxjyUOsMKku7j9YaDKvbDi2dzC0ihFoM6ods2SbhfAAro+Gwlew== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/nested-clients" "^3.996.19" + "@aws-sdk/types" "^3.973.7" + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.9.tgz#4dc1e7a155e612b447387c268740781c785d5810" + integrity sha512-COToYKgquDyligbcAep7ygs48RK+mwe/IYprq4+TSrVFzNOYmzWvHf6werpnKV5VYpRiwdn+Wa5ZXkPqLVwcTg== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@aws-sdk/util-arn-parser" "^3.972.3" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-config-provider" "^4.2.2" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.9.tgz#ad62cbc4c5f310a5d104b7fc1150eca13a3c07a4" + integrity sha512-V/FNCjFxnh4VGu+HdSiW4Yg5GELihA1MIDSAdsEPvuayXBVmr0Jaa6jdLAZLH38KYXl/vVjri9DQJWnTAujHEA== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@^3.974.7": + version "3.974.7" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.7.tgz#cc2c8efc5932e7bb55d58d717fe60c45fbf21a41" + integrity sha512-uU4/ch2CLHB8Phu1oTKnnQ4e8Ujqi49zEnQYBhWYT53zfFvtJCdGsaOoypBr8Fm/pmCBssRmGoIQ4sixgdLP9w== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-crypto/util" "5.2.0" + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/crc64-nvme" "^3.972.6" + "@aws-sdk/types" "^3.973.7" + "@smithy/is-array-buffer" "^4.2.2" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-stream" "^4.5.22" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.9.tgz#0a7e66857bcb0ebce1aff1cd0e9eb2fe46069260" + integrity sha512-je5vRdNw4SkuTnmRbFZLdye4sQ0faLt8kwka5wnnSU30q1mHO4X+idGEJOOE+Tn1ME7Oryn05xxkDvIb3UaLaQ== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.972.9.tgz#35a7a35b678d931970b146024078c509631861ad" + integrity sha512-TyfOi2XNdOZpNKeTJwRUsVAGa+14nkyMb2VVGG+eDgcWG/ed6+NUo72N3hT6QJioxym80NSinErD+LBRF0Ir1w== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.972.9.tgz#a47610fe11f953718d405ec3b36d807c9f3c8b22" + integrity sha512-HsVgDrruhqI28RkaXALm8grJ7Agc1wF6Et0xh6pom8NdO2VdO/SD9U/tPwUjewwK/pVoka+EShBxyCvgsPCtog== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@^3.972.10": + version "3.972.10" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.10.tgz#9300b3fa7843f5c353b6be7a3c64a2cf486c3a22" + integrity sha512-RVQQbq5orQ/GHUnXvqEOj2HHPBJm+mM+ySwZKS5UaLBwra5ugRtiH09PLUoOZRl7a1YzaOzXSuGbn9iD5j60WQ== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@aws/lambda-invoke-store" "^0.2.2" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@^3.972.28": + version "3.972.28" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.28.tgz#cfdcaab69da8870e039dc58499ac323cd7667242" + integrity sha512-qJHcJQH9UNPUrnPlRtCozKjtqAaypQ5IgQxTNoPsVYIQeuwNIA8Rwt3NvGij1vCDYDfCmZaPLpnJEHlZXeFqmg== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/types" "^3.973.7" + "@aws-sdk/util-arn-parser" "^3.972.3" + "@smithy/core" "^3.23.14" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/signature-v4" "^5.3.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + "@smithy/util-config-provider" "^4.2.2" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-stream" "^4.5.22" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.972.9.tgz#3658fd92752682316c48b736d6c013a75cfcd7aa" + integrity sha512-wSA2BR7L0CyBNDJeSrleIIzC+DzL93YNTdfU0KPGLiocK6YsRv1nPAzPF+BFSdcs0Qa5ku5Kcf4KvQcWwKGenQ== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@^3.972.29": + version "3.972.29" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.29.tgz#60931e54bf78cfd41bb39e620d86e30bececbf43" + integrity sha512-f/sIRzuTfEjg6NsbMYvye2VsmnQoNgntntleQyx5uGacUYzszbfIlO3GcI6G6daWUmTm0IDZc11qMHWwF0o0mQ== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/types" "^3.973.7" + "@aws-sdk/util-endpoints" "^3.996.6" + "@smithy/core" "^3.23.14" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-retry" "^4.3.0" + tslib "^2.6.2" + +"@aws-sdk/nested-clients@^3.996.19": + version "3.996.19" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.996.19.tgz#3e43e3154038e33a59917ec5d015d1f438b6af22" + integrity sha512-uFkmCDXvmQYLanlYdOFS0+MQWkrj9wPMt/ZCc/0J0fjPim6F5jBVBmEomvGY/j77ILW6GTPwN22Jc174Mhkw6Q== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/middleware-host-header" "^3.972.9" + "@aws-sdk/middleware-logger" "^3.972.9" + "@aws-sdk/middleware-recursion-detection" "^3.972.10" + "@aws-sdk/middleware-user-agent" "^3.972.29" + "@aws-sdk/region-config-resolver" "^3.972.11" + "@aws-sdk/types" "^3.973.7" + "@aws-sdk/util-endpoints" "^3.996.6" + "@aws-sdk/util-user-agent-browser" "^3.972.9" + "@aws-sdk/util-user-agent-node" "^3.973.15" + "@smithy/config-resolver" "^4.4.14" + "@smithy/core" "^3.23.14" + "@smithy/fetch-http-handler" "^5.3.16" + "@smithy/hash-node" "^4.2.13" + "@smithy/invalid-dependency" "^4.2.13" + "@smithy/middleware-content-length" "^4.2.13" + "@smithy/middleware-endpoint" "^4.4.29" + "@smithy/middleware-retry" "^4.5.0" + "@smithy/middleware-serde" "^4.2.17" + "@smithy/middleware-stack" "^4.2.13" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/node-http-handler" "^4.5.2" + "@smithy/protocol-http" "^5.3.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + "@smithy/url-parser" "^4.2.13" + "@smithy/util-base64" "^4.3.2" + "@smithy/util-body-length-browser" "^4.2.2" + "@smithy/util-body-length-node" "^4.2.3" + "@smithy/util-defaults-mode-browser" "^4.3.45" + "@smithy/util-defaults-mode-node" "^4.2.49" + "@smithy/util-endpoints" "^3.3.4" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-retry" "^4.3.0" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@^3.972.11": + version "3.972.11" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.11.tgz#b9e48d6b900b2a525adecd62ce67597ebf330835" + integrity sha512-6Q8B1dcx6BBqUTY1Mc/eROKA0FImEEY5VPSd6AGPEUf0ErjExz4snVqa9kNJSoVDV1rKaNf3qrWojgcKW+SdDg== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/config-resolver" "^4.4.14" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@^3.996.16": + version "3.996.16" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.16.tgz#a078e17caa4b94dad8add2e8b1be6f2362d4c83f" + integrity sha512-EMdXYB4r/k5RWq86fugjRhid5JA+Z6MpS7n4sij4u5/C+STrkvuf9aFu41rJA9MjUzxCLzv8U2XL8cH2GSRYpQ== + dependencies: + "@aws-sdk/middleware-sdk-s3" "^3.972.28" + "@aws-sdk/types" "^3.973.7" + "@smithy/protocol-http" "^5.3.13" + "@smithy/signature-v4" "^5.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.1026.0": + version "3.1026.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.1026.0.tgz#af571864ad4ff3ab2a81ce38cc6d2fa58019df70" + integrity sha512-Ieq/HiRrbEtrYP387Nes0XlR7H1pJiJOZKv+QyQzMYpvTiDs0VKy2ZB3E2Zf+aFovWmeE7lRE4lXyF7dYM6GgA== + dependencies: + "@aws-sdk/core" "^3.973.27" + "@aws-sdk/nested-clients" "^3.996.19" + "@aws-sdk/types" "^3.973.7" + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/types@^3.222.0", "@aws-sdk/types@^3.973.7": + version "3.973.7" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.973.7.tgz#0dc48b436638d9f19ca52f686912edda2d5d6dee" + integrity sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@^3.972.3": + version "3.972.3" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.972.3.tgz#ed989862bbb172ce16d9e1cd5790e5fe367219c2" + integrity sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@^3.996.6": + version "3.996.6" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.996.6.tgz#90934298b655d036d0b181b9fc3239629ba25166" + integrity sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/types" "^4.14.0" + "@smithy/url-parser" "^4.2.13" + "@smithy/util-endpoints" "^3.3.4" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.965.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz#e30e6ff2aff6436209ed42c765dec2d2a48df7c0" + integrity sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@^3.972.9": + version "3.972.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.9.tgz#3fe2f2bf5949d6ccc21c1bcdd75fd79db6cd4d7f" + integrity sha512-sn/LMzTbGjYqCCF24390WxPd6hkpoSptiUn5DzVp4cD71yqw+yGEGm1YCxyEoPXyc8qciM8UzLJcZBFslxo5Uw== + dependencies: + "@aws-sdk/types" "^3.973.7" + "@smithy/types" "^4.14.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@^3.973.15": + version "3.973.15" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.15.tgz#ac4e1a42c89c205d30aa90992171848f8524d490" + integrity sha512-fYn3s9PtKdgQkczGZCFMgkNEe8aq1JCVbnRqjqN9RSVW43xn2RV9xdcZ3z01a48Jpkuh/xCmBKJxdLOo4Ozg7w== + dependencies: + "@aws-sdk/middleware-user-agent" "^3.972.29" + "@aws-sdk/types" "^3.973.7" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-config-provider" "^4.2.2" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@^3.972.17": + version "3.972.17" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.972.17.tgz#748480460eaf075acaf16804b2c32158cbfe984d" + integrity sha512-Ra7hjqAZf1OXRRMueB13qex7mFJRDK/pgCvdSFemXBT8KCGnQDPoKzHY1SjN+TjJVmnpSF14W5tJ1vDamFu+Gg== + dependencies: + "@smithy/types" "^4.14.0" + fast-xml-parser "5.5.8" + tslib "^2.6.2" + +"@aws/lambda-invoke-store@^0.2.2": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz#802f6a50f6b6589063ef63ba8acdee86fcb9f395" + integrity sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ== + +"@aztec/accounts@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/accounts/-/accounts-4.2.0-aztecnr-rc.2.tgz#490c39d3c82f016271c12a0a9a075077b1b89cff" + integrity sha512-CTIBp0WafXcnsHQcPeGnANCIHPhibvfZFoS0lvwlY4ypeVJoNDOQTwTkvPkG1TXjnuiY2rOZ0qLK7yreJf/oFw== + dependencies: + "@aztec/aztec.js" "4.2.0-aztecnr-rc.2" + "@aztec/entrypoints" "4.2.0-aztecnr-rc.2" + "@aztec/ethereum" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + tslib "^2.4.0" + +"@aztec/aztec.js@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/aztec.js/-/aztec.js-4.2.0-aztecnr-rc.2.tgz#0aaf280d9839e27b210019a66691e62f5754cfee" + integrity sha512-tAlj7kYEto0zGa+OwvtnRENQmGbYCeKFcQEVXqAmiox8P+/iHt4KI+mRxmLgPWqhFbsZJPr33lJXSS08s8MPSA== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/entrypoints" "4.2.0-aztecnr-rc.2" + "@aztec/ethereum" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/l1-artifacts" "4.2.0-aztecnr-rc.2" + "@aztec/protocol-contracts" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + axios "^1.13.5" + tslib "^2.4.0" + viem "npm:@aztec/viem@2.38.2" + zod "^3.23.8" + +"@aztec/bb-prover@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/bb-prover/-/bb-prover-4.2.0-aztecnr-rc.2.tgz#3f4d5438c1a4e416cce62d7f3be6419ecfab1aa4" + integrity sha512-DcVksNFCF+wKsxQoKCnm/c0KSHVwkE42qt2uH5v1xibBsRHE24ftlRYHYrBZ9CWcZXa4Zz7beXzQEr2ZydmQQQ== + dependencies: + "@aztec/bb.js" "4.2.0-aztecnr-rc.2" + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/noir-noirc_abi" "4.2.0-aztecnr-rc.2" + "@aztec/noir-protocol-circuits-types" "4.2.0-aztecnr-rc.2" + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + "@aztec/simulator" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + "@aztec/telemetry-client" "4.2.0-aztecnr-rc.2" + "@aztec/world-state" "4.2.0-aztecnr-rc.2" + commander "^12.1.0" + pako "^2.1.0" + source-map-support "^0.5.21" + tslib "^2.4.0" + +"@aztec/bb.js@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/bb.js/-/bb.js-4.2.0-aztecnr-rc.2.tgz#9eab340c5aa1621caf5ed1e98e8ea99daba97064" + integrity sha512-ksFWHrm8QYAXP059paItEKCM/UhpHg5Dwl/eSp2BI6EAtD9+JlonkOwJ+94TYai2y5Gz0qnrgd65dsvDwJelVQ== + dependencies: + comlink "^4.4.1" + commander "^12.1.0" + idb-keyval "^6.2.1" + msgpackr "^1.11.2" + pako "^2.1.0" + tslib "^2.4.0" + +"@aztec/blob-lib@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/blob-lib/-/blob-lib-4.2.0-aztecnr-rc.2.tgz#6acdb7d95486012d2c520fadb074c9a7f649f2bb" + integrity sha512-iXFx9S8W5Q4AmpqtgYHB6jxnJnGIFz/68YCoZbKj6Gy+jfelU1VYCKvZc3YbqcY9s/QGN68Y9HSf8lNSMCZOcQ== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@crate-crypto/node-eth-kzg" "^0.10.0" + tslib "^2.4.0" + +"@aztec/builder@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/builder/-/builder-4.2.0-aztecnr-rc.2.tgz#dcc52b99b3a217472cd36948125ff2d6c20bacdf" + integrity sha512-W4AjGJgi0AhGiniO3cVTBFnsy5wUOJ6922EoOcMFQ1CP/ZMOIYAqRfYagF2eFaYnExEeZC46cuOgHhir9at1PA== + dependencies: + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + commander "^12.1.0" + +"@aztec/constants@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/constants/-/constants-4.2.0-aztecnr-rc.2.tgz#f065f4159f8e3b02874b738d5f6a8576ebdcb27c" + integrity sha512-CxctSLeUP59HJoxHXmczleJyta7DLuqz5FV2Jbq0Bqx/saMbhkCXfm6I9KnnlhvXdFZ+y2d3J1BrDTg0dEapIg== + dependencies: + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + tslib "^2.4.0" + +"@aztec/entrypoints@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/entrypoints/-/entrypoints-4.2.0-aztecnr-rc.2.tgz#5ea8f8edfbd8b4928f5d5201be13282a2ad5b3e9" + integrity sha512-2+/GWwJ/UsOIJArXqP4MaNXl4xZrN4d74znkTbLio6us5NBK/B/4OjtCkEZD5Qwb7DdNGfXSP088bs/yQX8Y6A== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/protocol-contracts" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + tslib "^2.4.0" + zod "^3.23.8" + +"@aztec/ethereum@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/ethereum/-/ethereum-4.2.0-aztecnr-rc.2.tgz#76cb2bfd7ec78a7126275ea4cafe1d3247d155f1" + integrity sha512-Xbrr0TqXZrY2OAsP72MINmiV9xBqDTd8zk8zTudUlnv8947wsYYPS6O0HcegM3xzQkJJoFDE5ZH3QiHiVxePoA== + dependencies: + "@aztec/blob-lib" "4.2.0-aztecnr-rc.2" + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/l1-artifacts" "4.2.0-aztecnr-rc.2" + "@viem/anvil" "^0.0.10" + dotenv "^16.0.3" + lodash.chunk "^4.2.0" + lodash.pickby "^4.5.0" + tslib "^2.4.0" + viem "npm:@aztec/viem@2.38.2" + zod "^3.23.8" + +"@aztec/foundation@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/foundation/-/foundation-4.2.0-aztecnr-rc.2.tgz#fd422e642bb424072e16b40ba2c932cdf11b0718" + integrity sha512-iNLLuhWISJIY1Mo4TSqDuMhP7lbVNKcHzYLCujY7sTIQHg358vNShDiFqUat9fMuigBFD8o+JuRr+xX8jl1WPQ== + dependencies: + "@aztec/bb.js" "4.2.0-aztecnr-rc.2" + "@koa/cors" "^5.0.0" + "@noble/curves" "=1.7.0" + "@noble/hashes" "^1.6.1" + "@scure/bip39" "^2.0.1" + bn.js "^5.2.1" + colorette "^2.0.20" + detect-node "^2.1.0" + hash.js "^1.1.7" + koa "^2.16.1" + koa-bodyparser "^4.4.0" + koa-compress "^5.1.0" + koa-router "^13.1.1" + leveldown "^6.1.1" + lodash.chunk "^4.2.0" + lodash.clonedeepwith "^4.5.0" + pako "^2.1.0" + pino "^9.5.0" + pino-pretty "^13.0.0" + sha3 "^2.1.4" + undici "^5.28.5" + zod "^3.23.8" + +"@aztec/key-store@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/key-store/-/key-store-4.2.0-aztecnr-rc.2.tgz#93c52fbd3f8cf875343669b1d00b5d86c0ed9925" + integrity sha512-48v0REsHRYbD5ShwN3GpQNTmsHB5k9Yvme43Yf4HpCNNl7Z3JPnxKs395HZSb6pNUltvV8s8pjN9+9q3o0fr1w== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/kv-store" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + tslib "^2.4.0" + +"@aztec/kv-store@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/kv-store/-/kv-store-4.2.0-aztecnr-rc.2.tgz#97f1e1e4dd5e595061a2f3b85ab394b9d2a6aa57" + integrity sha512-svqtFq0PzAd9WUnAGtOKg9OFQQZbxlbklkbX00Jk4OLYnA0U6cWQLwPUWedzYQfE/ueK6wSoFjWj2ghQe8gMGg== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/ethereum" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/native" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + idb "^8.0.0" + lmdb "^3.2.0" + msgpackr "^1.11.2" + ohash "^2.0.11" + ordered-binary "^1.5.3" + +"@aztec/l1-artifacts@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/l1-artifacts/-/l1-artifacts-4.2.0-aztecnr-rc.2.tgz#42af9b2a6c8de7c47b41f4f5ed395ccde3f67d76" + integrity sha512-LbrF85CPKx4qfevV7JeVz5FDQytcxeGIdtjXChL2THKKmPAbr+TFOv3Qdb6EGP55sRM4MFrDE+Z6K9HMrnELdA== + dependencies: + tslib "^2.4.0" + +"@aztec/merkle-tree@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/merkle-tree/-/merkle-tree-4.2.0-aztecnr-rc.2.tgz#023281b061799821ca1136227859cab4950afc7e" + integrity sha512-dVbuh79Oc/kVx3MPis5Qwn1+m/u0jyHHat8Q1DAX+L1d6GSqGYaqSj0BBN5zkKEIjRCi53o7k7KUuJvv5TjzqA== + dependencies: + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/kv-store" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + sha256 "^0.2.0" + tslib "^2.4.0" + +"@aztec/native@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/native/-/native-4.2.0-aztecnr-rc.2.tgz#5acd395123da89b97be944415d37e25c867f9b97" + integrity sha512-4q+r7ejGipckbcIyj2yGbekN7fOC0PXQ1/OgqRyS3ird26aI5UsNVxuTAyFMrhIHJL98eZ8cjbc/Sf7lOpEk3w== + dependencies: + "@aztec/bb.js" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + msgpackr "^1.11.2" + +"@aztec/noir-acvm_js@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-acvm_js/-/noir-acvm_js-4.2.0-aztecnr-rc.2.tgz#5508016147afb9502acb1151a92cf3de4f61ed85" + integrity sha512-OBubDpTTYEcz2EX8APl1mfn3OHDvMuZIm0t1//+u1BZbosrAjCpI76Vz39DNKpCZups4A+dJKHXlkj+RsFstbw== + +"@aztec/noir-contracts.js@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-contracts.js/-/noir-contracts.js-4.2.0-aztecnr-rc.2.tgz#38a2c9c72245ba9f122be83fef0d1edcdf147564" + integrity sha512-WYNXApevXSEHggthbwgA5HIF1yP4s1bx4pNbZPPgV69AOQwjCjztTE6G3VCUrsC2sB+loNMnre2Csld0RrUXIQ== + dependencies: + "@aztec/aztec.js" "4.2.0-aztecnr-rc.2" + tslib "^2.4.0" + +"@aztec/noir-noir_codegen@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-noir_codegen/-/noir-noir_codegen-4.2.0-aztecnr-rc.2.tgz#1058dc85fd4810797e92f9b1a8f6f8be69ac663d" + integrity sha512-gnBaP+uL3uXqbFGUE/qssoHhQRjThZBKAuSwo4IRsVW8iwMLS9LdJntUWfqyB599vE7b1OL9q1UfUdu0DJbALg== + dependencies: + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + glob "^13.0.0" + ts-command-line-args "^2.5.1" + +"@aztec/noir-noir_js@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-noir_js/-/noir-noir_js-4.2.0-aztecnr-rc.2.tgz#6aa66357b6640df7d350dda7151882a9585521d6" + integrity sha512-cifGp5y5wn/oowb+zxlslwvE97yPjkIQ0iPVB1UbmZPUvTdQBl5L2jTUtzvi7ZgF/RzXSBFc6Wx7twc+/fC30g== + dependencies: + "@aztec/noir-acvm_js" "4.2.0-aztecnr-rc.2" + "@aztec/noir-noirc_abi" "4.2.0-aztecnr-rc.2" + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + pako "^2.1.0" + +"@aztec/noir-noirc_abi@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-noirc_abi/-/noir-noirc_abi-4.2.0-aztecnr-rc.2.tgz#a909d9ac5fd8af38f7b5d4de9d7528a98e1e1b76" + integrity sha512-ivXHmrH7hoSB3dVJHws78+GrRq9w0sSLteTzkucXEC7BQ6G5mYArK6eZ3d/S1tr8x+himjU10A9h3yjsMXGb0A== + dependencies: + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + +"@aztec/noir-protocol-circuits-types@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-protocol-circuits-types/-/noir-protocol-circuits-types-4.2.0-aztecnr-rc.2.tgz#28fd59c5c867ad8ab1ddf436caca4a031acf1277" + integrity sha512-ZlY4SyqbAfYmSL7FGNLwet1ELbRsuEcAybPCFP0xp1Td5tLjHTQ7i37u6RPu8NSalpia4ziU5lF25Ng0suzung== + dependencies: + "@aztec/blob-lib" "4.2.0-aztecnr-rc.2" + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/noir-acvm_js" "4.2.0-aztecnr-rc.2" + "@aztec/noir-noir_codegen" "4.2.0-aztecnr-rc.2" + "@aztec/noir-noirc_abi" "4.2.0-aztecnr-rc.2" + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + change-case "^5.4.4" + tslib "^2.4.0" + +"@aztec/noir-types@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-types/-/noir-types-4.2.0-aztecnr-rc.2.tgz#097171c8fd310e7063c6b08892c280577cd4e822" + integrity sha512-5lP70mkEDZymZ+XyUjP4V9lGTISWQi4vLD+btSQC89KXBQan5a+wL/sJdizy2LtqX8AacXb3lta+Sq8n5BcheA== + +"@aztec/protocol-contracts@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/protocol-contracts/-/protocol-contracts-4.2.0-aztecnr-rc.2.tgz#774e8e34cca922a8051625899c2e252e3d2fe1c4" + integrity sha512-3y+KN1kmUJGvILkEkRe/Zl+sakWsEqadY3XxficnSaD8Gf6YCH1OH/tpZwc/CCw9iFwvuJxMGMo5EffXFkLB4Q== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + lodash.chunk "^4.2.0" + lodash.omit "^4.5.0" + tslib "^2.4.0" + +"@aztec/pxe@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/pxe/-/pxe-4.2.0-aztecnr-rc.2.tgz#5e2ee2d1352ea4bb91e1ca2ea52f553c47c13e67" + integrity sha512-V8p0EvbhYdAif7oQ3ihQ1GmPgTN5zBKGtwyWm8q+CW/eAOXLV3MLxyFUiHCHQGg9chbPnxbPvtyOfeMvbwwWRg== + dependencies: + "@aztec/bb-prover" "4.2.0-aztecnr-rc.2" + "@aztec/bb.js" "4.2.0-aztecnr-rc.2" + "@aztec/builder" "4.2.0-aztecnr-rc.2" + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/ethereum" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/key-store" "4.2.0-aztecnr-rc.2" + "@aztec/kv-store" "4.2.0-aztecnr-rc.2" + "@aztec/noir-protocol-circuits-types" "4.2.0-aztecnr-rc.2" + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + "@aztec/protocol-contracts" "4.2.0-aztecnr-rc.2" + "@aztec/simulator" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + koa "^2.16.1" + koa-router "^13.1.1" + lodash.omit "^4.5.0" + sha3 "^2.1.4" + tslib "^2.4.0" + viem "npm:@aztec/viem@2.38.2" + +"@aztec/simulator@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/simulator/-/simulator-4.2.0-aztecnr-rc.2.tgz#b8214ce2431350846996f4dafecee1e2ab87191e" + integrity sha512-Sw8nrUrmS1GqKJ0GTNM1ObAJ6SqvmdZxcJlddAjCCbxRRCPaXyjGLdNyNj1uTs/VKleplN/mKzXU74582U7wqg== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/native" "4.2.0-aztecnr-rc.2" + "@aztec/noir-acvm_js" "4.2.0-aztecnr-rc.2" + "@aztec/noir-noirc_abi" "4.2.0-aztecnr-rc.2" + "@aztec/noir-protocol-circuits-types" "4.2.0-aztecnr-rc.2" + "@aztec/noir-types" "4.2.0-aztecnr-rc.2" + "@aztec/protocol-contracts" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + "@aztec/telemetry-client" "4.2.0-aztecnr-rc.2" + "@aztec/world-state" "4.2.0-aztecnr-rc.2" + lodash.clonedeep "^4.5.0" + lodash.merge "^4.6.2" + tslib "^2.4.0" + +"@aztec/stdlib@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/stdlib/-/stdlib-4.2.0-aztecnr-rc.2.tgz#15d9e3afee55b38d6d6ad2ee63ab3a7a790f3306" + integrity sha512-Kf1rmn+s6DWKkLrKgj7VNe4/G93zY7n2URgLJTfavScJIoZXLtxy6Z8DtyukzDCa30Ux1ATni/ydDEC64UBxfw== + dependencies: + "@aws-sdk/client-s3" "^3.892.0" + "@aztec/bb.js" "4.2.0-aztecnr-rc.2" + "@aztec/blob-lib" "4.2.0-aztecnr-rc.2" + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/ethereum" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/l1-artifacts" "4.2.0-aztecnr-rc.2" + "@aztec/noir-noirc_abi" "4.2.0-aztecnr-rc.2" + "@aztec/validator-ha-signer" "4.2.0-aztecnr-rc.2" + "@google-cloud/storage" "^7.15.0" + axios "^1.13.5" + json-stringify-deterministic "1.0.12" + lodash.chunk "^4.2.0" + lodash.isequal "^4.5.0" + lodash.omit "^4.5.0" + lodash.times "^4.3.2" + msgpackr "^1.11.2" + pako "^2.1.0" + tslib "^2.4.0" + viem "npm:@aztec/viem@2.38.2" + zod "^3.23.8" + +"@aztec/telemetry-client@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/telemetry-client/-/telemetry-client-4.2.0-aztecnr-rc.2.tgz#c5a0a7933d3054a68cacf3be43d76c6fd48e5ff3" + integrity sha512-6NwrUng4b9ZJIuwNEGkDczsyI5S6AtZG/RdxkEGt0CvimXkpUwjQE/Rrea0mpHnc8fVjG5lD0vKk3LpnngCyhA== + dependencies: + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + "@opentelemetry/api" "^1.9.0" + "@opentelemetry/api-logs" "^0.55.0" + "@opentelemetry/core" "^1.28.0" + "@opentelemetry/exporter-logs-otlp-http" "^0.55.0" + "@opentelemetry/exporter-metrics-otlp-http" "^0.55.0" + "@opentelemetry/exporter-trace-otlp-http" "^0.55.0" + "@opentelemetry/host-metrics" "^0.36.2" + "@opentelemetry/otlp-exporter-base" "^0.55.0" + "@opentelemetry/resource-detector-gcp" "^0.32.0" + "@opentelemetry/resources" "^1.28.0" + "@opentelemetry/sdk-logs" "^0.55.0" + "@opentelemetry/sdk-metrics" "^1.28.0" + "@opentelemetry/sdk-trace-node" "^1.28.0" + "@opentelemetry/semantic-conventions" "^1.28.0" + prom-client "^15.1.3" + viem "npm:@aztec/viem@2.38.2" + +"@aztec/validator-ha-signer@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/validator-ha-signer/-/validator-ha-signer-4.2.0-aztecnr-rc.2.tgz#03d34775e7cf099122d3cfee592663e4b78d4924" + integrity sha512-VYTfdAKUIn0ruRVx/+h9XAoyPeT+THJeBo5ClXU336Kctdo1Ybb3IYyEDYuwHeqm7DpiHuNN0wAhkHohAO78KA== + dependencies: + "@aztec/ethereum" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + node-pg-migrate "^8.0.4" + pg "^8.11.3" + tslib "^2.4.0" + zod "^3.23.8" + +"@aztec/wallet-sdk@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/wallet-sdk/-/wallet-sdk-4.2.0-aztecnr-rc.2.tgz#d1f43d1260cc2582d279ab801f2bd0958949b8a1" + integrity sha512-ffJ41ln5GQfxHwM6D25VUpXH/vjQ1HWKd3TmVaa4Kwt3nLeNR3VGvUHeivm74eXh53a+eAJFi3SbwEEqsWM0mA== + dependencies: + "@aztec/aztec.js" "4.2.0-aztecnr-rc.2" + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/entrypoints" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/pxe" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + +"@aztec/wallets@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/wallets/-/wallets-4.2.0-aztecnr-rc.2.tgz#d065e281abeef29366089001cf61f72cfd89f132" + integrity sha512-+REyXLuG2OpzqqxDKkgrcXZKh+9/ob1X1T6TLx0cEgqft8QzOlcgYw7qxMGa7Unf0o+2SS3fvFM7oXn8hB45Bw== + dependencies: + "@aztec/accounts" "4.2.0-aztecnr-rc.2" + "@aztec/aztec.js" "4.2.0-aztecnr-rc.2" + "@aztec/entrypoints" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/kv-store" "4.2.0-aztecnr-rc.2" + "@aztec/protocol-contracts" "4.2.0-aztecnr-rc.2" + "@aztec/pxe" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + "@aztec/wallet-sdk" "4.2.0-aztecnr-rc.2" + +"@aztec/world-state@4.2.0-aztecnr-rc.2": + version "4.2.0-aztecnr-rc.2" + resolved "https://registry.yarnpkg.com/@aztec/world-state/-/world-state-4.2.0-aztecnr-rc.2.tgz#a1dc76ec863bf5f687b80517745f3955ed225fc5" + integrity sha512-lpjp2p6aLbW/6j7Buskrew6PP8uL/ZbUX2hy9Lt3DGYhygi072jUnMjbUHAQnj4elRbzWMtLmKEH16/6hrYaCg== + dependencies: + "@aztec/constants" "4.2.0-aztecnr-rc.2" + "@aztec/foundation" "4.2.0-aztecnr-rc.2" + "@aztec/kv-store" "4.2.0-aztecnr-rc.2" + "@aztec/merkle-tree" "4.2.0-aztecnr-rc.2" + "@aztec/native" "4.2.0-aztecnr-rc.2" + "@aztec/protocol-contracts" "4.2.0-aztecnr-rc.2" + "@aztec/stdlib" "4.2.0-aztecnr-rc.2" + "@aztec/telemetry-client" "4.2.0-aztecnr-rc.2" + tslib "^2.4.0" + zod "^3.23.8" + +"@crate-crypto/node-eth-kzg-darwin-arm64@0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg-darwin-arm64/-/node-eth-kzg-darwin-arm64-0.10.0.tgz#bdc363b21d91b54bccfb5df513527cfaddcb3f60" + integrity sha512-cKhqkrRdnWhgPycHkcdwfu/w41PuCvAERkX5yYDR3cSYR4h87Gn4t/infE6UNsPDBCN7yYV42YmZfQDfEt2xrw== + +"@crate-crypto/node-eth-kzg-darwin-x64@0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg-darwin-x64/-/node-eth-kzg-darwin-x64-0.10.0.tgz#f036979451f05e1b15f48aa6c4b4734824526db0" + integrity sha512-8fn4+UBP01ZBxVARTZvxPBGrmcUbYFM/b5z0wZkEevQ9Sz5GYk8hursgpqbhekj+xTCxmwa9pPkzDbtG6oZGQg== + +"@crate-crypto/node-eth-kzg-linux-arm64-gnu@0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg-linux-arm64-gnu/-/node-eth-kzg-linux-arm64-gnu-0.10.0.tgz#f08670152db67b4b56302a0e7c545e3ce3339dcc" + integrity sha512-euuqBTDLOpI9wNx0jO7AD24BdiCs9sz8cBybsdGJvyZ8QLUIezTnA/aXcrZBzsA5ZOrHYjaWS2NJpgDdAjLLuQ== + +"@crate-crypto/node-eth-kzg-linux-x64-gnu@0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg-linux-x64-gnu/-/node-eth-kzg-linux-x64-gnu-0.10.0.tgz#4beea66c650cbc62b6605f1e20c7e77a7cd73ecd" + integrity sha512-b4klE/jp98PBZ7PWuFE1OscWBILSS8jP+JMbIJ+qE7y42s/6ImWH5bWmVdFOfh6u0o95cb9hCS0xIECM80SqBg== + +"@crate-crypto/node-eth-kzg-win32-arm64-msvc@0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg-win32-arm64-msvc/-/node-eth-kzg-win32-arm64-msvc-0.10.0.tgz#9da2998eb80ae240441ac3ef099aff916efadd25" + integrity sha512-tFKv02TG/JYsD4gvV0gTvjLqd09/4g/B37fCPXIuEFzq5LgIuWHu37hhQ6K8eIfoXZOTY3wqqkY1jTXYhs2sTA== + +"@crate-crypto/node-eth-kzg-win32-x64-msvc@0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg-win32-x64-msvc/-/node-eth-kzg-win32-x64-msvc-0.10.0.tgz#13c07c99dc8b4070d7b32d0063ad744bf9af6470" + integrity sha512-mYieW1mBesbLFRB2j4LdodpCkwIxZ8ZHZzzwV+MXqapI61B2SbH+FyMYQ5lJYqQeMHCY0ojq5ScW1zZj1uNGjA== + +"@crate-crypto/node-eth-kzg@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@crate-crypto/node-eth-kzg/-/node-eth-kzg-0.10.0.tgz#69167c4ab5dd2858afa70ef7added99f6097c560" + integrity sha512-sGDPH1nW2EhJzjzHyINvTQwDNGRzdq/2vVzFwwrmFOHtIBaRjXGqo7wKj/JoJoNjuRSGeXz/EmaahRq0pgxzqw== + optionalDependencies: + "@crate-crypto/node-eth-kzg-darwin-arm64" "0.10.0" + "@crate-crypto/node-eth-kzg-darwin-x64" "0.10.0" + "@crate-crypto/node-eth-kzg-linux-arm64-gnu" "0.10.0" + "@crate-crypto/node-eth-kzg-linux-x64-gnu" "0.10.0" + "@crate-crypto/node-eth-kzg-win32-arm64-msvc" "0.10.0" + "@crate-crypto/node-eth-kzg-win32-x64-msvc" "0.10.0" + +"@esbuild/aix-ppc64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz#82b74f92aa78d720b714162939fb248c90addf53" + integrity sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg== + +"@esbuild/android-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz#f78cb8a3121fc205a53285adb24972db385d185d" + integrity sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ== + +"@esbuild/android-arm@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.7.tgz#593e10a1450bbfcac6cb321f61f468453bac209d" + integrity sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ== + +"@esbuild/android-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.7.tgz#453143d073326033d2d22caf9e48de4bae274b07" + integrity sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg== + +"@esbuild/darwin-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz#6f23000fb9b40b7e04b7d0606c0693bd0632f322" + integrity sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw== + +"@esbuild/darwin-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz#27393dd18bb1263c663979c5f1576e00c2d024be" + integrity sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ== + +"@esbuild/freebsd-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz#22e4638fa502d1c0027077324c97640e3adf3a62" + integrity sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w== + +"@esbuild/freebsd-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz#9224b8e4fea924ce2194e3efc3e9aebf822192d6" + integrity sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ== + +"@esbuild/linux-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz#4f5d1c27527d817b35684ae21419e57c2bda0966" + integrity sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A== + +"@esbuild/linux-arm@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz#b9e9d070c8c1c0449cf12b20eac37d70a4595921" + integrity sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA== + +"@esbuild/linux-ia32@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz#3f80fb696aa96051a94047f35c85b08b21c36f9e" + integrity sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg== + +"@esbuild/linux-loong64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz#9be1f2c28210b13ebb4156221bba356fe1675205" + integrity sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q== + +"@esbuild/linux-mips64el@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz#4ab5ee67a3dfcbcb5e8fd7883dae6e735b1163b8" + integrity sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw== + +"@esbuild/linux-ppc64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz#dac78c689f6499459c4321e5c15032c12307e7ea" + integrity sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ== + +"@esbuild/linux-riscv64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz#050f7d3b355c3a98308e935bc4d6325da91b0027" + integrity sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ== + +"@esbuild/linux-s390x@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz#d61f715ce61d43fe5844ad0d8f463f88cbe4fef6" + integrity sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw== + +"@esbuild/linux-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz#ca8e1aa478fc8209257bf3ac8f79c4dc2982f32a" + integrity sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA== + +"@esbuild/netbsd-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz#1650f2c1b948deeb3ef948f2fc30614723c09690" + integrity sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w== + +"@esbuild/netbsd-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz#65772ab342c4b3319bf0705a211050aac1b6e320" + integrity sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw== + +"@esbuild/openbsd-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz#37ed7cfa66549d7955852fce37d0c3de4e715ea1" + integrity sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A== + +"@esbuild/openbsd-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz#01bf3d385855ef50cb33db7c4b52f957c34cd179" + integrity sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg== + +"@esbuild/openharmony-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz#6c1f94b34086599aabda4eac8f638294b9877410" + integrity sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw== + +"@esbuild/sunos-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz#4b0dd17ae0a6941d2d0fd35a906392517071a90d" + integrity sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA== + +"@esbuild/win32-arm64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz#34193ab5565d6ff68ca928ac04be75102ccb2e77" + integrity sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA== + +"@esbuild/win32-ia32@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz#eb67f0e4482515d8c1894ede631c327a4da9fc4d" + integrity sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw== + +"@esbuild/win32-x64@0.27.7": + version "0.27.7" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz#8fe30b3088b89b4873c3a6cc87597ae3920c0a8b" + integrity sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg== + +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + +"@google-cloud/paginator@^5.0.0": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-5.0.2.tgz#86ad773266ce9f3b82955a8f75e22cd012ccc889" + integrity sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-4.0.0.tgz#d600e0433daf51b88c1fa95ac7f02e38e80a07be" + integrity sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA== + +"@google-cloud/promisify@<4.1.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-4.0.0.tgz#a906e533ebdd0f754dca2509933334ce58b8c8b1" + integrity sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g== + +"@google-cloud/storage@^7.15.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-7.19.0.tgz#34fb7cc4eacede5a2f1f0d6cefa0c70a22078c5b" + integrity sha512-n2FjE7NAOYyshogdc7KQOl/VZb4sneqPjWouSyia9CMDdMhRX5+RIbqalNmC7LOLzuLAN89VlF2HvG8na9G+zQ== + dependencies: + "@google-cloud/paginator" "^5.0.0" + "@google-cloud/projectify" "^4.0.0" + "@google-cloud/promisify" "<4.1.0" + abort-controller "^3.0.0" + async-retry "^1.3.3" + duplexify "^4.1.3" + fast-xml-parser "^5.3.4" + gaxios "^6.0.2" + google-auth-library "^9.6.3" + html-entities "^2.5.2" + mime "^3.0.0" + p-limit "^3.0.1" + retry-request "^7.0.0" + teeny-request "^9.0.0" + uuid "^8.0.0" + +"@hapi/bourne@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-3.0.0.tgz#f11fdf7dda62fe8e336fa7c6642d9041f30356d7" + integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w== + +"@harperfast/extended-iterable@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz#471489c5058331017e821bf6c33de70fc2c073ee" + integrity sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw== + +"@isaacs/cliui@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-9.0.0.tgz#4d0a3f127058043bf2e7ee169eaf30ed901302f3" + integrity sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg== + +"@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@koa/cors@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd" + integrity sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw== + dependencies: + vary "^1.1.2" + +"@lmdb/lmdb-darwin-arm64@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.3.tgz#e304f2eacf5739c2241cf299ddd25d50501d1fa9" + integrity sha512-Ob379nnG6FpfVi9WUVupUVsMFa0+jbkelilrBAdJgNlg6dDtXKeTi+pzL+G3f1z3SNdXXWUAL5N8LTp7szXEVw== + +"@lmdb/lmdb-darwin-x64@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.3.tgz#1b785144e53f80755efa99e4c421711735cff7db" + integrity sha512-fbKZ6gonDCWENiXiRoDC4KdBBXi2rlDr1uYj/SErpIAHuTfnLo0Il1hvmbDLeiCPLaPjbXlvcMiR3vLnrNnWMw== + +"@lmdb/lmdb-linux-arm64@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.3.tgz#43758610a1f9e0728b67d4daa30f5ed3345a8755" + integrity sha512-VYWkuWS8uQSyszMe5KGVJPD3YSkaXVrUz/6hbg3zkBvhfOTyrIVMN9M3cZjpU4yxVRBmGViZ5kgjoKz7n3sw2w== + +"@lmdb/lmdb-linux-arm@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.3.tgz#e3b0322a06243b46198b9a099db964e32d9b7676" + integrity sha512-A80EUIRBiKA+0iMc5DxT2u8msgY+K05Lok133IKb3eJVlJkmJie4+LM0MjNyV+mREnu8UwhlNFupSikPy/eTPw== + +"@lmdb/lmdb-linux-x64@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.3.tgz#5f643a33ec83274e8af2dce5b55c428c17b09dde" + integrity sha512-JAeG8rJaL1klzg+VKyRqp0wPSbuPo1ZuNmO/IBRs8QRrSIPxF9r3r1TcIVVRLaaJmI0+2KOjbFRjtvFWFH6cMQ== + +"@lmdb/lmdb-win32-arm64@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.3.tgz#74d59f28ab27673827efea86dba57c1691c5c802" + integrity sha512-9QdgjU5VW0MJ3wy94h4fQ+cNkxeJ0KasjvisOhLuvlCep2KSOzr1i65Js3ElHBRQX8N+jVD8/+LWIM7flfGZ4w== + +"@lmdb/lmdb-win32-x64@3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.3.tgz#fa932a1eab2f005845bf93d86dfa6eedd79c1846" + integrity sha512-0nd13c9ypIDkdsJbHv1PMvk6MZrwHLQP05AXZdxvv8lklxRrZxPK2d8nSo8HLoMXyLt0hA2yQ3fydQaSRrkz0g== + +"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz#9edec61b22c3082018a79f6d1c30289ddf3d9d11" + integrity sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw== + +"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz#33677a275204898ad8acbf62734fc4dc0b6a4855" + integrity sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw== + +"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz#19edf7cdc2e7063ee328403c1d895a86dd28f4bb" + integrity sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg== + +"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz#94fb0543ba2e28766c3fc439cabbe0440ae70159" + integrity sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw== + +"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz#4a0609ab5fe44d07c9c60a11e4484d3c38bbd6e3" + integrity sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg== + +"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz#0aa5502d547b57abfc4ac492de68e2006e417242" + integrity sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ== + +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== + +"@noble/curves@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.1.tgz#9654a0bc6c13420ae252ddcf975eaf0f58f0a35c" + integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@=1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" + +"@noble/curves@~1.9.0": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + +"@noble/hashes@1.8.0", "@noble/hashes@^1.6.1", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@noble/hashes@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" + integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== + +"@nodable/entities@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@nodable/entities/-/entities-1.1.0.tgz#f98e5ee5a6e987b4cad56eb97be81043d9b8d31d" + integrity sha512-bidpxmTBP0pOsxULw6XlxzQpTgrAGLDHGBK/JuWhPDL6ZV0GZ/PmN9CA9do6e+A9lYI6qx6ikJUtJYRxup141g== + +"@opentelemetry/api-logs@0.55.0", "@opentelemetry/api-logs@^0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.55.0.tgz#5cd7461820d864600250deb3803c32367a6bb2d2" + integrity sha512-3cpa+qI45VHYcA5c0bHM6VHo9gicv3p5mlLHNG3rLyjQU8b7e0st1rWtrUn3JbZ3DwwCfhKop4eQ9UuYlC6Pkg== + dependencies: + "@opentelemetry/api" "^1.3.0" + +"@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.4.0", "@opentelemetry/api@^1.9.0": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.1.tgz#c1b0346de336ba55af2d5a7970882037baedec05" + integrity sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q== + +"@opentelemetry/context-async-hooks@1.30.1": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz#4f76280691a742597fd0bf682982126857622948" + integrity sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA== + +"@opentelemetry/core@1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.28.0.tgz#e97290a3e36c59480ffb2287fe2713c66749274c" + integrity sha512-ZLwRMV+fNDpVmF2WYUdBHlq0eOWtEaUJSusrzjGnBt7iSRvfjFE3RXYUZJrqou/wIDWV0DwQ5KIfYe9WXg9Xqw== + dependencies: + "@opentelemetry/semantic-conventions" "1.27.0" + +"@opentelemetry/core@1.30.1", "@opentelemetry/core@^1.0.0", "@opentelemetry/core@^1.28.0": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.30.1.tgz#a0b468bb396358df801881709ea38299fc30ab27" + integrity sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ== + dependencies: + "@opentelemetry/semantic-conventions" "1.28.0" + +"@opentelemetry/exporter-logs-otlp-http@^0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.55.0.tgz#d9879d36cdf5a114fae662a7f83ef832bdee4cf0" + integrity sha512-fpFObWWq+DoLVrBU2dyMEaVkibByEkmKQZIUIjW/4j7lwIsTgW7aJCoD9RYFVB/tButcqov5Es2C0J2wTjM2tg== + dependencies: + "@opentelemetry/api-logs" "0.55.0" + "@opentelemetry/core" "1.28.0" + "@opentelemetry/otlp-exporter-base" "0.55.0" + "@opentelemetry/otlp-transformer" "0.55.0" + "@opentelemetry/sdk-logs" "0.55.0" + +"@opentelemetry/exporter-metrics-otlp-http@^0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.55.0.tgz#461aa311899df3f6221b3d9bc231040a378ec6d8" + integrity sha512-3MqDNZzgXmLaiVo9gs9kCw/zPEaZYKIT0+jeMWscWHL/jrA9BNArTOYWUHEPabAQmWQ2BbvgNC7yzlqjoynQwA== + dependencies: + "@opentelemetry/core" "1.28.0" + "@opentelemetry/otlp-exporter-base" "0.55.0" + "@opentelemetry/otlp-transformer" "0.55.0" + "@opentelemetry/resources" "1.28.0" + "@opentelemetry/sdk-metrics" "1.28.0" + +"@opentelemetry/exporter-trace-otlp-http@^0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.55.0.tgz#275e458aa3bd33c52d77f4357706bcfa53d27f28" + integrity sha512-lMiNic63EVHpW+eChmLD2CieDmwQBFi72+LFbh8+5hY0ShrDGrsGP/zuT5MRh7M/vM/UZYO/2A/FYd7CMQGR7A== + dependencies: + "@opentelemetry/core" "1.28.0" + "@opentelemetry/otlp-exporter-base" "0.55.0" + "@opentelemetry/otlp-transformer" "0.55.0" + "@opentelemetry/resources" "1.28.0" + "@opentelemetry/sdk-trace-base" "1.28.0" + +"@opentelemetry/host-metrics@^0.36.2": + version "0.36.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/host-metrics/-/host-metrics-0.36.2.tgz#c609ca3564c824b99fb3f6440835fadbd8a855f6" + integrity sha512-eMdea86cfIqx3cdFpcKU3StrjqFkQDIVp7NANVnVWO8O6hDw/DBwGwu4Gi1wJCuoQ2JVwKNWQxUTSRheB6O29Q== + dependencies: + systeminformation "5.23.8" + +"@opentelemetry/otlp-exporter-base@0.55.0", "@opentelemetry/otlp-exporter-base@^0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.55.0.tgz#db17332497e4a97e4ca85d394fb91cbbcfd76d84" + integrity sha512-iHQI0Zzq3h1T6xUJTVFwmFl5Dt5y1es+fl4kM+k5T/3YvmVyeYkSiF+wHCg6oKrlUAJfk+t55kaAu3sYmt7ZYA== + dependencies: + "@opentelemetry/core" "1.28.0" + "@opentelemetry/otlp-transformer" "0.55.0" + +"@opentelemetry/otlp-transformer@0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.55.0.tgz#316b9325983e660cb4f18cb76fa84ce1c0cdad42" + integrity sha512-kVqEfxtp6mSN2Dhpy0REo1ghP4PYhC1kMHQJ2qVlO99Pc+aigELjZDfg7/YKmL71gR6wVGIeJfiql/eXL7sQPA== + dependencies: + "@opentelemetry/api-logs" "0.55.0" + "@opentelemetry/core" "1.28.0" + "@opentelemetry/resources" "1.28.0" + "@opentelemetry/sdk-logs" "0.55.0" + "@opentelemetry/sdk-metrics" "1.28.0" + "@opentelemetry/sdk-trace-base" "1.28.0" + protobufjs "^7.3.0" + +"@opentelemetry/propagator-b3@1.30.1": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-1.30.1.tgz#b73321e5f30f062a9229887a4aa80c771107fdd2" + integrity sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ== + dependencies: + "@opentelemetry/core" "1.30.1" + +"@opentelemetry/propagator-jaeger@1.30.1": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.30.1.tgz#c06c9dacbe818b80cfb13c4dbf0b57df1ad26b71" + integrity sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg== + dependencies: + "@opentelemetry/core" "1.30.1" + +"@opentelemetry/resource-detector-gcp@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.32.0.tgz#4b0fcf8dd09891945250a3f8b0e87fc7c3e6bd49" + integrity sha512-+WdWSG4sZAfsk5DvRj/OUmatsHc+7Rdz8xdmxQdr1jpfUWjcKwOkGA4rondIf2ou/qPLOeYCs6hLLexsRdZaUw== + dependencies: + "@opentelemetry/core" "^1.0.0" + "@opentelemetry/resources" "^1.10.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + gcp-metadata "^6.0.0" + +"@opentelemetry/resources@1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.28.0.tgz#c8c27ae7559c817f9d117f1bf96d76f893fb29f5" + integrity sha512-cIyXSVJjGeTICENN40YSvLDAq4Y2502hGK3iN7tfdynQLKWb3XWZQEkPc+eSx47kiy11YeFAlYkEfXwR1w8kfw== + dependencies: + "@opentelemetry/core" "1.28.0" + "@opentelemetry/semantic-conventions" "1.27.0" + +"@opentelemetry/resources@1.30.1", "@opentelemetry/resources@^1.10.0", "@opentelemetry/resources@^1.28.0": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.30.1.tgz#a4eae17ebd96947fdc7a64f931ca4b71e18ce964" + integrity sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA== + dependencies: + "@opentelemetry/core" "1.30.1" + "@opentelemetry/semantic-conventions" "1.28.0" + +"@opentelemetry/sdk-logs@0.55.0", "@opentelemetry/sdk-logs@^0.55.0": + version "0.55.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.55.0.tgz#78844e502167723a258c75a6b4f3de3900c13ea3" + integrity sha512-TSx+Yg/d48uWW6HtjS1AD5x6WPfLhDWLl/WxC7I2fMevaiBuKCuraxTB8MDXieCNnBI24bw9ytyXrDCswFfWgA== + dependencies: + "@opentelemetry/api-logs" "0.55.0" + "@opentelemetry/core" "1.28.0" + "@opentelemetry/resources" "1.28.0" + +"@opentelemetry/sdk-metrics@1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.28.0.tgz#257b5295bbe9de1ad31c5e8cb43a660c25911d20" + integrity sha512-43tqMK/0BcKTyOvm15/WQ3HLr0Vu/ucAl/D84NO7iSlv6O4eOprxSHa3sUtmYkaZWHqdDJV0AHVz/R6u4JALVQ== + dependencies: + "@opentelemetry/core" "1.28.0" + "@opentelemetry/resources" "1.28.0" + +"@opentelemetry/sdk-metrics@^1.28.0": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz#70e2bcd275b9df6e7e925e3fe53cfe71329b5fc8" + integrity sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog== + dependencies: + "@opentelemetry/core" "1.30.1" + "@opentelemetry/resources" "1.30.1" + +"@opentelemetry/sdk-trace-base@1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.28.0.tgz#6195dc8cd78bd74394cf54c67c5cbd8d1528516c" + integrity sha512-ceUVWuCpIao7Y5xE02Xs3nQi0tOGmMea17ecBdwtCvdo9ekmO+ijc9RFDgfifMl7XCBf41zne/1POM3LqSTZDA== + dependencies: + "@opentelemetry/core" "1.28.0" + "@opentelemetry/resources" "1.28.0" + "@opentelemetry/semantic-conventions" "1.27.0" + +"@opentelemetry/sdk-trace-base@1.30.1": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz#41a42234096dc98e8f454d24551fc80b816feb34" + integrity sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg== + dependencies: + "@opentelemetry/core" "1.30.1" + "@opentelemetry/resources" "1.30.1" + "@opentelemetry/semantic-conventions" "1.28.0" + +"@opentelemetry/sdk-trace-node@^1.28.0": + version "1.30.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.30.1.tgz#bd7d68fcfb4d4ae76ea09810df9668b7dd09a2e5" + integrity sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ== + dependencies: + "@opentelemetry/context-async-hooks" "1.30.1" + "@opentelemetry/core" "1.30.1" + "@opentelemetry/propagator-b3" "1.30.1" + "@opentelemetry/propagator-jaeger" "1.30.1" + "@opentelemetry/sdk-trace-base" "1.30.1" + semver "^7.5.2" + +"@opentelemetry/semantic-conventions@1.27.0": + version "1.27.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz#1a857dcc95a5ab30122e04417148211e6f945e6c" + integrity sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg== + +"@opentelemetry/semantic-conventions@1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz#337fb2bca0453d0726696e745f50064411f646d6" + integrity sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA== + +"@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0": + version "1.40.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz#10b2944ca559386590683392022a897eefd011d3" + integrity sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw== + +"@pinojs/redact@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@pinojs/redact/-/redact-0.4.0.tgz#c3de060dd12640dcc838516aa2a6803cc7b2e9d6" + integrity sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg== + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + +"@rollup/rollup-android-arm-eabi@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz#043f145716234529052ef9e1ce1d847ffbe9e674" + integrity sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA== + +"@rollup/rollup-android-arm64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz#023e1bd146e7519087dfd9e8b29e4cf9f8ecd35c" + integrity sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA== + +"@rollup/rollup-darwin-arm64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz#55ccb5487c02419954c57a7a80602885d616e1ee" + integrity sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw== + +"@rollup/rollup-darwin-x64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz#254b65404b14488c83225e88b8819376ad71a784" + integrity sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew== + +"@rollup/rollup-freebsd-arm64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz#6377ff38c052c76fcaffb7b2728d3172fe676fe6" + integrity sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w== + +"@rollup/rollup-freebsd-x64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz#ba3902309d088eaf7139b916f09b7140b28b406d" + integrity sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g== + +"@rollup/rollup-linux-arm-gnueabihf@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz#e011b9a14638267e53b446286e838dbdaf53f167" + integrity sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g== + +"@rollup/rollup-linux-arm-musleabihf@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz#0bce9ce9a009490abd28fd922dd97ed521311afe" + integrity sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg== + +"@rollup/rollup-linux-arm64-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz#6f6cfbbf324fbb4ceff213abdf7f322fd45d25ff" + integrity sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ== + +"@rollup/rollup-linux-arm64-musl@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz#f7cb3eecaea9c151ef77342af05f38ae924bf795" + integrity sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA== + +"@rollup/rollup-linux-loong64-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz#499bfac6bb669fd88bb664357bf6be996a28b92f" + integrity sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ== + +"@rollup/rollup-linux-loong64-musl@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz#127dfac08764764396bbe04453c545d38a3ab518" + integrity sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw== + +"@rollup/rollup-linux-ppc64-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz#6a72f4d95852aac18326c5bf708393e8f3a41b70" + integrity sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw== + +"@rollup/rollup-linux-ppc64-musl@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz#ba8674666b00d6f9066cb9a5771a8430c34d2de6" + integrity sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg== + +"@rollup/rollup-linux-riscv64-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz#17cc38b2a71e302547cad29bcf78d0db2618c922" + integrity sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg== + +"@rollup/rollup-linux-riscv64-musl@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz#e36a41e2d8bd247331bd5cfc13b8c951d33454a2" + integrity sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg== + +"@rollup/rollup-linux-s390x-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz#1687265f1f4bdea0726c761a58c2db9933609d68" + integrity sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ== + +"@rollup/rollup-linux-x64-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz#56a6a0d9076f2a05a976031493b24a20ddcc0e77" + integrity sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg== + +"@rollup/rollup-linux-x64-musl@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz#bc240ebb5b9fd8d41ca8a80cb458452e8c187e0f" + integrity sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w== + +"@rollup/rollup-openbsd-x64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz#6f80d48a006c4b2ffa7724e95a3e33f6975872af" + integrity sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw== + +"@rollup/rollup-openharmony-arm64@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz#8f6db6f70d0a48abd833b263cd6dd3e7199c4c0e" + integrity sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA== + +"@rollup/rollup-win32-arm64-msvc@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz#b68989bfa815d0b3d4e302ecd90bda744438b177" + integrity sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g== + +"@rollup/rollup-win32-ia32-msvc@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz#c098e45338c50f22f1b288476354f025b746285b" + integrity sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg== + +"@rollup/rollup-win32-x64-gnu@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz#2c9e15be155b79d05999953b1737b2903842e903" + integrity sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg== + +"@rollup/rollup-win32-x64-msvc@4.60.1": + version "4.60.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz#23b860113e9f87eea015d1fa3a4240a52b42fcd4" + integrity sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ== + +"@scure/base@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" + integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== + +"@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/bip32@1.7.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== + dependencies: + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/bip39@1.6.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/bip39@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-2.0.1.tgz#47a6dc15e04faf200041239d46ae3bb7c3c96add" + integrity sha512-PsxdFj/d2AcJcZDX1FXN3dDgitDDTmwf78rKZq1a6c1P1Nan1X/Sxc7667zU3U+AN60g7SxxP0YCVw2H/hBycg== + dependencies: + "@noble/hashes" "2.0.1" + "@scure/base" "2.0.0" + +"@smithy/chunked-blob-reader-native@^4.2.3": + version "4.2.3" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.3.tgz#9e79a80d8d44798e7ce7a8f968cbbbaf5a40d950" + integrity sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw== + dependencies: + "@smithy/util-base64" "^4.3.2" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^5.2.2": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.2.tgz#3af48e37b10e5afed478bb31d2b7bc03c81d196c" + integrity sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^4.4.14", "@smithy/config-resolver@^4.4.15": + version "4.4.15" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-4.4.15.tgz#38c396181d7ac41f2906c8c72f557ce366254cef" + integrity sha512-BJdMBY5YO9iHh+lPLYdHv6LbX+J8IcPCYMl1IJdBt2KDWNHwONHrPVHk3ttYBqJd9wxv84wlbN0f7GlQzcQtNQ== + dependencies: + "@smithy/node-config-provider" "^4.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-config-provider" "^4.2.2" + "@smithy/util-endpoints" "^3.4.0" + "@smithy/util-middleware" "^4.2.13" + tslib "^2.6.2" + +"@smithy/core@^3.23.14": + version "3.23.14" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.23.14.tgz#29c3b6cf771ee8898018a1cc34c0fe3f418468e5" + integrity sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg== + dependencies: + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + "@smithy/url-parser" "^4.2.13" + "@smithy/util-base64" "^4.3.2" + "@smithy/util-body-length-browser" "^4.2.2" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-stream" "^4.5.22" + "@smithy/util-utf8" "^4.2.2" + "@smithy/uuid" "^1.1.2" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.13.tgz#c0533f362dec6644f403c7789d8e81233f78c63f" + integrity sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ== + dependencies: + "@smithy/node-config-provider" "^4.3.13" + "@smithy/property-provider" "^4.2.13" + "@smithy/types" "^4.14.0" + "@smithy/url-parser" "^4.2.13" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-4.2.13.tgz#7fcdf18bc1acaec395b5d387d65136973bd3e1cc" + integrity sha512-vYahwBAtRaAcFbOmE9aLr12z7RiHYDSLcnogSdxfm7kKfsNa3wH+NU5r7vTeB5rKvLsWyPjVX8iH94brP7umiQ== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^4.14.0" + "@smithy/util-hex-encoding" "^4.2.2" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.13.tgz#3b7f4fe380e022db489ca5eef0291b3835c369e6" + integrity sha512-wwybfcOX0tLqCcBP378TIU9IqrDuZq/tDV48LlZNydMpCnqnYr+hWBAYbRE+rFFf/p7IkDJySM3bgiMKP2ihPg== + dependencies: + "@smithy/eventstream-serde-universal" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^4.3.13": + version "4.3.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.13.tgz#75477c75a5d8d4f2844319ba713b345a8b1615e0" + integrity sha512-ied1lO559PtAsMJzg2TKRlctLnEi1PfkNeMMpdwXDImk1zV9uvS/Oxoy/vcy9uv1GKZAjDAB5xT6ziE9fzm5wA== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.13.tgz#6ac8f2b06355ba15a3ccf84fc053fff9bd741e35" + integrity sha512-hFyK+ORJrxAN3RYoaD6+gsGDQjeix8HOEkosoajvXYZ4VeqonM3G4jd9IIRm/sWGXUKmudkY9KdYjzosUqdM8A== + dependencies: + "@smithy/eventstream-serde-universal" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.13.tgz#805c5dfea13bcffb72e3ea46a03de43ddb70843b" + integrity sha512-kRrq4EKLGeOxhC2CBEhRNcu1KSzNJzYY7RK3S7CxMPgB5dRrv55WqQOtRwQxQLC04xqORFLUgnDlc6xrNUULaA== + dependencies: + "@smithy/eventstream-codec" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^5.3.16": + version "5.3.16" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.16.tgz#2cd94de19ac2bcdb51682259cf6dcacbb1b382a9" + integrity sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ== + dependencies: + "@smithy/protocol-http" "^5.3.13" + "@smithy/querystring-builder" "^4.2.13" + "@smithy/types" "^4.14.0" + "@smithy/util-base64" "^4.3.2" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^4.2.14": + version "4.2.14" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.14.tgz#c32a6a5b70fa94e324f2ca04296e2355ddfe4c9b" + integrity sha512-rtQ5es8r/5v4rav7q5QTsfx9CtCyzrz/g7ZZZBH2xtMmd6G/KQrLOWfSHTvFOUPlVy59RQvxeBYJaLRoybMEyA== + dependencies: + "@smithy/chunked-blob-reader" "^5.2.2" + "@smithy/chunked-blob-reader-native" "^4.2.3" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/hash-node@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-4.2.13.tgz#5ec1b80c27f5446136ce98bf6ab0b0594ca34511" + integrity sha512-4/oy9h0jjmY80a2gOIo75iLl8TOPhmtx4E2Hz+PfMjvx/vLtGY4TMU/35WRyH2JHPfT5CVB38u4JRow7gnmzJA== + dependencies: + "@smithy/types" "^4.14.0" + "@smithy/util-buffer-from" "^4.2.2" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-4.2.13.tgz#0e0912b12b8f11c360446812e2ada8fec3f6ddd1" + integrity sha512-WdQ7HwUjINXETeh6dqUeob1UHIYx8kAn9PSp1HhM2WWegiZBYVy2WXIs1lB07SZLan/udys9SBnQGt9MQbDpdg== + dependencies: + "@smithy/types" "^4.14.0" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-4.2.13.tgz#0f23859d529ba669f24860baacb41835f604a8ae" + integrity sha512-jvC0RB/8BLj2SMIkY0Npl425IdnxZJxInpZJbu563zIRnVjpDMXevU3VMCRSabaLB0kf/eFIOusdGstrLJ8IDg== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz#c401ce54b12a16529eb1c938a0b6c2247cb763b8" + integrity sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-4.2.13.tgz#4c96c41336d7d655758c3a7457439fabc9d4b6cd" + integrity sha512-cNm7I9NXolFxtS20ojROddOEpSAeI1Obq6pd1Kj5HtHws3s9Fkk8DdHDfQSs5KuxCewZuVK6UqrJnfJmiMzDuQ== + dependencies: + "@smithy/types" "^4.14.0" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-4.2.13.tgz#0bbc3706fe1321ba99be29703ff98abde996d49d" + integrity sha512-IPMLm/LE4AZwu6qiE8Rr8vJsWhs9AtOdySRXrOM7xnvclp77Tyh7hMs/FRrMf26kgIe67vFJXXOSmVxS7oKeig== + dependencies: + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^4.4.29": + version "4.4.29" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.29.tgz#86fa2f206469e48bff1b30b2c35e433b5f453119" + integrity sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw== + dependencies: + "@smithy/core" "^3.23.14" + "@smithy/middleware-serde" "^4.2.17" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + "@smithy/url-parser" "^4.2.13" + "@smithy/util-middleware" "^4.2.13" + tslib "^2.6.2" + +"@smithy/middleware-retry@^4.5.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.5.1.tgz#1b46e559c3857da1ef5bc6eca5228a521d7d6b40" + integrity sha512-/zY+Gp7Qj2D2hVm3irkCyONER7E9MiX3cUUm/k2ZmhkzZkrPgwVS4aJ5NriZUEN/M0D1hhjrgjUmX04HhRwdWA== + dependencies: + "@smithy/core" "^3.23.14" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/service-error-classification" "^4.2.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-retry" "^4.3.1" + "@smithy/uuid" "^1.1.2" + tslib "^2.6.2" + +"@smithy/middleware-serde@^4.2.17": + version "4.2.17" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-4.2.17.tgz#45b1eaa99c3b536042eb56365096e6681f2a347b" + integrity sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ== + dependencies: + "@smithy/core" "^3.23.14" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-4.2.13.tgz#88007ea7eb40ab3ff632701c21149e0e8a57b55f" + integrity sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^4.3.13": + version "4.3.13" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-4.3.13.tgz#a65c696a38a0c2e7012652b1c1138799882b12bc" + integrity sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw== + dependencies: + "@smithy/property-provider" "^4.2.13" + "@smithy/shared-ini-file-loader" "^4.4.8" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^4.5.2": + version "4.5.2" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.5.2.tgz#21d70f4c9cf1ce59921567bab59ae1177b6c60b1" + integrity sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA== + dependencies: + "@smithy/protocol-http" "^5.3.13" + "@smithy/querystring-builder" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/property-provider@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-4.2.13.tgz#4859f887414f2c251517125258870a70509f8bbd" + integrity sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^5.3.13": + version "5.3.13" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-5.3.13.tgz#1e8fcacd61282cafc2c783ab002cb0debe763588" + integrity sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-4.2.13.tgz#1f3c009493a06d83f998da70f5920246dfcd88dd" + integrity sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ== + dependencies: + "@smithy/types" "^4.14.0" + "@smithy/util-uri-escape" "^4.2.2" + tslib "^2.6.2" + +"@smithy/querystring-parser@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-4.2.13.tgz#c2ab4446a50d0de232bbffdab534b3e0023bf879" + integrity sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-4.2.13.tgz#22aa256bbad30d98e13a4896eee165ee184cd33b" + integrity sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw== + dependencies: + "@smithy/types" "^4.14.0" + +"@smithy/shared-ini-file-loader@^4.4.8": + version "4.4.8" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.8.tgz#c45099e8aea8f48af97d05be91ab6ae93d105ae7" + integrity sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^5.3.13": + version "5.3.13" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-5.3.13.tgz#0c3760a5837673ddbb66c433637d5e16742b991f" + integrity sha512-YpYSyM0vMDwKbHD/JA7bVOF6kToVRpa+FM5ateEVRpsTNu564g1muBlkTubXhSKKYXInhpADF46FPyrZcTLpXg== + dependencies: + "@smithy/is-array-buffer" "^4.2.2" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-hex-encoding" "^4.2.2" + "@smithy/util-middleware" "^4.2.13" + "@smithy/util-uri-escape" "^4.2.2" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@smithy/smithy-client@^4.12.9": + version "4.12.9" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.12.9.tgz#2eb54ee07050a8bcd3792f8b8c4e03fac4bfb422" + integrity sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ== + dependencies: + "@smithy/core" "^3.23.14" + "@smithy/middleware-endpoint" "^4.4.29" + "@smithy/middleware-stack" "^4.2.13" + "@smithy/protocol-http" "^5.3.13" + "@smithy/types" "^4.14.0" + "@smithy/util-stream" "^4.5.22" + tslib "^2.6.2" + +"@smithy/types@^4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.14.0.tgz#72fb6fd315f2eff7d4878142db2d1db4ef94f9bc" + integrity sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-4.2.13.tgz#cc582733d1181e1a135b05bb600f12c9889be7f4" + integrity sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw== + dependencies: + "@smithy/querystring-parser" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/util-base64@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-4.3.2.tgz#be02bcb29a87be744356467ea25ffa413e695cea" + integrity sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ== + dependencies: + "@smithy/util-buffer-from" "^4.2.2" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz#c4404277d22039872abdb80e7800f9a63f263862" + integrity sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^4.2.3": + version "4.2.3" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz#f923ca530defb86a9ac3ca2d3066bcca7b304fbc" + integrity sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz#2c6b7857757dfd88f6cd2d36016179a40ccc913b" + integrity sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q== + dependencies: + "@smithy/is-array-buffer" "^4.2.2" + tslib "^2.6.2" + +"@smithy/util-config-provider@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz#52ebf9d8942838d18bc5fb1520de1e8699d7aad6" + integrity sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^4.3.45": + version "4.3.45" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.45.tgz#42cb7fb97857a6b67d54e38adaf1476fdc7d1339" + integrity sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw== + dependencies: + "@smithy/property-provider" "^4.2.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^4.2.49": + version "4.2.50" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.50.tgz#6893eeb9036cb73bcc1cd9ed5f50bdbcbd745cda" + integrity sha512-xpjncL5XozFA3No7WypTsPU1du0fFS8flIyO+Wh2nhCy7bpEapvU7BR55Bg+wrfw+1cRA+8G8UsTjaxgzrMzXg== + dependencies: + "@smithy/config-resolver" "^4.4.15" + "@smithy/credential-provider-imds" "^4.2.13" + "@smithy/node-config-provider" "^4.3.13" + "@smithy/property-provider" "^4.2.13" + "@smithy/smithy-client" "^4.12.9" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^3.3.4", "@smithy/util-endpoints@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-3.4.0.tgz#e66c4b34ad4cc1ef52864e3ba667b5e7f9109456" + integrity sha512-QQHGPKkw6NPcU6TJ1rNEEa201srPtZiX4k61xL163vvs9sTqW/XKz+UEuJ00uvPqoN+5Rs4Ka1UJ7+Mp03IXJw== + dependencies: + "@smithy/node-config-provider" "^4.3.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz#4abf3335dd1eb884041d8589ca7628d81a6fd1d3" + integrity sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^4.2.13": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-4.2.13.tgz#fda5518f95cc3f4a3086d9ee46cc42797baaedf8" + integrity sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/util-retry@^4.3.0", "@smithy/util-retry@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-4.3.1.tgz#80fff293d0b25734ed25e763cd6570d2b7e34c76" + integrity sha512-FwmicpgWOkP5kZUjN3y+3JIom8NLGqSAJBeoIgK0rIToI817TEBHCrd0A2qGeKQlgDeP+Jzn4i0H/NLAXGy9uQ== + dependencies: + "@smithy/service-error-classification" "^4.2.13" + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/util-stream@^4.5.22": + version "4.5.22" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.5.22.tgz#16e449bbd174243b9e202f0f75d33a1d700c2020" + integrity sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew== + dependencies: + "@smithy/fetch-http-handler" "^5.3.16" + "@smithy/node-http-handler" "^4.5.2" + "@smithy/types" "^4.14.0" + "@smithy/util-base64" "^4.3.2" + "@smithy/util-buffer-from" "^4.2.2" + "@smithy/util-hex-encoding" "^4.2.2" + "@smithy/util-utf8" "^4.2.2" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz#48e40206e7fe9daefc8d44bb43a1ab17e76abf4a" + integrity sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-4.2.2.tgz#21db686982e6f3393ac262e49143b42370130f13" + integrity sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw== + dependencies: + "@smithy/util-buffer-from" "^4.2.2" + tslib "^2.6.2" + +"@smithy/util-waiter@^4.2.15": + version "4.2.15" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-4.2.15.tgz#0338ad7e5b47380836cfedd21a6b5bda4e43a88f" + integrity sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg== + dependencies: + "@smithy/types" "^4.14.0" + tslib "^2.6.2" + +"@smithy/uuid@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@smithy/uuid/-/uuid-1.1.2.tgz#b6e97c7158615e4a3c775e809c00d8c269b5a12e" + integrity sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g== + dependencies: + tslib "^2.6.2" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/caseless@*": + version "0.12.5" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.5.tgz#db9468cb1b1b5a925b8f34822f1669df0c5472f5" + integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg== + +"@types/chai@^5.2.2": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a" + integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA== + dependencies: + "@types/deep-eql" "*" + assertion-error "^2.0.1" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + +"@types/estree@1.0.8", "@types/estree@^1.0.0": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/node@*", "@types/node@>=13.7.0": + version "25.6.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.6.0.tgz#4e09bad9b469871f2d0f68140198cbd714f4edca" + integrity sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ== + dependencies: + undici-types "~7.19.0" + +"@types/node@^22.0.0": + version "22.19.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.17.tgz#09c71fb34ba2510f8ac865361b1fcb9552b8a581" + integrity sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q== + dependencies: + undici-types "~6.21.0" + +"@types/request@^2.48.8": + version "2.48.13" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.13.tgz#abdf4256524e801ea8fdda54320f083edb5a6b80" + integrity sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.5" + +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + +"@viem/anvil@^0.0.10": + version "0.0.10" + resolved "https://registry.yarnpkg.com/@viem/anvil/-/anvil-0.0.10.tgz#aa64fd96017d6875c9e8bebc223d394a55bc3a72" + integrity sha512-9PzYXBRikfSUhhm8Bd0avv07agwcbMJ5FaSu2D2vbE0cxkvXGtolL3fW5nz2yefMqOqVQL4XzfM5nwY81x3ytw== + dependencies: + execa "^7.1.1" + get-port "^6.1.2" + http-proxy "^1.18.1" + ws "^8.13.0" + +"@vitest/expect@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.2.4.tgz#8362124cd811a5ee11c5768207b9df53d34f2433" + integrity sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig== + dependencies: + "@types/chai" "^5.2.2" + "@vitest/spy" "3.2.4" + "@vitest/utils" "3.2.4" + chai "^5.2.0" + tinyrainbow "^2.0.0" + +"@vitest/mocker@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.2.4.tgz#4471c4efbd62db0d4fa203e65cc6b058a85cabd3" + integrity sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ== + dependencies: + "@vitest/spy" "3.2.4" + estree-walker "^3.0.3" + magic-string "^0.30.17" + +"@vitest/pretty-format@3.2.4", "@vitest/pretty-format@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.2.4.tgz#3c102f79e82b204a26c7a5921bf47d534919d3b4" + integrity sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA== + dependencies: + tinyrainbow "^2.0.0" + +"@vitest/runner@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.2.4.tgz#5ce0274f24a971f6500f6fc166d53d8382430766" + integrity sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ== + dependencies: + "@vitest/utils" "3.2.4" + pathe "^2.0.3" + strip-literal "^3.0.0" + +"@vitest/snapshot@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.2.4.tgz#40a8bc0346ac0aee923c0eefc2dc005d90bc987c" + integrity sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ== + dependencies: + "@vitest/pretty-format" "3.2.4" + magic-string "^0.30.17" + pathe "^2.0.3" + +"@vitest/spy@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.2.4.tgz#cc18f26f40f3f028da6620046881f4e4518c2599" + integrity sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw== + dependencies: + tinyspy "^4.0.3" + +"@vitest/utils@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.2.4.tgz#c0813bc42d99527fb8c5b138c7a88516bca46fea" + integrity sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA== + dependencies: + "@vitest/pretty-format" "3.2.4" + loupe "^3.1.4" + tinyrainbow "^2.0.0" + +abitype@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.1.0.tgz#510c5b3f92901877977af5e864841f443bf55406" + integrity sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A== + +abitype@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.2.3.tgz#bec3e09dea97d99ef6c719140bee663a329ad1f4" + integrity sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-leveldown@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#08d19d4e26fb5be426f7a57004851b39e1795a2e" + integrity sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ== + dependencies: + buffer "^6.0.3" + catering "^2.0.0" + is-buffer "^2.0.5" + level-concat-iterator "^3.0.0" + level-supports "^2.0.1" + queue-microtask "^1.2.3" + +accepts@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +axios@^1.13.5: + version "1.15.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.15.0.tgz#0fcee91ef03d386514474904b27863b2c683bf4f" + integrity sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q== + dependencies: + follow-redirects "^1.15.11" + form-data "^4.0.5" + proxy-from-env "^2.1.0" + +balanced-match@^4.0.2: + version "4.0.4" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a" + integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== + +base64-js@^1.3.0, base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bignumber.js@^9.0.0: + version "9.3.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.1.tgz#759c5aaddf2ffdc4f154f7b493e1c8770f88c4d7" + integrity sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ== + +bintrees@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" + integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== + +bn.js@^5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.3.tgz#16a9e409616b23fef3ccbedb8d42f13bff80295e" + integrity sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w== + +bowser@^2.11.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.14.1.tgz#4ea39bf31e305184522d7ad7bfd91389e4f0cb79" + integrity sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg== + +brace-expansion@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.5.tgz#dcc3a37116b79f3e1b46db994ced5d570e930fdb" + integrity sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ== + dependencies: + balanced-match "^4.0.2" + +buffer-equal-constant-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@6.0.3, buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bytes@^3.1.2, bytes@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +cache-content-type@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c" + integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA== + dependencies: + mime-types "^2.1.18" + ylru "^1.2.0" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bound@^1.0.2, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +catering@^2.0.0, catering@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + +chai@^5.2.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.3.3.tgz#dd3da955e270916a4bd3f625f4b919996ada7e06" + integrity sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +change-case@^5.4.4: + version "5.4.4" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-5.4.4.tgz#0d52b507d8fb8f204343432381d1a6d7bff97a02" + integrity sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w== + +check-error@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.3.tgz#2427361117b70cca8dc89680ead32b157019caf5" + integrity sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co-body@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.2.0.tgz#afd776d60e5659f4eee862df83499698eb1aea1b" + integrity sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA== + dependencies: + "@hapi/bourne" "^3.0.0" + inflation "^2.0.0" + qs "^6.5.2" + raw-body "^2.3.3" + type-is "^1.6.16" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.20, colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +comlink@^4.4.1: + version "4.4.2" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.2.tgz#cbbcd82742fbebc06489c28a183eedc5c60a2bca" + integrity sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g== + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +compressible@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +content-disposition@~0.5.2: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +convert-hex@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/convert-hex/-/convert-hex-0.1.0.tgz#08c04568922c27776b8a2e81a95d393362ea0b65" + integrity sha512-w20BOb1PiR/sEJdS6wNrUjF5CSfscZFUp7R9NSlXH8h2wynzXVEPFPJECAnkNylZ+cvf3p7TyRUHggDmrwXT9A== + +convert-string@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/convert-string/-/convert-string-0.1.0.tgz#79ce41a9bb0d03bcf72cdc6a8f3c56fbbc64410a" + integrity sha512-1KX9ESmtl8xpT2LN2tFnKSbV4NiarbVi8DVb39ZriijvtTklyrT+4dT1wsGMHKD3CJUjXgvJzstm9qL9ICojGA== + +cookies@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.9.1.tgz#3ffed6f60bb4fb5f146feeedba50acc418af67e3" + integrity sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw== + dependencies: + depd "~2.0.0" + keygrip "~1.1.0" + +copy-to@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5" + integrity sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + +debug@4, debug@^4.3.2, debug@^4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + +deep-equal@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw== + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@^2.0.0, depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-libc@^2.0.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +detect-node@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +dotenv@^16.0.3: + version "16.6.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" + integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +duplexify@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +esbuild@^0.27.0, esbuild@~0.27.0: + version "0.27.7" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.7.tgz#bcadce22b2f3fd76f257e3a64f83a64986fea11f" + integrity sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w== + optionalDependencies: + "@esbuild/aix-ppc64" "0.27.7" + "@esbuild/android-arm" "0.27.7" + "@esbuild/android-arm64" "0.27.7" + "@esbuild/android-x64" "0.27.7" + "@esbuild/darwin-arm64" "0.27.7" + "@esbuild/darwin-x64" "0.27.7" + "@esbuild/freebsd-arm64" "0.27.7" + "@esbuild/freebsd-x64" "0.27.7" + "@esbuild/linux-arm" "0.27.7" + "@esbuild/linux-arm64" "0.27.7" + "@esbuild/linux-ia32" "0.27.7" + "@esbuild/linux-loong64" "0.27.7" + "@esbuild/linux-mips64el" "0.27.7" + "@esbuild/linux-ppc64" "0.27.7" + "@esbuild/linux-riscv64" "0.27.7" + "@esbuild/linux-s390x" "0.27.7" + "@esbuild/linux-x64" "0.27.7" + "@esbuild/netbsd-arm64" "0.27.7" + "@esbuild/netbsd-x64" "0.27.7" + "@esbuild/openbsd-arm64" "0.27.7" + "@esbuild/openbsd-x64" "0.27.7" + "@esbuild/openharmony-arm64" "0.27.7" + "@esbuild/sunos-x64" "0.27.7" + "@esbuild/win32-arm64" "0.27.7" + "@esbuild/win32-ia32" "0.27.7" + "@esbuild/win32-x64" "0.27.7" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + +expect-type@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" + integrity sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA== + +extend@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-copy@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-4.0.3.tgz#935adef81c26276dcbe8892347af307b5090206a" + integrity sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fast-xml-builder@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz#0c407a1d9d5996336c0cd76f7ff785cac6413017" + integrity sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg== + dependencies: + path-expression-matcher "^1.1.3" + +fast-xml-parser@5.5.8: + version "5.5.8" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.5.8.tgz#929571ed8c5eb96e6d9bd572ba14fc4b84875716" + integrity sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ== + dependencies: + fast-xml-builder "^1.1.4" + path-expression-matcher "^1.2.0" + strnum "^2.2.0" + +fast-xml-parser@^5.3.4: + version "5.6.0" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.6.0.tgz#4ade6df478c2532a462b693278fa6393c295a9e3" + integrity sha512-5G+uaEBbOm9M4dgMOV3K/rBzfUNGqGqoUTaYJM3hBwM8t71w07gxLQZoTsjkY8FtfjabqgQHEkeIySBDYeBmJw== + dependencies: + "@nodable/entities" "^1.1.0" + fast-xml-builder "^1.1.4" + path-expression-matcher "^1.5.0" + strnum "^2.2.3" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +follow-redirects@^1.0.0, follow-redirects@^1.15.11: + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +foreground-child@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +form-data@^2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.5.tgz#a5f6364ad7e4e67e95b4a07e2d8c6f711c74f624" + integrity sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.35" + safe-buffer "^5.2.1" + +form-data@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" + integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + +fresh@~0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gaxios@^6.0.0, gaxios@^6.0.2, gaxios@^6.1.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.7.1.tgz#ebd9f7093ede3ba502685e73390248bb5b7f71fb" + integrity sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ== + dependencies: + extend "^3.0.2" + https-proxy-agent "^7.0.1" + is-stream "^2.0.0" + node-fetch "^2.6.9" + uuid "^9.0.1" + +gcp-metadata@^6.0.0, gcp-metadata@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.1.tgz#f65aa69f546bc56e116061d137d3f5f90bdec494" + integrity sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A== + dependencies: + gaxios "^6.1.1" + google-logging-utils "^0.0.2" + json-bigint "^1.0.0" + +generator-function@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.1.tgz#0e75dd410d1243687a0ba2e951b94eedb8f737a2" + integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-port@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-6.1.2.tgz#c1228abb67ba0e17fb346da33b15187833b9c08a" + integrity sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw== + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-tsconfig@^4.7.5: + version "4.14.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.14.0.tgz#985d85c52a9903864280ccc2448d413fbf1efed8" + integrity sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob@^13.0.0: + version "13.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-13.0.6.tgz#078666566a425147ccacfbd2e332deb66a2be71d" + integrity sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw== + dependencies: + minimatch "^10.2.2" + minipass "^7.1.3" + path-scurry "^2.0.2" + +glob@~11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.1.0.tgz#4f826576e4eb99c7dad383793d2f9f08f67e50a6" + integrity sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw== + dependencies: + foreground-child "^3.3.1" + jackspeak "^4.1.1" + minimatch "^10.1.1" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^2.0.0" + +google-auth-library@^9.6.3: + version "9.15.1" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.15.1.tgz#0c5d84ed1890b2375f1cd74f03ac7b806b392928" + integrity sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng== + dependencies: + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + gaxios "^6.1.1" + gcp-metadata "^6.1.0" + gtoken "^7.0.0" + jws "^4.0.0" + +google-logging-utils@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-0.0.2.tgz#5fd837e06fa334da450433b9e3e1870c1594466a" + integrity sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ== + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +gtoken@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.1.0.tgz#d61b4ebd10132222817f7222b1e6064bd463fc26" + integrity sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw== + dependencies: + gaxios "^6.0.0" + jws "^4.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +html-entities@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.6.0.tgz#7c64f1ea3b36818ccae3d3fb48b6974208e984f8" + integrity sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ== + +http-assert@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.5.0.tgz#c389ccd87ac16ed2dfa6246fd73b926aa00e6b8f" + integrity sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w== + dependencies: + deep-equal "~1.0.1" + http-errors "~1.8.0" + +http-errors@^1.6.3, http-errors@~1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-errors@^2.0.0, http-errors@^2.0.1, http-errors@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b" + integrity sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ== + dependencies: + depd "~2.0.0" + inherits "~2.0.4" + setprototypeof "~1.2.0" + statuses "~2.0.2" + toidentifier "~1.0.1" + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +https-proxy-agent@^7.0.1: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +iconv-lite@~0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +idb-keyval@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.2.tgz#b0171b5f73944854a3291a5cdba8e12768c4854a" + integrity sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg== + +idb@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/idb/-/idb-8.0.3.tgz#c91e558f15a8d53f1d7f53a094d226fc3ad71fd9" + integrity sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg== + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +inflation@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.1.0.tgz#9214db11a47e6f756d111c4f9df96971c60f886c" + integrity sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ== + +inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.2.tgz#ae3b61e3d5ea4e4839b90bad22b02335051a17d5" + integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== + dependencies: + call-bound "^1.0.4" + generator-function "^2.0.0" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== + +jackspeak@^4.1.1: + version "4.2.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.2.3.tgz#27ef80f33b93412037c3bea4f8eddf80e1931483" + integrity sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg== + dependencies: + "@isaacs/cliui" "^9.0.0" + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +js-tokens@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" + integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + +json-stringify-deterministic@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz#aaa3f907466ed01e3afd77b898d0a2b3b132820a" + integrity sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g== + +jwa@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.1.tgz#bf8176d1ad0cd72e0f3f58338595a13e110bc804" + integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== + dependencies: + buffer-equal-constant-time "^1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.1.tgz#07edc1be8fac20e677b283ece261498bd38f0690" + integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== + dependencies: + jwa "^2.0.1" + safe-buffer "^5.0.1" + +keygrip@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" + integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== + dependencies: + tsscmp "1.0.6" + +koa-bodyparser@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/koa-bodyparser/-/koa-bodyparser-4.4.1.tgz#a908d848e142cc57d9eece478e932bf00dce3029" + integrity sha512-kBH3IYPMb+iAXnrxIhXnW+gXV8OTzCu8VPDqvcDHW9SQrbkHmqPQtiZwrltNmSq6/lpipHnT7k7PsjlVD7kK0w== + dependencies: + co-body "^6.0.0" + copy-to "^2.0.1" + type-is "^1.6.18" + +koa-compose@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877" + integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw== + +koa-compress@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/koa-compress/-/koa-compress-5.2.1.tgz#a602ba25302e7dff2388e9b885d56028d55710ef" + integrity sha512-k8VJMZI7vvSq1/G/t6Jggeg4h7fec1NJxcYaDWC4/1PK6mJFPs0OYqj44vx/soUcDVEJR7ysR5cc6pszKpnzXA== + dependencies: + bytes "^3.1.2" + compressible "^2.0.18" + http-errors "^2.0.1" + koa-is-json "^1.0.0" + negotiator "^1.0.0" + +koa-convert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-2.0.0.tgz#86a0c44d81d40551bae22fee6709904573eea4f5" + integrity sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA== + dependencies: + co "^4.6.0" + koa-compose "^4.1.0" + +koa-is-json@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14" + integrity sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw== + +koa-router@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-13.1.1.tgz#7b7d08b1aba82c4cc50ad71164b0d6d33d368784" + integrity sha512-3GxRi7CxEgsfGhdFf4OW4OLv0DFdyNl2drcOCtoezi+LDSnkg0mhr1Iq5Q25R4FJt3Gw6dcAKrcpaCJ7WJfhYg== + dependencies: + debug "^4.4.1" + http-errors "^2.0.0" + koa-compose "^4.1.0" + path-to-regexp "^6.3.0" + +koa@^2.16.1: + version "2.16.4" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.16.4.tgz#303b996f5c3f2a3bb771c7db5e4303ee05f2265f" + integrity sha512-3An0GCLDSR34tsCO4H8Tef8Pp2ngtaZDAZnsWJYelqXUK5wyiHvGItgK/xcSkmHLSTn1Jcho1mRQs2ehRzvKKw== + dependencies: + accepts "^1.3.5" + cache-content-type "^1.0.0" + content-disposition "~0.5.2" + content-type "^1.0.4" + cookies "~0.9.0" + debug "^4.3.2" + delegates "^1.0.0" + depd "^2.0.0" + destroy "^1.0.4" + encodeurl "^1.0.2" + escape-html "^1.0.3" + fresh "~0.5.2" + http-assert "^1.3.0" + http-errors "^1.6.3" + is-generator-function "^1.0.7" + koa-compose "^4.1.0" + koa-convert "^2.0.0" + on-finished "^2.3.0" + only "~0.0.2" + parseurl "^1.3.2" + statuses "^1.5.0" + type-is "^1.6.16" + vary "^1.1.2" + +level-concat-iterator@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" + integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== + dependencies: + catering "^2.1.0" + +level-supports@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" + integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== + +leveldown@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.1.tgz#0f0e480fa88fd807abf94c33cb7e40966ea4b5ce" + integrity sha512-88c+E+Eizn4CkQOBHwqlCJaTNEjGpaEIikn1S+cINc5E9HEvJ77bqY4JY/HxT5u0caWqsc3P3DcFIKBI1vHt+A== + dependencies: + abstract-leveldown "^7.2.0" + napi-macros "~2.0.0" + node-gyp-build "^4.3.0" + +lmdb@^3.2.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-3.5.3.tgz#ef6d2d50e3d2ecf58109ecbe15a6d254c30bdcfe" + integrity sha512-6A0iRKOv/N62P1vU8qhBr32tHQIY6pQMe8b6zqI4VLELqV8fWHUMdnfNjMR+Kyh7ZeRCo8PDzAnW2g+SJSoP1A== + dependencies: + "@harperfast/extended-iterable" "^1.0.3" + msgpackr "^1.11.2" + node-addon-api "^6.1.0" + node-gyp-build-optional-packages "5.2.2" + ordered-binary "^1.5.3" + weak-lru-cache "^1.2.2" + optionalDependencies: + "@lmdb/lmdb-darwin-arm64" "3.5.3" + "@lmdb/lmdb-darwin-x64" "3.5.3" + "@lmdb/lmdb-linux-arm" "3.5.3" + "@lmdb/lmdb-linux-arm64" "3.5.3" + "@lmdb/lmdb-linux-x64" "3.5.3" + "@lmdb/lmdb-win32-arm64" "3.5.3" + "@lmdb/lmdb-win32-x64" "3.5.3" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.chunk@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" + integrity sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w== + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.clonedeepwith@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4" + integrity sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.omit@^4.5.0: + version "4.18.0" + resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.18.0.tgz#d16d96a68db2c803c45da9450fdac953c59a1858" + integrity sha512-hZXIupXdHtocTnvIJ2aCd2vxKYtxex6gbiGuPvgBRnFQO9yu3AtmDAbVuCXcSsQx3INo/1g71OktlFFA/ES8Xg== + +lodash.pickby@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" + integrity sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q== + +lodash.times@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/lodash.times/-/lodash.times-4.3.2.tgz#3e1f2565c431754d54ab57f2ed1741939285ca1d" + integrity sha512-FfaJzl0SA35CRPDh5SWe2BTght6y5KSK7yJv166qIp/8q7qOwBDCvuDZE2RUSMRpBkLF6rZKbLEUoTmaP3qg6A== + +long@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" + integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== + +loupe@^3.1.0, loupe@^3.1.4: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" + integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== + +lru-cache@^11.0.0: + version "11.3.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.3.5.tgz#29047d348c0b2793e3112a01c739bb7c6d855637" + integrity sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw== + +magic-string@^0.30.17: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +"mime-db@>= 1.43.0 < 2": + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.35, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@^10.1.1, minimatch@^10.2.2: + version "10.2.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" + integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== + dependencies: + brace-expansion "^5.0.5" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^7.1.2, minipass@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" + integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +msgpackr-extract@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz#e9d87023de39ce714872f9e9504e3c1996d61012" + integrity sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA== + dependencies: + node-gyp-build-optional-packages "5.2.2" + optionalDependencies: + "@msgpackr-extract/msgpackr-extract-darwin-arm64" "3.0.3" + "@msgpackr-extract/msgpackr-extract-darwin-x64" "3.0.3" + "@msgpackr-extract/msgpackr-extract-linux-arm" "3.0.3" + "@msgpackr-extract/msgpackr-extract-linux-arm64" "3.0.3" + "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.3" + "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.3" + +msgpackr@^1.11.2: + version "1.11.9" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.11.9.tgz#1aa99ed379a066374ac82b62f8ad70723bbd3a59" + integrity sha512-FkoAAyyA6HM8wL882EcEyFZ9s7hVADSwG9xrVx3dxxNQAtgADTrJoEWivID82Iv1zWDsv/OtbrrcZAzGzOMdNw== + optionalDependencies: + msgpackr-extract "^3.0.2" + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +napi-macros@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + +node-addon-api@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" + integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== + +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build-optional-packages@5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz#522f50c2d53134d7f3a76cd7255de4ab6c96a3a4" + integrity sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw== + dependencies: + detect-libc "^2.0.1" + +node-gyp-build@^4.3.0: + version "4.8.4" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== + +node-pg-migrate@^8.0.4: + version "8.0.4" + resolved "https://registry.yarnpkg.com/node-pg-migrate/-/node-pg-migrate-8.0.4.tgz#b2e519e7ebc4c2f7777ef4b5cf0a01591ddef2ee" + integrity sha512-HTlJ6fOT/2xHhAUtsqSN85PGMAqSbfGJNRwQF8+ZwQ1+sVGNUTl/ZGEshPsOI3yV22tPIyHXrKXr3S0JxeYLrg== + dependencies: + glob "~11.1.0" + yargs "~17.7.0" + +npm-run-path@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" + integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== + dependencies: + path-key "^4.0.0" + +object-inspect@^1.13.3, object-inspect@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +ohash@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-2.0.11.tgz#60b11e8cff62ca9dee88d13747a5baa145f5900b" + integrity sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ== + +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + +on-finished@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +only@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" + integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ== + +ordered-binary@^1.5.3: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ordered-binary/-/ordered-binary-1.6.1.tgz#5ac240ea719d6a0e6d4f0485385d3f9cb1cd4432" + integrity sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w== + +ox@0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.9.6.tgz#5cf02523b6db364c10ee7f293ff1e664e0e1eab7" + integrity sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.0.9" + eventemitter3 "5.0.1" + +p-limit@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +pako@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + +parseurl@^1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-expression-matcher@^1.1.3, path-expression-matcher@^1.2.0, path-expression-matcher@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz#3b98545dc88ffebb593e2d8458d0929da9275f4a" + integrity sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-scurry@^2.0.0, path-scurry@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.2.tgz#6be0d0ee02a10d9e0de7a98bae65e182c9061f85" + integrity sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg== + dependencies: + lru-cache "^11.0.0" + minipass "^7.1.2" + +path-to-regexp@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" + integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== + +pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +pathval@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" + integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== + +pg-cloudflare@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz#386035d4bfcf1a7045b026f8b21acf5353f14d65" + integrity sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ== + +pg-connection-string@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.12.0.tgz#4084f917902bb2daae3dc1376fe24ac7b4eaccf2" + integrity sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ== + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-pool@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.13.0.tgz#416482e9700e8f80c685a6ae5681697a413c13a3" + integrity sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA== + +pg-protocol@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.13.0.tgz#fdaf6d020bca590d58bb991b4b16fc448efe0511" + integrity sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w== + +pg-types@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@^8.11.3: + version "8.20.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.20.0.tgz#1a274de944cb329fd6dd77a6d371a005ba6b136d" + integrity sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA== + dependencies: + pg-connection-string "^2.12.0" + pg-pool "^3.13.0" + pg-protocol "^1.13.0" + pg-types "2.2.0" + pgpass "1.0.5" + optionalDependencies: + pg-cloudflare "^1.3.0" + +pgpass@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== + dependencies: + split2 "^4.1.0" + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^4.0.2, picomatch@^4.0.3, picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + +pino-abstract-transport@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" + integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== + dependencies: + split2 "^4.0.0" + +pino-abstract-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23" + integrity sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg== + dependencies: + split2 "^4.0.0" + +pino-pretty@^13.0.0: + version "13.1.3" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.1.3.tgz#2274cccda925dd355c104079a5029f6598d0381b" + integrity sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^4.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pump "^3.0.0" + secure-json-parse "^4.0.0" + sonic-boom "^4.0.1" + strip-json-comments "^5.0.2" + +pino-std-serializers@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz#a7b0cd65225f29e92540e7853bd73b07479893fc" + integrity sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw== + +pino@^9.5.0: + version "9.14.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-9.14.0.tgz#673d9711c2d1e64d18670c1ec05ef7ba14562556" + integrity sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w== + dependencies: + "@pinojs/redact" "^0.4.0" + atomic-sleep "^1.0.0" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^2.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^3.0.0" + +postcss@^8.5.6: + version "8.5.9" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4" + integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.1.tgz#c40b3da0222c500ff1e51c5d7014b60b79697c7a" + integrity sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ== + +postgres-date@~1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== + +prom-client@^15.1.3: + version "15.1.3" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.3.tgz#69fa8de93a88bc9783173db5f758dc1c69fa8fc2" + integrity sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g== + dependencies: + "@opentelemetry/api" "^1.4.0" + tdigest "^0.1.1" + +protobufjs@^7.3.0: + version "7.5.5" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.5.5.tgz#b7089ca4410374c75150baf277353ef76db69f96" + integrity sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== + +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +qs@^6.5.2: + version "6.15.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.1.tgz#bdb55aed06bfac257a90c44a446a73fba5575c8f" + integrity sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg== + dependencies: + side-channel "^1.1.0" + +queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +raw-body@^2.3.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.3.tgz#11c6650ee770a7de1b494f197927de0c923822e2" + integrity sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA== + dependencies: + bytes "~3.1.2" + http-errors "~2.0.1" + iconv-lite "~0.4.24" + unpipe "~1.0.0" + +readable-stream@^3.1.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +retry-request@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-7.0.2.tgz#60bf48cfb424ec01b03fca6665dee91d06dd95f3" + integrity sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w== + dependencies: + "@types/request" "^2.48.8" + extend "^3.0.2" + teeny-request "^9.0.0" + +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +rollup@^4.43.0: + version "4.60.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.60.1.tgz#b4aa2bcb3a5e1437b5fad40d43fe42d4bde7a42d" + integrity sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.60.1" + "@rollup/rollup-android-arm64" "4.60.1" + "@rollup/rollup-darwin-arm64" "4.60.1" + "@rollup/rollup-darwin-x64" "4.60.1" + "@rollup/rollup-freebsd-arm64" "4.60.1" + "@rollup/rollup-freebsd-x64" "4.60.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.60.1" + "@rollup/rollup-linux-arm-musleabihf" "4.60.1" + "@rollup/rollup-linux-arm64-gnu" "4.60.1" + "@rollup/rollup-linux-arm64-musl" "4.60.1" + "@rollup/rollup-linux-loong64-gnu" "4.60.1" + "@rollup/rollup-linux-loong64-musl" "4.60.1" + "@rollup/rollup-linux-ppc64-gnu" "4.60.1" + "@rollup/rollup-linux-ppc64-musl" "4.60.1" + "@rollup/rollup-linux-riscv64-gnu" "4.60.1" + "@rollup/rollup-linux-riscv64-musl" "4.60.1" + "@rollup/rollup-linux-s390x-gnu" "4.60.1" + "@rollup/rollup-linux-x64-gnu" "4.60.1" + "@rollup/rollup-linux-x64-musl" "4.60.1" + "@rollup/rollup-openbsd-x64" "4.60.1" + "@rollup/rollup-openharmony-arm64" "4.60.1" + "@rollup/rollup-win32-arm64-msvc" "4.60.1" + "@rollup/rollup-win32-ia32-msvc" "4.60.1" + "@rollup/rollup-win32-x64-gnu" "4.60.1" + "@rollup/rollup-win32-x64-msvc" "4.60.1" + fsevents "~2.3.2" + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +secure-json-parse@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c" + integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA== + +semver@^7.5.2: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== + +setprototypeof@1.2.0, setprototypeof@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha256@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/sha256/-/sha256-0.2.0.tgz#73a0b418daab7035bff86e8491e363412fc2ab05" + integrity sha512-kTWMJUaez5iiT9CcMv8jSq6kMhw3ST0uRdcIWl3D77s6AsLXNXRp3heeqqfu5+Dyfu4hwpQnMzhqHh8iNQxw0w== + dependencies: + convert-hex "~0.1.0" + convert-string "~0.1.0" + +sha3@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f" + integrity sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg== + dependencies: + buffer "6.0.3" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel-list@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" + integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.4" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + +signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +sonic-boom@^4.0.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.1.tgz#28598250df4899c0ac572d7e2f0460690ba6a030" + integrity sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q== + dependencies: + atomic-sleep "^1.0.0" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@^0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split2@^4.0.0, split2@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + +"statuses@>= 1.5.0 < 2", statuses@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +statuses@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== + +std-env@^3.9.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== + +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +strip-json-comments@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf" + integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw== + +strip-literal@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-3.1.0.tgz#222b243dd2d49c0bcd0de8906adbd84177196032" + integrity sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg== + dependencies: + js-tokens "^9.0.1" + +strnum@^2.2.0, strnum@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.3.tgz#0119fce02749a11bb126a4d686ac5dbdf6e57586" + integrity sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg== + +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +systeminformation@5.23.8: + version "5.23.8" + resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.23.8.tgz#b8efa73b36221cbcb432e3fe83dc1878a43f986a" + integrity sha512-Osd24mNKe6jr/YoXLLK3k8TMdzaxDffhpCxgkfgBHcapykIkd50HXThM3TCEuHO2pPuCsSx2ms/SunqhU5MmsQ== + +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +tdigest@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced" + integrity sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA== + dependencies: + bintrees "1.0.2" + +teeny-request@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-9.0.0.tgz#18140de2eb6595771b1b02203312dfad79a4716d" + integrity sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g== + dependencies: + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.9" + stream-events "^1.0.5" + uuid "^9.0.0" + +thread-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== + dependencies: + real-require "^0.2.0" + +tinybench@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.14, tinyglobby@^0.2.15: + version "0.2.16" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6" + integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +tinypool@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.1.1.tgz#059f2d042bd37567fbc017d3d426bdd2a2612591" + integrity sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg== + +tinyrainbow@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" + integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== + +tinyspy@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-4.0.4.tgz#d77a002fb53a88aa1429b419c1c92492e0c81f78" + integrity sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q== + +toidentifier@1.0.1, toidentifier@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-command-line-args@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +tslib@^2.4.0, tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsscmp@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== + +tsx@^4.20.6: + version "4.21.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.21.0.tgz#32aa6cf17481e336f756195e6fe04dae3e6308b1" + integrity sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw== + dependencies: + esbuild "~0.27.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + +type-is@^1.6.16, type-is@^1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.19.0: + version "7.19.2" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.19.2.tgz#1b67fc26d0f157a0cba3a58a5b5c1e2276b8ba2a" + integrity sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg== + +undici@^5.28.5: + version "5.29.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3" + integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg== + dependencies: + "@fastify/busboy" "^2.0.0" + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.0.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuid@^9.0.0, uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +vary@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +"viem@npm:@aztec/viem@2.38.2": + version "2.38.2" + resolved "https://registry.yarnpkg.com/@aztec/viem/-/viem-2.38.2.tgz#9c626b46569cce1f30f08f7be23fb73846aea520" + integrity sha512-q975q5/On5DSTQDJb0yu0AewnCPIckP4EHp2XOx1GrRn0yJd3TdOKVwuH7HjWtyvh3moFaPogBSHnp7bj4GpdQ== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.1.0" + isows "1.0.7" + ox "0.9.6" + ws "8.18.3" + +vite-node@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.2.4.tgz#f3676d94c4af1e76898c162c92728bca65f7bb07" + integrity sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg== + dependencies: + cac "^6.7.14" + debug "^4.4.1" + es-module-lexer "^1.7.0" + pathe "^2.0.3" + vite "^5.0.0 || ^6.0.0 || ^7.0.0-0" + +"vite@^5.0.0 || ^6.0.0 || ^7.0.0-0": + version "7.3.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.2.tgz#cb041794d4c1395e28baea98198fd6e8f4b96b5c" + integrity sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg== + dependencies: + esbuild "^0.27.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^3.0.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.2.4.tgz#0637b903ad79d1539a25bc34c0ed54b5c67702ea" + integrity sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A== + dependencies: + "@types/chai" "^5.2.2" + "@vitest/expect" "3.2.4" + "@vitest/mocker" "3.2.4" + "@vitest/pretty-format" "^3.2.4" + "@vitest/runner" "3.2.4" + "@vitest/snapshot" "3.2.4" + "@vitest/spy" "3.2.4" + "@vitest/utils" "3.2.4" + chai "^5.2.0" + debug "^4.4.1" + expect-type "^1.2.1" + magic-string "^0.30.17" + pathe "^2.0.3" + picomatch "^4.0.2" + std-env "^3.9.0" + tinybench "^2.9.0" + tinyexec "^0.3.2" + tinyglobby "^0.2.14" + tinypool "^1.1.1" + tinyrainbow "^2.0.0" + vite "^5.0.0 || ^6.0.0 || ^7.0.0-0" + vite-node "3.2.4" + why-is-node-running "^2.3.0" + +weak-lru-cache@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz#fdbb6741f36bae9540d12f480ce8254060dccd19" + integrity sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@8.18.3: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +ws@^8.13.0: + version "8.20.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8" + integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA== + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@~17.7.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +ylru@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.4.0.tgz#0cf0aa57e9c24f8a2cbde0cc1ca2c9592ac4e0f6" + integrity sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@^3.23.8: + version "3.25.76" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From b67108e85d122ae821ba9bbb93f096162b6f05a1 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 10:06:13 -0400 Subject: [PATCH 02/11] Update zkemail dependency to use Aztec v4.2.0 compatibility --- zkemail_verification/circuit/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkemail_verification/circuit/Nargo.toml b/zkemail_verification/circuit/Nargo.toml index 29c4306..0c0162e 100644 --- a/zkemail_verification/circuit/Nargo.toml +++ b/zkemail_verification/circuit/Nargo.toml @@ -5,5 +5,5 @@ authors = [""] compiler_version = ">=1.0.0" [dependencies] -zkemail = { path = "/workspaces/sandbox/zkemail.nr/lib" } +zkemail = { tag = "update/aztec-4.2.0-compat", git = "https://github.com/critesjosh/zkemail.nr", directory = "lib" } sha256 = { git = "https://github.com/noir-lang/sha256", tag = "v0.3.0" } From ad2fab228d10a3e759ad71bd435a42b4128db6b0 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 10:16:34 -0400 Subject: [PATCH 03/11] Add ZKEmail testnet verification workflow and update README with deployment details --- .github/workflows/zkemail-testnet.yml | 95 +++++++++++++++++++++++++++ zkemail_verification/README.md | 10 +-- 2 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/zkemail-testnet.yml diff --git a/.github/workflows/zkemail-testnet.yml b/.github/workflows/zkemail-testnet.yml new file mode 100644 index 0000000..0c19ca4 --- /dev/null +++ b/.github/workflows/zkemail-testnet.yml @@ -0,0 +1,95 @@ +name: ZKEmail Testnet Verification + +on: + push: + branches: + - next + pull_request: + branches: + - next + paths: + - "zkemail_verification/**" + - ".github/workflows/zkemail-testnet.yml" + workflow_dispatch: + +jobs: + zkemail-testnet: + name: ZKEmail Proof Verification on Testnet + runs-on: ubuntu-latest + env: + AZTEC_VERSION: 4.2.0-aztecnr-rc.2 + TESTNET_URL: https://rpc.testnet.aztec-labs.com + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: "yarn" + cache-dependency-path: zkemail_verification/yarn.lock + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Install Aztec CLI + run: | + INSTALL_URL="https://install.aztec.network/${{ env.AZTEC_VERSION }}/" + curl -sL $INSTALL_URL > tmp.sh + VERSION=${{ env.AZTEC_VERSION }} bash tmp.sh <<< yes "yes" + + - name: Update path + run: | + echo "$HOME/.aztec/current/bin" >> $GITHUB_PATH + echo "$HOME/.aztec/current/node_modules/.bin" >> $GITHUB_PATH + echo "$HOME/.aztec/bin" >> $GITHUB_PATH + + - name: Install project dependencies + working-directory: zkemail_verification + run: yarn install --frozen-lockfile + + - name: Compile Noir circuit + working-directory: zkemail_verification/circuit + run: nargo compile + timeout-minutes: 10 + + - name: Change ownership for nargo files + run: sudo chown -R $(whoami) ~/nargo || true + + - name: Compile contract and generate artifacts + working-directory: zkemail_verification + run: | + ulimit -s unlimited + script -e -c "yarn ccc" + timeout-minutes: 15 + + - name: Generate proof data + working-directory: zkemail_verification + env: + BB_SINGLE_THREADED: "1" + HARDWARE_CONCURRENCY: "1" + NODE_OPTIONS: "--max-old-space-size=6144" + run: yarn data + timeout-minutes: 30 + + - name: Check testnet is reachable + run: | + echo "Checking testnet status..." + curl -sf ${{ env.TESTNET_URL }}/status || (echo "Testnet unreachable" && exit 1) + echo "Testnet is reachable" + + - name: Deploy and verify on testnet + working-directory: zkemail_verification + run: yarn testnet + timeout-minutes: 20 + + - name: Upload proof data on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: zkemail-testnet-logs + path: | + zkemail_verification/data.json + retention-days: 7 diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index 875afde..8237cd2 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -21,11 +21,11 @@ Successfully deployed and verified on the Aztec testnet (`https://rpc.testnet.az | Step | Transaction Hash | |------|-----------------| -| Account deployment | `0x190a55042b4a4bd063150c0b1d2a233c07e8b4b7decb3ba57e2527c646acd2be` | -| Contract deployment | `0x258f5c271e67ce681cf7db8641984d78d6e7718268d6cb4b9897d8ac624709bc` | -| Email proof verification | `0x2c053bad6f58bfcdea0b2bc4b918e0e31bb3d38aed740ac836e227cd5b7bca4e` | +| Account deployment | `0x11507f85ba674c2f47bb5bd71a6a039a43006bc44f84e835a0179b820d644eef` | +| Contract deployment | `0x08cc244ad4363930ec56e273881c29748aeeb8cce6a710457a43811f379c9fd6` | +| Email proof verification | `0x175b215e2c3bf3450c13f4494e9a099a2b2bad7eea0c9e55e659e38c65ae530b` | -**Contract address**: `0x1bbf99d2acd54c9dc9ef58fd05892fec9d5916fa66949aead6877964879a142b` +**Contract address**: `0x0f96d7850491bfe2983fb9cb7b4a77b843ad18fbfe763e776a79e2ec11cacf9f` ## How It Works @@ -180,7 +180,7 @@ Ensure the circuit was compiled with `nargo compile` after any changes, then re- ## Dependencies -- [zkemail.nr](https://github.com/zkemail/zkemail.nr) — Noir library for DKIM email verification +- [zkemail.nr](https://github.com/critesjosh/zkemail.nr/tree/update/aztec-4.2.0-compat) — Noir library for DKIM email verification (Aztec 4.2.0 branch) - [aztec-nr](https://github.com/AztecProtocol/aztec-nr/) v4.2.0-aztecnr-rc.2 — Aztec smart contract framework - [bb_proof_verification](https://github.com/AztecProtocol/aztec-packages/) — Barretenberg proof verification for Aztec contracts - [@aztec/bb.js](https://www.npmjs.com/package/@aztec/bb.js) 4.2.0-aztecnr-rc.2 — UltraHonk proving backend From 95d39c7e8a668dd69e7d5f7144284090d9be1f91 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 12:31:12 -0400 Subject: [PATCH 04/11] Update ZK email verification with recipient binding, intent binding, nullifier, and freshness checks Rework the circuit and contract from a simple domain-verification demo into a full email-based authorization flow: recipient binding via to-address hash, intent binding via subject hash, single-use nullifiers from the DKIM signature, and timestamp freshness checks. Update README to document the security model, contract API (including view functions), and fix Poseidon2 references. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/README.md | 159 +++++++------ zkemail_verification/circuit/Nargo.toml | 2 +- zkemail_verification/circuit/Prover.toml | 34 +++ zkemail_verification/circuit/src/main.nr | 218 ++++++++++++++---- zkemail_verification/contract/src/main.nr | 85 +++++-- zkemail_verification/scripts/generate_data.ts | 155 ++++++++----- zkemail_verification/scripts/run_testnet.ts | 34 +-- .../scripts/run_verification.ts | 48 ++-- .../tests/zkemail_verification.test.ts | 78 +++++-- 9 files changed, 576 insertions(+), 237 deletions(-) create mode 100644 zkemail_verification/circuit/Prover.toml diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index 8237cd2..7aa6f18 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -1,59 +1,73 @@ -# Verify ZK Email Proofs in Aztec Contracts +# ZK Email Auth for Aztec -Proves that an email was sent from a specific domain (`icloud.com`) using DKIM signature verification in a Noir circuit, then verifies that proof on-chain inside an Aztec private smart contract. +Proves email-based authorization using DKIM signature verification in a Noir circuit, then verifies that proof on-chain inside an Aztec private smart contract. Each email proof binds to a specific recipient, encodes an intent via the subject field, is single-use (nullifier), and must be fresh (timestamp check). -Built to validate the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library's compatibility with Aztec 4.2.0. +Built with the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library on Aztec 4.2.0. -## Overview +## Security Model -This project implements: +The contract enforces four constraints on each email proof: -- **Noir Circuit** (`circuit/`): Verifies a 2048-bit RSA DKIM signature, checks the body hash, extracts the sender address, and asserts the sender domain is `icloud.com`. Returns three public outputs: two public key hashes (root of trust) and an email nullifier. -- **Aztec Contract** (`contract/`): A private smart contract that verifies the Noir proof on-chain using `verify_honk_proof` and tracks a per-user verification count. -- **Proof Generation** (`scripts/generate_data.ts`): Generates an UltraHonk proof from hardcoded test email data and verifies it off-chain before writing `data.json`. -- **On-chain Verification** (`scripts/run_testnet.ts`): Deploys the contract and submits the proof for verification on the Aztec testnet. +1. **Recipient binding** — The email's `to` address must hash to the `authorized_email_hash` stored at deployment. Only emails sent to the account owner's address are accepted. +2. **Intent binding** — The email's `subject` field is hashed and compared against a caller-provided `expected_intent_hash`. This ties the email to a specific action (e.g., a Poseidon hash of calldata placed in the subject). +3. **Single use** — The DKIM signature is hashed into a nullifier and pushed on-chain. Replaying the same email proof fails because the nullifier already exists. +4. **Freshness** — The DKIM `t=` timestamp is extracted and checked in a public function against the block timestamp. Emails older than `max_email_age` seconds are rejected. -**Aztec Version**: `4.2.0-aztecnr-rc.2` (compatible with testnet `4.2.0-rc.1`) +The sender's domain is also verified to be `icloud.com` via DKIM. -## Testnet Deployment +## How It Works -Successfully deployed and verified on the Aztec testnet (`https://rpc.testnet.aztec-labs.com`) with real proofs enabled. +``` + ┌──────────────────────────┐ +Raw Email ──> [Noir Circuit] ──> │ 6 public outputs: │ + │ │ [0] pubkey_hash[0] │ + │ DKIM verify │ [1] pubkey_hash[1] │ + │ from domain │ [2] email_nullifier │──> [Aztec Contract] + │ to address │ [3] to_address_hash │ │ + │ subject │ [4] intent_hash │ │ verify_honk_proof() + │ timestamp │ [5] dkim_timestamp │ │ check recipient + │ └──────────────────────────┘ │ check intent + │ │ push nullifier + │ Body verification omitted — │ check freshness + │ all auth data is in DKIM-signed headers, │ + │ avoiding extra SHA256 hashing cost │ +``` -| Step | Transaction Hash | -|------|-----------------| -| Account deployment | `0x11507f85ba674c2f47bb5bd71a6a039a43006bc44f84e835a0179b820d644eef` | -| Contract deployment | `0x08cc244ad4363930ec56e273881c29748aeeb8cce6a710457a43811f379c9fd6` | -| Email proof verification | `0x175b215e2c3bf3450c13f4494e9a099a2b2bad7eea0c9e55e659e38c65ae530b` | +### Circuit (`circuit/src/main.nr`) -**Contract address**: `0x0f96d7850491bfe2983fb9cb7b4a77b843ad18fbfe763e776a79e2ec11cacf9f` +Uses [zkemail.nr](https://github.com/zkemail/zkemail.nr) to: +- Verify the 2048-bit RSA DKIM signature over the email header +- Extract and verify the sender domain is `icloud.com` +- Extract the `to` address and output its Poseidon2 hash (identity binding) +- Extract the `subject` field and output its Poseidon2 hash (intent binding) +- Parse the `t=` tag from the DKIM-Signature header (timestamp for freshness) +- Output a Poseidon2 hash of the DKIM signature as an email nullifier (replay prevention) -## How It Works +Body verification is omitted since all authorization-relevant data lives in the DKIM-signed headers. This avoids the ~114K constraint SHA256 body hash computation. -``` -Raw Email ──> [Noir Circuit] ──> UltraHonk Proof ──> [Aztec Contract] ──> On-chain Verification - │ │ - │ DKIM verify │ verify_honk_proof() - │ Body hash check │ Increment counter - │ Domain = icloud.com │ - │ │ - └──> 3 public outputs: └──> VK hash stored in - pubkey_hash[0] PublicImmutable storage - pubkey_hash[1] - email_nullifier -``` +### Contract (`contract/src/main.nr`) + +- `constructor(vk_hash, authorized_email_hash, max_email_age)` — Stores the verification key hash, the Poseidon2 hash of the authorized recipient email, and the maximum email age in seconds. +- `verify_email(expected_intent_hash, vk, proof, public_inputs)` — **Private function** that: + 1. Verifies the UltraHonk proof against the stored VK hash + 2. Asserts `public_inputs[3]` (to address hash) matches `authorized_email_hash` + 3. Asserts `public_inputs[4]` (subject hash) matches `expected_intent_hash` + 4. Pushes `public_inputs[2]` (email nullifier) to prevent replay + 5. Enqueues a public call to check `public_inputs[5]` (timestamp) is fresh +- `_check_email_freshness(email_timestamp, max_age)` — **Public function** that checks `block.timestamp - email_timestamp <= max_age` +- `get_authorized_email_hash()` — **View function** that returns the stored authorized email hash +- `get_max_email_age()` — **View function** that returns the stored maximum email age -1. The **inner circuit** (`circuit/src/main.nr`) uses the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library to: - - Verify the DKIM RSA signature over the email header - - Extract and verify the body hash from the DKIM-Signature header against a SHA256 hash of the body - - Extract the sender email address from the `From:` header - - Assert the sender domain is `icloud.com` - - Output the public key hash (Poseidon), redc parameter hash, and email nullifier (Pedersen) +### Intent Encoding -2. An **UltraHonk proof** is generated off-chain using Barretenberg (`@aztec/bb.js`), then verified off-chain to confirm validity. +The email subject serves as the intent field. For this example, the subject is hashed with Poseidon2 inside the circuit and output as `intent_hash`. To authorize an action: -3. The **Aztec contract** (`contract/src/main.nr`) calls `verify_honk_proof(vk, proof, public_inputs, vk_hash)` inside a private function. The VK hash is stored at deployment to bind the contract to the specific circuit. On successful verification, a public counter is incremented. +1. Compute `intent_hash = Poseidon2(pack_31(subject_bytes) ++ [subject_length])` off-chain +2. Include the intent text as the email subject (e.g., a Poseidon hash of the calldata encoded as a string) +3. The circuit hashes the subject and outputs it +4. The contract verifies the proof's `intent_hash` matches the caller's `expected_intent_hash` -4. With `proverEnabled: true`, the PXE generates real ClientIVC proofs that enforce the `verify_honk_proof` constraint during private kernel execution — the inner proof is cryptographically verified, not skipped. +For a production system, the subject would contain a Poseidon hash of the calldata — easier to parse in-circuit than ASCII text and supports arbitrary call data encoding. ## Prerequisites @@ -74,10 +88,10 @@ nargo --version # 1.0.0-beta.18 ``` . ├── circuit/ # Inner Noir circuit (vanilla bin, not Aztec contract) -│ ├── src/main.nr # DKIM verify + domain check + public outputs -│ └── Nargo.toml # Depends on zkemail.nr and sha256 +│ ├── src/main.nr # DKIM verify + address/subject/timestamp extraction +│ └── Nargo.toml # Depends on zkemail.nr ├── contract/ # Aztec smart contract -│ ├── src/main.nr # verify_honk_proof + counter storage +│ ├── src/main.nr # verify_honk_proof + nullifier + timestamp check │ ├── artifacts/ # Generated TypeScript bindings │ └── Nargo.toml # Depends on aztec-nr and bb_proof_verification ├── scripts/ @@ -109,12 +123,6 @@ yarn ccc yarn data ``` -### Deploy to Testnet - -```bash -yarn testnet -``` - ### Deploy to Local Network ```bash @@ -128,41 +136,42 @@ yarn verify yarn test ``` +### Deploy to Testnet + +```bash +yarn testnet +``` + ## Scripts | Command | Description | |---------|-------------| | `yarn ccc` | Compile Aztec contract + generate TypeScript bindings | | `yarn data` | Generate UltraHonk proof from test email data, verify off-chain, write `data.json` | -| `yarn testnet` | Deploy contract and verify proof on the Aztec testnet | | `yarn verify` | Deploy contract and verify proof on local network | +| `yarn testnet` | Deploy contract and verify proof on the Aztec testnet | | `yarn test` | Run Vitest integration tests against local network | ## Circuit Details -The inner circuit verifies a DKIM-signed email from `icloud.com` using ~222K constraints: +The inner circuit verifies a DKIM-signed email from `icloud.com` and extracts auth data from the headers: -| Component | Constraints | Description | -|-----------|------------|-------------| -| DKIM signature verification | ~86,500 | RSA-2048 PKCS#1 v1.5 over SHA256 header hash | -| Body hash (SHA256) | ~114,000 | SHA256 over email body, compared to DKIM `bh=` field | -| Address extraction | ~16,000 | Extract and validate `From:` email address | -| Domain check | ~100 | Assert domain bytes match `icloud.com` | -| Key + nullifier hashing | ~10,200 | Poseidon hash of pubkey, Pedersen hash of signature | +| Component | Description | +|-----------|-------------| +| DKIM signature verification | RSA-2048 PKCS#1 v1.5 over SHA256 header hash | +| From address extraction | Extract sender email and verify domain is `icloud.com` | +| To address hashing | Extract recipient email, Poseidon2 hash for identity binding | +| Subject hashing | Extract subject field, Poseidon2 hash for intent binding | +| Timestamp extraction | Parse `t=` tag from DKIM-Signature for freshness check | +| Nullifier computation | Poseidon2 hash of DKIM signature for replay prevention | -**Public outputs** (3 fields): +**Public outputs** (6 fields): - `pubkey_hash[0]` — Poseidon hash of RSA modulus (root of trust) - `pubkey_hash[1]` — Poseidon hash of RSA redc parameter -- `email_nullifier` — Pedersen hash of DKIM signature (prevents double-use) - -## Contract Details - -The `ZKEmailVerifier` contract stores a verification key hash at deployment and exposes: - -- `verify_email(owner, vk, proof, public_inputs)` — **private function** that verifies the UltraHonk proof and enqueues a public state update -- `get_verification_count(owner)` — **public view** that returns how many emails have been verified for an address - -The contract uses the hybrid private/public execution pattern: proof verification happens privately (the email content is never revealed on-chain), while the verification count is updated publicly. +- `email_nullifier` — Poseidon2 hash of DKIM signature (prevents replay) +- `to_address_hash` — Poseidon2 hash of recipient email (identity binding) +- `intent_hash` — Poseidon2 hash of subject content (intent binding) +- `dkim_timestamp` — DKIM signing timestamp in seconds (freshness) ## Troubleshooting @@ -172,15 +181,19 @@ Run `yarn ccc` to compile the contract and generate TypeScript bindings. **"Cannot find module '../data.json'"** Run `yarn data` to generate the proof data. -**"Failed to connect" on testnet** -Check testnet status: `curl https://rpc.testnet.aztec-labs.com/status` +**"Email recipient does not match authorized address"** +The `to` address in the email doesn't match the `authorized_email_hash` stored at deployment. Ensure the proof was generated with the correct test email. + +**"Email has expired"** +The DKIM timestamp is older than `max_email_age`. For testing with the hardcoded test email (April 2024), use a large `max_email_age` value. -**Proof verification fails off-chain** -Ensure the circuit was compiled with `nargo compile` after any changes, then re-run `yarn data`. +**"Duplicate nullifier"** +The same email proof has already been used. Each email can only authorize one action. ## Dependencies - [zkemail.nr](https://github.com/critesjosh/zkemail.nr/tree/update/aztec-4.2.0-compat) — Noir library for DKIM email verification (Aztec 4.2.0 branch) +- [poseidon](https://github.com/noir-lang/poseidon) v0.2.0 — Poseidon2 hash function for Noir - [aztec-nr](https://github.com/AztecProtocol/aztec-nr/) v4.2.0-aztecnr-rc.2 — Aztec smart contract framework - [bb_proof_verification](https://github.com/AztecProtocol/aztec-packages/) — Barretenberg proof verification for Aztec contracts - [@aztec/bb.js](https://www.npmjs.com/package/@aztec/bb.js) 4.2.0-aztecnr-rc.2 — UltraHonk proving backend diff --git a/zkemail_verification/circuit/Nargo.toml b/zkemail_verification/circuit/Nargo.toml index 0c0162e..d86553a 100644 --- a/zkemail_verification/circuit/Nargo.toml +++ b/zkemail_verification/circuit/Nargo.toml @@ -6,4 +6,4 @@ compiler_version = ">=1.0.0" [dependencies] zkemail = { tag = "update/aztec-4.2.0-compat", git = "https://github.com/critesjosh/zkemail.nr", directory = "lib" } -sha256 = { git = "https://github.com/noir-lang/sha256", tag = "v0.3.0" } +poseidon = { tag = "v0.2.0", git = "https://github.com/noir-lang/poseidon" } diff --git a/zkemail_verification/circuit/Prover.toml b/zkemail_verification/circuit/Prover.toml new file mode 100644 index 0000000..8dc2c6a --- /dev/null +++ b/zkemail_verification/circuit/Prover.toml @@ -0,0 +1,34 @@ +dkim_timestamp_index = "" +signature = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""] + +[dkim_header_sequence] +index = "" +length = "" + +[from_address_sequence] +index = "" +length = "" + +[from_header_sequence] +index = "" +length = "" + +[header] +len = "" +storage = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""] + +[pubkey] +modulus = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""] +redc = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""] + +[subject_header_sequence] +index = "" +length = "" + +[to_address_sequence] +index = "" +length = "" + +[to_header_sequence] +index = "" +length = "" diff --git a/zkemail_verification/circuit/src/main.nr b/zkemail_verification/circuit/src/main.nr index 6c6a75b..f422d92 100644 --- a/zkemail_verification/circuit/src/main.nr +++ b/zkemail_verification/circuit/src/main.nr @@ -1,77 +1,217 @@ -use sha256::sha256_var; -use std::{collections::bounded_vec::BoundedVec, hash::pedersen_hash}; +use std::collections::bounded_vec::BoundedVec; +use poseidon::poseidon2::Poseidon2; use zkemail::{ - dkim::RSAPubkey, headers::body_hash::get_body_hash, - headers::email_address::get_email_address, KEY_LIMBS_2048, MAX_EMAIL_ADDRESS_LENGTH, Sequence, + dkim::RSAPubkey, headers::email_address::get_email_address, KEY_LIMBS_2048, + MAX_EMAIL_ADDRESS_LENGTH, Sequence, }; global MAX_EMAIL_HEADER_LENGTH: u32 = 512; -global MAX_EMAIL_BODY_LENGTH: u32 = 1024; +global MAX_SUBJECT_LENGTH: u32 = 128; +global MAX_TIMESTAMP_DIGITS: u32 = 10; global EXPECTED_DOMAIN: [u8; 10] = comptime { "icloud.com".as_bytes() }; -/// Verify a DKIM-signed email from the icloud.com domain +/// Verify a DKIM-signed email and extract authentication data. +/// +/// Proves: sender is from icloud.com, recipient matches, subject encodes intent, +/// email is timestamped, and provides a nullifier to prevent reuse. +/// +/// Body verification is omitted -- all auth-relevant data is in DKIM-signed headers, +/// avoiding the extra SHA256 hashing cost of body verification. /// /// Returns: -/// [0]: Poseidon hash of DKIM public key modulus +/// [0]: Poseidon hash of DKIM public key modulus (root of trust) /// [1]: Poseidon hash of DKIM public key redc parameter -/// [2]: Pedersen hash of DKIM signature (email nullifier) +/// [2]: Email nullifier (Poseidon2 hash of DKIM signature -- prevents replay) +/// [3]: Poseidon2 hash of recipient (to) email address (identity binding) +/// [4]: Poseidon2 hash of email subject (intent binding) +/// [5]: DKIM signing timestamp in seconds since epoch (freshness) fn main( header: BoundedVec, - body: BoundedVec, pubkey: RSAPubkey, signature: [Field; KEY_LIMBS_2048], - body_hash_index: u32, dkim_header_sequence: Sequence, from_header_sequence: Sequence, from_address_sequence: Sequence, -) -> pub [Field; 3] { + to_header_sequence: Sequence, + to_address_sequence: Sequence, + subject_header_sequence: Sequence, + dkim_timestamp_index: u32, +) -> pub [Field; 6] { assert(header.len() <= MAX_EMAIL_HEADER_LENGTH); - assert(body.len() <= MAX_EMAIL_BODY_LENGTH); - // Verify the DKIM signature over the header - pubkey.verify_dkim_signature(header, signature); + // 1. Verify the DKIM signature over the email header + let _ = pubkey.verify_dkim_signature(header, signature); - // Extract the body hash from the DKIM-Signature header and verify against computed body hash - let signed_body_hash = get_body_hash(header, dkim_header_sequence, body_hash_index); - let computed_body_hash: [u8; 32] = sha256_var(body.storage(), body.len() as u32); - assert( - signed_body_hash == computed_body_hash, - "SHA256 hash computed over body does not match body hash found in DKIM-signed header", + // 2. Extract and verify the sender's domain is icloud.com + let from_address: BoundedVec = get_email_address( + header, + from_header_sequence, + from_address_sequence, + comptime { "from".as_bytes() }, ); + verify_domain(from_address, EXPECTED_DOMAIN); - // Extract the from email address - let from_field_name = comptime { "from".as_bytes() }; - let from_address: BoundedVec = - get_email_address(header, from_header_sequence, from_address_sequence, from_field_name); + // 3. Extract recipient (to) address and hash for identity binding + let to_address: BoundedVec = get_email_address( + header, + to_header_sequence, + to_address_sequence, + comptime { "to".as_bytes() }, + ); + let to_address_hash = hash_address(to_address); - // Find the '@' in the from address and verify the domain matches "icloud.com" + // 4. Extract subject and hash for intent binding + let intent_hash = extract_and_hash_subject(header, subject_header_sequence); + + // 5. Parse the DKIM signing timestamp (t= tag) for freshness checks + let timestamp = extract_dkim_timestamp(header, dkim_header_sequence, dkim_timestamp_index); + + // 6. Compute email nullifier and public key hash + let email_nullifier = Poseidon2::hash(signature, KEY_LIMBS_2048); + let pubkey_hash = pubkey.hash(); + + [pubkey_hash[0], pubkey_hash[1], email_nullifier, to_address_hash, intent_hash, timestamp] +} + +/// Verify the domain part of an email address matches the expected domain. +fn verify_domain( + address: BoundedVec, + expected_domain: [u8; DOMAIN_LEN], +) { let mut at_index: u32 = 0; let mut found_at = false; for i in 0..MAX_EMAIL_ADDRESS_LENGTH { - if i < from_address.len() { - if from_address.get_unchecked(i) == 64 { + if i < address.len() { + if address.get_unchecked(i) == 64 { + // '@' at_index = i + 1; found_at = true; } } } - assert(found_at, "No @ symbol found in from address"); + assert(found_at, "No @ symbol found in email address"); - // Check the domain length matches - let domain_len = from_address.len() - at_index; - assert(domain_len == 10, "Domain length does not match icloud.com"); + let domain_len = address.len() - at_index; + assert(domain_len == DOMAIN_LEN as u32, "Domain length mismatch"); + for i in 0..DOMAIN_LEN { + assert( + address.get_unchecked(at_index + i) == expected_domain[i], + "Email domain does not match expected", + ); + } +} + +/// Hash an email address deterministically using Poseidon2 over packed 31-byte fields. +/// +/// Packs address bytes big-endian into ceil(320/31)=11 Field elements, appends length. +fn hash_address(address: BoundedVec) -> Field { + // ceil(320/31) = 11 packed fields + 1 length field + let mut packed: [Field; 12] = [0; 12]; + for i in 0..MAX_EMAIL_ADDRESS_LENGTH { + if i < address.len() { + let field_idx = i / 31; + packed[field_idx] = packed[field_idx] * 256 + address.get_unchecked(i) as Field; + } + } + packed[11] = address.len() as Field; + Poseidon2::hash(packed, 12) +} - // Check each byte of the domain - for i in 0..10 { +/// Extract and validate the subject header field, then hash its value for intent binding. +/// +/// Validates the "subject:" prefix and CRLF boundaries to prevent header injection. +/// Hashes subject value bytes (after prefix) using Poseidon2 over packed fields. +fn extract_and_hash_subject( + header: BoundedVec, + subject_sequence: Sequence, +) -> Field { + // Validate "subject:" prefix + let prefix: [u8; 8] = comptime { "subject:".as_bytes() }; + for i in 0..8 { assert( - from_address.get_unchecked(at_index + i) == EXPECTED_DOMAIN[i], - "Email domain does not match icloud.com", + header.get_unchecked(subject_sequence.index + i) == prefix[i], + "Invalid subject header prefix", ); } - // Compute standard outputs - let email_nullifier = pedersen_hash(signature); - let pubkey_hash = pubkey.hash(); - [pubkey_hash[0], pubkey_hash[1], email_nullifier] + // Validate CRLF boundary before field (or start of header) + if subject_sequence.index > 0 { + assert( + header.get_unchecked(subject_sequence.index - 1) == 10, // LF + "Subject field must follow a line feed", + ); + } + + // Validate CR after field (start of CRLF terminator) + let end_idx = subject_sequence.index + subject_sequence.length; + assert(end_idx < header.len(), "Subject extends past header"); + assert( + header.get_unchecked(end_idx) == 13, // CR + "Subject field must end before carriage return", + ); + + // Extract subject value bytes (after "subject:" prefix) + let value_start = subject_sequence.index + 8; + let value_len = subject_sequence.length - 8; + assert(value_len <= MAX_SUBJECT_LENGTH, "Subject too long"); + + // Hash subject value: pack into ceil(128/31)=5 fields + 1 length field + let mut packed: [Field; 6] = [0; 6]; + for i in 0..MAX_SUBJECT_LENGTH { + if i < value_len { + let field_idx = i / 31; + packed[field_idx] = packed[field_idx] * 256 + + header.get_unchecked(value_start + i) as Field; + } + } + packed[5] = value_len as Field; + Poseidon2::hash(packed, 6) } +/// Extract the DKIM signing timestamp from the t= tag in the DKIM-Signature header. +/// +/// The prover supplies the index of the first timestamp digit. The circuit verifies +/// the "t=" prefix and parses the decimal value. This timestamp represents when the +/// mail server signed the email. +fn extract_dkim_timestamp( + header: BoundedVec, + dkim_sequence: Sequence, + timestamp_index: u32, +) -> Field { + // Verify timestamp_index falls within the DKIM header field + assert( + timestamp_index >= dkim_sequence.index + 2, + "Timestamp index too early in DKIM header", + ); + assert( + timestamp_index + MAX_TIMESTAMP_DIGITS <= header.len(), + "Not enough header bytes for timestamp digits", + ); + + // Verify "t=" prefix immediately before the digits + assert( + header.get_unchecked(timestamp_index - 2) == 116, // 't' + "Expected 't' before timestamp value", + ); + assert( + header.get_unchecked(timestamp_index - 1) == 61, // '=' + "Expected '=' before timestamp value", + ); + + // Parse decimal digits until non-digit (';' or end of header field) + let mut timestamp: Field = 0; + let mut done = false; + for i in 0..MAX_TIMESTAMP_DIGITS { + if !done { + let byte = header.get_unchecked(timestamp_index + i); + if (byte >= 48) & (byte <= 57) { + // '0'-'9' + timestamp = timestamp * 10 + (byte - 48) as Field; + } else { + done = true; + } + } + } + + timestamp +} diff --git a/zkemail_verification/contract/src/main.nr b/zkemail_verification/contract/src/main.nr index 3000bc3..7760a4f 100644 --- a/zkemail_verification/contract/src/main.nr +++ b/zkemail_verification/contract/src/main.nr @@ -5,47 +5,104 @@ pub contract ZKEmailVerifier { use aztec::{ macros::{functions::{external, initializer, only_self, view}, storage::storage}, oracle::logging::debug_log_format, - protocol::{address::AztecAddress, traits::ToField}, - state_vars::{Map, PublicImmutable, PublicMutable}, + state_vars::PublicImmutable, }; use bb_proof_verification::{UltraHonkVerificationKey, UltraHonkZKProof, verify_honk_proof}; #[storage] struct Storage { - verification_count: Map, Context>, vk_hash: PublicImmutable, + /// Pedersen hash of the authorized recipient email address. + /// Only emails sent TO this address can authorize actions. + authorized_email_hash: PublicImmutable, + /// Maximum allowed age of an email in seconds. + /// Emails older than this (based on DKIM signing timestamp) are rejected. + max_email_age: PublicImmutable, } #[initializer] #[external("public")] - fn constructor(owner: AztecAddress, vk_hash: Field) { - self.storage.verification_count.at(owner).write(0); + fn constructor(vk_hash: Field, authorized_email_hash: Field, max_email_age: Field) { self.storage.vk_hash.initialize(vk_hash); + self.storage.authorized_email_hash.initialize(authorized_email_hash); + self.storage.max_email_age.initialize(max_email_age); } + /// Verify an email proof and authorize an intent. + /// + /// The caller provides an expected_intent_hash which must match the hash of + /// the email's subject field (public_inputs[4]). This binds the email to a + /// specific action. + /// + /// Public inputs layout from the circuit: + /// [0]: pubkey_hash[0] -- DKIM key identity + /// [1]: pubkey_hash[1] -- DKIM key identity + /// [2]: email_nullifier -- prevents email reuse + /// [3]: to_address_hash -- must match authorized_email_hash + /// [4]: intent_hash -- hash of email subject (action being authorized) + /// [5]: dkim_timestamp -- when the email was signed #[external("private")] fn verify_email( - owner: AztecAddress, + expected_intent_hash: Field, verification_key: UltraHonkVerificationKey, proof: UltraHonkZKProof, - public_inputs: [Field; 3], + public_inputs: [Field; 6], ) { - debug_log_format("Verifying email proof for owner {0}", [owner.to_field()]); + debug_log_format("Verifying email proof...", []); + + // Verify the ZK proof against the stored verification key hash let vk_hash = self.storage.vk_hash.read(); verify_honk_proof(verification_key, proof, public_inputs, vk_hash); - self.enqueue_self._increment_verification_count(owner); + + // Verify the email was sent to the authorized address + let authorized_email_hash = self.storage.authorized_email_hash.read(); + assert( + public_inputs[3] == authorized_email_hash, + "Email recipient does not match authorized address", + ); + + // Verify the intent matches what the caller expects + assert( + public_inputs[4] == expected_intent_hash, + "Email subject does not match expected intent", + ); + + // Push the email nullifier to prevent reuse of this email proof. + // The nullifier is automatically siloed by the contract address. + // If this nullifier has already been emitted, the transaction will fail. + self.context.push_nullifier(public_inputs[2]); + + // Enqueue a public call to verify the email timestamp is fresh enough. + // This must be checked in public context where the block timestamp is available. + let max_email_age = self.storage.max_email_age.read(); + self.enqueue_self._check_email_freshness(public_inputs[5], max_email_age); } + /// Public function to verify the email's DKIM timestamp is recent enough. + /// Called via enqueue from the private verify_email function. #[only_self] #[external("public")] - fn _increment_verification_count(owner: AztecAddress) { - let current = self.storage.verification_count.at(owner).read(); - self.storage.verification_count.at(owner).write(current + 1); + fn _check_email_freshness(email_timestamp: Field, max_age: Field) { + let current_ts: u64 = self.context.timestamp(); + let email_ts: u64 = email_timestamp as u64; + let max_age_secs: u64 = max_age as u64; + + assert(current_ts >= email_ts, "Email timestamp is in the future"); + assert( + current_ts - email_ts <= max_age_secs, + "Email has expired -- DKIM timestamp is too old", + ); + } + + #[view] + #[external("public")] + fn get_authorized_email_hash() -> Field { + self.storage.authorized_email_hash.read() } #[view] #[external("public")] - fn get_verification_count(owner: AztecAddress) -> Field { - self.storage.verification_count.at(owner).read() + fn get_max_email_age() -> Field { + self.storage.max_email_age.read() } } diff --git a/zkemail_verification/scripts/generate_data.ts b/zkemail_verification/scripts/generate_data.ts index 422f8ae..69178f7 100644 --- a/zkemail_verification/scripts/generate_data.ts +++ b/zkemail_verification/scripts/generate_data.ts @@ -7,6 +7,9 @@ import { exit } from 'process'; // ============================================================================= // Test data from zkemail.nr/lib/src/tests/test_inputs.nr (EmailLarge module) // Email from: runnier.leagues.0j@icloud.com +// Email to: zkewtest@gmail.com +// Subject: Bitcoin +// DKIM timestamp: 1712141644 // ============================================================================= const HEADER_BYTES = [ @@ -35,47 +38,6 @@ const HEADER_BYTES = [ 103, 101, 45, 73, 100, 58, 68, 97, 116, 101, 58, 116, 111, 59, 32, 98, 61, ]; -const BODY_BYTES = [ - 84, 104, 101, 32, 84, 105, 109, 101, 115, 32, 48, 51, 47, 74, 97, 110, 47, 50, 48, 48, 57, - 32, 67, 104, 97, 110, 99, 101, 108, 108, 111, 114, 32, 111, 110, 32, 98, 114, 105, 110, 107, - 32, 111, 102, 32, 115, 101, 99, 111, 110, 100, 32, 98, 97, 105, 108, 111, 117, 116, 32, 102, - 111, 114, 32, 98, 97, 110, 107, 115, 13, 10, 13, 10, 49, 53, 32, 121, 101, 97, 114, 115, 32, - 97, 103, 111, 44, 32, 83, 97, 116, 111, 115, 104, 105, 32, 109, 105, 110, 101, 100, 32, 116, - 104, 101, 32, 102, 105, 114, 115, 116, 32, 98, 108, 111, 99, 107, 32, 111, 102, 32, 116, - 104, 101, 32, 66, 105, 116, 99, 111, 105, 110, 32, 98, 108, 111, 99, 107, 99, 104, 97, 105, - 110, 32, 61, 13, 10, 65, 102, 116, 101, 114, 32, 116, 104, 101, 32, 66, 105, 116, 99, 111, - 105, 110, 32, 119, 104, 105, 116, 101, 32, 112, 97, 112, 101, 114, 32, 97, 112, 112, 101, - 97, 114, 101, 100, 32, 111, 110, 32, 79, 99, 116, 111, 98, 101, 114, 32, 51, 49, 44, 32, 50, - 48, 48, 56, 44, 32, 111, 110, 32, 97, 32, 61, 13, 10, 99, 114, 121, 112, 116, 111, 103, 114, - 97, 112, 104, 121, 32, 109, 97, 105, 108, 105, 110, 103, 32, 108, 105, 115, 116, 44, 32, - 116, 104, 101, 32, 71, 101, 110, 101, 115, 105, 115, 32, 66, 108, 111, 99, 107, 32, 61, 69, - 50, 61, 56, 48, 61, 57, 52, 32, 116, 104, 101, 32, 102, 105, 114, 115, 116, 32, 98, 105, - 116, 99, 111, 105, 110, 32, 61, 13, 10, 98, 108, 111, 99, 107, 32, 97, 110, 100, 32, 116, - 104, 101, 32, 98, 97, 115, 105, 115, 32, 111, 102, 32, 116, 104, 101, 32, 101, 110, 116, - 105, 114, 101, 32, 66, 105, 116, 99, 111, 105, 110, 32, 116, 114, 97, 100, 105, 110, 103, - 32, 115, 121, 115, 116, 101, 109, 32, 105, 110, 32, 112, 108, 97, 99, 101, 32, 116, 111, 32, - 61, 13, 10, 116, 104, 105, 115, 32, 100, 97, 121, 32, 61, 69, 50, 61, 56, 48, 61, 57, 52, - 32, 119, 97, 115, 32, 109, 105, 110, 101, 100, 32, 111, 110, 32, 74, 97, 110, 117, 97, 114, - 121, 32, 51, 44, 32, 50, 48, 48, 57, 46, 61, 50, 48, 13, 10, 13, 10, 84, 104, 101, 32, 71, - 101, 110, 101, 115, 105, 115, 32, 66, 108, 111, 99, 107, 32, 105, 115, 32, 97, 108, 115, - 111, 32, 107, 110, 111, 119, 110, 32, 97, 115, 32, 66, 108, 111, 99, 107, 32, 48, 32, 111, - 114, 32, 66, 108, 111, 99, 107, 32, 49, 44, 32, 97, 110, 100, 32, 105, 115, 32, 115, 116, - 105, 108, 108, 32, 105, 110, 32, 61, 13, 10, 116, 104, 101, 32, 66, 105, 116, 99, 111, 105, - 110, 32, 110, 101, 116, 119, 111, 114, 107, 44, 32, 119, 104, 101, 114, 101, 32, 105, 116, - 32, 119, 105, 108, 108, 32, 114, 101, 109, 97, 105, 110, 32, 97, 115, 32, 108, 111, 110, - 103, 32, 97, 115, 32, 116, 104, 101, 114, 101, 32, 105, 115, 32, 97, 32, 99, 111, 109, 112, - 117, 116, 101, 114, 32, 61, 13, 10, 114, 117, 110, 110, 105, 110, 103, 32, 116, 104, 101, - 32, 66, 105, 116, 99, 111, 105, 110, 32, 115, 111, 102, 116, 119, 97, 114, 101, 46, 61, 50, - 48, 13, 10, 13, 10, 65, 108, 108, 32, 110, 111, 100, 101, 115, 32, 105, 110, 32, 116, 104, - 101, 32, 66, 105, 116, 99, 111, 105, 110, 32, 110, 101, 116, 119, 111, 114, 107, 32, 99, 97, - 110, 32, 99, 111, 110, 115, 117, 108, 116, 32, 105, 116, 44, 32, 101, 118, 101, 110, 32, - 105, 102, 32, 105, 116, 32, 105, 115, 32, 97, 116, 32, 116, 104, 101, 32, 61, 13, 10, 111, - 116, 104, 101, 114, 32, 101, 110, 100, 32, 111, 102, 32, 116, 104, 101, 32, 110, 101, 116, - 119, 111, 114, 107, 32, 119, 105, 116, 104, 32, 104, 117, 110, 100, 114, 101, 100, 115, 32, - 111, 102, 32, 116, 104, 111, 117, 115, 97, 110, 100, 115, 32, 111, 102, 32, 98, 108, 111, - 99, 107, 115, 46, 13, 10, -]; - // RSA public key modulus limbs (18 x 120-bit) const MODULUS_LIMBS = [ "0xe5cf995b5ef59ce9943d1f4209b6ab", @@ -143,16 +105,95 @@ const SIGNATURE_LIMBS = [ ]; const MAX_HEADER_LENGTH = 512; -const MAX_BODY_LENGTH = 1024; + +// ============================================================================= +// Compute header field positions programmatically +// ============================================================================= + +function findHeaderField(headerBytes: number[], fieldName: string): { index: number; length: number } { + const nameBytes = Array.from(fieldName).map(c => c.charCodeAt(0)); + const colon = 58; // ':' + const cr = 13; // '\r' + const lf = 10; // '\n' + + for (let i = 0; i < headerBytes.length; i++) { + // Check start-of-line: either i==0 or preceded by \r\n + const atLineStart = i === 0 || (i >= 2 && headerBytes[i - 2] === cr && headerBytes[i - 1] === lf); + if (!atLineStart) continue; + + // Check field name match + let match = true; + for (let j = 0; j < nameBytes.length; j++) { + if (headerBytes[i + j] !== nameBytes[j]) { match = false; break; } + } + if (!match || headerBytes[i + nameBytes.length] !== colon) continue; + + // Find end of field (next \r\n) + let end = i + nameBytes.length + 1; + while (end < headerBytes.length - 1 && !(headerBytes[end] === cr && headerBytes[end + 1] === lf)) { + end++; + } + return { index: i, length: end - i }; + } + throw new Error(`Header field "${fieldName}" not found`); +} + +function findEmailAddressInField(headerBytes: number[], fieldSeq: { index: number; length: number }, fieldName: string): { index: number; length: number } { + // Address starts after "fieldname:" + const valueStart = fieldSeq.index + fieldName.length + 1; + const valueEnd = fieldSeq.index + fieldSeq.length; + + // Check for angle-bracket format: "Display Name " + let addrStart = valueStart; + let addrEnd = valueEnd; + for (let i = valueStart; i < valueEnd; i++) { + if (headerBytes[i] === 60) addrStart = i + 1; // '<' + if (headerBytes[i] === 62) addrEnd = i; // '>' + } + return { index: addrStart, length: addrEnd - addrStart }; +} + +function findDkimTimestampIndex(headerBytes: number[], dkimSeq: { index: number; length: number }): number { + // Search for "; t=" or " t=" within the DKIM header field + const dkimEnd = dkimSeq.index + dkimSeq.length; + for (let i = dkimSeq.index; i < dkimEnd - 2; i++) { + if (headerBytes[i] === 116 && headerBytes[i + 1] === 61) { // 't' '=' + // Verify preceded by '; ' or ' ' + if (i > 0 && (headerBytes[i - 1] === 32 || headerBytes[i - 1] === 59)) { + // Verify followed by a digit + if (headerBytes[i + 2] >= 48 && headerBytes[i + 2] <= 57) { + return i + 2; // index of first digit + } + } + } + } + throw new Error("DKIM timestamp (t=) tag not found in DKIM-Signature header"); +} + +// Compute all header field positions +const fromSeq = findHeaderField(HEADER_BYTES, "from"); +const fromAddrSeq = findEmailAddressInField(HEADER_BYTES, fromSeq, "from"); +const toSeq = findHeaderField(HEADER_BYTES, "to"); +const toAddrSeq = findEmailAddressInField(HEADER_BYTES, toSeq, "to"); +const subjectSeq = findHeaderField(HEADER_BYTES, "subject"); +const dkimSeq = findHeaderField(HEADER_BYTES, "dkim-signature"); +const dkimTimestampIndex = findDkimTimestampIndex(HEADER_BYTES, dkimSeq); + +console.log("Header field positions:"); +console.log(` from: index=${fromSeq.index}, length=${fromSeq.length}`); +console.log(` from address: index=${fromAddrSeq.index}, length=${fromAddrSeq.length} (${String.fromCharCode(...HEADER_BYTES.slice(fromAddrSeq.index, fromAddrSeq.index + fromAddrSeq.length))})`); +console.log(` to: index=${toSeq.index}, length=${toSeq.length}`); +console.log(` to address: index=${toAddrSeq.index}, length=${toAddrSeq.length} (${String.fromCharCode(...HEADER_BYTES.slice(toAddrSeq.index, toAddrSeq.index + toAddrSeq.length))})`); +console.log(` subject: index=${subjectSeq.index}, length=${subjectSeq.length} (${String.fromCharCode(...HEADER_BYTES.slice(subjectSeq.index + 8, subjectSeq.index + subjectSeq.length))})`); +console.log(` dkim: index=${dkimSeq.index}, length=${dkimSeq.length}`); +console.log(` dkim timestamp digit start: index=${dkimTimestampIndex}`); // ============================================================================= // Build circuit inputs // ============================================================================= -// Pad arrays to max length with zeros function padArray(arr: number[], maxLen: number): string[] { - const padded = [...arr.map(b => b.toString()), ...Array(maxLen - arr.length).fill("0")]; - return padded; + return [...arr.map(b => b.toString()), ...Array(maxLen - arr.length).fill("0")]; } const inputs = { @@ -160,19 +201,18 @@ const inputs = { storage: padArray(HEADER_BYTES, MAX_HEADER_LENGTH), len: HEADER_BYTES.length.toString(), }, - body: { - storage: padArray(BODY_BYTES, MAX_BODY_LENGTH), - len: BODY_BYTES.length.toString(), - }, pubkey: { modulus: MODULUS_LIMBS, redc: REDC_LIMBS, }, signature: SIGNATURE_LIMBS, - body_hash_index: "361", - dkim_header_sequence: { index: "267", length: "203" }, - from_header_sequence: { index: "0", length: "34" }, - from_address_sequence: { index: "5", length: "29" }, + dkim_header_sequence: { index: dkimSeq.index.toString(), length: dkimSeq.length.toString() }, + from_header_sequence: { index: fromSeq.index.toString(), length: fromSeq.length.toString() }, + from_address_sequence: { index: fromAddrSeq.index.toString(), length: fromAddrSeq.length.toString() }, + to_header_sequence: { index: toSeq.index.toString(), length: toSeq.length.toString() }, + to_address_sequence: { index: toAddrSeq.index.toString(), length: toAddrSeq.length.toString() }, + subject_header_sequence: { index: subjectSeq.index.toString(), length: subjectSeq.length.toString() }, + dkim_timestamp_index: dkimTimestampIndex.toString(), }; // ============================================================================= @@ -228,6 +268,15 @@ console.log(`VK size: ${vkAsFields.length}`); console.log(`Proof size: ${proofAsFields.length}`); console.log(`Public inputs: ${proofData.publicInputs.length}`); +// Log public input meanings +console.log("\nPublic inputs breakdown:"); +console.log(` [0] pubkey_hash[0]: ${proofData.publicInputs[0]}`); +console.log(` [1] pubkey_hash[1]: ${proofData.publicInputs[1]}`); +console.log(` [2] email_nullifier: ${proofData.publicInputs[2]}`); +console.log(` [3] to_address_hash: ${proofData.publicInputs[3]}`); +console.log(` [4] intent_hash: ${proofData.publicInputs[4]}`); +console.log(` [5] dkim_timestamp: ${proofData.publicInputs[5]}`); + // Write data.json const data = { vkAsFields: vkAsFields, diff --git a/zkemail_verification/scripts/run_testnet.ts b/zkemail_verification/scripts/run_testnet.ts index 8903bbd..99c93b6 100644 --- a/zkemail_verification/scripts/run_testnet.ts +++ b/zkemail_verification/scripts/run_testnet.ts @@ -12,6 +12,10 @@ import assert from "node:assert"; const TESTNET_URL = "https://rpc.testnet.aztec-labs.com"; +// Maximum email age in seconds. Set very large for testing with old test email (April 2024). +// In production, use a much shorter window (e.g., 15 * 60 for 15 minutes). +const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60; + const sponsoredFPC = await getSponsoredFPCInstance(); const sponsoredPaymentMethod = new SponsoredFeePaymentMethod( sponsoredFPC.address @@ -51,24 +55,25 @@ async function main() { fee: { paymentMethod: sponsoredPaymentMethod }, }; + // Public inputs from proof: + // [3] = to_address_hash (used as authorized_email_hash) + // [4] = intent_hash (subject hash) + const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike; + const intentHash = data.publicInputs[4] as unknown as FieldLike; + console.log("Deploying ZKEmailVerifier contract..."); const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( testWallet, - ownerAddress, - data.vkHash as unknown as FieldLike + data.vkHash as unknown as FieldLike, + authorizedEmailHash, + MAX_EMAIL_AGE, ).send(sendOpts); console.log(`Contract deployed at: ${zkEmailVerifier.address.toString()}`); - // Check initial verification count - let counterValue = (await zkEmailVerifier.methods - .get_verification_count(ownerAddress) - .simulate({ from: ownerAddress })).result; - console.log(`Initial verification count: ${counterValue}`); - console.log("Submitting ZK email proof for on-chain verification..."); const { receipt: tx } = await zkEmailVerifier.methods.verify_email( - ownerAddress, + intentHash, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], @@ -77,14 +82,11 @@ async function main() { console.log(`Transaction hash: ${tx.txHash.toString()}`); console.log(`Transaction status: ${tx.status}`); - // Read verification count - counterValue = (await zkEmailVerifier.methods - .get_verification_count(ownerAddress) - .simulate({ from: ownerAddress })).result; - console.log(`Verification count after proof: ${counterValue}`); - - assert(counterValue === 1n, `Expected verification count 1, got ${counterValue}`); console.log("SUCCESS: ZK email proof verified on Aztec testnet!"); + console.log(" - Recipient address verified against authorized email hash"); + console.log(" - Intent hash verified from email subject"); + console.log(" - Email nullifier pushed (prevents reuse)"); + console.log(" - Email freshness checked against timestamp"); await testWallet.stop(); } diff --git a/zkemail_verification/scripts/run_verification.ts b/zkemail_verification/scripts/run_verification.ts index 2c411ba..38ef73b 100644 --- a/zkemail_verification/scripts/run_verification.ts +++ b/zkemail_verification/scripts/run_verification.ts @@ -12,6 +12,10 @@ import assert from "node:assert"; export const NODE_URL = "http://localhost:8080"; +// Maximum email age in seconds. Set very large for testing with old test email (April 2024). +// In production, use a much shorter window (e.g., 15 * 60 for 15 minutes). +const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60; + const sponsoredFPC = await getSponsoredFPCInstance(); const sponsoredPaymentMethod = new SponsoredFeePaymentMethod( sponsoredFPC.address @@ -49,11 +53,18 @@ async function main() { const ownerAddress = accounts[0].item; console.info('Owner address:', ownerAddress.toString()); + // Public inputs from proof: + // [3] = to_address_hash (used as authorized_email_hash) + // [4] = intent_hash (subject hash) + const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike; + const intentHash = data.publicInputs[4] as unknown as FieldLike; + console.log("Deploying ZKEmailVerifier contract..."); const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( testWallet, - ownerAddress, - data.vkHash as unknown as FieldLike + data.vkHash as unknown as FieldLike, + authorizedEmailHash, + MAX_EMAIL_AGE, ) .send({ from: ownerAddress, @@ -62,12 +73,6 @@ async function main() { console.log("Contract deployed at:", zkEmailVerifier.address.toString()); - // Check initial verification count - let counterValue = (await zkEmailVerifier.methods - .get_verification_count(ownerAddress) - .simulate({ from: ownerAddress })).result; - console.log(`Initial verification count: ${counterValue}`); - console.log("Submitting email proof for on-chain verification (this may take 5-15 minutes with real proofs)..."); const opts = { from: ownerAddress, @@ -75,20 +80,31 @@ async function main() { }; await zkEmailVerifier.methods.verify_email( - ownerAddress, + intentHash, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], ).send(opts); - // Check verification count after - counterValue = (await zkEmailVerifier.methods - .get_verification_count(ownerAddress) - .simulate({ from: ownerAddress })).result; - console.log(`Verification count after proof: ${counterValue}`); - - assert(counterValue === 1n, `Expected verification count to be 1, got ${counterValue}`); console.log("SUCCESS: Email proof verified on-chain!"); + console.log(" - Recipient address verified against authorized email hash"); + console.log(" - Intent hash verified from email subject"); + console.log(" - Email nullifier pushed (prevents reuse)"); + console.log(" - Email freshness checked against timestamp"); + + // Attempting to reuse the same email proof should fail + console.log("\nAttempting to reuse the same email proof (should fail)..."); + try { + await zkEmailVerifier.methods.verify_email( + intentHash, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(opts); + assert.fail("Expected reuse to fail due to duplicate nullifier"); + } catch (e: any) { + console.log("Reuse correctly rejected:", e.message?.substring(0, 100)); + } } main().catch((error) => { diff --git a/zkemail_verification/tests/zkemail_verification.test.ts b/zkemail_verification/tests/zkemail_verification.test.ts index 6bacde4..f35bcc3 100644 --- a/zkemail_verification/tests/zkemail_verification.test.ts +++ b/zkemail_verification/tests/zkemail_verification.test.ts @@ -15,12 +15,22 @@ import data from '../data.json' const NODE_URL = 'http://localhost:8080' const TEST_TIMEOUT = 1200000 // 20 minutes +// Maximum email age in seconds. Set very large for testing with old test email (April 2024). +// In production, use a much shorter window (e.g., 15 * 60 for 15 minutes). +const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60; + describe("ZKEmail Verification", () => { let testWallet: EmbeddedWallet let ownerAddress: AztecAddress let zkEmailVerifierContract: ZKEmailVerifierContract let sponsoredPaymentMethod: SponsoredFeePaymentMethod + // Public inputs from proof: + // [3] = to_address_hash (authorized email hash) + // [4] = intent_hash (subject hash) + const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike + const intentHash = data.publicInputs[4] as unknown as FieldLike + beforeAll(async () => { console.log(`Connecting to Aztec Node at ${NODE_URL}`) const aztecNode = await createAztecNodeClient(NODE_URL) @@ -58,7 +68,7 @@ describe("ZKEmail Verification", () => { } }) - test("should deploy ZKEmailVerifier contract", async () => { + test("should deploy ZKEmailVerifier contract with authorized email and max age", async () => { const sendOpts = { from: ownerAddress, fee: { paymentMethod: sponsoredPaymentMethod }, @@ -66,8 +76,9 @@ describe("ZKEmail Verification", () => { ;({ contract: zkEmailVerifierContract } = await ZKEmailVerifierContract.deploy( testWallet, - ownerAddress, - data.vkHash as unknown as FieldLike + data.vkHash as unknown as FieldLike, + authorizedEmailHash, + MAX_EMAIL_AGE, ) .send(sendOpts)) @@ -77,7 +88,7 @@ describe("ZKEmail Verification", () => { console.log("Contract deployed at address:", zkEmailVerifierContract.address.toString()) }, TEST_TIMEOUT) - test("should verify email proof and increment verification count", async () => { + test("should verify email proof with correct intent and recipient", async () => { const sendOpts = { from: ownerAddress, fee: { paymentMethod: sponsoredPaymentMethod }, @@ -85,7 +96,7 @@ describe("ZKEmail Verification", () => { console.log("Submitting email proof for on-chain verification...") const { receipt: tx } = await zkEmailVerifierContract.methods.verify_email( - ownerAddress, + intentHash, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], @@ -96,37 +107,54 @@ describe("ZKEmail Verification", () => { console.log(`Transaction hash: ${tx.txHash.toString()}`) console.log(`Transaction status: ${tx.status}`) + console.log("Email proof verified — nullifier pushed, timestamp checked") }, TEST_TIMEOUT) - test("should read verification count", async () => { - const { result: counterValue } = await zkEmailVerifierContract.methods.get_verification_count( - ownerAddress - ).simulate({ from: ownerAddress }) + test("should reject reuse of the same email proof (nullifier prevents replay)", async () => { + const sendOpts = { + from: ownerAddress, + fee: { paymentMethod: sponsoredPaymentMethod }, + } - expect(counterValue).toBe(1n) - console.log(`Verification count: ${counterValue}`) + console.log("Attempting to reuse the same email proof (should fail due to duplicate nullifier)...") + await expect( + zkEmailVerifierContract.methods.verify_email( + intentHash, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(sendOpts) + ).rejects.toThrow() + + console.log("Replay correctly rejected — email nullifier prevents reuse") }, TEST_TIMEOUT) - test("should verify same proof again and increment count to 2", async () => { + test("should reject email proof with wrong intent hash", async () => { const sendOpts = { from: ownerAddress, fee: { paymentMethod: sponsoredPaymentMethod }, } - const { receipt: tx } = await zkEmailVerifierContract.methods.verify_email( - ownerAddress, - data.vkAsFields as unknown as FieldLike[], - data.proofAsFields as unknown as FieldLike[], - data.publicInputs as unknown as FieldLike[], - ).send(sendOpts) - expect(tx).toBeDefined() - expect(tx.executionResult).toBe(TxExecutionResult.SUCCESS) + const wrongIntentHash = Fr.random() as unknown as FieldLike + + console.log("Submitting proof with wrong intent hash (should fail)...") + await expect( + zkEmailVerifierContract.methods.verify_email( + wrongIntentHash, + data.vkAsFields as unknown as FieldLike[], + data.proofAsFields as unknown as FieldLike[], + data.publicInputs as unknown as FieldLike[], + ).send(sendOpts) + ).rejects.toThrow() + + console.log("Wrong intent hash correctly rejected") + }, TEST_TIMEOUT) - const { result: counterValue } = await zkEmailVerifierContract.methods.get_verification_count( - ownerAddress - ).simulate({ from: ownerAddress }) + test("should read stored authorized email hash", async () => { + const { result: storedHash } = await zkEmailVerifierContract.methods.get_authorized_email_hash() + .simulate({ from: ownerAddress }) - expect(counterValue).toBe(2n) - console.log(`Verification count after second proof: ${counterValue}`) + expect(storedHash).toBe(BigInt(data.publicInputs[3])) + console.log(`Stored authorized email hash: ${storedHash}`) }, TEST_TIMEOUT) }) From 7665ab33a8bb2310e1670a1ef5141864d31ae44e Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 12:49:52 -0400 Subject: [PATCH 05/11] Update README to document trusted DKIM key binding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The contract now stores trusted DKIM public key hashes and verifies them against proof outputs, preventing forgery with self-generated keypairs. Update the security model (4 → 5 constraints), constructor signature (3 → 5 params), verify_email steps, diagram, and troubleshooting to match the actual contract code. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/README.md | 51 ++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index 7aa6f18..9ea3cd4 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -6,14 +6,27 @@ Built with the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library on Az ## Security Model -The contract enforces four constraints on each email proof: +The contract enforces five constraints on each email proof: -1. **Recipient binding** — The email's `to` address must hash to the `authorized_email_hash` stored at deployment. Only emails sent to the account owner's address are accepted. -2. **Intent binding** — The email's `subject` field is hashed and compared against a caller-provided `expected_intent_hash`. This ties the email to a specific action (e.g., a Poseidon hash of calldata placed in the subject). -3. **Single use** — The DKIM signature is hashed into a nullifier and pushed on-chain. Replaying the same email proof fails because the nullifier already exists. -4. **Freshness** — The DKIM `t=` timestamp is extracted and checked in a public function against the block timestamp. Emails older than `max_email_age` seconds are rejected. +1. **DKIM key binding** — The proof's DKIM public key hash (`public_inputs[0]`, `[1]`) must match the trusted key hashes stored at deployment. Without this, an attacker could generate their own RSA keypair, forge a DKIM signature, and produce a valid proof. +2. **Recipient binding** — The email's `to` address must hash to the `authorized_email_hash` stored at deployment. Only emails sent to the account owner's address are accepted. +3. **Intent binding** — The email's `subject` field is hashed and compared against a caller-provided `expected_intent_hash`. This ties the email to a specific action (e.g., a Poseidon hash of calldata placed in the subject). +4. **Single use** — The DKIM signature is hashed into a nullifier and pushed on-chain. Replaying the same email proof fails because the nullifier already exists. +5. **Freshness** — The DKIM `t=` timestamp is extracted and checked in a public function against the block timestamp. Emails older than `max_email_age` seconds are rejected. -The sender's domain is also verified to be `icloud.com` via DKIM. +The sender's domain is also verified to be `icloud.com` via DKIM in the circuit. + +### DKIM Key Rotation Caveat + +This example pins the trusted DKIM public key hash at contract deployment time. In practice, mail providers rotate their DKIM signing keys periodically — a domain can publish a new key under the same selector, or switch selectors entirely. When that happens, proofs generated with the old key will still verify, but proofs using the new key will be rejected by the contract (the key hash won't match). + +A production system should replace the static key hash with a **DKIM key registry** that tracks current keys per `(domain, selector)` pair. The two main approaches: + +1. **DNSSEC-aware proof** — The prover includes the full DNSSEC chain from the DNS root to the DKIM TXT record. The circuit or a dedicated verifier contract validates the chain, proving the key was authentically published in DNS. This is the strongest trust model but requires in-circuit DNSSEC signature verification (multiple RSA/ECDSA checks across the delegation chain) and handling of signature validity windows. + +2. **Narrowly-scoped DNSSEC oracle** — An off-chain service resolves the DKIM TXT record with full DNSSEC validation and submits signed `(domain, selector, key_hash, expires_at)` attestations to an on-chain registry. The email verifier contract checks the proof's key against the registry. This is simpler to implement and sufficient when the oracle's trust boundary is acceptable. + +In either case, the contract should check key expiry and support updates without redeployment. ## How It Works @@ -25,11 +38,11 @@ Raw Email ──> [Noir Circuit] ──> │ 6 public outputs: │ │ from domain │ [2] email_nullifier │──> [Aztec Contract] │ to address │ [3] to_address_hash │ │ │ subject │ [4] intent_hash │ │ verify_honk_proof() - │ timestamp │ [5] dkim_timestamp │ │ check recipient - │ └──────────────────────────┘ │ check intent - │ │ push nullifier - │ Body verification omitted — │ check freshness - │ all auth data is in DKIM-signed headers, │ + │ timestamp │ [5] dkim_timestamp │ │ check DKIM key + │ └──────────────────────────┘ │ check recipient + │ │ check intent + │ Body verification omitted — │ push nullifier + │ all auth data is in DKIM-signed headers, │ check freshness │ avoiding extra SHA256 hashing cost │ ``` @@ -47,13 +60,14 @@ Body verification is omitted since all authorization-relevant data lives in the ### Contract (`contract/src/main.nr`) -- `constructor(vk_hash, authorized_email_hash, max_email_age)` — Stores the verification key hash, the Poseidon2 hash of the authorized recipient email, and the maximum email age in seconds. +- `constructor(vk_hash, trusted_dkim_key_hash_0, trusted_dkim_key_hash_1, authorized_email_hash, max_email_age)` — Stores the verification key hash, the trusted DKIM public key hashes (modulus and redc), the Poseidon2 hash of the authorized recipient email, and the maximum email age in seconds. - `verify_email(expected_intent_hash, vk, proof, public_inputs)` — **Private function** that: 1. Verifies the UltraHonk proof against the stored VK hash - 2. Asserts `public_inputs[3]` (to address hash) matches `authorized_email_hash` - 3. Asserts `public_inputs[4]` (subject hash) matches `expected_intent_hash` - 4. Pushes `public_inputs[2]` (email nullifier) to prevent replay - 5. Enqueues a public call to check `public_inputs[5]` (timestamp) is fresh + 2. Asserts `public_inputs[0]` and `[1]` (DKIM key hashes) match the trusted key + 3. Asserts `public_inputs[3]` (to address hash) matches `authorized_email_hash` + 4. Asserts `public_inputs[4]` (subject hash) matches `expected_intent_hash` + 5. Pushes `public_inputs[2]` (email nullifier) to prevent replay + 6. Enqueues a public call to check `public_inputs[5]` (timestamp) is fresh - `_check_email_freshness(email_timestamp, max_age)` — **Public function** that checks `block.timestamp - email_timestamp <= max_age` - `get_authorized_email_hash()` — **View function** that returns the stored authorized email hash - `get_max_email_age()` — **View function** that returns the stored maximum email age @@ -91,7 +105,7 @@ nargo --version # 1.0.0-beta.18 │ ├── src/main.nr # DKIM verify + address/subject/timestamp extraction │ └── Nargo.toml # Depends on zkemail.nr ├── contract/ # Aztec smart contract -│ ├── src/main.nr # verify_honk_proof + nullifier + timestamp check +│ ├── src/main.nr # verify_honk_proof + DKIM key + nullifier + timestamp │ ├── artifacts/ # Generated TypeScript bindings │ └── Nargo.toml # Depends on aztec-nr and bb_proof_verification ├── scripts/ @@ -181,6 +195,9 @@ Run `yarn ccc` to compile the contract and generate TypeScript bindings. **"Cannot find module '../data.json'"** Run `yarn data` to generate the proof data. +**"DKIM public key does not match trusted key"** +The proof was generated with a DKIM key that doesn't match the trusted key hashes stored at deployment. This can happen after a DKIM key rotation. Redeploy the contract with the current key hashes from the proof's `public_inputs[0]` and `[1]`. + **"Email recipient does not match authorized address"** The `to` address in the email doesn't match the `authorized_email_hash` stored at deployment. Ensure the proof was generated with the correct test email. From f7f49787db403f23875b73299fdcbdc7238f372f Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 12:52:01 -0400 Subject: [PATCH 06/11] Add trusted DKIM key binding and tighten timestamp validation Store trusted DKIM public key hashes at deployment and verify them against proof outputs in verify_email, preventing forgery with self-generated keypairs. Tighten timestamp extraction to ensure the t= tag falls strictly within the DKIM-Signature header field. Make header field parsing case-insensitive per RFC 5322. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/circuit/src/main.nr | 12 +++++-- zkemail_verification/contract/src/main.nr | 35 ++++++++++++++++--- zkemail_verification/scripts/generate_data.ts | 9 +++-- zkemail_verification/scripts/run_testnet.ts | 6 ++++ .../scripts/run_verification.ts | 6 ++++ .../tests/zkemail_verification.test.ts | 6 ++++ 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/zkemail_verification/circuit/src/main.nr b/zkemail_verification/circuit/src/main.nr index f422d92..d762500 100644 --- a/zkemail_verification/circuit/src/main.nr +++ b/zkemail_verification/circuit/src/main.nr @@ -43,6 +43,9 @@ fn main( let _ = pubkey.verify_dkim_signature(header, signature); // 2. Extract and verify the sender's domain is icloud.com + // NOTE: Header field names are matched in lowercase. This assumes DKIM + // c=relaxed canonicalization, which lowercases header names before signing. + // The TypeScript parser matches case-insensitively per RFC 5322. let from_address: BoundedVec = get_email_address( header, from_header_sequence, @@ -178,14 +181,17 @@ fn extract_dkim_timestamp( dkim_sequence: Sequence, timestamp_index: u32, ) -> Field { - // Verify timestamp_index falls within the DKIM header field + // Verify timestamp_index falls strictly within the DKIM header field. + // Both the "t=" prefix and all digits must be inside the DKIM-Signature sequence, + // otherwise a prover could point to a t= in a later, unsigned header line. + let dkim_end = dkim_sequence.index + dkim_sequence.length; assert( timestamp_index >= dkim_sequence.index + 2, "Timestamp index too early in DKIM header", ); assert( - timestamp_index + MAX_TIMESTAMP_DIGITS <= header.len(), - "Not enough header bytes for timestamp digits", + timestamp_index + MAX_TIMESTAMP_DIGITS <= dkim_end, + "Timestamp digits extend past DKIM header field", ); // Verify "t=" prefix immediately before the digits diff --git a/zkemail_verification/contract/src/main.nr b/zkemail_verification/contract/src/main.nr index 7760a4f..718d568 100644 --- a/zkemail_verification/contract/src/main.nr +++ b/zkemail_verification/contract/src/main.nr @@ -12,7 +12,12 @@ pub contract ZKEmailVerifier { #[storage] struct Storage { vk_hash: PublicImmutable, - /// Pedersen hash of the authorized recipient email address. + /// Poseidon hash of the trusted DKIM RSA public key modulus. + /// Proofs must use a key whose hash matches, preventing self-signed forgeries. + trusted_dkim_key_hash_0: PublicImmutable, + /// Poseidon hash of the trusted DKIM RSA public key redc parameter. + trusted_dkim_key_hash_1: PublicImmutable, + /// Poseidon2 hash of the authorized recipient email address. /// Only emails sent TO this address can authorize actions. authorized_email_hash: PublicImmutable, /// Maximum allowed age of an email in seconds. @@ -22,8 +27,16 @@ pub contract ZKEmailVerifier { #[initializer] #[external("public")] - fn constructor(vk_hash: Field, authorized_email_hash: Field, max_email_age: Field) { + fn constructor( + vk_hash: Field, + trusted_dkim_key_hash_0: Field, + trusted_dkim_key_hash_1: Field, + authorized_email_hash: Field, + max_email_age: Field, + ) { self.storage.vk_hash.initialize(vk_hash); + self.storage.trusted_dkim_key_hash_0.initialize(trusted_dkim_key_hash_0); + self.storage.trusted_dkim_key_hash_1.initialize(trusted_dkim_key_hash_1); self.storage.authorized_email_hash.initialize(authorized_email_hash); self.storage.max_email_age.initialize(max_email_age); } @@ -35,8 +48,8 @@ pub contract ZKEmailVerifier { /// specific action. /// /// Public inputs layout from the circuit: - /// [0]: pubkey_hash[0] -- DKIM key identity - /// [1]: pubkey_hash[1] -- DKIM key identity + /// [0]: pubkey_hash[0] -- must match trusted DKIM key + /// [1]: pubkey_hash[1] -- must match trusted DKIM key /// [2]: email_nullifier -- prevents email reuse /// [3]: to_address_hash -- must match authorized_email_hash /// [4]: intent_hash -- hash of email subject (action being authorized) @@ -54,6 +67,20 @@ pub contract ZKEmailVerifier { let vk_hash = self.storage.vk_hash.read(); verify_honk_proof(verification_key, proof, public_inputs, vk_hash); + // Verify the DKIM public key matches the trusted key. + // Without this, an attacker could generate their own RSA keypair, + // forge a DKIM signature, and produce a valid proof. + let trusted_key_0 = self.storage.trusted_dkim_key_hash_0.read(); + let trusted_key_1 = self.storage.trusted_dkim_key_hash_1.read(); + assert( + public_inputs[0] == trusted_key_0, + "DKIM public key does not match trusted key (modulus)", + ); + assert( + public_inputs[1] == trusted_key_1, + "DKIM public key does not match trusted key (redc)", + ); + // Verify the email was sent to the authorized address let authorized_email_hash = self.storage.authorized_email_hash.read(); assert( diff --git a/zkemail_verification/scripts/generate_data.ts b/zkemail_verification/scripts/generate_data.ts index 69178f7..ce837f0 100644 --- a/zkemail_verification/scripts/generate_data.ts +++ b/zkemail_verification/scripts/generate_data.ts @@ -121,10 +121,15 @@ function findHeaderField(headerBytes: number[], fieldName: string): { index: num const atLineStart = i === 0 || (i >= 2 && headerBytes[i - 2] === cr && headerBytes[i - 1] === lf); if (!atLineStart) continue; - // Check field name match + // Check field name match (case-insensitive per RFC 5322) let match = true; for (let j = 0; j < nameBytes.length; j++) { - if (headerBytes[i + j] !== nameBytes[j]) { match = false; break; } + // Compare lowercase: ASCII uppercase A-Z (65-90) -> lowercase a-z (97-122) + const hb = headerBytes[i + j]; + const nb = nameBytes[j]; + const hbLower = (hb >= 65 && hb <= 90) ? hb + 32 : hb; + const nbLower = (nb >= 65 && nb <= 90) ? nb + 32 : nb; + if (hbLower !== nbLower) { match = false; break; } } if (!match || headerBytes[i + nameBytes.length] !== colon) continue; diff --git a/zkemail_verification/scripts/run_testnet.ts b/zkemail_verification/scripts/run_testnet.ts index 99c93b6..31d762c 100644 --- a/zkemail_verification/scripts/run_testnet.ts +++ b/zkemail_verification/scripts/run_testnet.ts @@ -56,8 +56,12 @@ async function main() { }; // Public inputs from proof: + // [0] = trusted DKIM pubkey hash (modulus) + // [1] = trusted DKIM pubkey hash (redc) // [3] = to_address_hash (used as authorized_email_hash) // [4] = intent_hash (subject hash) + const trustedDkimKeyHash0 = data.publicInputs[0] as unknown as FieldLike; + const trustedDkimKeyHash1 = data.publicInputs[1] as unknown as FieldLike; const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike; const intentHash = data.publicInputs[4] as unknown as FieldLike; @@ -65,6 +69,8 @@ async function main() { const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( testWallet, data.vkHash as unknown as FieldLike, + trustedDkimKeyHash0, + trustedDkimKeyHash1, authorizedEmailHash, MAX_EMAIL_AGE, ).send(sendOpts); diff --git a/zkemail_verification/scripts/run_verification.ts b/zkemail_verification/scripts/run_verification.ts index 38ef73b..74d5af0 100644 --- a/zkemail_verification/scripts/run_verification.ts +++ b/zkemail_verification/scripts/run_verification.ts @@ -54,8 +54,12 @@ async function main() { console.info('Owner address:', ownerAddress.toString()); // Public inputs from proof: + // [0] = trusted DKIM pubkey hash (modulus) + // [1] = trusted DKIM pubkey hash (redc) // [3] = to_address_hash (used as authorized_email_hash) // [4] = intent_hash (subject hash) + const trustedDkimKeyHash0 = data.publicInputs[0] as unknown as FieldLike; + const trustedDkimKeyHash1 = data.publicInputs[1] as unknown as FieldLike; const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike; const intentHash = data.publicInputs[4] as unknown as FieldLike; @@ -63,6 +67,8 @@ async function main() { const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( testWallet, data.vkHash as unknown as FieldLike, + trustedDkimKeyHash0, + trustedDkimKeyHash1, authorizedEmailHash, MAX_EMAIL_AGE, ) diff --git a/zkemail_verification/tests/zkemail_verification.test.ts b/zkemail_verification/tests/zkemail_verification.test.ts index f35bcc3..4c4beee 100644 --- a/zkemail_verification/tests/zkemail_verification.test.ts +++ b/zkemail_verification/tests/zkemail_verification.test.ts @@ -26,8 +26,12 @@ describe("ZKEmail Verification", () => { let sponsoredPaymentMethod: SponsoredFeePaymentMethod // Public inputs from proof: + // [0] = trusted DKIM pubkey hash (modulus) + // [1] = trusted DKIM pubkey hash (redc) // [3] = to_address_hash (authorized email hash) // [4] = intent_hash (subject hash) + const trustedDkimKeyHash0 = data.publicInputs[0] as unknown as FieldLike + const trustedDkimKeyHash1 = data.publicInputs[1] as unknown as FieldLike const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike const intentHash = data.publicInputs[4] as unknown as FieldLike @@ -77,6 +81,8 @@ describe("ZKEmail Verification", () => { ;({ contract: zkEmailVerifierContract } = await ZKEmailVerifierContract.deploy( testWallet, data.vkHash as unknown as FieldLike, + trustedDkimKeyHash0, + trustedDkimKeyHash1, authorizedEmailHash, MAX_EMAIL_AGE, ) From fbbf111035050b03ab07c746cd62c16bbdba93b1 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 14:04:06 -0400 Subject: [PATCH 07/11] Fix case-sensitive header parsing and circular trust in troubleshooting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review comments: [P2] Revert case-insensitive header field matching in generate_data.ts. The header input is DKIM-canonicalized (c=relaxed), so field names are always lowercase — case-insensitive matching was unnecessary and masked the real requirement. Update circuit and script comments to state the canonicalization requirement definitively. [P3] Rewrite DKIM key mismatch troubleshooting to direct operators to a trusted DNS source rather than the rejected proof's own public inputs, which are prover-controlled. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/README.md | 2 +- zkemail_verification/circuit/src/main.nr | 5 ++--- zkemail_verification/scripts/generate_data.ts | 11 ++++------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index 9ea3cd4..a78930d 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -196,7 +196,7 @@ Run `yarn ccc` to compile the contract and generate TypeScript bindings. Run `yarn data` to generate the proof data. **"DKIM public key does not match trusted key"** -The proof was generated with a DKIM key that doesn't match the trusted key hashes stored at deployment. This can happen after a DKIM key rotation. Redeploy the contract with the current key hashes from the proof's `public_inputs[0]` and `[1]`. +The proof was generated with a DKIM key that doesn't match the trusted key hashes stored at deployment. This can happen after a DKIM key rotation. To resolve, look up the current DKIM public key from DNS (e.g., `dig TXT ._domainkey.icloud.com`), compute its Poseidon hash, and redeploy the contract with the updated key hashes. Do not take key hashes from the rejected proof's own public inputs — those are prover-controlled and may not reflect a legitimate key. **"Email recipient does not match authorized address"** The `to` address in the email doesn't match the `authorized_email_hash` stored at deployment. Ensure the proof was generated with the correct test email. diff --git a/zkemail_verification/circuit/src/main.nr b/zkemail_verification/circuit/src/main.nr index d762500..93054fc 100644 --- a/zkemail_verification/circuit/src/main.nr +++ b/zkemail_verification/circuit/src/main.nr @@ -43,9 +43,8 @@ fn main( let _ = pubkey.verify_dkim_signature(header, signature); // 2. Extract and verify the sender's domain is icloud.com - // NOTE: Header field names are matched in lowercase. This assumes DKIM - // c=relaxed canonicalization, which lowercases header names before signing. - // The TypeScript parser matches case-insensitively per RFC 5322. + // The header input must be DKIM-canonicalized (c=relaxed), which lowercases + // field names. All field name comparisons below use lowercase literals. let from_address: BoundedVec = get_email_address( header, from_header_sequence, diff --git a/zkemail_verification/scripts/generate_data.ts b/zkemail_verification/scripts/generate_data.ts index ce837f0..709ecf8 100644 --- a/zkemail_verification/scripts/generate_data.ts +++ b/zkemail_verification/scripts/generate_data.ts @@ -121,15 +121,12 @@ function findHeaderField(headerBytes: number[], fieldName: string): { index: num const atLineStart = i === 0 || (i >= 2 && headerBytes[i - 2] === cr && headerBytes[i - 1] === lf); if (!atLineStart) continue; - // Check field name match (case-insensitive per RFC 5322) + // Check field name match (exact, lowercase). + // The header input must be DKIM-canonicalized (c=relaxed lowercases field names), + // so field names are always lowercase. The circuit asserts lowercase too. let match = true; for (let j = 0; j < nameBytes.length; j++) { - // Compare lowercase: ASCII uppercase A-Z (65-90) -> lowercase a-z (97-122) - const hb = headerBytes[i + j]; - const nb = nameBytes[j]; - const hbLower = (hb >= 65 && hb <= 90) ? hb + 32 : hb; - const nbLower = (nb >= 65 && nb <= 90) ? nb + 32 : nb; - if (hbLower !== nbLower) { match = false; break; } + if (headerBytes[i + j] !== nameBytes[j]) { match = false; break; } } if (!match || headerBytes[i + nameBytes.length] !== colon) continue; From a4ad5d5c772cd8e9cb8921298c183f0cca24c3ed Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 15:09:11 -0400 Subject: [PATCH 08/11] Rework ZKEmail example into offchain-authorized token transfers using partial notes Renames ZKEmailVerifier to EmailClaim and integrates the offchain transfer tutorial pattern: Bob deposits tokens mapped to his email address hash, Carol creates a partial note and completes it by submitting a verified zkEmail proof. The circuit now outputs 7 public inputs (adds from_address_hash for sender identification), the contract manages token balances and partial note completion, and the security model expands from 5 to 6 points. Also hardens timestamp parsing to reject empty t= values. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/README.md | 214 +++++++----------- zkemail_verification/circuit/src/main.nr | 32 ++- zkemail_verification/contract/Nargo.toml | 7 +- zkemail_verification/contract/src/main.nr | 208 +++++++++++++---- zkemail_verification/scripts/generate_data.ts | 13 +- zkemail_verification/scripts/run_testnet.ts | 126 +++++++---- .../scripts/run_verification.ts | 150 +++++++----- .../tests/zkemail_verification.test.ts | 189 ++++++++-------- 8 files changed, 553 insertions(+), 386 deletions(-) diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index a78930d..4f478ea 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -1,87 +1,91 @@ -# ZK Email Auth for Aztec +# ZK Email Offchain Transfers for Aztec -Proves email-based authorization using DKIM signature verification in a Noir circuit, then verifies that proof on-chain inside an Aztec private smart contract. Each email proof binds to a specific recipient, encodes an intent via the subject field, is single-use (nullifier), and must be fresh (timestamp check). +A complete example of offchain-authorized token transfers using DKIM-signed emails. Bob deposits tokens into a contract, then authorizes payments by sending a plain email. Carol creates a partial note, gets Bob's email authorization, generates a zkEmail proof, and submits it to claim her tokens. Bob never touches the network after the initial deposit. -Built with the [zkemail.nr](https://github.com/zkemail/zkemail.nr) library on Aztec 4.2.0. +Built with [zkemail.nr](https://github.com/zkemail/zkemail.nr) and the [Offchain-Authorized Transfers](https://docs.aztec.network/tutorials/contract_tutorials/offchain_transfer) tutorial pattern on Aztec 4.2.0. -## Security Model +## Overview + +This project combines **partial notes** with **zkEmail proof verification** to enable email-authorized token payments entirely on L2: -The contract enforces five constraints on each email proof: +1. **Bob deposits** tokens into the `EmailClaim` contract, mapped to his email address hash +2. **Carol creates a partial note** (a private commitment to receive tokens) +3. **Bob sends an email** with the intended action in the subject line +4. **Carol generates a zkEmail proof** offchain using a Noir circuit +5. **Carol submits the proof** to complete her partial note and receive the tokens -1. **DKIM key binding** — The proof's DKIM public key hash (`public_inputs[0]`, `[1]`) must match the trusted key hashes stored at deployment. Without this, an attacker could generate their own RSA keypair, forge a DKIM signature, and produce a valid proof. -2. **Recipient binding** — The email's `to` address must hash to the `authorized_email_hash` stored at deployment. Only emails sent to the account owner's address are accepted. -3. **Intent binding** — The email's `subject` field is hashed and compared against a caller-provided `expected_intent_hash`. This ties the email to a specific action (e.g., a Poseidon hash of calldata placed in the subject). -4. **Single use** — The DKIM signature is hashed into a nullifier and pushed on-chain. Replaying the same email proof fails because the nullifier already exists. -5. **Freshness** — The DKIM `t=` timestamp is extracted and checked in a public function against the block timestamp. Emails older than `max_email_age` seconds are rejected. +Bob's only onchain action is the initial deposit. Everything after that is an email from any standard mail client. + +## Security Model -The sender's domain is also verified to be `icloud.com` via DKIM in the circuit. +The contract enforces a 6-point security model on each email claim: + +1. **DKIM key binding** -- The proof's DKIM public key hash must match the trusted key stored at deployment. Prevents self-signed forgeries. +2. **Sender identification** -- The `From` address hash identifies the depositor, used to look up whose balance to deduct. +3. **Recipient binding** -- The email's `To` address hash must match the expected recipient. Prevents using an email sent to someone else. +4. **Intent binding** -- The email's `Subject` hash must match the expected action. Prevents reusing an email for a different purpose. +5. **Single use** -- Each email produces a unique nullifier pushed to Aztec's nullifier tree. The protocol rejects duplicate claims. +6. **Freshness** -- The DKIM signing timestamp must be within `max_email_age` seconds of the block timestamp. ### DKIM Key Rotation Caveat -This example pins the trusted DKIM public key hash at contract deployment time. In practice, mail providers rotate their DKIM signing keys periodically — a domain can publish a new key under the same selector, or switch selectors entirely. When that happens, proofs generated with the old key will still verify, but proofs using the new key will be rejected by the contract (the key hash won't match). +This example pins the trusted DKIM public key hash at contract deployment time. In practice, mail providers rotate their DKIM signing keys periodically. When that happens, proofs using the new key will be rejected by the contract. A production system should replace the static key hash with a **DKIM key registry** that tracks current keys per `(domain, selector)` pair. The two main approaches: -1. **DNSSEC-aware proof** — The prover includes the full DNSSEC chain from the DNS root to the DKIM TXT record. The circuit or a dedicated verifier contract validates the chain, proving the key was authentically published in DNS. This is the strongest trust model but requires in-circuit DNSSEC signature verification (multiple RSA/ECDSA checks across the delegation chain) and handling of signature validity windows. +1. **DNSSEC-aware proof** -- The prover includes the full DNSSEC chain from the DNS root to the DKIM TXT record. Strongest trust model but requires in-circuit DNSSEC signature verification. -2. **Narrowly-scoped DNSSEC oracle** — An off-chain service resolves the DKIM TXT record with full DNSSEC validation and submits signed `(domain, selector, key_hash, expires_at)` attestations to an on-chain registry. The email verifier contract checks the proof's key against the registry. This is simpler to implement and sufficient when the oracle's trust boundary is acceptable. +2. **Narrowly-scoped DNSSEC oracle** -- An off-chain service resolves the DKIM TXT record with full DNSSEC validation and submits signed attestations to an on-chain registry. Simpler to implement. In either case, the contract should check key expiry and support updates without redeployment. -## How It Works +### Partial Note UX Note -``` - ┌──────────────────────────┐ -Raw Email ──> [Noir Circuit] ──> │ 6 public outputs: │ - │ │ [0] pubkey_hash[0] │ - │ DKIM verify │ [1] pubkey_hash[1] │ - │ from domain │ [2] email_nullifier │──> [Aztec Contract] - │ to address │ [3] to_address_hash │ │ - │ subject │ [4] intent_hash │ │ verify_honk_proof() - │ timestamp │ [5] dkim_timestamp │ │ check DKIM key - │ └──────────────────────────┘ │ check recipient - │ │ check intent - │ Body verification omitted — │ push nullifier - │ all auth data is in DKIM-signed headers, │ check freshness - │ avoiding extra SHA256 hashing cost │ -``` +At Aztec v4.2.0, `UintNote::partial()` samples randomness internally via the oracle, meaning Carol cannot precompute the partial note commitment offchain -- she must get it from the transaction return value. A future `UintNote::partial_with_randomness(randomness)` API (where Carol supplies the randomness) would let Carol compute the commitment deterministically before submitting any transaction. This would improve the UX by allowing Carol to include the commitment in the email she asks Bob to send, before her `create_claim` transaction even lands. -### Circuit (`circuit/src/main.nr`) +### Privacy Tradeoffs -Uses [zkemail.nr](https://github.com/zkemail/zkemail.nr) to: -- Verify the 2048-bit RSA DKIM signature over the email header -- Extract and verify the sender domain is `icloud.com` -- Extract the `to` address and output its Poseidon2 hash (identity binding) -- Extract the `subject` field and output its Poseidon2 hash (intent binding) -- Parse the `t=` tag from the DKIM-Signature header (timestamp for freshness) -- Output a Poseidon2 hash of the DKIM signature as an email nullifier (replay prevention) +- **Bob's deposit is public.** Observers can see how much Bob deposited and when funds are consumed. +- **Carol's identity is hidden.** The partial note commitment hides her address. +- **The claim amount is public.** The partial note is completed in public, so the amount is visible. -Body verification is omitted since all authorization-relevant data lives in the DKIM-signed headers. This avoids the ~114K constraint SHA256 body hash computation. +## Architecture -### Contract (`contract/src/main.nr`) +``` + +----------------------------+ +Raw Email --> [Noir Circuit] --> | 7 public outputs: | + | | [0] pubkey_hash[0] | + | DKIM verify | [1] pubkey_hash[1] | + | from domain | [2] email_nullifier |--> [EmailClaim Contract] + | from addr | [3] from_address_hash | | + | to addr | [4] to_address_hash | | verify_honk_proof() + | subject | [5] intent_hash | | check DKIM key + | timestamp | [6] dkim_timestamp | | identify depositor + | +----------------------------+ | check recipient + | | check intent + | Body verification omitted -- | push nullifier + | all auth data is in DKIM-signed headers | check freshness + | | deduct balance + | | complete partial note +``` -- `constructor(vk_hash, trusted_dkim_key_hash_0, trusted_dkim_key_hash_1, authorized_email_hash, max_email_age)` — Stores the verification key hash, the trusted DKIM public key hashes (modulus and redc), the Poseidon2 hash of the authorized recipient email, and the maximum email age in seconds. -- `verify_email(expected_intent_hash, vk, proof, public_inputs)` — **Private function** that: - 1. Verifies the UltraHonk proof against the stored VK hash - 2. Asserts `public_inputs[0]` and `[1]` (DKIM key hashes) match the trusted key - 3. Asserts `public_inputs[3]` (to address hash) matches `authorized_email_hash` - 4. Asserts `public_inputs[4]` (subject hash) matches `expected_intent_hash` - 5. Pushes `public_inputs[2]` (email nullifier) to prevent replay - 6. Enqueues a public call to check `public_inputs[5]` (timestamp) is fresh -- `_check_email_freshness(email_timestamp, max_age)` — **Public function** that checks `block.timestamp - email_timestamp <= max_age` -- `get_authorized_email_hash()` — **View function** that returns the stored authorized email hash -- `get_max_email_age()` — **View function** that returns the stored maximum email age +### Circuit (`circuit/src/main.nr`) -### Intent Encoding +Standalone Noir binary using [zkemail.nr](https://github.com/zkemail/zkemail.nr): +- Verifies 2048-bit RSA DKIM signature over the email header +- Extracts sender domain (`icloud.com`) and full sender address hash +- Extracts recipient address hash, subject hash, and DKIM timestamp +- Outputs Poseidon2 hash of the DKIM signature as an email nullifier -The email subject serves as the intent field. For this example, the subject is hashed with Poseidon2 inside the circuit and output as `intent_hash`. To authorize an action: +### Contract (`contract/src/main.nr`) -1. Compute `intent_hash = Poseidon2(pack_31(subject_bytes) ++ [subject_length])` off-chain -2. Include the intent text as the email subject (e.g., a Poseidon hash of the calldata encoded as a string) -3. The circuit hashes the subject and outputs it -4. The contract verifies the proof's `intent_hash` matches the caller's `expected_intent_hash` +Aztec contract following the `EmailClaim` pattern from the [offchain transfer tutorial](https://docs.aztec.network/tutorials/contract_tutorials/offchain_transfer): -For a production system, the subject would contain a Poseidon hash of the calldata — easier to parse in-circuit than ASCII text and supports arbitrary call data encoding. +- `constructor(token, vk_hash, trusted_dkim_key_hash_0, trusted_dkim_key_hash_1, max_email_age)` -- Binds to a token, sets trusted DKIM key and email age limit +- `deposit(email_address_hash, amount, authwit_nonce)` -- Bob deposits tokens mapped to his email address hash +- `create_claim()` -- Carol creates a partial note (private commitment) +- `claim_with_email(expected_recipient_hash, expected_intent_hash, partial_note, amount, vk, proof, public_inputs)` -- Verifies the email proof, enforces the 6-point security model, then enqueues public completion +- `_complete(...)` -- Public function that checks freshness, deducts from depositor balance, and completes the partial note ## Prerequisites @@ -92,33 +96,6 @@ For a production system, the subject would contain a Poseidon hash of the callda # Install Aztec CLI bash -i <(curl -s https://install.aztec.network) aztec-up 4.2.0-aztecnr-rc.2 - -# Verify nargo (bundled with Aztec CLI) -nargo --version # 1.0.0-beta.18 -``` - -## Project Structure - -``` -. -├── circuit/ # Inner Noir circuit (vanilla bin, not Aztec contract) -│ ├── src/main.nr # DKIM verify + address/subject/timestamp extraction -│ └── Nargo.toml # Depends on zkemail.nr -├── contract/ # Aztec smart contract -│ ├── src/main.nr # verify_honk_proof + DKIM key + nullifier + timestamp -│ ├── artifacts/ # Generated TypeScript bindings -│ └── Nargo.toml # Depends on aztec-nr and bb_proof_verification -├── scripts/ -│ ├── generate_data.ts # Build circuit inputs, generate + verify proof -│ ├── run_verification.ts # Deploy + verify on local network -│ ├── run_testnet.ts # Deploy + verify on Aztec testnet -│ └── sponsored_fpc.ts # SponsoredFPC fee payment utility -├── tests/ -│ └── zkemail_verification.test.ts # Vitest integration tests -├── data.json # Generated proof data (created by yarn data) -├── package.json -├── tsconfig.json -└── vitest.config.ts ``` ## Quick Start @@ -143,7 +120,7 @@ yarn data # Start local network in a separate terminal aztec start --local-network -# Deploy and verify +# Deploy token + email claim contract, deposit, create claim, verify proof yarn verify # Or run the full test suite @@ -161,56 +138,27 @@ yarn testnet | Command | Description | |---------|-------------| | `yarn ccc` | Compile Aztec contract + generate TypeScript bindings | -| `yarn data` | Generate UltraHonk proof from test email data, verify off-chain, write `data.json` | -| `yarn verify` | Deploy contract and verify proof on local network | -| `yarn testnet` | Deploy contract and verify proof on the Aztec testnet | +| `yarn data` | Generate UltraHonk proof from test email data, write `data.json` | +| `yarn verify` | Full flow on local network: deploy, deposit, claim, verify | +| `yarn testnet` | Full flow on Aztec testnet | | `yarn test` | Run Vitest integration tests against local network | -## Circuit Details - -The inner circuit verifies a DKIM-signed email from `icloud.com` and extracts auth data from the headers: - -| Component | Description | -|-----------|-------------| -| DKIM signature verification | RSA-2048 PKCS#1 v1.5 over SHA256 header hash | -| From address extraction | Extract sender email and verify domain is `icloud.com` | -| To address hashing | Extract recipient email, Poseidon2 hash for identity binding | -| Subject hashing | Extract subject field, Poseidon2 hash for intent binding | -| Timestamp extraction | Parse `t=` tag from DKIM-Signature for freshness check | -| Nullifier computation | Poseidon2 hash of DKIM signature for replay prevention | - -**Public outputs** (6 fields): -- `pubkey_hash[0]` — Poseidon hash of RSA modulus (root of trust) -- `pubkey_hash[1]` — Poseidon hash of RSA redc parameter -- `email_nullifier` — Poseidon2 hash of DKIM signature (prevents replay) -- `to_address_hash` — Poseidon2 hash of recipient email (identity binding) -- `intent_hash` — Poseidon2 hash of subject content (intent binding) -- `dkim_timestamp` — DKIM signing timestamp in seconds (freshness) - -## Troubleshooting - -**"Cannot find module '../contract/artifacts/ZKEmailVerifier'"** -Run `yarn ccc` to compile the contract and generate TypeScript bindings. - -**"Cannot find module '../data.json'"** -Run `yarn data` to generate the proof data. - -**"DKIM public key does not match trusted key"** -The proof was generated with a DKIM key that doesn't match the trusted key hashes stored at deployment. This can happen after a DKIM key rotation. To resolve, look up the current DKIM public key from DNS (e.g., `dig TXT ._domainkey.icloud.com`), compute its Poseidon hash, and redeploy the contract with the updated key hashes. Do not take key hashes from the rejected proof's own public inputs — those are prover-controlled and may not reflect a legitimate key. - -**"Email recipient does not match authorized address"** -The `to` address in the email doesn't match the `authorized_email_hash` stored at deployment. Ensure the proof was generated with the correct test email. - -**"Email has expired"** -The DKIM timestamp is older than `max_email_age`. For testing with the hardcoded test email (April 2024), use a large `max_email_age` value. +## Circuit Public Outputs (7 fields) -**"Duplicate nullifier"** -The same email proof has already been used. Each email can only authorize one action. +| Index | Output | Description | +|-------|--------|-------------| +| `[0]` | `pubkey_hash[0]` | Poseidon hash of DKIM RSA modulus (root of trust) | +| `[1]` | `pubkey_hash[1]` | Poseidon hash of DKIM RSA redc parameter | +| `[2]` | `email_nullifier` | Poseidon2 hash of DKIM signature (prevents replay) | +| `[3]` | `from_address_hash` | Poseidon2 hash of sender email (depositor identification) | +| `[4]` | `to_address_hash` | Poseidon2 hash of recipient email (recipient binding) | +| `[5]` | `intent_hash` | Poseidon2 hash of subject content (intent binding) | +| `[6]` | `dkim_timestamp` | DKIM signing timestamp in seconds (freshness) | ## Dependencies -- [zkemail.nr](https://github.com/critesjosh/zkemail.nr/tree/update/aztec-4.2.0-compat) — Noir library for DKIM email verification (Aztec 4.2.0 branch) -- [poseidon](https://github.com/noir-lang/poseidon) v0.2.0 — Poseidon2 hash function for Noir -- [aztec-nr](https://github.com/AztecProtocol/aztec-nr/) v4.2.0-aztecnr-rc.2 — Aztec smart contract framework -- [bb_proof_verification](https://github.com/AztecProtocol/aztec-packages/) — Barretenberg proof verification for Aztec contracts -- [@aztec/bb.js](https://www.npmjs.com/package/@aztec/bb.js) 4.2.0-aztecnr-rc.2 — UltraHonk proving backend +- [zkemail.nr](https://github.com/critesjosh/zkemail.nr/tree/update/aztec-4.2.0-compat) -- Noir DKIM email verification +- [poseidon](https://github.com/noir-lang/poseidon) v0.2.0 -- Poseidon2 hashing for Noir +- [aztec-nr](https://github.com/AztecProtocol/aztec-packages/) v4.2.0-aztecnr-rc.2 -- Aztec smart contract framework +- [bb_proof_verification](https://github.com/AztecProtocol/aztec-packages/) -- Barretenberg proof verification +- [@aztec/bb.js](https://www.npmjs.com/package/@aztec/bb.js) 4.2.0-aztecnr-rc.2 -- UltraHonk proving backend diff --git a/zkemail_verification/circuit/src/main.nr b/zkemail_verification/circuit/src/main.nr index 93054fc..4c314f2 100644 --- a/zkemail_verification/circuit/src/main.nr +++ b/zkemail_verification/circuit/src/main.nr @@ -22,9 +22,10 @@ global EXPECTED_DOMAIN: [u8; 10] = comptime { "icloud.com".as_bytes() }; /// [0]: Poseidon hash of DKIM public key modulus (root of trust) /// [1]: Poseidon hash of DKIM public key redc parameter /// [2]: Email nullifier (Poseidon2 hash of DKIM signature -- prevents replay) -/// [3]: Poseidon2 hash of recipient (to) email address (identity binding) -/// [4]: Poseidon2 hash of email subject (intent binding) -/// [5]: DKIM signing timestamp in seconds since epoch (freshness) +/// [3]: Poseidon2 hash of sender (from) email address (depositor identification) +/// [4]: Poseidon2 hash of recipient (to) email address (recipient binding) +/// [5]: Poseidon2 hash of email subject (intent binding) +/// [6]: DKIM signing timestamp in seconds since epoch (freshness) fn main( header: BoundedVec, pubkey: RSAPubkey, @@ -36,15 +37,17 @@ fn main( to_address_sequence: Sequence, subject_header_sequence: Sequence, dkim_timestamp_index: u32, -) -> pub [Field; 6] { +) -> pub [Field; 7] { assert(header.len() <= MAX_EMAIL_HEADER_LENGTH); // 1. Verify the DKIM signature over the email header let _ = pubkey.verify_dkim_signature(header, signature); - // 2. Extract and verify the sender's domain is icloud.com - // The header input must be DKIM-canonicalized (c=relaxed), which lowercases - // field names. All field name comparisons below use lowercase literals. + // 2. Extract and verify the sender's domain is icloud.com, then hash the full address. + // The domain check restricts which mail servers are trusted. The full address hash + // identifies the specific sender (e.g. bob@icloud.com) for deposit lookup. + // NOTE: Header field names are matched in lowercase. This assumes DKIM + // c=relaxed canonicalization, which lowercases header names before signing. let from_address: BoundedVec = get_email_address( header, from_header_sequence, @@ -52,8 +55,9 @@ fn main( comptime { "from".as_bytes() }, ); verify_domain(from_address, EXPECTED_DOMAIN); + let from_address_hash = hash_address(from_address); - // 3. Extract recipient (to) address and hash for identity binding + // 3. Extract recipient (to) address and hash for recipient binding let to_address: BoundedVec = get_email_address( header, to_header_sequence, @@ -72,7 +76,7 @@ fn main( let email_nullifier = Poseidon2::hash(signature, KEY_LIMBS_2048); let pubkey_hash = pubkey.hash(); - [pubkey_hash[0], pubkey_hash[1], email_nullifier, to_address_hash, intent_hash, timestamp] + [pubkey_hash[0], pubkey_hash[1], email_nullifier, from_address_hash, to_address_hash, intent_hash, timestamp] } /// Verify the domain part of an email address matches the expected domain. @@ -203,10 +207,14 @@ fn extract_dkim_timestamp( "Expected '=' before timestamp value", ); - // Parse decimal digits until non-digit (';' or end of header field) - let mut timestamp: Field = 0; + // Parse decimal digits until non-digit (';' or end of header field). + // The first byte must be a digit to prevent parsing an empty t= value as 0. + let first_byte = header.get_unchecked(timestamp_index); + assert((first_byte >= 48) & (first_byte <= 57), "Timestamp must start with a digit"); + + let mut timestamp: Field = (first_byte - 48) as Field; let mut done = false; - for i in 0..MAX_TIMESTAMP_DIGITS { + for i in 1..MAX_TIMESTAMP_DIGITS { if !done { let byte = header.get_unchecked(timestamp_index + i); if (byte >= 48) & (byte <= 57) { diff --git a/zkemail_verification/contract/Nargo.toml b/zkemail_verification/contract/Nargo.toml index 595996c..47a2bd9 100644 --- a/zkemail_verification/contract/Nargo.toml +++ b/zkemail_verification/contract/Nargo.toml @@ -1,8 +1,11 @@ [package] -name = "ZKEmailVerifier" +name = "EmailClaim" type = "contract" authors = [""] [dependencies] -aztec = { git = "https://github.com/AztecProtocol/aztec-nr/", tag = "v4.2.0-aztecnr-rc.2", directory = "aztec" } +aztec = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.2.0-aztecnr-rc.2", directory = "noir-projects/aztec-nr/aztec" } +uint_note = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.2.0-aztecnr-rc.2", directory = "noir-projects/aztec-nr/uint-note" } +balance_set = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.2.0-aztecnr-rc.2", directory = "noir-projects/aztec-nr/balance-set" } +token = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.2.0-aztecnr-rc.2", directory = "noir-projects/noir-contracts/contracts/app/token_contract" } bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v4.2.0-aztecnr-rc.2", directory = "barretenberg/noir/bb_proof_verification" } diff --git a/zkemail_verification/contract/src/main.nr b/zkemail_verification/contract/src/main.nr index 718d568..664f9fb 100644 --- a/zkemail_verification/contract/src/main.nr +++ b/zkemail_verification/contract/src/main.nr @@ -1,73 +1,153 @@ use aztec::macros::aztec; +/// A contract that completes partial notes using verified email proofs, entirely on L2. +/// +/// Bob deposits tokens into this contract and registers his email address hash. When Bob wants +/// to pay Carol, she creates a partial note for herself, sends Bob the commitment, and Bob sends +/// an email authorizing the payment. Carol generates a zkEmail proof offchain using a Noir circuit +/// and submits it to this contract. The contract verifies the proof using recursive proof +/// verification (verify_honk_proof), deducts from Bob's balance, and completes Carol's note. +/// +/// The contract enforces a 6-point security model: +/// 1. DKIM key binding -- only proofs using a trusted mail server key are accepted +/// 2. Sender identification -- the from-address hash identifies the depositor +/// 3. Recipient binding -- the email must be sent TO the authorized address +/// 4. Intent binding -- the email subject must match the expected action +/// 5. Single-use enforcement -- each email can only be claimed once (nullifier) +/// 6. Freshness -- emails older than max_email_age are rejected #[aztec] -pub contract ZKEmailVerifier { +pub contract EmailClaim { use aztec::{ - macros::{functions::{external, initializer, only_self, view}, storage::storage}, - oracle::logging::debug_log_format, - state_vars::PublicImmutable, + macros::{ + functions::{external, initializer, only_self, view}, + storage::storage, + }, + protocol::address::AztecAddress, + state_vars::{Map, Owned, PublicImmutable, PublicMutable, StateVariable}, }; + + use uint_note::{PartialUintNote, UintNote}; + use balance_set::BalanceSet; + use token::Token; use bb_proof_verification::{UltraHonkVerificationKey, UltraHonkZKProof, verify_honk_proof}; #[storage] struct Storage { + /// The token contract that this contract interacts with. + token: PublicImmutable, + /// Hash of the email verification circuit's verification key. Set at deployment and + /// never changed. The contract only accepts proofs generated from this specific circuit. vk_hash: PublicImmutable, /// Poseidon hash of the trusted DKIM RSA public key modulus. /// Proofs must use a key whose hash matches, preventing self-signed forgeries. trusted_dkim_key_hash_0: PublicImmutable, /// Poseidon hash of the trusted DKIM RSA public key redc parameter. trusted_dkim_key_hash_1: PublicImmutable, - /// Poseidon2 hash of the authorized recipient email address. - /// Only emails sent TO this address can authorize actions. - authorized_email_hash: PublicImmutable, /// Maximum allowed age of an email in seconds. /// Emails older than this (based on DKIM signing timestamp) are rejected. max_email_age: PublicImmutable, + /// Public balance per email address hash. Bob deposits tokens and maps them to his + /// email address hash. + deposits: Map, Context>, + /// Private balance storage for recipients. Partial notes are completed into this. + balances: Owned, Context>, } - #[initializer] #[external("public")] + #[initializer] fn constructor( + token: AztecAddress, vk_hash: Field, trusted_dkim_key_hash_0: Field, trusted_dkim_key_hash_1: Field, - authorized_email_hash: Field, max_email_age: Field, ) { + assert(!token.is_zero(), "Token address cannot be zero"); + self.storage.token.initialize(token); self.storage.vk_hash.initialize(vk_hash); self.storage.trusted_dkim_key_hash_0.initialize(trusted_dkim_key_hash_0); self.storage.trusted_dkim_key_hash_1.initialize(trusted_dkim_key_hash_1); - self.storage.authorized_email_hash.initialize(authorized_email_hash); self.storage.max_email_age.initialize(max_email_age); } - /// Verify an email proof and authorize an intent. + /// Bob deposits tokens and associates them with his email address hash. + /// + /// The email address hash is a Poseidon2 hash of the sender's email address bytes -- + /// the same hash that the email verification circuit produces from the From header. + /// Bob must know this hash and use the same email address when sending payment emails. + /// + /// Requires a public authwit on the token contract authorizing the transfer. + #[external("public")] + fn deposit(email_address_hash: Field, amount: u128, authwit_nonce: Field) { + assert(amount > 0, "Amount must be positive"); + let depositor = self.msg_sender(); + + // Transfer tokens from depositor to this contract. + self.call(Token::at(self.storage.token.read()).transfer_in_public( + depositor, + self.address, + amount, + authwit_nonce, + )); + + // Credit the email address hash balance. + let current = self.storage.deposits.at(email_address_hash).read(); + self.storage.deposits.at(email_address_hash).write(current + amount); + } + + /// Carol creates a partial note for herself, to be funded later via `claim_with_email`. + /// + /// Returns the PartialUintNote whose commitment Carol sends to Bob for inclusion in + /// the email subject. Randomness is sampled by the oracle for privacy. + #[external("private")] + fn create_claim() -> pub PartialUintNote { + let recipient = self.msg_sender(); + UintNote::partial( + recipient, + self.context, + recipient, + self.address, + ) + } + + /// Verify a zkEmail proof and complete a partial note, entirely on L2. + /// + /// The caller submits a proof generated by the email verification circuit. The proof + /// attests that a DKIM-signed email was sent from a specific sender on a verified + /// domain, to the correct recipient, with a subject encoding the intended action. + /// The contract enforces a 6-point security model: /// - /// The caller provides an expected_intent_hash which must match the hash of - /// the email's subject field (public_inputs[4]). This binds the email to a - /// specific action. + /// 1. DKIM key binding: the proof's public key hash must match the trusted key + /// 2. Sender identification: the from-address hash identifies the depositor + /// 3. Recipient binding: the email's to-address hash must match expected_recipient_hash + /// 4. Intent binding: the email's subject hash must match expected_intent_hash + /// 5. Single-use: the email nullifier prevents the same email from being claimed twice + /// 6. Freshness: the DKIM timestamp must be recent enough /// - /// Public inputs layout from the circuit: - /// [0]: pubkey_hash[0] -- must match trusted DKIM key - /// [1]: pubkey_hash[1] -- must match trusted DKIM key - /// [2]: email_nullifier -- prevents email reuse - /// [3]: to_address_hash -- must match authorized_email_hash - /// [4]: intent_hash -- hash of email subject (action being authorized) - /// [5]: dkim_timestamp -- when the email was signed + /// The circuit's public inputs are 7 fields: + /// [0] DKIM public key hash (modulus) + /// [1] DKIM public key hash (redc parameter) + /// [2] Email nullifier (prevents replay) + /// [3] Sender (from) address hash (depositor identification) + /// [4] Recipient (to) address hash (recipient binding) + /// [5] Subject hash (intent binding) + /// [6] DKIM signing timestamp (freshness) #[external("private")] - fn verify_email( + fn claim_with_email( + expected_recipient_hash: Field, expected_intent_hash: Field, + partial_note: PartialUintNote, + amount: u128, verification_key: UltraHonkVerificationKey, proof: UltraHonkZKProof, - public_inputs: [Field; 6], + public_inputs: [Field; 7], ) { - debug_log_format("Verifying email proof...", []); - - // Verify the ZK proof against the stored verification key hash + // Verify the zkEmail proof in private. This proves the email is authentically + // DKIM-signed without revealing the email contents onchain. let vk_hash = self.storage.vk_hash.read(); verify_honk_proof(verification_key, proof, public_inputs, vk_hash); - // Verify the DKIM public key matches the trusted key. + // 1. DKIM key binding: verify the proof used the trusted mail server key. // Without this, an attacker could generate their own RSA keypair, // forge a DKIM signature, and produce a valid proof. let trusted_key_0 = self.storage.trusted_dkim_key_hash_0.read(); @@ -81,55 +161,87 @@ pub contract ZKEmailVerifier { "DKIM public key does not match trusted key (redc)", ); - // Verify the email was sent to the authorized address - let authorized_email_hash = self.storage.authorized_email_hash.read(); + // 2. Sender identification: public_inputs[3] is the Poseidon2 hash of the + // sender's full email address (e.g. bob@icloud.com). The contract uses this + // to look up the correct deposit balance in the public completion step. + let from_address_hash = public_inputs[3]; + + // 3. Recipient binding: verify the email was sent to the expected address. + // This prevents an attacker from using an email sent to a different address. assert( - public_inputs[3] == authorized_email_hash, - "Email recipient does not match authorized address", + public_inputs[4] == expected_recipient_hash, + "Email recipient does not match expected address", ); - // Verify the intent matches what the caller expects + // 4. Intent binding: verify the email subject matches the expected action. + // The subject should encode the claim details (amount, commitment, etc.) + // in a canonical format agreed upon offchain. assert( - public_inputs[4] == expected_intent_hash, + public_inputs[5] == expected_intent_hash, "Email subject does not match expected intent", ); - // Push the email nullifier to prevent reuse of this email proof. + // 5. Single-use: push the email nullifier to prevent reuse. // The nullifier is automatically siloed by the contract address. // If this nullifier has already been emitted, the transaction will fail. self.context.push_nullifier(public_inputs[2]); - // Enqueue a public call to verify the email timestamp is fresh enough. + // 6. Freshness: enqueue a public call to verify the email timestamp is recent. // This must be checked in public context where the block timestamp is available. let max_email_age = self.storage.max_email_age.read(); - self.enqueue_self._check_email_freshness(public_inputs[5], max_email_age); + + // Enqueue the public completion: check freshness, deduct balance, complete note. + self.enqueue_self._complete( + from_address_hash, + partial_note, + amount, + public_inputs[6], + max_email_age, + ); } - /// Public function to verify the email's DKIM timestamp is recent enough. - /// Called via enqueue from the private verify_email function. - #[only_self] + /// Public completion step enqueued from `claim_with_email`. #[external("public")] - fn _check_email_freshness(email_timestamp: Field, max_age: Field) { + #[only_self] + fn _complete( + from_address_hash: Field, + partial_note: PartialUintNote, + amount: u128, + email_timestamp: Field, + max_age: Field, + ) { + // 6. Freshness check: reject emails that are too old. let current_ts: u64 = self.context.timestamp(); let email_ts: u64 = email_timestamp as u64; let max_age_secs: u64 = max_age as u64; - assert(current_ts >= email_ts, "Email timestamp is in the future"); assert( current_ts - email_ts <= max_age_secs, "Email has expired -- DKIM timestamp is too old", ); + + // Deduct from the depositor's balance. + let balance = self.storage.deposits.at(from_address_hash).read(); + assert(balance >= amount, "Insufficient depositor balance"); + self.storage.deposits.at(from_address_hash).write(balance - amount); + + // Complete the partial note with the claimed amount. + partial_note.complete( + self.context, + self.address, + self.storage.balances.get_storage_slot(), + amount, + ); } - #[view] #[external("public")] - fn get_authorized_email_hash() -> Field { - self.storage.authorized_email_hash.read() + #[view] + fn get_deposit_balance(email_address_hash: Field) -> pub u128 { + self.storage.deposits.at(email_address_hash).read() } - #[view] - #[external("public")] - fn get_max_email_age() -> Field { - self.storage.max_email_age.read() + #[external("utility")] + unconstrained fn get_private_balance(owner: AztecAddress) -> pub u128 { + self.storage.balances.at(owner).balance_of() } } diff --git a/zkemail_verification/scripts/generate_data.ts b/zkemail_verification/scripts/generate_data.ts index 709ecf8..cdcbbef 100644 --- a/zkemail_verification/scripts/generate_data.ts +++ b/zkemail_verification/scripts/generate_data.ts @@ -272,12 +272,13 @@ console.log(`Public inputs: ${proofData.publicInputs.length}`); // Log public input meanings console.log("\nPublic inputs breakdown:"); -console.log(` [0] pubkey_hash[0]: ${proofData.publicInputs[0]}`); -console.log(` [1] pubkey_hash[1]: ${proofData.publicInputs[1]}`); -console.log(` [2] email_nullifier: ${proofData.publicInputs[2]}`); -console.log(` [3] to_address_hash: ${proofData.publicInputs[3]}`); -console.log(` [4] intent_hash: ${proofData.publicInputs[4]}`); -console.log(` [5] dkim_timestamp: ${proofData.publicInputs[5]}`); +console.log(` [0] pubkey_hash[0]: ${proofData.publicInputs[0]}`); +console.log(` [1] pubkey_hash[1]: ${proofData.publicInputs[1]}`); +console.log(` [2] email_nullifier: ${proofData.publicInputs[2]}`); +console.log(` [3] from_address_hash: ${proofData.publicInputs[3]}`); +console.log(` [4] to_address_hash: ${proofData.publicInputs[4]}`); +console.log(` [5] intent_hash: ${proofData.publicInputs[5]}`); +console.log(` [6] dkim_timestamp: ${proofData.publicInputs[6]}`); // Write data.json const data = { diff --git a/zkemail_verification/scripts/run_testnet.ts b/zkemail_verification/scripts/run_testnet.ts index 31d762c..2322ead 100644 --- a/zkemail_verification/scripts/run_testnet.ts +++ b/zkemail_verification/scripts/run_testnet.ts @@ -3,18 +3,20 @@ import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee"; import type { FieldLike } from "@aztec/aztec.js/abi"; import { getSponsoredFPCInstance } from "./sponsored_fpc.js"; import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC"; -import { ZKEmailVerifierContract } from "../contract/artifacts/ZKEmailVerifier"; +import { TokenContract } from "@aztec/noir-contracts.js/Token"; +import { EmailClaimContract } from "../contract/artifacts/EmailClaim"; import data from "../data.json"; import { EmbeddedWallet } from "@aztec/wallets/embedded"; import { NO_FROM } from "@aztec/aztec.js/account"; import { Fr } from "@aztec/aztec.js/fields"; -import assert from "node:assert"; const TESTNET_URL = "https://rpc.testnet.aztec-labs.com"; // Maximum email age in seconds. Set very large for testing with old test email (April 2024). // In production, use a much shorter window (e.g., 15 * 60 for 15 minutes). const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60; +const DEPOSIT_AMOUNT = 500n; +const CLAIM_AMOUNT = 100n; const sponsoredFPC = await getSponsoredFPCInstance(); const sponsoredPaymentMethod = new SponsoredFeePaymentMethod( @@ -27,7 +29,6 @@ async function main() { const nodeInfo = await aztecNode.getNodeInfo(); console.log(`Testnet node version: ${nodeInfo.nodeVersion}`); - console.log(`Real proofs enabled: ${nodeInfo.realProofs}`); console.log("Creating EmbeddedWallet..."); const testWallet = await EmbeddedWallet.create(aztecNode, { @@ -35,64 +36,109 @@ async function main() { ephemeral: true, }); await testWallet.registerContract(sponsoredFPC, SponsoredFPCContract.artifact); - console.log("EmbeddedWallet configured"); - console.log("Creating Schnorr account..."); - const account = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); - const manager = await account.getDeployMethod(); - console.log("Deploying account (this will take a while on testnet with real proofs)..."); - await manager.send({ + // Create two accounts: Bob (depositor) and Carol (recipient) + console.log("Creating Bob's account..."); + const bobAccount = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); + await (await bobAccount.getDeployMethod()).send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + + console.log("Creating Carol's account..."); + const carolAccount = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); + await (await carolAccount.getDeployMethod()).send({ from: NO_FROM, fee: { paymentMethod: sponsoredPaymentMethod }, }); const accounts = await testWallet.getAccounts(); - const ownerAddress = accounts[0].item; - console.log(`Owner address: ${ownerAddress.toString()}`); + const bobAddress = accounts[0].item; + const carolAddress = accounts[1].item; + console.log(`Bob: ${bobAddress}`); + console.log(`Carol: ${carolAddress}`); - const sendOpts = { - from: ownerAddress, + const sendOpts = (from: any) => ({ + from, fee: { paymentMethod: sponsoredPaymentMethod }, - }; + }); - // Public inputs from proof: - // [0] = trusted DKIM pubkey hash (modulus) - // [1] = trusted DKIM pubkey hash (redc) - // [3] = to_address_hash (used as authorized_email_hash) - // [4] = intent_hash (subject hash) + // Public inputs from proof const trustedDkimKeyHash0 = data.publicInputs[0] as unknown as FieldLike; const trustedDkimKeyHash1 = data.publicInputs[1] as unknown as FieldLike; - const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike; - const intentHash = data.publicInputs[4] as unknown as FieldLike; + const fromAddressHash = data.publicInputs[3] as unknown as FieldLike; + const toAddressHash = data.publicInputs[4] as unknown as FieldLike; + const intentHash = data.publicInputs[5] as unknown as FieldLike; - console.log("Deploying ZKEmailVerifier contract..."); - const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( + // 1. Deploy Token contract + console.log("\n--- Deploy Token ---"); + const { contract: token } = await TokenContract.deploy( testWallet, + bobAddress, + "TestToken", + "TT", + 18, + ).send(sendOpts(bobAddress)); + console.log(`Token deployed at: ${token.address}`); + + // Mint tokens to Bob + await token.methods.mint_to_public(bobAddress, DEPOSIT_AMOUNT).send(sendOpts(bobAddress)); + console.log(`Minted ${DEPOSIT_AMOUNT} tokens to Bob`); + + // 2. Deploy EmailClaim contract + console.log("\n--- Deploy EmailClaim ---"); + const { contract: emailClaim } = await EmailClaimContract.deploy( + testWallet, + token.address, data.vkHash as unknown as FieldLike, trustedDkimKeyHash0, trustedDkimKeyHash1, - authorizedEmailHash, MAX_EMAIL_AGE, - ).send(sendOpts); - - console.log(`Contract deployed at: ${zkEmailVerifier.address.toString()}`); - - console.log("Submitting ZK email proof for on-chain verification..."); - const { receipt: tx } = await zkEmailVerifier.methods.verify_email( + ).send(sendOpts(bobAddress)); + console.log(`EmailClaim deployed at: ${emailClaim.address}`); + + // 3. Bob deposits tokens + console.log("\n--- Bob Deposits ---"); + const authwitNonce = Fr.random(); + await testWallet.setPublicAuthWit( + { + caller: emailClaim.address, + action: token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce), + }, + true, + ).send(sendOpts(bobAddress)); + + await emailClaim.methods.deposit( + fromAddressHash, + DEPOSIT_AMOUNT, + authwitNonce, + ).send(sendOpts(bobAddress)); + console.log(`Bob deposited ${DEPOSIT_AMOUNT} tokens`); + + // 4. Carol creates a claim + console.log("\n--- Carol Creates Claim ---"); + const { result: partialNote } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)); + console.log(`Partial note created: ${partialNote}`); + + // 5. Carol claims with email proof + console.log("\n--- Carol Claims with Email Proof ---"); + const { receipt: tx } = await emailClaim.methods.claim_with_email( + toAddressHash, intentHash, + partialNote, + CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], - ).send(sendOpts); - - console.log(`Transaction hash: ${tx.txHash.toString()}`); - console.log(`Transaction status: ${tx.status}`); - - console.log("SUCCESS: ZK email proof verified on Aztec testnet!"); - console.log(" - Recipient address verified against authorized email hash"); - console.log(" - Intent hash verified from email subject"); - console.log(" - Email nullifier pushed (prevents reuse)"); - console.log(" - Email freshness checked against timestamp"); + ).send(sendOpts(carolAddress)); + console.log(`Claim tx: ${tx.txHash}`); + console.log(`Status: ${tx.status}`); + + // 6. Verify + console.log("\n--- Verify ---"); + const depositAfter = (await emailClaim.methods.get_deposit_balance(fromAddressHash).simulate({ from: bobAddress })).result; + console.log(`Bob's deposit balance: ${depositAfter}`); + console.log("\nSUCCESS: Offchain email-authorized token transfer completed on testnet!"); await testWallet.stop(); } diff --git a/zkemail_verification/scripts/run_verification.ts b/zkemail_verification/scripts/run_verification.ts index 74d5af0..8260425 100644 --- a/zkemail_verification/scripts/run_verification.ts +++ b/zkemail_verification/scripts/run_verification.ts @@ -3,18 +3,20 @@ import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee"; import type { FieldLike } from "@aztec/aztec.js/abi"; import { getSponsoredFPCInstance } from "./sponsored_fpc.js"; import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC"; -import { ZKEmailVerifierContract } from "../contract/artifacts/ZKEmailVerifier"; +import { TokenContract } from "@aztec/noir-contracts.js/Token"; +import { EmailClaimContract } from "../contract/artifacts/EmailClaim"; import data from "../data.json"; import { EmbeddedWallet } from "@aztec/wallets/embedded"; import { NO_FROM } from "@aztec/aztec.js/account"; import { Fr } from "@aztec/aztec.js/fields"; -import assert from "node:assert"; export const NODE_URL = "http://localhost:8080"; // Maximum email age in seconds. Set very large for testing with old test email (April 2024). // In production, use a much shorter window (e.g., 15 * 60 for 15 minutes). const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60; +const DEPOSIT_AMOUNT = 500n; +const CLAIM_AMOUNT = 100n; const sponsoredFPC = await getSponsoredFPCInstance(); const sponsoredPaymentMethod = new SponsoredFeePaymentMethod( @@ -29,7 +31,6 @@ export const setupWallet = async (): Promise => { ephemeral: true, }); await wallet.registerContract(sponsoredFPC, SponsoredFPCContract.artifact); - return wallet; } catch (error) { console.error("Failed to setup local network:", error); @@ -41,76 +42,113 @@ async function main() { console.log("Setting up wallet with proverEnabled: true..."); const testWallet = await setupWallet(); - console.log("Creating Schnorr account..."); - const account = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); - const manager = await account.getDeployMethod(); - await manager - .send({ - from: NO_FROM, - fee: { paymentMethod: sponsoredPaymentMethod }, - }); + // Create two accounts: Bob (depositor) and Carol (recipient) + console.log("Creating Bob's account..."); + const bobAccount = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); + await (await bobAccount.getDeployMethod()).send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + + console.log("Creating Carol's account..."); + const carolAccount = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()); + await (await carolAccount.getDeployMethod()).send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + const accounts = await testWallet.getAccounts(); - const ownerAddress = accounts[0].item; - console.info('Owner address:', ownerAddress.toString()); - - // Public inputs from proof: - // [0] = trusted DKIM pubkey hash (modulus) - // [1] = trusted DKIM pubkey hash (redc) - // [3] = to_address_hash (used as authorized_email_hash) - // [4] = intent_hash (subject hash) + const bobAddress = accounts[0].item; + const carolAddress = accounts[1].item; + console.log(`Bob: ${bobAddress}`); + console.log(`Carol: ${carolAddress}`); + + const sendOpts = (from: any) => ({ + from, + fee: { paymentMethod: sponsoredPaymentMethod }, + }); + + // Public inputs from proof const trustedDkimKeyHash0 = data.publicInputs[0] as unknown as FieldLike; const trustedDkimKeyHash1 = data.publicInputs[1] as unknown as FieldLike; - const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike; - const intentHash = data.publicInputs[4] as unknown as FieldLike; + const fromAddressHash = data.publicInputs[3] as unknown as FieldLike; + const toAddressHash = data.publicInputs[4] as unknown as FieldLike; + const intentHash = data.publicInputs[5] as unknown as FieldLike; - console.log("Deploying ZKEmailVerifier contract..."); - const { contract: zkEmailVerifier } = await ZKEmailVerifierContract.deploy( + // 1. Deploy Token contract + console.log("\n--- Deploy Token ---"); + const { contract: token } = await TokenContract.deploy( testWallet, + bobAddress, // admin + "TestToken", + "TT", + 18, + ).send(sendOpts(bobAddress)); + console.log(`Token deployed at: ${token.address}`); + + // Mint tokens to Bob's public balance + await token.methods.mint_to_public(bobAddress, DEPOSIT_AMOUNT).send(sendOpts(bobAddress)); + const bobPublicBalance = (await token.methods.balance_of_public(bobAddress).simulate({ from: bobAddress })).result; + console.log(`Bob's public token balance: ${bobPublicBalance}`); + + // 2. Deploy EmailClaim contract + console.log("\n--- Deploy EmailClaim ---"); + const { contract: emailClaim } = await EmailClaimContract.deploy( + testWallet, + token.address, data.vkHash as unknown as FieldLike, trustedDkimKeyHash0, trustedDkimKeyHash1, - authorizedEmailHash, MAX_EMAIL_AGE, - ) - .send({ - from: ownerAddress, - fee: { paymentMethod: sponsoredPaymentMethod }, - }); + ).send(sendOpts(bobAddress)); + console.log(`EmailClaim deployed at: ${emailClaim.address}`); - console.log("Contract deployed at:", zkEmailVerifier.address.toString()); + // 3. Bob deposits tokens + console.log("\n--- Bob Deposits ---"); + // Bob authorizes the EmailClaim contract to pull his tokens + const authwitNonce = Fr.random(); + await testWallet.setPublicAuthWit( + { + caller: emailClaim.address, + action: token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce), + }, + true, + ).send(sendOpts(bobAddress)); - console.log("Submitting email proof for on-chain verification (this may take 5-15 minutes with real proofs)..."); - const opts = { - from: ownerAddress, - fee: { paymentMethod: sponsoredPaymentMethod }, - }; + await emailClaim.methods.deposit( + fromAddressHash, + DEPOSIT_AMOUNT, + authwitNonce, + ).send(sendOpts(bobAddress)); + + const depositBalance = (await emailClaim.methods.get_deposit_balance(fromAddressHash).simulate({ from: bobAddress })).result; + console.log(`Deposit balance for Bob's email: ${depositBalance}`); - await zkEmailVerifier.methods.verify_email( + // 4. Carol creates a claim (partial note) + console.log("\n--- Carol Creates Claim ---"); + const { result: partialNote } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)); + console.log(`Partial note commitment: ${partialNote}`); + + // 5. Carol submits the email proof to complete the claim + console.log("\n--- Carol Claims with Email Proof ---"); + await emailClaim.methods.claim_with_email( + toAddressHash, intentHash, + partialNote, + CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], - ).send(opts); - - console.log("SUCCESS: Email proof verified on-chain!"); - console.log(" - Recipient address verified against authorized email hash"); - console.log(" - Intent hash verified from email subject"); - console.log(" - Email nullifier pushed (prevents reuse)"); - console.log(" - Email freshness checked against timestamp"); + ).send(sendOpts(carolAddress)); + console.log("Email proof verified and claim completed!"); - // Attempting to reuse the same email proof should fail - console.log("\nAttempting to reuse the same email proof (should fail)..."); - try { - await zkEmailVerifier.methods.verify_email( - intentHash, - data.vkAsFields as unknown as FieldLike[], - data.proofAsFields as unknown as FieldLike[], - data.publicInputs as unknown as FieldLike[], - ).send(opts); - assert.fail("Expected reuse to fail due to duplicate nullifier"); - } catch (e: any) { - console.log("Reuse correctly rejected:", e.message?.substring(0, 100)); - } + // 6. Verify balances + console.log("\n--- Verify ---"); + const depositAfter = (await emailClaim.methods.get_deposit_balance(fromAddressHash).simulate({ from: bobAddress })).result; + const carolPrivateBalance = await emailClaim.methods.get_private_balance(carolAddress).simulate({ from: carolAddress }); + console.log(`Bob's deposit balance after claim: ${depositAfter}`); + console.log(`Carol's private balance: ${carolPrivateBalance}`); + console.log("\nSUCCESS: Offchain email authorization completed!"); } main().catch((error) => { diff --git a/zkemail_verification/tests/zkemail_verification.test.ts b/zkemail_verification/tests/zkemail_verification.test.ts index 4c4beee..165b5d0 100644 --- a/zkemail_verification/tests/zkemail_verification.test.ts +++ b/zkemail_verification/tests/zkemail_verification.test.ts @@ -8,7 +8,8 @@ import { createAztecNodeClient } from "@aztec/aztec.js/node" import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee" import { EmbeddedWallet } from "@aztec/wallets/embedded" import { SponsoredFPCContract } from "@aztec/noir-contracts.js/SponsoredFPC" -import { ZKEmailVerifierContract } from '../contract/artifacts/ZKEmailVerifier' +import { TokenContract } from "@aztec/noir-contracts.js/Token" +import { EmailClaimContract } from '../contract/artifacts/EmailClaim' import { getSponsoredFPCInstance } from '../scripts/sponsored_fpc' import data from '../data.json' @@ -17,53 +18,62 @@ const TEST_TIMEOUT = 1200000 // 20 minutes // Maximum email age in seconds. Set very large for testing with old test email (April 2024). // In production, use a much shorter window (e.g., 15 * 60 for 15 minutes). -const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60; +const MAX_EMAIL_AGE = 100 * 365 * 24 * 60 * 60 +const DEPOSIT_AMOUNT = 500n +const CLAIM_AMOUNT = 100n -describe("ZKEmail Verification", () => { +describe("ZKEmail Offchain Transfer", () => { let testWallet: EmbeddedWallet - let ownerAddress: AztecAddress - let zkEmailVerifierContract: ZKEmailVerifierContract + let bobAddress: AztecAddress + let carolAddress: AztecAddress + let token: TokenContract + let emailClaim: EmailClaimContract let sponsoredPaymentMethod: SponsoredFeePaymentMethod - // Public inputs from proof: - // [0] = trusted DKIM pubkey hash (modulus) - // [1] = trusted DKIM pubkey hash (redc) - // [3] = to_address_hash (authorized email hash) - // [4] = intent_hash (subject hash) + // Public inputs from proof const trustedDkimKeyHash0 = data.publicInputs[0] as unknown as FieldLike const trustedDkimKeyHash1 = data.publicInputs[1] as unknown as FieldLike - const authorizedEmailHash = data.publicInputs[3] as unknown as FieldLike - const intentHash = data.publicInputs[4] as unknown as FieldLike + const fromAddressHash = data.publicInputs[3] as unknown as FieldLike + const toAddressHash = data.publicInputs[4] as unknown as FieldLike + const intentHash = data.publicInputs[5] as unknown as FieldLike + + const sendOpts = (from: AztecAddress) => ({ + from, + fee: { paymentMethod: sponsoredPaymentMethod }, + }) beforeAll(async () => { console.log(`Connecting to Aztec Node at ${NODE_URL}`) const aztecNode = await createAztecNodeClient(NODE_URL) - const sponsoredFPC = await getSponsoredFPCInstance() sponsoredPaymentMethod = new SponsoredFeePaymentMethod(sponsoredFPC.address) - // Create EmbeddedWallet with proverEnabled: true for real proof verification testWallet = await EmbeddedWallet.create(aztecNode, { pxeConfig: { proverEnabled: true }, ephemeral: true, }) - await testWallet.registerContract(sponsoredFPC, SponsoredFPCContract.artifact) - console.log('EmbeddedWallet configured with proverEnabled: true') - console.log('Creating owner account...') - const ownerAccountManager = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()) - const ownerDeployMethod = await ownerAccountManager.getDeployMethod() - console.log('Deploying account (this may take a while with real proof generation)...') - await ownerDeployMethod.send({ + // Create Bob and Carol accounts + console.log('Creating Bob account...') + const bobAccountManager = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()) + await (await bobAccountManager.getDeployMethod()).send({ + from: NO_FROM, + fee: { paymentMethod: sponsoredPaymentMethod }, + }) + + console.log('Creating Carol account...') + const carolAccountManager = await testWallet.createSchnorrAccount(Fr.random(), Fr.random()) + await (await carolAccountManager.getDeployMethod()).send({ from: NO_FROM, fee: { paymentMethod: sponsoredPaymentMethod }, }) - console.log('Account deployed!') const accounts = await testWallet.getAccounts() - ownerAddress = accounts[0].item - console.info('Owner address:', ownerAddress.toString()) + bobAddress = accounts[0].item + carolAddress = accounts[1].item + console.log(`Bob: ${bobAddress}`) + console.log(`Carol: ${carolAddress}`) }, TEST_TIMEOUT) afterAll(async () => { @@ -72,95 +82,96 @@ describe("ZKEmail Verification", () => { } }) - test("should deploy ZKEmailVerifier contract with authorized email and max age", async () => { - const sendOpts = { - from: ownerAddress, - fee: { paymentMethod: sponsoredPaymentMethod }, - } - - ;({ contract: zkEmailVerifierContract } = await ZKEmailVerifierContract.deploy( + test("should deploy Token and EmailClaim contracts", async () => { + // Deploy token + ;({ contract: token } = await TokenContract.deploy( testWallet, + bobAddress, + "TestToken", + "TT", + 18, + ).send(sendOpts(bobAddress))) + expect(token.address.toString()).not.toBe("") + + // Mint to Bob + await token.methods.mint_to_public(bobAddress, DEPOSIT_AMOUNT).send(sendOpts(bobAddress)) + + // Deploy EmailClaim + ;({ contract: emailClaim } = await EmailClaimContract.deploy( + testWallet, + token.address, data.vkHash as unknown as FieldLike, trustedDkimKeyHash0, trustedDkimKeyHash1, - authorizedEmailHash, MAX_EMAIL_AGE, - ) - .send(sendOpts)) + ).send(sendOpts(bobAddress))) + expect(emailClaim.address.toString()).not.toBe("") - expect(zkEmailVerifierContract.address).toBeDefined() - expect(zkEmailVerifierContract.address.toString()).not.toBe("") + console.log(`Token: ${token.address}`) + console.log(`EmailClaim: ${emailClaim.address}`) + }, TEST_TIMEOUT) - console.log("Contract deployed at address:", zkEmailVerifierContract.address.toString()) + test("should allow Bob to deposit tokens", async () => { + const authwitNonce = Fr.random() + await testWallet.setPublicAuthWit( + { + caller: emailClaim.address, + action: token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce), + }, + true, + ).send(sendOpts(bobAddress)) + + await emailClaim.methods.deposit( + fromAddressHash, + DEPOSIT_AMOUNT, + authwitNonce, + ).send(sendOpts(bobAddress)) + + const balance = (await emailClaim.methods.get_deposit_balance(fromAddressHash).simulate({ from: bobAddress })).result + expect(balance).toBe(DEPOSIT_AMOUNT) + console.log(`Bob deposited ${DEPOSIT_AMOUNT}, balance: ${balance}`) }, TEST_TIMEOUT) - test("should verify email proof with correct intent and recipient", async () => { - const sendOpts = { - from: ownerAddress, - fee: { paymentMethod: sponsoredPaymentMethod }, - } + test("should allow Carol to create a claim and complete it with email proof", async () => { + // Carol creates partial note + const { result: partialNote } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)) + expect(partialNote).toBeDefined() + console.log(`Partial note: ${partialNote}`) - console.log("Submitting email proof for on-chain verification...") - const { receipt: tx } = await zkEmailVerifierContract.methods.verify_email( + // Carol completes claim with email proof + const { receipt: tx } = await emailClaim.methods.claim_with_email( + toAddressHash, intentHash, + partialNote, + CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], - ).send(sendOpts) - expect(tx).toBeDefined() - expect(tx.txHash).toBeDefined() + ).send(sendOpts(carolAddress)) expect(tx.executionResult).toBe(TxExecutionResult.SUCCESS) - - console.log(`Transaction hash: ${tx.txHash.toString()}`) - console.log(`Transaction status: ${tx.status}`) - console.log("Email proof verified — nullifier pushed, timestamp checked") + console.log(`Claim tx: ${tx.txHash}`) }, TEST_TIMEOUT) - test("should reject reuse of the same email proof (nullifier prevents replay)", async () => { - const sendOpts = { - from: ownerAddress, - fee: { paymentMethod: sponsoredPaymentMethod }, - } - - console.log("Attempting to reuse the same email proof (should fail due to duplicate nullifier)...") - await expect( - zkEmailVerifierContract.methods.verify_email( - intentHash, - data.vkAsFields as unknown as FieldLike[], - data.proofAsFields as unknown as FieldLike[], - data.publicInputs as unknown as FieldLike[], - ).send(sendOpts) - ).rejects.toThrow() - - console.log("Replay correctly rejected — email nullifier prevents reuse") + test("should reflect correct balances after claim", async () => { + const depositAfter = (await emailClaim.methods.get_deposit_balance(fromAddressHash).simulate({ from: bobAddress })).result + expect(depositAfter).toBe(DEPOSIT_AMOUNT - CLAIM_AMOUNT) + console.log(`Bob's deposit after claim: ${depositAfter}`) }, TEST_TIMEOUT) - test("should reject email proof with wrong intent hash", async () => { - const sendOpts = { - from: ownerAddress, - fee: { paymentMethod: sponsoredPaymentMethod }, - } + test("should reject replay of same email proof", async () => { + const { result: partialNote2 } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)) - const wrongIntentHash = Fr.random() as unknown as FieldLike - - console.log("Submitting proof with wrong intent hash (should fail)...") await expect( - zkEmailVerifierContract.methods.verify_email( - wrongIntentHash, + emailClaim.methods.claim_with_email( + toAddressHash, + intentHash, + partialNote2, + CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], data.publicInputs as unknown as FieldLike[], - ).send(sendOpts) + ).send(sendOpts(carolAddress)) ).rejects.toThrow() - - console.log("Wrong intent hash correctly rejected") - }, TEST_TIMEOUT) - - test("should read stored authorized email hash", async () => { - const { result: storedHash } = await zkEmailVerifierContract.methods.get_authorized_email_hash() - .simulate({ from: ownerAddress }) - - expect(storedHash).toBe(BigInt(data.publicInputs[3])) - console.log(`Stored authorized email hash: ${storedHash}`) + console.log("Replay correctly rejected -- nullifier prevents reuse") }, TEST_TIMEOUT) }) From 508dad92912336ae66bcf9e749347696292c5e67 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 15:20:35 -0400 Subject: [PATCH 09/11] Use SetPublicAuthwitContractInteraction for public authwit setup Replace testWallet.setPublicAuthWit().send() with the explicit SetPublicAuthwitContractInteraction.create() API, which is the correct way to set public authwits on EmbeddedWallet. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/scripts/run_testnet.ts | 14 ++++++++------ zkemail_verification/scripts/run_verification.ts | 14 ++++++++------ .../tests/zkemail_verification.test.ts | 14 ++++++++------ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/zkemail_verification/scripts/run_testnet.ts b/zkemail_verification/scripts/run_testnet.ts index 2322ead..3f6f26f 100644 --- a/zkemail_verification/scripts/run_testnet.ts +++ b/zkemail_verification/scripts/run_testnet.ts @@ -9,6 +9,7 @@ import data from "../data.json"; import { EmbeddedWallet } from "@aztec/wallets/embedded"; import { NO_FROM } from "@aztec/aztec.js/account"; import { Fr } from "@aztec/aztec.js/fields"; +import { SetPublicAuthwitContractInteraction } from "@aztec/aztec.js/authorization"; const TESTNET_URL = "https://rpc.testnet.aztec-labs.com"; @@ -100,13 +101,14 @@ async function main() { // 3. Bob deposits tokens console.log("\n--- Bob Deposits ---"); const authwitNonce = Fr.random(); - await testWallet.setPublicAuthWit( - { - caller: emailClaim.address, - action: token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce), - }, + const depositAction = token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce); + const authwit = await SetPublicAuthwitContractInteraction.create( + testWallet, + bobAddress, + { caller: emailClaim.address, action: depositAction }, true, - ).send(sendOpts(bobAddress)); + ); + await authwit.send(sendOpts(bobAddress)); await emailClaim.methods.deposit( fromAddressHash, diff --git a/zkemail_verification/scripts/run_verification.ts b/zkemail_verification/scripts/run_verification.ts index 8260425..9193c84 100644 --- a/zkemail_verification/scripts/run_verification.ts +++ b/zkemail_verification/scripts/run_verification.ts @@ -9,6 +9,7 @@ import data from "../data.json"; import { EmbeddedWallet } from "@aztec/wallets/embedded"; import { NO_FROM } from "@aztec/aztec.js/account"; import { Fr } from "@aztec/aztec.js/fields"; +import { SetPublicAuthwitContractInteraction } from "@aztec/aztec.js/authorization"; export const NODE_URL = "http://localhost:8080"; @@ -107,13 +108,14 @@ async function main() { console.log("\n--- Bob Deposits ---"); // Bob authorizes the EmailClaim contract to pull his tokens const authwitNonce = Fr.random(); - await testWallet.setPublicAuthWit( - { - caller: emailClaim.address, - action: token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce), - }, + const depositAction = token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce); + const authwit = await SetPublicAuthwitContractInteraction.create( + testWallet, + bobAddress, + { caller: emailClaim.address, action: depositAction }, true, - ).send(sendOpts(bobAddress)); + ); + await authwit.send(sendOpts(bobAddress)); await emailClaim.methods.deposit( fromAddressHash, diff --git a/zkemail_verification/tests/zkemail_verification.test.ts b/zkemail_verification/tests/zkemail_verification.test.ts index 165b5d0..ef26647 100644 --- a/zkemail_verification/tests/zkemail_verification.test.ts +++ b/zkemail_verification/tests/zkemail_verification.test.ts @@ -4,6 +4,7 @@ import { TxExecutionResult } from "@aztec/aztec.js/tx" import { AztecAddress } from "@aztec/aztec.js/addresses" import { NO_FROM } from "@aztec/aztec.js/account" import { Fr } from "@aztec/aztec.js/fields" +import { SetPublicAuthwitContractInteraction } from "@aztec/aztec.js/authorization" import { createAztecNodeClient } from "@aztec/aztec.js/node" import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee" import { EmbeddedWallet } from "@aztec/wallets/embedded" @@ -113,13 +114,14 @@ describe("ZKEmail Offchain Transfer", () => { test("should allow Bob to deposit tokens", async () => { const authwitNonce = Fr.random() - await testWallet.setPublicAuthWit( - { - caller: emailClaim.address, - action: token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce), - }, + const depositAction = token.methods.transfer_in_public(bobAddress, emailClaim.address, DEPOSIT_AMOUNT, authwitNonce) + const authwit = await SetPublicAuthwitContractInteraction.create( + testWallet, + bobAddress, + { caller: emailClaim.address, action: depositAction }, true, - ).send(sendOpts(bobAddress)) + ) + await authwit.send(sendOpts(bobAddress)) await emailClaim.methods.deposit( fromAddressHash, From 5a96ddd4f8f18f7a0b5a4d4dc3d7ec67a6385e28 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 15:24:03 -0400 Subject: [PATCH 10/11] Expand privacy tradeoffs section in README Clarify what stays private (email content, Carol's identity) vs. what is public (deposit amounts, email address hash linkability, claim amounts, deposit-to-claim linkage). Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index 4f478ea..a268244 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -45,9 +45,15 @@ At Aztec v4.2.0, `UintNote::partial()` samples randomness internally via the ora ### Privacy Tradeoffs -- **Bob's deposit is public.** Observers can see how much Bob deposited and when funds are consumed. -- **Carol's identity is hidden.** The partial note commitment hides her address. -- **The claim amount is public.** The partial note is completed in public, so the amount is visible. +**What stays private:** +- **The email is never revealed onchain.** The zkEmail proof attests to properties of the email (sender, recipient, subject, timestamp) without exposing the raw headers or body. Observers see only hashes and the proof. +- **Carol's identity is hidden.** The partial note commitment hides her address. Observers cannot determine who received the tokens. + +**What is public:** +- **Bob's deposit and balance.** The `deposit()` call and the `deposits` map are public state. Observers can see how much Bob deposited, his email address hash, and when funds are deducted. +- **Bob's email address hash is linkable.** The `from_address_hash` is stored in public state and passed through `_complete`. Anyone who knows (or guesses) Bob's email address can compute the hash and confirm he is the depositor. +- **The claim amount is visible.** The partial note is completed in `_complete` (a public function), so the transfer amount is onchain. +- **Deposit-to-claim linkage.** An observer can see that a specific deposit balance was deducted in the same transaction that completed a partial note, linking the funding source to the claim event -- even though Carol's identity remains hidden. ## Architecture From cd78e30544f42b0c60d2502d75086d383a705ddc Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 15 Apr 2026 15:53:33 -0400 Subject: [PATCH 11/11] Accept caller-provided randomness in create_claim for deterministic partial notes Replaces UintNote::partial() with manual partial note creation that accepts a randomness parameter, allowing Carol to compute the commitment offchain before the transaction lands. Updates scripts and tests to compute commitments client-side via poseidon2HashWithSeparator and pass { commitment } to claim_with_email. Co-Authored-By: Claude Opus 4.6 (1M context) --- zkemail_verification/README.md | 4 +- zkemail_verification/contract/src/main.nr | 58 ++++++++++++++++--- zkemail_verification/scripts/run_testnet.ts | 16 ++++- .../scripts/run_verification.ts | 13 ++++- .../tests/zkemail_verification.test.ts | 25 ++++++-- 5 files changed, 94 insertions(+), 22 deletions(-) diff --git a/zkemail_verification/README.md b/zkemail_verification/README.md index a268244..55af7bf 100644 --- a/zkemail_verification/README.md +++ b/zkemail_verification/README.md @@ -39,9 +39,9 @@ A production system should replace the static key hash with a **DKIM key registr In either case, the contract should check key expiry and support updates without redeployment. -### Partial Note UX Note +### Deterministic Partial Notes -At Aztec v4.2.0, `UintNote::partial()` samples randomness internally via the oracle, meaning Carol cannot precompute the partial note commitment offchain -- she must get it from the transaction return value. A future `UintNote::partial_with_randomness(randomness)` API (where Carol supplies the randomness) would let Carol compute the commitment deterministically before submitting any transaction. This would improve the UX by allowing Carol to include the commitment in the email she asks Bob to send, before her `create_claim` transaction even lands. +The contract's `create_claim(randomness)` accepts caller-provided randomness so Carol can compute the partial note commitment offchain as `poseidon2([carolAddress, randomness], DomainSeparator.NOTE_HASH)` before the transaction lands. This lets Carol include the commitment in the email she asks Bob to send, without waiting for `create_claim` to finalize. The standard `UintNote::partial()` at v4.2.0 samples randomness from the oracle, which doesn't support this UX -- so the contract reimplements the partial note creation logic with explicit randomness. Carol is responsible for generating cryptographically-strong randomness; a predictable value enables brute-force recovery of her address from the public commitment. ### Privacy Tradeoffs diff --git a/zkemail_verification/contract/src/main.nr b/zkemail_verification/contract/src/main.nr index 664f9fb..89c1de2 100644 --- a/zkemail_verification/contract/src/main.nr +++ b/zkemail_verification/contract/src/main.nr @@ -22,15 +22,36 @@ pub contract EmailClaim { functions::{external, initializer, only_self, view}, storage::storage, }, - protocol::address::AztecAddress, + messages::{ + logs::partial_note::encode_partial_note_private_message, + message_delivery::{do_private_message_delivery, MessageDelivery}, + }, + protocol::{ + address::AztecAddress, + constants::DOM_SEP__NOTE_HASH, + hash::poseidon2_hash_with_separator, + traits::{FromField, ToField}, + }, state_vars::{Map, Owned, PublicImmutable, PublicMutable, StateVariable}, }; use uint_note::{PartialUintNote, UintNote}; + use aztec::note::note_interface::NoteType; use balance_set::BalanceSet; use token::Token; use bb_proof_verification::{UltraHonkVerificationKey, UltraHonkZKProof, verify_honk_proof}; + /// Log content type for partial note delivery. Replicates the internal + /// UintPartialNotePrivateLogContent from uint_note. + #[derive(aztec::protocol::traits::Packable)] + struct PartialLogContent {} + + impl NoteType for PartialLogContent { + fn get_id() -> Field { + UintNote::get_id() + } + } + #[storage] struct Storage { /// The token contract that this contract interacts with. @@ -97,17 +118,38 @@ pub contract EmailClaim { /// Carol creates a partial note for herself, to be funded later via `claim_with_email`. /// - /// Returns the PartialUintNote whose commitment Carol sends to Bob for inclusion in - /// the email subject. Randomness is sampled by the oracle for privacy. + /// Carol provides randomness so the commitment is deterministic from her inputs, + /// allowing her to compute it offchain before the transaction lands. The commitment + /// is `poseidon2([owner, randomness], DOM_SEP__NOTE_HASH)`. + /// + /// The caller is responsible for generating cryptographically-strong randomness. #[external("private")] - fn create_claim() -> pub PartialUintNote { + fn create_claim(randomness: Field) -> pub PartialUintNote { let recipient = self.msg_sender(); - UintNote::partial( - recipient, + + // Compute the partial note commitment (same as uint_note's compute_partial_commitment) + let commitment = poseidon2_hash_with_separator( + [recipient.to_field(), randomness], + DOM_SEP__NOTE_HASH, + ); + + // Send the partial note log to the recipient for note discovery + let private_log_content = PartialLogContent {}; + do_private_message_delivery( self.context, + || encode_partial_note_private_message(private_log_content, recipient, randomness, commitment), + Option::none(), recipient, - self.address, - ) + MessageDelivery.ONCHAIN_UNCONSTRAINED, + ); + + let partial_note = PartialUintNote::from_field(commitment); + + // Push validity commitment to nullifier tree + let validity_commitment = partial_note.compute_validity_commitment(self.address); + self.context.push_nullifier(validity_commitment); + + partial_note } /// Verify a zkEmail proof and complete a partial note, entirely on L2. diff --git a/zkemail_verification/scripts/run_testnet.ts b/zkemail_verification/scripts/run_testnet.ts index 3f6f26f..073733a 100644 --- a/zkemail_verification/scripts/run_testnet.ts +++ b/zkemail_verification/scripts/run_testnet.ts @@ -10,6 +10,8 @@ import { EmbeddedWallet } from "@aztec/wallets/embedded"; import { NO_FROM } from "@aztec/aztec.js/account"; import { Fr } from "@aztec/aztec.js/fields"; import { SetPublicAuthwitContractInteraction } from "@aztec/aztec.js/authorization"; +import { poseidon2HashWithSeparator } from "@aztec/foundation/crypto/poseidon"; +import { DomainSeparator } from "@aztec/constants"; const TESTNET_URL = "https://rpc.testnet.aztec-labs.com"; @@ -119,15 +121,23 @@ async function main() { // 4. Carol creates a claim console.log("\n--- Carol Creates Claim ---"); - const { result: partialNote } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)); - console.log(`Partial note created: ${partialNote}`); + // Carol generates randomness and computes the commitment offchain + const randomness = Fr.random(); + const commitment = await poseidon2HashWithSeparator( + [carolAddress.toField(), randomness], + DomainSeparator.NOTE_HASH, + ); + + // Carol submits the partial note creation + await emailClaim.methods.create_claim(randomness).send(sendOpts(carolAddress)); + console.log(`Partial note commitment: ${commitment}`); // 5. Carol claims with email proof console.log("\n--- Carol Claims with Email Proof ---"); const { receipt: tx } = await emailClaim.methods.claim_with_email( toAddressHash, intentHash, - partialNote, + { commitment }, CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], diff --git a/zkemail_verification/scripts/run_verification.ts b/zkemail_verification/scripts/run_verification.ts index 9193c84..6f2ab71 100644 --- a/zkemail_verification/scripts/run_verification.ts +++ b/zkemail_verification/scripts/run_verification.ts @@ -10,6 +10,8 @@ import { EmbeddedWallet } from "@aztec/wallets/embedded"; import { NO_FROM } from "@aztec/aztec.js/account"; import { Fr } from "@aztec/aztec.js/fields"; import { SetPublicAuthwitContractInteraction } from "@aztec/aztec.js/authorization"; +import { poseidon2HashWithSeparator } from "@aztec/foundation/crypto/poseidon"; +import { DomainSeparator } from "@aztec/constants"; export const NODE_URL = "http://localhost:8080"; @@ -128,15 +130,20 @@ async function main() { // 4. Carol creates a claim (partial note) console.log("\n--- Carol Creates Claim ---"); - const { result: partialNote } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)); - console.log(`Partial note commitment: ${partialNote}`); + const randomness = Fr.random(); + const commitment = await poseidon2HashWithSeparator( + [carolAddress.toField(), randomness], + DomainSeparator.NOTE_HASH, + ); + await emailClaim.methods.create_claim(randomness).send(sendOpts(carolAddress)); + console.log(`Partial note commitment: ${commitment}`); // 5. Carol submits the email proof to complete the claim console.log("\n--- Carol Claims with Email Proof ---"); await emailClaim.methods.claim_with_email( toAddressHash, intentHash, - partialNote, + { commitment }, CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], diff --git a/zkemail_verification/tests/zkemail_verification.test.ts b/zkemail_verification/tests/zkemail_verification.test.ts index ef26647..a4bd42f 100644 --- a/zkemail_verification/tests/zkemail_verification.test.ts +++ b/zkemail_verification/tests/zkemail_verification.test.ts @@ -5,6 +5,8 @@ import { AztecAddress } from "@aztec/aztec.js/addresses" import { NO_FROM } from "@aztec/aztec.js/account" import { Fr } from "@aztec/aztec.js/fields" import { SetPublicAuthwitContractInteraction } from "@aztec/aztec.js/authorization" +import { poseidon2HashWithSeparator } from "@aztec/foundation/crypto/poseidon" +import { DomainSeparator } from "@aztec/constants" import { createAztecNodeClient } from "@aztec/aztec.js/node" import { SponsoredFeePaymentMethod } from "@aztec/aztec.js/fee" import { EmbeddedWallet } from "@aztec/wallets/embedded" @@ -135,16 +137,22 @@ describe("ZKEmail Offchain Transfer", () => { }, TEST_TIMEOUT) test("should allow Carol to create a claim and complete it with email proof", async () => { + // Carol generates randomness and computes commitment offchain + const randomness = Fr.random() + const commitment = await poseidon2HashWithSeparator( + [carolAddress.toField(), randomness], + DomainSeparator.NOTE_HASH, + ) + // Carol creates partial note - const { result: partialNote } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)) - expect(partialNote).toBeDefined() - console.log(`Partial note: ${partialNote}`) + await emailClaim.methods.create_claim(randomness).send(sendOpts(carolAddress)) + console.log(`Partial note commitment: ${commitment}`) // Carol completes claim with email proof const { receipt: tx } = await emailClaim.methods.claim_with_email( toAddressHash, intentHash, - partialNote, + { commitment }, CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[], @@ -161,13 +169,18 @@ describe("ZKEmail Offchain Transfer", () => { }, TEST_TIMEOUT) test("should reject replay of same email proof", async () => { - const { result: partialNote2 } = await emailClaim.methods.create_claim().send(sendOpts(carolAddress)) + const randomness2 = Fr.random() + const commitment2 = await poseidon2HashWithSeparator( + [carolAddress.toField(), randomness2], + DomainSeparator.NOTE_HASH, + ) + await emailClaim.methods.create_claim(randomness2).send(sendOpts(carolAddress)) await expect( emailClaim.methods.claim_with_email( toAddressHash, intentHash, - partialNote2, + { commitment: commitment2 }, CLAIM_AMOUNT, data.vkAsFields as unknown as FieldLike[], data.proofAsFields as unknown as FieldLike[],