From a6aabe402f4c3aa792f6b9556b12a7e0df8b3319 Mon Sep 17 00:00:00 2001
From: Sandeep chauhan <92181599+ryzen-xp@users.noreply.github.com>
Date: Wed, 1 Apr 2026 13:28:26 +0530
Subject: [PATCH 01/65] chore(readme): Update README.md
---
README.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 3b84b04..67d4616 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
# π Alien Gateway
-[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/build_test.yml)
-[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/checks.yml)
+[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/contract.yml)
+[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/sdk_tests.yml)
+[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/pre-commit-validation.yml)
[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/zk_circuits.yml)
From 6ecc616bb272937cfba20eb771db7f744a258d4a Mon Sep 17 00:00:00 2001
From: Sandeep chauhan <92181599+ryzen-xp@users.noreply.github.com>
Date: Wed, 1 Apr 2026 13:30:59 +0530
Subject: [PATCH 02/65] fix(readme): fix readme
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 67d4616..2635b13 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
# π Alien Gateway
-[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/contract.yml)
-[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/sdk_tests.yml)
-[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/pre-commit-validation.yml)
+[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/contract.yml)
+[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/sdk_tests.yml)
+[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/pre-commit-validation.yml)
[](https://github.com/Alien-Protocol/Alien-Gateway/actions/workflows/zk_circuits.yml)
From d6a01e0af9acfa577099543a5253c5aebd7f058e Mon Sep 17 00:00:00 2001
From: ryzen_xp
Date: Sat, 4 Apr 2026 12:55:51 +0530
Subject: [PATCH 03/65] feat(zk): add witness-genrator.sh file
---
zk/input.json | 6 -
zk/scripts/prove_non_inclusion.ts | 56 ----------
zk/scripts/trusted-setup.sh | 2 +-
zk/scripts/verify_proof.ts | 60 ----------
zk/scripts/witness-gen.sh | 178 ++++++++++++++++++++++++++++++
5 files changed, 179 insertions(+), 123 deletions(-)
delete mode 100644 zk/input.json
delete mode 100644 zk/scripts/prove_non_inclusion.ts
delete mode 100644 zk/scripts/verify_proof.ts
create mode 100755 zk/scripts/witness-gen.sh
diff --git a/zk/input.json b/zk/input.json
deleted file mode 100644
index 59f77a2..0000000
--- a/zk/input.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "username": [
- 97, 109, 97, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ]
-}
diff --git a/zk/scripts/prove_non_inclusion.ts b/zk/scripts/prove_non_inclusion.ts
deleted file mode 100644
index faa7e70..0000000
--- a/zk/scripts/prove_non_inclusion.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import * as fs from "fs";
-import * as path from "path";
-import snarkjs from "snarkjs";
-
-/**
- * Minimal proof generator for `merkle_non_inclusion`.
- *
- * Usage (from `zk/`):
- * npx ts-node scripts/prove_non_inclusion.ts ./input.json
- *
- * The `input.json` must match the circuit's signal names, e.g.:
- * {
- * "username": ["... 32 elements ..."],
- * "leaf_before": "...",
- * "leaf_after": "...",
- * "merklePathBeforeSiblings": ["... 20 ..."],
- * "merklePathBeforeIndices": ["... 20 ..."],
- * "merklePathAfterSiblings": ["... 20 ..."],
- * "merklePathAfterIndices": ["... 20 ..."],
- * "root": "..."
- * }
- */
-async function main() {
- const inputPath = process.argv[2];
- if (!inputPath) {
- throw new Error("Missing input path. Usage: prove_non_inclusion.ts ");
- }
-
- const CIRCUIT = "merkle_non_inclusion";
- const BUILD_DIR = path.join("build", CIRCUIT);
- const WASM_PATH = path.join(BUILD_DIR, "wasm", `${CIRCUIT}_js`, `${CIRCUIT}.wasm`);
- const ZKEY_PATH = path.join(BUILD_DIR, `${CIRCUIT}_final.zkey`);
-
- const raw = fs.readFileSync(inputPath, "utf8");
- const input = JSON.parse(raw);
-
- const { proof, publicSignals } = await snarkjs.groth16.fullProve(input, WASM_PATH, ZKEY_PATH);
-
- process.stdout.write(
- JSON.stringify(
- {
- publicSignals,
- proof,
- },
- null,
- 2,
- ),
- );
- process.stdout.write("\n");
-}
-
-main().catch((err) => {
- process.stderr.write(String(err) + "\n");
- process.exit(1);
-});
-
diff --git a/zk/scripts/trusted-setup.sh b/zk/scripts/trusted-setup.sh
index be5efbe..d251dd3 100755
--- a/zk/scripts/trusted-setup.sh
+++ b/zk/scripts/trusted-setup.sh
@@ -3,7 +3,7 @@
set -e
# βββββββββββββββββββββββββββββββββββββββββββββ
-# Alien Gateway β Trusted Setup (Linux)
+# Alien Protocol β Trusted Setup (Linux)
# βββββββββββββββββββββββββββββββββββββββββββββ
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
diff --git a/zk/scripts/verify_proof.ts b/zk/scripts/verify_proof.ts
deleted file mode 100644
index c6c115a..0000000
--- a/zk/scripts/verify_proof.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-import { groth16 } from 'snarkjs';
-
-/**
- * Supported circuit types for proof verification.
- */
-export type CircuitType = 'non_inclusion' | 'update';
-
-/**
- * Result of proof verification.
- */
-export interface ProofVerificationResult {
- valid: boolean;
- message: string;
-}
-
-/**
- * Verifies a Groth16 proof against the correct verification key for the given circuit type.
- * @param type - The circuit type ('non_inclusion' or 'update').
- * @param proof - The proof object (as generated by snarkjs proof scripts).
- * @param publicSignals - The public signals array.
- * @returns ProofVerificationResult with validity and status message.
- */
-export async function verifyProof(
- type: CircuitType,
- proof: any,
- publicSignals: any
-): Promise {
- try {
- const vkeyPath = getVerificationKeyPath(type);
- if (!fs.existsSync(vkeyPath)) {
- return { valid: false, message: `Verification key not found: ${vkeyPath}` };
- }
- const vkey = JSON.parse(fs.readFileSync(vkeyPath, 'utf-8'));
- const res = await groth16.verify(vkey, publicSignals, proof);
- if (res === true) {
- return { valid: true, message: 'Proof is valid.' };
- } else {
- return { valid: false, message: 'Proof is invalid.' };
- }
- } catch (err: any) {
- return { valid: false, message: `Verification error: ${err.message}` };
- }
-}
-
-/**
- * Returns the path to the verification key for the given circuit type.
- * @param type - The circuit type.
- */
-function getVerificationKeyPath(type: CircuitType): string {
- switch (type) {
- case 'non_inclusion':
- return path.join(__dirname, '../build/merkle_non_inclusion/verification_key.json');
- case 'update':
- return path.join(__dirname, '../build/merkle_update/verification_key.json');
- default:
- throw new Error(`Unsupported circuit type: ${type}`);
- }
-}
diff --git a/zk/scripts/witness-gen.sh b/zk/scripts/witness-gen.sh
new file mode 100755
index 0000000..f71542f
--- /dev/null
+++ b/zk/scripts/witness-gen.sh
@@ -0,0 +1,178 @@
+#!/bin/bash
+
+set -e
+
+# βββββββββββββββββββββββββββββββββββββββββββββ
+# Alien Protocol β Witness Generator
+# βββββββββββββββββββββββββββββββββββββββββββββ
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ZK_DIR="$(dirname "$SCRIPT_DIR")"
+
+BUILD_DIR="$ZK_DIR/build"
+INPUT_DIR="$ZK_DIR/inputs"
+WITNESS_DIR="$ZK_DIR/witnesses"
+
+CIRCUITS=(
+ "merkle_inclusion"
+ "merkle_non_inclusion"
+ "merkle_update"
+ "merkle_update_proof"
+ "username_merkle"
+ "username_hash"
+)
+
+GREEN="\033[0;32m"
+RED="\033[0;31m"
+CYAN="\033[0;36m"
+YELLOW="\033[0;33m"
+RESET="\033[0m"
+
+ok() { echo -e "${GREEN} β $1${RESET}"; }
+fail() { echo -e "${RED} β $1${RESET}"; exit 1; }
+info() { echo -e "${CYAN}βΆ $1${RESET}"; }
+warn() { echo -e "${YELLOW} β $1${RESET}"; }
+
+# ββ Argument parsing ββββββββββββββββββββββββββ
+
+TARGET=""
+INPUT_OVERRIDE=""
+
+usage() {
+ echo ""
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " -c, --circuit Generate witness for a single circuit only"
+ echo " -i, --input Override input JSON path for single-circuit mode"
+ echo " -h, --help Show this help message"
+ echo ""
+ echo "Circuits:"
+ for c in "${CIRCUITS[@]}"; do
+ echo " - $c"
+ done
+ echo ""
+ echo "Input files are expected at: \$ZK_DIR/inputs/.json"
+ echo "Witness outputs go to: \$ZK_DIR/witnesses//"
+ echo ""
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -c|--circuit)
+ TARGET="$2"; shift 2 ;;
+ -i|--input)
+ INPUT_OVERRIDE="$2"; shift 2 ;;
+ -h|--help)
+ usage; exit 0 ;;
+ *)
+ echo -e "${RED}Unknown option: $1${RESET}"
+ usage; exit 1 ;;
+ esac
+done
+
+if [ -n "$INPUT_OVERRIDE" ] && [ -z "$TARGET" ]; then
+ echo -e "${RED} β --input requires --circuit to be specified${RESET}"
+ usage; exit 1
+fi
+
+# ββ Build circuit list ββββββββββββββββββββββββ
+
+if [ -n "$TARGET" ]; then
+ FOUND=0
+ for c in "${CIRCUITS[@]}"; do
+ [ "$c" = "$TARGET" ] && FOUND=1 && break
+ done
+ [ "$FOUND" -eq 1 ] || fail "Unknown circuit: '$TARGET'. Run with --help to list valid circuits."
+ RUN_CIRCUITS=("$TARGET")
+else
+ RUN_CIRCUITS=("${CIRCUITS[@]}")
+fi
+
+# ββ Preflight βββββββββββββββββββββββββββββββββ
+
+echo ""
+echo "================================================"
+echo " Alien Protocol β Witness Generator"
+echo "================================================"
+echo ""
+
+mkdir -p "$WITNESS_DIR"
+
+# ββ Main loop βββββββββββββββββββββββββββββββββ
+
+PASS=0
+SKIP=0
+FAIL_LIST=()
+
+for CIRCUIT in "${RUN_CIRCUITS[@]}"; do
+ info "Generating witness: $CIRCUIT"
+
+ # Resolve input file
+ if [ -n "$INPUT_OVERRIDE" ]; then
+ INPUT_FILE="$INPUT_OVERRIDE"
+ else
+ INPUT_FILE="$INPUT_DIR/${CIRCUIT}.json"
+ fi
+
+ WASM_FILE="$BUILD_DIR/$CIRCUIT/wasm/${CIRCUIT}_js/$CIRCUIT.wasm"
+ WASM_JS="$BUILD_DIR/$CIRCUIT/wasm/${CIRCUIT}_js/generate_witness.js"
+ OUT_DIR="$WITNESS_DIR/$CIRCUIT"
+ WITNESS_OUT="$OUT_DIR/${CIRCUIT}.wtns"
+
+ # Input check
+ if [ ! -f "$INPUT_FILE" ]; then
+ warn "$CIRCUIT β input not found at $INPUT_FILE, skipping"
+ SKIP=$((SKIP + 1))
+ echo ""
+ continue
+ fi
+
+ # Artifact checks
+ [ -f "$WASM_FILE" ] || fail "$CIRCUIT β wasm not found at $WASM_FILE (run compile first)"
+ [ -f "$WASM_JS" ] || fail "$CIRCUIT β generate_witness.js not found at $WASM_JS"
+
+ mkdir -p "$OUT_DIR"
+
+ # Generate witness via snarkjs (delegates to wasm internally)
+ snarkjs wtns calculate \
+ "$WASM_FILE" \
+ "$INPUT_FILE" \
+ "$WITNESS_OUT" \
+ || { FAIL_LIST+=("$CIRCUIT"); echo ""; continue; }
+
+ # Verify witness against r1cs
+ R1CS="$BUILD_DIR/$CIRCUIT/$CIRCUIT.r1cs"
+ if [ -f "$R1CS" ]; then
+ snarkjs wtns check "$R1CS" "$WITNESS_OUT" \
+ && ok "$CIRCUIT witness verified against r1cs" \
+ || { warn "$CIRCUIT β witness check failed (proof may still work, continuing)"; }
+ fi
+
+ ok "$CIRCUIT witness generated"
+ echo " βββ $WITNESS_OUT"
+ echo ""
+
+ PASS=$((PASS + 1))
+done
+
+# ββ Summary βββββββββββββββββββββββββββββββββββ
+
+echo "================================================"
+
+if [ ${#FAIL_LIST[@]} -gt 0 ]; then
+ echo -e "${RED} ${#FAIL_LIST[@]} circuit(s) failed:${RESET}"
+ for f in "${FAIL_LIST[@]}"; do
+ echo -e "${RED} - $f${RESET}"
+ done
+fi
+
+if [ "$SKIP" -gt 0 ]; then
+ echo -e "${YELLOW} $SKIP circuit(s) skipped (no input file)${RESET}"
+fi
+
+echo -e "${GREEN} $PASS circuit(s) succeeded${RESET}"
+echo "================================================"
+echo ""
+
+[ ${#FAIL_LIST[@]} -eq 0 ] || exit 1
\ No newline at end of file
From 384cb8f25537aff2190efcbb9a093adb5a7869a9 Mon Sep 17 00:00:00 2001
From: ryzen-xp
Date: Thu, 16 Apr 2026 12:37:11 +0530
Subject: [PATCH 04/65] feat(zk): added some verifier contracts
---
.gitignore | 1 +
zk/inputs/merkle_inclusion.json | 81 +
zk/inputs/merkle_non_inclusion.json | 127 ++
zk/inputs/merkle_update.json | 14 +
zk/inputs/merkle_update_proof.json | 82 +
zk/inputs/username_hash.json | 36 +
zk/inputs/username_merkle.json | 44 +
zk/scripts/export-verifiers.sh | 163 ++
zk/scripts/gen_non_inclusion_input.js | 126 ++
zk/scripts/soroban-setup.sh | 517 +++++
zk/soroban/tools/groth16_verifier/Cargo.lock | 1792 +++++++++++++++++
zk/soroban/tools/groth16_verifier/Cargo.toml | 34 +
zk/soroban/tools/groth16_verifier/Makefile | 16 +
zk/soroban/tools/groth16_verifier/README | 28 +
.../data/auxiliary/input.json | 1 +
.../data/auxiliary/multiplier2.circom | 16 +
.../data/auxiliary/multiplier2_0000.zkey | Bin 0 -> 3652 bytes
.../data/auxiliary/multiplier2_0001.zkey | Bin 0 -> 4226 bytes
.../data/auxiliary/pot12_0000.ptau | Bin 0 -> 2359552 bytes
.../data/auxiliary/pot12_0001.ptau | Bin 0 -> 2361684 bytes
.../data/auxiliary/pot12_final.ptau | Bin 0 -> 7079844 bytes
.../data/auxiliary/witness.wtns | Bin 0 -> 204 bytes
.../tools/groth16_verifier/data/proof.json | 28 +
.../tools/groth16_verifier/data/public.json | 3 +
.../data/verification_key.json | 94 +
.../groth16_verifier/rust-toolchain.toml | 4 +
zk/soroban/tools/groth16_verifier/src/lib.rs | 67 +
zk/soroban/tools/groth16_verifier/src/test.rs | 139 ++
zk/soroban/tools/soroban-examples | 1 +
zk/soroban/tools/soroban-privacy-pools | 1 +
zk/tests/test_non_inclusion_proof.js | 9 +-
zk/tsconfig.json | 3 +-
zk/verifiers/MerkleInclusionVerifier.sol | 177 ++
zk/verifiers/MerkleNonInclusionVerifier.sol | 184 ++
zk/verifiers/MerkleUpdateProofVerifier.sol | 184 ++
zk/verifiers/MerkleUpdateVerifier.sol | 170 ++
zk/verifiers/UsernameHashVerifier.sol | 170 ++
zk/verifiers/UsernameMerkleVerifier.sol | 170 ++
.../merkle_inclusion/merkle_inclusion.wtns | Bin 0 -> 267212 bytes
.../merkle_non_inclusion.wtns | Bin 0 -> 463628 bytes
zk/witnesses/merkle_update/merkle_update.wtns | Bin 0 -> 31468 bytes
.../merkle_update_proof.wtns | Bin 0 -> 422092 bytes
zk/witnesses/username_hash/username_hash.wtns | Bin 0 -> 111020 bytes
.../username_merkle/username_merkle.wtns | Bin 0 -> 126764 bytes
44 files changed, 4476 insertions(+), 6 deletions(-)
create mode 100644 zk/inputs/merkle_inclusion.json
create mode 100644 zk/inputs/merkle_non_inclusion.json
create mode 100644 zk/inputs/merkle_update.json
create mode 100644 zk/inputs/merkle_update_proof.json
create mode 100644 zk/inputs/username_hash.json
create mode 100644 zk/inputs/username_merkle.json
create mode 100755 zk/scripts/export-verifiers.sh
create mode 100644 zk/scripts/gen_non_inclusion_input.js
create mode 100755 zk/scripts/soroban-setup.sh
create mode 100644 zk/soroban/tools/groth16_verifier/Cargo.lock
create mode 100644 zk/soroban/tools/groth16_verifier/Cargo.toml
create mode 100644 zk/soroban/tools/groth16_verifier/Makefile
create mode 100644 zk/soroban/tools/groth16_verifier/README
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/input.json
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2.circom
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2_0000.zkey
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2_0001.zkey
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_0000.ptau
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_0001.ptau
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_final.ptau
create mode 100644 zk/soroban/tools/groth16_verifier/data/auxiliary/witness.wtns
create mode 100644 zk/soroban/tools/groth16_verifier/data/proof.json
create mode 100644 zk/soroban/tools/groth16_verifier/data/public.json
create mode 100644 zk/soroban/tools/groth16_verifier/data/verification_key.json
create mode 100644 zk/soroban/tools/groth16_verifier/rust-toolchain.toml
create mode 100644 zk/soroban/tools/groth16_verifier/src/lib.rs
create mode 100644 zk/soroban/tools/groth16_verifier/src/test.rs
create mode 160000 zk/soroban/tools/soroban-examples
create mode 160000 zk/soroban/tools/soroban-privacy-pools
create mode 100644 zk/verifiers/MerkleInclusionVerifier.sol
create mode 100644 zk/verifiers/MerkleNonInclusionVerifier.sol
create mode 100644 zk/verifiers/MerkleUpdateProofVerifier.sol
create mode 100644 zk/verifiers/MerkleUpdateVerifier.sol
create mode 100644 zk/verifiers/UsernameHashVerifier.sol
create mode 100644 zk/verifiers/UsernameMerkleVerifier.sol
create mode 100644 zk/witnesses/merkle_inclusion/merkle_inclusion.wtns
create mode 100644 zk/witnesses/merkle_non_inclusion/merkle_non_inclusion.wtns
create mode 100644 zk/witnesses/merkle_update/merkle_update.wtns
create mode 100644 zk/witnesses/merkle_update_proof/merkle_update_proof.wtns
create mode 100644 zk/witnesses/username_hash/username_hash.wtns
create mode 100644 zk/witnesses/username_merkle/username_merkle.wtns
diff --git a/.gitignore b/.gitignore
index 0da9c90..7bf284f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ node_modules
.deployments
# Soroban test snapshots β now committed as regression guards
# gateway-contract/contracts/**/test_snapshots/
+zk/soroban/bls_setup/*.ptau
diff --git a/zk/inputs/merkle_inclusion.json b/zk/inputs/merkle_inclusion.json
new file mode 100644
index 0000000..79bcecf
--- /dev/null
+++ b/zk/inputs/merkle_inclusion.json
@@ -0,0 +1,81 @@
+{
+ "username": [
+ 97,
+ 108,
+ 105,
+ 99,
+ 101,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "pathElements": [
+ "0",
+ "14744269619966411208579211824598458697587494354926760081771325075741142829156",
+ "7423237065226347324353380772367382631490014989348495481811164164159255474657",
+ "11286972368698509976183087595462810875513684078608517520839298933882497716792",
+ "3607627140608796879659380071776844901612302623152076817094415224584923813162",
+ "19712377064642672829441595136074946683621277828620209496774504837737984048981",
+ "20775607673010627194014556968476266066927294572720319469184847051418138353016",
+ "3396914609616007258851405644437304192397291162432396347162513310381425243293",
+ "21551820661461729022865262380882070649935529853313286572328683688269863701601",
+ "6573136701248752079028194407151022595060682063033565181951145966236778420039",
+ "12413880268183407374852357075976609371175688755676981206018884971008854919922",
+ "14271763308400718165336499097156975241954733520325982997864342600795471836726",
+ "20066985985293572387227381049700832219069292839614107140851619262827735677018",
+ "9394776414966240069580838672673694685292165040808226440647796406499139370960",
+ "11331146992410411304059858900317123658895005918277453009197229807340014528524",
+ "15819538789928229930262697811477882737253464456578333862691129291651619515538",
+ "19217088683336594659449020493828377907203207941212636669271704950158751593251",
+ "21035245323335827719745544373081896983162834604456827698288649288827293579666",
+ "6939770416153240137322503476966641397417391950902474480970945462551409848591",
+ "10941962436777715901943463195175331263348098796018438960955633645115732864202"
+ ],
+ "pathIndices": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "root": "19251718161323922017312276837404159234266520776390526140106670846322149160180"
+}
\ No newline at end of file
diff --git a/zk/inputs/merkle_non_inclusion.json b/zk/inputs/merkle_non_inclusion.json
new file mode 100644
index 0000000..3a008f0
--- /dev/null
+++ b/zk/inputs/merkle_non_inclusion.json
@@ -0,0 +1,127 @@
+{
+ "username": [
+ "1",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "leaf_before": "4405521749221103786392116719819727519805035450850027008049803932188059466061",
+ "leaf_after": "4405521749221103786392116719819727519805035450850027008049803932188059466063",
+ "merklePathBeforeSiblings": [
+ "4405521749221103786392116719819727519805035450850027008049803932188059466063",
+ "14744269619966411208579211824598458697587494354926760081771325075741142829156",
+ "7423237065226347324353380772367382631490014989348495481811164164159255474657",
+ "11286972368698509976183087595462810875513684078608517520839298933882497716792",
+ "3607627140608796879659380071776844901612302623152076817094415224584923813162",
+ "19712377064642672829441595136074946683621277828620209496774504837737984048981",
+ "20775607673010627194014556968476266066927294572720319469184847051418138353016",
+ "3396914609616007258851405644437304192397291162432396347162513310381425243293",
+ "21551820661461729022865262380882070649935529853313286572328683688269863701601",
+ "6573136701248752079028194407151022595060682063033565181951145966236778420039",
+ "12413880268183407374852357075976609371175688755676981206018884971008854919922",
+ "14271763308400718165336499097156975241954733520325982997864342600795471836726",
+ "20066985985293572387227381049700832219069292839614107140851619262827735677018",
+ "9394776414966240069580838672673694685292165040808226440647796406499139370960",
+ "11331146992410411304059858900317123658895005918277453009197229807340014528524",
+ "15819538789928229930262697811477882737253464456578333862691129291651619515538",
+ "19217088683336594659449020493828377907203207941212636669271704950158751593251",
+ "21035245323335827719745544373081896983162834604456827698288649288827293579666",
+ "6939770416153240137322503476966641397417391950902474480970945462551409848591",
+ "10941962436777715901943463195175331263348098796018438960955633645115732864202"
+ ],
+ "merklePathBeforeIndices": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "merklePathAfterSiblings": [
+ "4405521749221103786392116719819727519805035450850027008049803932188059466061",
+ "14744269619966411208579211824598458697587494354926760081771325075741142829156",
+ "7423237065226347324353380772367382631490014989348495481811164164159255474657",
+ "11286972368698509976183087595462810875513684078608517520839298933882497716792",
+ "3607627140608796879659380071776844901612302623152076817094415224584923813162",
+ "19712377064642672829441595136074946683621277828620209496774504837737984048981",
+ "20775607673010627194014556968476266066927294572720319469184847051418138353016",
+ "3396914609616007258851405644437304192397291162432396347162513310381425243293",
+ "21551820661461729022865262380882070649935529853313286572328683688269863701601",
+ "6573136701248752079028194407151022595060682063033565181951145966236778420039",
+ "12413880268183407374852357075976609371175688755676981206018884971008854919922",
+ "14271763308400718165336499097156975241954733520325982997864342600795471836726",
+ "20066985985293572387227381049700832219069292839614107140851619262827735677018",
+ "9394776414966240069580838672673694685292165040808226440647796406499139370960",
+ "11331146992410411304059858900317123658895005918277453009197229807340014528524",
+ "15819538789928229930262697811477882737253464456578333862691129291651619515538",
+ "19217088683336594659449020493828377907203207941212636669271704950158751593251",
+ "21035245323335827719745544373081896983162834604456827698288649288827293579666",
+ "6939770416153240137322503476966641397417391950902474480970945462551409848591",
+ "10941962436777715901943463195175331263348098796018438960955633645115732864202"
+ ],
+ "merklePathAfterIndices": [
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "root": "16722800360417514389077677753664546698908206670535312888152538083911647668375"
+}
diff --git a/zk/inputs/merkle_update.json b/zk/inputs/merkle_update.json
new file mode 100644
index 0000000..a3a024c
--- /dev/null
+++ b/zk/inputs/merkle_update.json
@@ -0,0 +1,14 @@
+{
+ "oldLeaf": "0",
+ "newLeaf": "13342458952701446598868087696288293641764068039906535540530736489771355138460",
+ "pathElements": [
+ "0",
+ "14744269619966411208579211824598458697587494354926760081771325075741142829156"
+ ],
+ "pathIndices": [
+ 0,
+ 0
+ ],
+ "oldRoot": "7423237065226347324353380772367382631490014989348495481811164164159255474657",
+ "newRoot": "1619322966775432746364575661595654911215511522560151567459433528644444565388"
+}
\ No newline at end of file
diff --git a/zk/inputs/merkle_update_proof.json b/zk/inputs/merkle_update_proof.json
new file mode 100644
index 0000000..4c545a0
--- /dev/null
+++ b/zk/inputs/merkle_update_proof.json
@@ -0,0 +1,82 @@
+{
+ "username": [
+ 97,
+ 108,
+ 105,
+ 99,
+ 101,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "merklePathSiblings": [
+ "0",
+ "14744269619966411208579211824598458697587494354926760081771325075741142829156",
+ "7423237065226347324353380772367382631490014989348495481811164164159255474657",
+ "11286972368698509976183087595462810875513684078608517520839298933882497716792",
+ "3607627140608796879659380071776844901612302623152076817094415224584923813162",
+ "19712377064642672829441595136074946683621277828620209496774504837737984048981",
+ "20775607673010627194014556968476266066927294572720319469184847051418138353016",
+ "3396914609616007258851405644437304192397291162432396347162513310381425243293",
+ "21551820661461729022865262380882070649935529853313286572328683688269863701601",
+ "6573136701248752079028194407151022595060682063033565181951145966236778420039",
+ "12413880268183407374852357075976609371175688755676981206018884971008854919922",
+ "14271763308400718165336499097156975241954733520325982997864342600795471836726",
+ "20066985985293572387227381049700832219069292839614107140851619262827735677018",
+ "9394776414966240069580838672673694685292165040808226440647796406499139370960",
+ "11331146992410411304059858900317123658895005918277453009197229807340014528524",
+ "15819538789928229930262697811477882737253464456578333862691129291651619515538",
+ "19217088683336594659449020493828377907203207941212636669271704950158751593251",
+ "21035245323335827719745544373081896983162834604456827698288649288827293579666",
+ "6939770416153240137322503476966641397417391950902474480970945462551409848591",
+ "10941962436777715901943463195175331263348098796018438960955633645115732864202"
+ ],
+ "merklePathIndices": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "oldRoot": "15019797232609675441998260052101280400536945603062888308240081994073687793470",
+ "newRoot": "19251718161323922017312276837404159234266520776390526140106670846322149160180"
+}
\ No newline at end of file
diff --git a/zk/inputs/username_hash.json b/zk/inputs/username_hash.json
new file mode 100644
index 0000000..63a80fa
--- /dev/null
+++ b/zk/inputs/username_hash.json
@@ -0,0 +1,36 @@
+{
+ "username": [
+ 97,
+ 108,
+ 105,
+ 99,
+ 101,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+}
\ No newline at end of file
diff --git a/zk/inputs/username_merkle.json b/zk/inputs/username_merkle.json
new file mode 100644
index 0000000..3789b91
--- /dev/null
+++ b/zk/inputs/username_merkle.json
@@ -0,0 +1,44 @@
+{
+ "username": [
+ 97,
+ 108,
+ 105,
+ 99,
+ 101,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "pathElements": [
+ "0",
+ "14744269619966411208579211824598458697587494354926760081771325075741142829156"
+ ],
+ "pathIndices": [
+ 0,
+ 0
+ ]
+}
\ No newline at end of file
diff --git a/zk/scripts/export-verifiers.sh b/zk/scripts/export-verifiers.sh
new file mode 100755
index 0000000..3220a82
--- /dev/null
+++ b/zk/scripts/export-verifiers.sh
@@ -0,0 +1,163 @@
+#!/bin/bash
+
+set -e
+
+# βββββββββββββββββββββββββββββββββββββββββββββ
+# Alien Protocol β Solidity Verifier Exporter
+# βββββββββββββββββββββββββββββββββββββββββββββ
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ZK_DIR="$(dirname "$SCRIPT_DIR")"
+
+BUILD_DIR="$ZK_DIR/build"
+CONTRACTS_DIR="$ZK_DIR/verifiers"
+
+# Map: circuit_name -> Solidity contract name
+declare -A CONTRACT_NAMES=(
+ ["merkle_inclusion"]="MerkleInclusionVerifier"
+ ["merkle_non_inclusion"]="MerkleNonInclusionVerifier"
+ ["merkle_update"]="MerkleUpdateVerifier"
+ ["merkle_update_proof"]="MerkleUpdateProofVerifier"
+ ["username_merkle"]="UsernameMerkleVerifier"
+ ["username_hash"]="UsernameHashVerifier"
+)
+
+CIRCUITS=(
+ "merkle_inclusion"
+ "merkle_non_inclusion"
+ "merkle_update"
+ "merkle_update_proof"
+ "username_merkle"
+ "username_hash"
+)
+
+GREEN="\033[0;32m"
+RED="\033[0;31m"
+CYAN="\033[0;36m"
+YELLOW="\033[0;33m"
+RESET="\033[0m"
+
+ok() { echo -e "${GREEN} β $1${RESET}"; }
+fail() { echo -e "${RED} β $1${RESET}"; }
+info() { echo -e "${CYAN}βΆ $1${RESET}"; }
+warn() { echo -e "${YELLOW} β $1${RESET}"; }
+
+# ββ Argument parsing ββββββββββββββββββββββββββ
+
+TARGET=""
+
+usage() {
+ echo ""
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " -c, --circuit Export verifier for a single circuit only"
+ echo " -h, --help Show this help message"
+ echo ""
+ echo "Circuits:"
+ for c in "${CIRCUITS[@]}"; do
+ echo " - $c β ${CONTRACT_NAMES[$c]}.sol"
+ done
+ echo ""
+ echo "Verifier contracts are written to: \$ZK_DIR/contracts/verifiers/"
+ echo ""
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -c|--circuit)
+ TARGET="$2"; shift 2 ;;
+ -h|--help)
+ usage; exit 0 ;;
+ *)
+ echo -e "${RED}Unknown option: $1${RESET}"
+ usage; exit 1 ;;
+ esac
+done
+
+# ββ Build circuit list ββββββββββββββββββββββββ
+
+if [ -n "$TARGET" ]; then
+ FOUND=0
+ for c in "${CIRCUITS[@]}"; do
+ [ "$c" = "$TARGET" ] && FOUND=1 && break
+ done
+ if [ "$FOUND" -eq 0 ]; then
+ fail "Unknown circuit: '$TARGET'. Run with --help to list valid circuits."
+ exit 1
+ fi
+ RUN_CIRCUITS=("$TARGET")
+else
+ RUN_CIRCUITS=("${CIRCUITS[@]}")
+fi
+
+# ββ Preflight βββββββββββββββββββββββββββββββββ
+
+echo ""
+echo "================================================"
+echo " Alien Protocol β Solidity Verifier Exporter"
+echo "================================================"
+echo ""
+
+mkdir -p "$CONTRACTS_DIR"
+
+# ββ Main loop βββββββββββββββββββββββββββββββββ
+
+PASS=0
+FAIL_LIST=()
+
+for CIRCUIT in "${RUN_CIRCUITS[@]}"; do
+ CONTRACT="${CONTRACT_NAMES[$CIRCUIT]}"
+ ZKEY="$BUILD_DIR/$CIRCUIT/${CIRCUIT}_final.zkey"
+ OUT_FILE="$CONTRACTS_DIR/${CONTRACT}.sol"
+
+ info "Exporting: $CIRCUIT β ${CONTRACT}.sol"
+
+ # Check zkey exists
+ if [ ! -f "$ZKEY" ]; then
+ warn "Skipping $CIRCUIT β zkey not found at $ZKEY"
+ warn "Run trusted-setup.sh first."
+ FAIL_LIST+=("$CIRCUIT (missing zkey)")
+ echo ""
+ continue
+ fi
+
+ # Export Solidity verifier
+ if snarkjs zkey export solidityverifier "$ZKEY" "$OUT_FILE"; then
+ ok "Exported β $OUT_FILE"
+ else
+ fail "Failed to export $CIRCUIT"
+ FAIL_LIST+=("$CIRCUIT (export error)")
+ echo ""
+ continue
+ fi
+
+ # Patch the contract name from the default "Groth16Verifier" to the proper name
+ if grep -q "contract Groth16Verifier" "$OUT_FILE"; then
+ sed -i "s/contract Groth16Verifier/contract ${CONTRACT}/g" "$OUT_FILE"
+ ok "Renamed contract β ${CONTRACT}"
+ fi
+
+ echo " βββ $OUT_FILE"
+ echo ""
+
+ PASS=$((PASS + 1))
+done
+
+# ββ Summary βββββββββββββββββββββββββββββββββββ
+
+echo "================================================"
+
+if [ ${#FAIL_LIST[@]} -gt 0 ]; then
+ echo -e "${RED} ${#FAIL_LIST[@]} export(s) failed:${RESET}"
+ for f in "${FAIL_LIST[@]}"; do
+ echo -e "${RED} - $f${RESET}"
+ done
+fi
+
+echo -e "${GREEN} $PASS verifier(s) exported successfully${RESET}"
+echo -e "${GREEN} Output directory: $CONTRACTS_DIR${RESET}"
+echo "================================================"
+echo ""
+
+[ ${#FAIL_LIST[@]} -eq 0 ] || exit 1
diff --git a/zk/scripts/gen_non_inclusion_input.js b/zk/scripts/gen_non_inclusion_input.js
new file mode 100644
index 0000000..347b72d
--- /dev/null
+++ b/zk/scripts/gen_non_inclusion_input.js
@@ -0,0 +1,126 @@
+const { buildPoseidon } = require("circomlibjs");
+const { writeFileSync } = require("fs");
+const path = require("path");
+
+const LEVELS = 20;
+const OUTPUT_PATH = path.join(__dirname, "..", "inputs", "merkle_non_inclusion.json");
+
+function buildEmptyHashes(poseidon, depth) {
+ const F = poseidon.F;
+ const hashes = [0n];
+ for (let i = 0; i < depth; i++) {
+ hashes.push(F.toObject(poseidon([hashes[i], hashes[i]])));
+ }
+ return hashes;
+}
+
+function computeRoot(poseidon, leaf, siblings, indices) {
+ const F = poseidon.F;
+ let current = leaf;
+ for (let i = 0; i < siblings.length; i++) {
+ const [left, right] = indices[i] === 0 ? [current, siblings[i]] : [siblings[i], current];
+ current = F.toObject(poseidon([left, right]));
+ }
+ return current;
+}
+
+function usernameHash(poseidon, username) {
+ const F = poseidon.F;
+ const chunks = [];
+
+ for (let i = 0; i < 8; i++) {
+ chunks[i] = F.toObject(
+ poseidon([
+ username[i * 4 + 0],
+ username[i * 4 + 1],
+ username[i * 4 + 2],
+ username[i * 4 + 3],
+ ])
+ );
+ }
+
+ const merged = [];
+ for (let i = 0; i < 2; i++) {
+ const offset = i * 4;
+ merged[i] = F.toObject(
+ poseidon([
+ chunks[offset + 0],
+ chunks[offset + 1],
+ chunks[offset + 2],
+ chunks[offset + 3],
+ ])
+ );
+ }
+
+ return F.toObject(poseidon([merged[0], merged[1]]));
+}
+
+async function main() {
+ const poseidon = await buildPoseidon();
+ const emptyHashes = buildEmptyHashes(poseidon, LEVELS);
+ const limit = 1n << 252n;
+
+ let username = null;
+ let hash = null;
+ let candidate = null;
+
+ // The circuit range-checks values with Num2Bits(252), so the hash and
+ // boundary leaves must stay strictly below 2^252.
+ for (let i = 1n; i < 5000n; i++) {
+ const nextUsername = new Array(32).fill(0n);
+ nextUsername[0] = i;
+
+ const nextHash = usernameHash(poseidon, nextUsername);
+ if (nextHash > 1n && nextHash < limit - 2n) {
+ candidate = i;
+ username = nextUsername;
+ hash = nextHash;
+ break;
+ }
+ }
+
+ if (username === null || hash === null || candidate === null) {
+ throw new Error("failed to find a username hash below 2^252");
+ }
+
+ const leafBefore = hash - 1n;
+ const leafAfter = hash + 1n;
+
+ const merklePathBeforeIndices = new Array(LEVELS).fill(0);
+ const merklePathAfterIndices = new Array(LEVELS).fill(0);
+ merklePathAfterIndices[0] = 1;
+
+ const merklePathBeforeSiblings = emptyHashes.slice(0, LEVELS);
+ const merklePathAfterSiblings = emptyHashes.slice(0, LEVELS);
+ merklePathBeforeSiblings[0] = leafAfter;
+ merklePathAfterSiblings[0] = leafBefore;
+
+ const root = computeRoot(
+ poseidon,
+ leafBefore,
+ merklePathBeforeSiblings,
+ merklePathBeforeIndices
+ );
+
+ const input = {
+ username: username.map((value) => value.toString()),
+ leaf_before: leafBefore.toString(),
+ leaf_after: leafAfter.toString(),
+ merklePathBeforeSiblings: merklePathBeforeSiblings.map((value) => value.toString()),
+ merklePathBeforeIndices,
+ merklePathAfterSiblings: merklePathAfterSiblings.map((value) => value.toString()),
+ merklePathAfterIndices,
+ root: root.toString(),
+ };
+
+ writeFileSync(OUTPUT_PATH, JSON.stringify(input, null, 2) + "\n");
+
+ console.log(`candidate = ${candidate.toString()}`);
+ console.log(`hash = ${hash.toString()}`);
+ console.log(`wrote ${OUTPUT_PATH}`);
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
diff --git a/zk/scripts/soroban-setup.sh b/zk/scripts/soroban-setup.sh
new file mode 100755
index 0000000..61d3c9e
--- /dev/null
+++ b/zk/scripts/soroban-setup.sh
@@ -0,0 +1,517 @@
+#!/bin/bash
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Alien Protocol β Soroban Verifier Pipeline
+#
+# What this script does (in order):
+#
+# PHASE 1 β Clone tools
+# β’ Clones circom2soroban and soroban-examples (groth16_verifier)
+#
+# PHASE 2 β BLS12-381 Trusted Setup (per circuit)
+# β’ Powers of Tau (BLS12-381, size 20)
+# β’ Phase 2 zkey generation + contribution
+# β’ Exports vkey.json
+#
+# PHASE 3 β Generate Proofs (per circuit)
+# β’ snarkjs groth16 prove β proof.json + public.json
+# β’ snarkjs groth16 verify (smoke-check)
+#
+# PHASE 4 β circom2soroban Conversion (per circuit)
+# β’ Converts vkey.json β Rust constants
+# β’ Converts proof.json β Rust proof bytes
+# β’ Converts public.jsonβ Rust public input bytes
+# β’ Writes one complete Soroban verifier .rs file per circuit
+#
+# Output layout:
+# zk/soroban/
+# βββ circom2soroban/ (tool clone)
+# βββ groth16_verifier/ (Soroban base verifier)
+# βββ bls_setup/ (ptau + new zkeys)
+# β βββ /
+# β βββ circuit_final.zkey
+# β βββ vkey.json
+# βββ proofs/
+# β βββ /
+# β βββ proof.json
+# β βββ public.json
+# βββ contracts/
+# βββ _verifier.rs
+#
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ZK_DIR="$(dirname "$SCRIPT_DIR")"
+
+BUILD_DIR="$ZK_DIR/build"
+WITNESS_DIR="$ZK_DIR/witnesses"
+SOROBAN_DIR="$ZK_DIR/soroban"
+
+BLS_SETUP_DIR="$SOROBAN_DIR/bls_setup"
+PROOF_DIR="$SOROBAN_DIR/proofs"
+CONTRACT_DIR="$SOROBAN_DIR/contracts"
+TOOLS_DIR="$SOROBAN_DIR/tools"
+
+CIRCUITS=(
+ "merkle_inclusion"
+ "merkle_non_inclusion"
+ "merkle_update"
+ "merkle_update_proof"
+ "username_merkle"
+ "username_hash"
+)
+
+# BLS12-381 Powers of Tau size β 2^20 = 1,048,576 constraints max
+POT_SIZE=20
+
+GREEN="\033[0;32m"
+RED="\033[0;31m"
+CYAN="\033[0;36m"
+YELLOW="\033[0;33m"
+BOLD="\033[1m"
+RESET="\033[0m"
+
+ok() { echo -e "${GREEN} β $1${RESET}"; }
+fail() { echo -e "${RED} β $1${RESET}"; exit 1; }
+info() { echo -e "${CYAN}βΆ $1${RESET}"; }
+warn() { echo -e "${YELLOW} β $1${RESET}"; }
+section() { echo -e "\n${BOLD}${CYAN}ββ $1 ββ${RESET}\n"; }
+
+# ββ Argument parsing ββββββββββββββββββββββββββ
+
+TARGET=""
+SKIP_SETUP=0
+SKIP_PROVE=0
+SKIP_CONVERT=0
+
+usage() {
+ echo ""
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " -c, --circuit Run pipeline for a single circuit only"
+ echo " --skip-setup Skip BLS12-381 trusted setup (use existing zkeys)"
+ echo " --skip-prove Skip proof generation (use existing proof.json)"
+ echo " --skip-convert Skip circom2soroban conversion"
+ echo " -h, --help Show this help message"
+ echo ""
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -c|--circuit) TARGET="$2"; shift 2 ;;
+ --skip-setup) SKIP_SETUP=1; shift ;;
+ --skip-prove) SKIP_PROVE=1; shift ;;
+ --skip-convert) SKIP_CONVERT=1; shift ;;
+ -h|--help) usage; exit 0 ;;
+ *)
+ echo -e "${RED}Unknown option: $1${RESET}"
+ usage; exit 1 ;;
+ esac
+done
+
+if [ -n "$TARGET" ]; then
+ FOUND=0
+ for c in "${CIRCUITS[@]}"; do [ "$c" = "$TARGET" ] && FOUND=1 && break; done
+ [ "$FOUND" -eq 1 ] || fail "Unknown circuit: '$TARGET'"
+ RUN_CIRCUITS=("$TARGET")
+else
+ RUN_CIRCUITS=("${CIRCUITS[@]}")
+fi
+
+# ββ Preflight checks ββββββββββββββββββββββββββ
+
+echo ""
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ"
+echo " Alien Protocol β Soroban Verifier Pipeline"
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ"
+
+command -v snarkjs >/dev/null 2>&1 || fail "snarkjs not found. Run: npm install -g snarkjs"
+command -v cargo >/dev/null 2>&1 || fail "cargo (Rust) not found. Install from https://rustup.rs"
+command -v git >/dev/null 2>&1 || fail "git not found."
+
+mkdir -p "$BLS_SETUP_DIR" "$PROOF_DIR" "$CONTRACT_DIR" "$TOOLS_DIR"
+
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+# PHASE 1 β Clone tools
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+section "PHASE 1 β Cloning Tools"
+
+C2S_DIR="$TOOLS_DIR/circom2soroban"
+GROTH16_DIR="$TOOLS_DIR/groth16_verifier"
+
+if [ ! -d "$C2S_DIR" ]; then
+ info "Cloning circom2soroban..."
+ git clone https://github.com/ymcrcat/soroban-privacy-pools.git "$TOOLS_DIR/soroban-privacy-pools"
+ # circom2soroban lives inside that repo
+ if [ -d "$TOOLS_DIR/soroban-privacy-pools/circom2soroban" ]; then
+ cp -r "$TOOLS_DIR/soroban-privacy-pools/circom2soroban" "$C2S_DIR"
+ ok "circom2soroban cloned"
+ else
+ warn "circom2soroban subdir not found in repo β will use manual Rust conversion"
+ C2S_DIR=""
+ fi
+else
+ ok "circom2soroban already present"
+fi
+
+if [ ! -d "$GROTH16_DIR" ]; then
+ info "Cloning soroban groth16_verifier example..."
+ git clone https://github.com/stellar/soroban-examples.git "$TOOLS_DIR/soroban-examples"
+ if [ -d "$TOOLS_DIR/soroban-examples/groth16_verifier" ]; then
+ cp -r "$TOOLS_DIR/soroban-examples/groth16_verifier" "$GROTH16_DIR"
+ ok "groth16_verifier cloned"
+ else
+ warn "groth16_verifier not found in soroban-examples"
+ GROTH16_DIR=""
+ fi
+else
+ ok "groth16_verifier already present"
+fi
+
+# Build circom2soroban if available
+C2S_BIN=""
+if [ -n "$C2S_DIR" ] && [ -f "$C2S_DIR/Cargo.toml" ]; then
+ info "Building circom2soroban..."
+ (cd "$C2S_DIR" && cargo build --release 2>&1) \
+ && C2S_BIN="$C2S_DIR/target/release/circom2soroban" \
+ && ok "circom2soroban built at $C2S_BIN" \
+ || warn "circom2soroban build failed β will generate Rust stubs manually"
+fi
+
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+# PHASE 2 β BLS12-381 Trusted Setup
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+if [ "$SKIP_SETUP" -eq 0 ]; then
+ section "PHASE 2 β BLS12-381 Trusted Setup"
+
+ POT_FILE="$BLS_SETUP_DIR/pot${POT_SIZE}_bls12381_final.ptau"
+
+ if [ ! -f "$POT_FILE" ]; then
+ info "Generating BLS12-381 Powers of Tau (size $POT_SIZE)..."
+ info "This takes a few minutes β grab a coffee β"
+
+ snarkjs powersoftau new bls12381 $POT_SIZE \
+ "$BLS_SETUP_DIR/pot${POT_SIZE}_0000.ptau" -v
+
+ snarkjs powersoftau contribute \
+ "$BLS_SETUP_DIR/pot${POT_SIZE}_0000.ptau" \
+ "$BLS_SETUP_DIR/pot${POT_SIZE}_0001.ptau" \
+ --name="Alien Protocol Contributor" \
+ --entropy="$(head -c 64 /dev/urandom | base64)" \
+ -v
+
+ snarkjs powersoftau prepare phase2 \
+ "$BLS_SETUP_DIR/pot${POT_SIZE}_0001.ptau" \
+ "$POT_FILE" -v
+
+ ok "BLS12-381 Powers of Tau ready β $POT_FILE"
+ else
+ ok "BLS12-381 ptau already exists, skipping"
+ fi
+
+ for CIRCUIT in "${RUN_CIRCUITS[@]}"; do
+ info "Setting up circuit: $CIRCUIT"
+
+ R1CS="$BUILD_DIR/$CIRCUIT/$CIRCUIT.r1cs"
+ CIRCUIT_SETUP_DIR="$BLS_SETUP_DIR/$CIRCUIT"
+ mkdir -p "$CIRCUIT_SETUP_DIR"
+
+ ZKEY_0="$CIRCUIT_SETUP_DIR/circuit_0000.zkey"
+ ZKEY_F="$CIRCUIT_SETUP_DIR/circuit_final.zkey"
+ VKEY="$CIRCUIT_SETUP_DIR/vkey.json"
+
+ [ -f "$R1CS" ] || fail "$CIRCUIT β r1cs not found at $R1CS (run compile first)"
+
+ if [ ! -f "$ZKEY_F" ]; then
+ snarkjs groth16 setup "$R1CS" "$POT_FILE" "$ZKEY_0"
+
+ snarkjs zkey contribute "$ZKEY_0" "$ZKEY_F" \
+ --name="Alien Protocol Phase2" \
+ --entropy="$(head -c 64 /dev/urandom | base64)" \
+ -v
+
+ rm -f "$ZKEY_0"
+ else
+ ok "$CIRCUIT β zkey already exists, skipping"
+ fi
+
+ if [ ! -f "$VKEY" ]; then
+ snarkjs zkey export verificationkey "$ZKEY_F" "$VKEY"
+ fi
+
+ ok "$CIRCUIT β BLS12-381 setup complete"
+ echo " βββ zkey : $ZKEY_F"
+ echo " βββ vkey : $VKEY"
+ echo ""
+ done
+else
+ warn "Skipping BLS12-381 trusted setup (--skip-setup)"
+fi
+
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+# PHASE 3 β Generate & Verify Proofs
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+if [ "$SKIP_PROVE" -eq 0 ]; then
+ section "PHASE 3 β Generating Proofs"
+
+ PROVE_FAIL=()
+
+ for CIRCUIT in "${RUN_CIRCUITS[@]}"; do
+ info "Proving: $CIRCUIT"
+
+ ZKEY_F="$BLS_SETUP_DIR/$CIRCUIT/circuit_final.zkey"
+ VKEY="$BLS_SETUP_DIR/$CIRCUIT/vkey.json"
+ WTNS="$WITNESS_DIR/$CIRCUIT/$CIRCUIT.wtns"
+ OUT="$PROOF_DIR/$CIRCUIT"
+ mkdir -p "$OUT"
+
+ PROOF="$OUT/proof.json"
+ PUBLIC="$OUT/public.json"
+
+ [ -f "$ZKEY_F" ] || { warn "$CIRCUIT β zkey missing, skipping prove"; PROVE_FAIL+=("$CIRCUIT"); continue; }
+ [ -f "$WTNS" ] || { warn "$CIRCUIT β witness missing at $WTNS, skipping"; PROVE_FAIL+=("$CIRCUIT"); continue; }
+
+ snarkjs groth16 prove "$ZKEY_F" "$WTNS" "$PROOF" "$PUBLIC"
+
+ # Smoke-check the proof
+ if snarkjs groth16 verify "$VKEY" "$PUBLIC" "$PROOF"; then
+ ok "$CIRCUIT β proof valid β"
+ else
+ warn "$CIRCUIT β proof generated but verification FAILED"
+ PROVE_FAIL+=("$CIRCUIT (verify failed)")
+ fi
+
+ echo " βββ proof : $PROOF"
+ echo " βββ public : $PUBLIC"
+ echo ""
+ done
+
+ if [ ${#PROVE_FAIL[@]} -gt 0 ]; then
+ warn "Proof generation issues:"
+ for f in "${PROVE_FAIL[@]}"; do echo " - $f"; done
+ fi
+else
+ warn "Skipping proof generation (--skip-prove)"
+fi
+
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+# PHASE 4 β circom2soroban Conversion
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+if [ "$SKIP_CONVERT" -eq 0 ]; then
+ section "PHASE 4 β Generating Soroban Verifier Contracts"
+
+ for CIRCUIT in "${RUN_CIRCUITS[@]}"; do
+ info "Converting: $CIRCUIT"
+
+ VKEY="$BLS_SETUP_DIR/$CIRCUIT/vkey.json"
+ PROOF="$PROOF_DIR/$CIRCUIT/proof.json"
+ PUBLIC="$PROOF_DIR/$CIRCUIT/public.json"
+ OUT_RS="$CONTRACT_DIR/${CIRCUIT}_verifier.rs"
+ C2S_OUT="$CONTRACT_DIR/${CIRCUIT}_c2s"
+ mkdir -p "$C2S_OUT"
+
+ [ -f "$VKEY" ] || { warn "$CIRCUIT β vkey missing, skipping conversion"; continue; }
+ [ -f "$PROOF" ] || { warn "$CIRCUIT β proof missing, skipping conversion"; continue; }
+ [ -f "$PUBLIC" ] || { warn "$CIRCUIT β public.json missing, skipping conversion"; continue; }
+
+ # ββ Run circom2soroban if available ββββββββββ
+ if [ -n "$C2S_BIN" ] && [ -x "$C2S_BIN" ]; then
+ "$C2S_BIN" vk "$VKEY" > "$C2S_OUT/vk_rust.txt" 2>/dev/null || true
+ "$C2S_BIN" proof "$PROOF" > "$C2S_OUT/proof_rust.txt" 2>/dev/null || true
+ "$C2S_BIN" public "$PUBLIC" > "$C2S_OUT/pub_rust.txt" 2>/dev/null || true
+ ok "$CIRCUIT β circom2soroban conversion done"
+ fi
+
+ # ββ Generate Soroban contract stub βββββββββββ
+ # Reads vkey.json and writes a complete Rust Soroban verifier
+ # that embeds the verification key constants and exposes
+ # a verify_proof(proof_bytes, public_bytes) β bool entry point.
+
+ CIRCUIT_PASCAL=$(echo "$CIRCUIT" | sed -r 's/(^|_)([a-z])/\U\2/g')
+
+ node - < "$OUT_RS"
+const fs = require('fs');
+const vkey = JSON.parse(fs.readFileSync('$VKEY', 'utf8'));
+
+// Extract verification key fields
+const alpha = vkey.vk_alpha_1;
+const beta = vkey.vk_beta_2;
+const gamma = vkey.vk_gamma_2;
+const delta = vkey.vk_delta_2;
+const ic = vkey.IC;
+
+function g1(pt) {
+ return \`G1Affine::from_xy_unchecked(
+ Fq::from_str("\${pt[0]}").unwrap(),
+ Fq::from_str("\${pt[1]}").unwrap(),
+ )\`;
+}
+
+function g2(pt) {
+ return \`G2Affine::from_xy_unchecked(
+ Fq2::new(
+ Fq::from_str("\${pt[0][0]}").unwrap(),
+ Fq::from_str("\${pt[0][1]}").unwrap(),
+ ),
+ Fq2::new(
+ Fq::from_str("\${pt[1][0]}").unwrap(),
+ Fq::from_str("\${pt[1][1]}").unwrap(),
+ ),
+ )\`;
+}
+
+const icLines = ic.map((pt, i) =>
+ \` // IC[\${i}]\n \${g1(pt)},\`
+).join('\n');
+
+const numIC = ic.length;
+const numPublic = ic.length - 1;
+
+const out = \`// SPDX-License-Identifier: Apache-2.0
+// Auto-generated by soroban-setup.sh (circom2soroban pipeline)
+// Circuit : $CIRCUIT
+// Curve : BLS12-381
+// Scheme : Groth16
+//
+// Usage:
+// 1. Copy this file into your Soroban contract crate.
+// 2. Add the groth16_verifier crate as a dependency.
+// 3. Call \\\`verify_proof(proof_bytes, public_bytes)\\\` from your contract.
+
+#![no_std]
+
+use soroban_sdk::{contract, contractimpl, Bytes, Env};
+use ark_bls12_381::{Bls12_381, Fq, Fq2, G1Affine, G2Affine};
+use ark_ff::Fp;
+use ark_groth16::{Groth16, PreparedVerifyingKey, VerifyingKey};
+use groth16_verifier::{deserialize_proof, deserialize_public_inputs};
+
+// ββ Verification Key Constants βββββββββββββββββββββββββββββ
+//
+// These constants are derived from the circuit-specific trusted
+// setup (BLS12-381 Powers of Tau). Changing any constant will
+// cause all proofs for this circuit to fail verification.
+
+const ALPHA_G1: fn() -> G1Affine = || {
+ \${g1(alpha)}
+};
+
+const BETA_G2: fn() -> G2Affine = || {
+ \${g2(beta)}
+};
+
+const GAMMA_G2: fn() -> G2Affine = || {
+ \${g2(gamma)}
+};
+
+const DELTA_G2: fn() -> G2Affine = || {
+ \${g2(delta)}
+};
+
+/// Input-output commitment bases IC[0..n].
+/// IC[0] is the constant term; IC[1..] correspond to public signals.
+const NUM_IC: usize = \${numIC};
+const NUM_PUBLIC: usize = \${numPublic};
+
+fn make_ic() -> [G1Affine; \${numIC}] {
+ [
+\${icLines}
+ ]
+}
+
+// ββ Soroban Contract βββββββββββββββββββββββββββββββββββββββ
+
+#[contract]
+pub struct ${CIRCUIT_PASCAL}Verifier;
+
+#[contractimpl]
+impl ${CIRCUIT_PASCAL}Verifier {
+ /// Verify a Groth16 proof for the \\\`$CIRCUIT\\\` circuit.
+ ///
+ /// # Arguments
+ /// * \\\`proof_bytes\\\` β serialized proof (output of circom2soroban proof)
+ /// * \\\`public_bytes\\\` β serialized public inputs (output of circom2soroban public)
+ ///
+ /// # Returns
+ /// \\\`true\\\` if the proof is valid, \\\`false\\\` otherwise.
+ pub fn verify_proof(
+ _env: Env,
+ proof_bytes: Bytes,
+ public_bytes: Bytes,
+ ) -> bool {
+ let vk = VerifyingKey:: {
+ alpha_g1: ALPHA_G1(),
+ beta_g2: BETA_G2(),
+ gamma_g2: GAMMA_G2(),
+ delta_g2: DELTA_G2(),
+ gamma_abc_g1: make_ic().to_vec(),
+ };
+
+ let pvk = Groth16::::process_vk(&vk)
+ .expect("vk processing failed");
+
+ let proof = match deserialize_proof(&proof_bytes.to_alloc_vec()) {
+ Ok(p) => p,
+ Err(_) => return false,
+ };
+
+ let public_inputs = match deserialize_public_inputs(
+ &public_bytes.to_alloc_vec(),
+ NUM_PUBLIC,
+ ) {
+ Ok(pi) => pi,
+ Err(_) => return false,
+ };
+
+ Groth16::::verify_with_processed_vk(
+ &pvk,
+ &public_inputs,
+ &proof,
+ )
+ .unwrap_or(false)
+ }
+}
+\`;
+
+process.stdout.write(out);
+NODEJS_EOF
+
+ ok "$CIRCUIT β Soroban contract written"
+ echo " βββ $OUT_RS"
+ echo ""
+ done
+fi
+
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Summary
+# βββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ"
+echo -e "${GREEN}${BOLD} Soroban Pipeline Complete${RESET}"
+echo ""
+echo " Output directories:"
+echo " BLS zkeys : $BLS_SETUP_DIR"
+echo " Proofs : $PROOF_DIR"
+echo " Contracts : $CONTRACT_DIR"
+echo ""
+echo " Next steps:"
+echo " 1. Copy a contract .rs into your Soroban crate:"
+echo " cp $CONTRACT_DIR/_verifier.rs my_contract/src/"
+echo ""
+echo " 2. Add dependencies to Cargo.toml:"
+echo " groth16_verifier = { path = \"$GROTH16_DIR\" }"
+echo " ark-bls12-381 = { version = \"0.4\", default-features = false }"
+echo " ark-groth16 = { version = \"0.4\", default-features = false }"
+echo ""
+echo " 3. Build & deploy:"
+echo " stellar contract build"
+echo " stellar contract deploy --wasm target/wasm32-unknown-unknown/release/*.wasm"
+echo ""
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ"
diff --git a/zk/soroban/tools/groth16_verifier/Cargo.lock b/zk/soroban/tools/groth16_verifier/Cargo.lock
new file mode 100644
index 0000000..05923da
--- /dev/null
+++ b/zk/soroban/tools/groth16_verifier/Cargo.lock
@@ -0,0 +1,1792 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "ahash"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
+dependencies = [
+ "derive_arbitrary",
+]
+
+[[package]]
+name = "ark-bls12-381"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488"
+dependencies = [
+ "ark-ec",
+ "ark-ff",
+ "ark-serialize",
+ "ark-std",
+]
+
+[[package]]
+name = "ark-bn254"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f"
+dependencies = [
+ "ark-ec",
+ "ark-ff",
+ "ark-std",
+]
+
+[[package]]
+name = "ark-ec"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba"
+dependencies = [
+ "ark-ff",
+ "ark-poly",
+ "ark-serialize",
+ "ark-std",
+ "derivative",
+ "hashbrown 0.13.2",
+ "itertools",
+ "num-traits",
+ "zeroize",
+]
+
+[[package]]
+name = "ark-ff"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba"
+dependencies = [
+ "ark-ff-asm",
+ "ark-ff-macros",
+ "ark-serialize",
+ "ark-std",
+ "derivative",
+ "digest",
+ "itertools",
+ "num-bigint",
+ "num-traits",
+ "paste",
+ "rustc_version",
+ "zeroize",
+]
+
+[[package]]
+name = "ark-ff-asm"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-ff-macros"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-poly"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf"
+dependencies = [
+ "ark-ff",
+ "ark-serialize",
+ "ark-std",
+ "derivative",
+ "hashbrown 0.13.2",
+]
+
+[[package]]
+name = "ark-serialize"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5"
+dependencies = [
+ "ark-serialize-derive",
+ "ark-std",
+ "digest",
+ "num-bigint",
+]
+
+[[package]]
+name = "ark-serialize-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ark-std"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185"
+dependencies = [
+ "num-traits",
+ "rand",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "base16ct"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes-lit"
+version = "0.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0adabf37211a5276e46335feabcbb1530c95eb3fdf85f324c7db942770aa025d"
+dependencies = [
+ "num-bigint",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cfg_eval"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "chrono"
+version = "0.4.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "num-traits",
+ "serde",
+ "windows-targets",
+]
+
+[[package]]
+name = "const-oid"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crate-git-revision"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c521bf1f43d31ed2f73441775ed31935d77901cb3451e44b38a1c1612fcbaf98"
+dependencies = [
+ "serde",
+ "serde_derive",
+ "serde_json",
+]
+
+[[package]]
+name = "crypto-bigint"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+dependencies = [
+ "generic-array",
+ "rand_core",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "ctor"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb"
+dependencies = [
+ "ctor-proc-macro",
+ "dtor",
+]
+
+[[package]]
+name = "ctor-proc-macro"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2"
+
+[[package]]
+name = "curve25519-dalek"
+version = "4.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "curve25519-dalek-derive",
+ "digest",
+ "fiat-crypto",
+ "rustc_version",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "darling"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "data-encoding"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
+
+[[package]]
+name = "der"
+version = "0.7.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
+dependencies = [
+ "const-oid",
+ "zeroize",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+ "serde",
+]
+
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "derive_arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "downcast-rs"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
+
+[[package]]
+name = "dtor"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301"
+dependencies = [
+ "dtor-proc-macro",
+]
+
+[[package]]
+name = "dtor-proc-macro"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"
+
+[[package]]
+name = "dyn-clone"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
+
+[[package]]
+name = "ecdsa"
+version = "0.16.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
+dependencies = [
+ "der",
+ "digest",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+]
+
+[[package]]
+name = "ed25519"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
+dependencies = [
+ "pkcs8",
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
+dependencies = [
+ "curve25519-dalek",
+ "ed25519",
+ "rand_core",
+ "serde",
+ "sha2",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "either"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.13.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "rand_core",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "escape-bytes"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bfcf67fea2815c2fc3b90873fae90957be12ff417335dfadc7f52927feb03b2"
+
+[[package]]
+name = "ethnum"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c"
+
+[[package]]
+name = "ff"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+dependencies = [
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+ "zeroize",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "hash32"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "hashbrown"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
+[[package]]
+name = "heapless"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
+dependencies = [
+ "hash32",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "hex-literal"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown 0.12.3",
+ "serde",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.15.2",
+ "serde",
+]
+
+[[package]]
+name = "indexmap-nostd"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590"
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "js-sys"
+version = "0.3.76"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "k256"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b"
+dependencies = [
+ "cfg-if",
+ "ecdsa",
+ "elliptic-curve",
+ "sha2",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
+dependencies = [
+ "cpufeatures",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.168"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
+
+[[package]]
+name = "libm"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "macro-string"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "num-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+
+[[package]]
+name = "p256"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "primeorder",
+ "sha2",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "primeorder"
+version = "0.13.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+dependencies = [
+ "elliptic-curve",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "ref-cast"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
+dependencies = [
+ "ref-cast-impl",
+]
+
+[[package]]
+name = "ref-cast-impl"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "rfc6979"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+dependencies = [
+ "hmac",
+ "subtle",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "schemars"
+version = "0.8.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615"
+dependencies = [
+ "dyn-clone",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "schemars"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
+dependencies = [
+ "dyn-clone",
+ "ref-cast",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "schemars"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
+dependencies = [
+ "dyn-clone",
+ "ref-cast",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "sec1"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
+
+[[package]]
+name = "serde"
+version = "1.0.216"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.216"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.133"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_with"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
+dependencies = [
+ "base64",
+ "chrono",
+ "hex",
+ "indexmap 1.9.3",
+ "indexmap 2.7.0",
+ "schemars 0.8.22",
+ "schemars 0.9.0",
+ "schemars 1.0.4",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "serde_with_macros",
+ "time",
+]
+
+[[package]]
+name = "serde_with_macros"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha3"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
+dependencies = [
+ "digest",
+ "keccak",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "signature"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+dependencies = [
+ "digest",
+ "rand_core",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "soroban-builtin-sdk-macros"
+version = "25.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7192e3a5551a7aeee90d2110b11b615798e81951fd8c8293c87ea7f88b0168f5"
+dependencies = [
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "soroban-env-common"
+version = "25.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfc49a80a68fc1005847308e63b9fce39874de731940b1807b721d472de3ff01"
+dependencies = [
+ "arbitrary",
+ "crate-git-revision",
+ "ethnum",
+ "num-derive",
+ "num-traits",
+ "serde",
+ "soroban-env-macros",
+ "soroban-wasmi",
+ "static_assertions",
+ "stellar-xdr",
+ "wasmparser",
+]
+
+[[package]]
+name = "soroban-env-guest"
+version = "25.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2334ba1cfe0a170ab744d96db0b4ca86934de9ff68187ceebc09dc342def55"
+dependencies = [
+ "soroban-env-common",
+ "static_assertions",
+]
+
+[[package]]
+name = "soroban-env-host"
+version = "25.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43af5d53c57bc2f546e122adc0b1cca6f93942c718977379aa19ddd04f06fcec"
+dependencies = [
+ "ark-bls12-381",
+ "ark-bn254",
+ "ark-ec",
+ "ark-ff",
+ "ark-serialize",
+ "curve25519-dalek",
+ "ecdsa",
+ "ed25519-dalek",
+ "elliptic-curve",
+ "generic-array",
+ "getrandom",
+ "hex-literal",
+ "hmac",
+ "k256",
+ "num-derive",
+ "num-integer",
+ "num-traits",
+ "p256",
+ "rand",
+ "rand_chacha",
+ "sec1",
+ "sha2",
+ "sha3",
+ "soroban-builtin-sdk-macros",
+ "soroban-env-common",
+ "soroban-wasmi",
+ "static_assertions",
+ "stellar-strkey 0.0.13",
+ "wasmparser",
+]
+
+[[package]]
+name = "soroban-env-macros"
+version = "25.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a989167512e3592d455b1e204d703cfe578a36672a77ed2f9e6f7e1bbfd9cc5c"
+dependencies = [
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "stellar-xdr",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "soroban-groth16-verifier-contract"
+version = "0.0.0"
+dependencies = [
+ "ark-bls12-381",
+ "ark-ec",
+ "ark-ff",
+ "ark-serialize",
+ "soroban-sdk",
+]
+
+[[package]]
+name = "soroban-ledger-snapshot"
+version = "25.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99c5285c83e7a5581879b7a65033eae53b24ac9689975aa6887f1d8ee3e941c9"
+dependencies = [
+ "serde",
+ "serde_json",
+ "serde_with",
+ "soroban-env-common",
+ "soroban-env-host",
+ "thiserror",
+]
+
+[[package]]
+name = "soroban-sdk"
+version = "25.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1262aa83e99a0fb3e8cd56d6e5ca4c28ac4f9871ac7173f65301a8b9a12c20f"
+dependencies = [
+ "arbitrary",
+ "bytes-lit",
+ "crate-git-revision",
+ "ctor",
+ "derive_arbitrary",
+ "ed25519-dalek",
+ "rand",
+ "rustc_version",
+ "serde",
+ "serde_json",
+ "soroban-env-guest",
+ "soroban-env-host",
+ "soroban-ledger-snapshot",
+ "soroban-sdk-macros",
+ "stellar-strkey 0.0.16",
+ "visibility",
+]
+
+[[package]]
+name = "soroban-sdk-macros"
+version = "25.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93b62c526917a1e77b6dce3cd841b6c271f0fff344ea93ad92a8c45afe8051b6"
+dependencies = [
+ "darling",
+ "heck",
+ "itertools",
+ "macro-string",
+ "proc-macro2",
+ "quote",
+ "sha2",
+ "soroban-env-common",
+ "soroban-spec",
+ "soroban-spec-rust",
+ "stellar-xdr",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "soroban-spec"
+version = "25.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0186c943a78de7038ce7eee478f521f7a7665440101ae0d24b4a59833fb6d833"
+dependencies = [
+ "base64",
+ "stellar-xdr",
+ "thiserror",
+ "wasmparser",
+]
+
+[[package]]
+name = "soroban-spec-rust"
+version = "25.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a948196ed0633be3a4125e0c7a4fc0bb6337942e538813b1f171331738f9058"
+dependencies = [
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "sha2",
+ "soroban-spec",
+ "stellar-xdr",
+ "syn 2.0.106",
+ "thiserror",
+]
+
+[[package]]
+name = "soroban-wasmi"
+version = "0.31.1-soroban.20.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "710403de32d0e0c35375518cb995d4fc056d0d48966f2e56ea471b8cb8fc9719"
+dependencies = [
+ "smallvec",
+ "spin",
+ "wasmi_arena",
+ "wasmi_core",
+ "wasmparser-nostd",
+]
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
+[[package]]
+name = "spki"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "stellar-strkey"
+version = "0.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee1832fb50c651ad10f734aaf5d31ca5acdfb197a6ecda64d93fcdb8885af913"
+dependencies = [
+ "crate-git-revision",
+ "data-encoding",
+]
+
+[[package]]
+name = "stellar-strkey"
+version = "0.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "084afcb0d458c3d5d5baa2d294b18f881e62cc258ef539d8fdf68be7dbe45520"
+dependencies = [
+ "crate-git-revision",
+ "data-encoding",
+ "heapless",
+]
+
+[[package]]
+name = "stellar-xdr"
+version = "25.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10d20dafed80076b227d4b17c0c508a4bbc4d5e4c3d4c1de7cd42242df4b1eaf"
+dependencies = [
+ "arbitrary",
+ "base64",
+ "cfg_eval",
+ "crate-git-revision",
+ "escape-bytes",
+ "ethnum",
+ "hex",
+ "serde",
+ "serde_with",
+ "sha2",
+ "stellar-strkey 0.0.13",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "time"
+version = "0.3.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+
+[[package]]
+name = "time-macros"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "visibility"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
+
+[[package]]
+name = "wasmi_arena"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073"
+
+[[package]]
+name = "wasmi_core"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a"
+dependencies = [
+ "downcast-rs",
+ "libm",
+ "num-traits",
+ "paste",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.116.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50"
+dependencies = [
+ "indexmap 2.7.0",
+ "semver",
+]
+
+[[package]]
+name = "wasmparser-nostd"
+version = "0.100.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa"
+dependencies = [
+ "indexmap-nostd",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
diff --git a/zk/soroban/tools/groth16_verifier/Cargo.toml b/zk/soroban/tools/groth16_verifier/Cargo.toml
new file mode 100644
index 0000000..89b0c5b
--- /dev/null
+++ b/zk/soroban/tools/groth16_verifier/Cargo.toml
@@ -0,0 +1,34 @@
+[package]
+name = "soroban-groth16-verifier-contract"
+version = "0.0.0"
+edition = "2021"
+publish = false
+rust-version = "1.89.0"
+
+[lib]
+crate-type = ["cdylib"]
+doctest = false
+
+[dependencies]
+soroban-sdk = { version = "25.1.0" }
+
+[dev-dependencies]
+soroban-sdk = { version = "25.1.0", features = ["testutils"] }
+ark-bls12-381 = { version = "0.4.0"}
+ark-serialize = { version = "0.4.2"}
+ark-ff = { version = "0.4.2"}
+ark-ec = { version = "0.4.2"}
+
+[profile.release]
+opt-level = "z"
+overflow-checks = true
+debug = 0
+strip = "symbols"
+debug-assertions = false
+panic = "abort"
+codegen-units = 1
+lto = true
+
+[profile.release-with-logs]
+inherits = "release"
+debug-assertions = true
diff --git a/zk/soroban/tools/groth16_verifier/Makefile b/zk/soroban/tools/groth16_verifier/Makefile
new file mode 100644
index 0000000..b971934
--- /dev/null
+++ b/zk/soroban/tools/groth16_verifier/Makefile
@@ -0,0 +1,16 @@
+default: build
+
+all: test
+
+test: build
+ cargo test
+
+build:
+ stellar contract build
+ @ls -l target/wasm32v1-none/release/*.wasm
+
+fmt:
+ cargo fmt --all
+
+clean:
+ cargo clean
diff --git a/zk/soroban/tools/groth16_verifier/README b/zk/soroban/tools/groth16_verifier/README
new file mode 100644
index 0000000..bef4649
--- /dev/null
+++ b/zk/soroban/tools/groth16_verifier/README
@@ -0,0 +1,28 @@
+# Groth16 Verifier Contract
+
+A demonstration of a Groth16 zero-knowledge proof verifier implemented as a Soroban smart contract.
+
+The proof and verification key are generated following the Circom2 (circom compiler 2.2.1) [getting-started guide](https://docs.circom.io/getting-started/installation/).
+
+The computation demonstrates a simple multiplication circuit: `a * b = c`, where:
+- `a` and `b` are private inputs
+- `c` is the public output
+
+The `./data` directory contains all input files (circuit definition, inputs) and generated outputs. For proof verification, three key files are required:
+- [proof.json](./data/proof.json) - Contains the zero-knowledge proof
+- [verification_key.json](./data/verification_key.json) - Contains the verification key
+- [public.json](./data/public.json) - Contains the public inputs/outputs
+
+Other intermediate artifacts, including witness generation code and outputs from the "Powers of Tau" ceremony, are included in `./data/auxiliary` for reproducibility.
+
+The [contract implementation](./src/lib.rs) is translated from the auto-generated [Solidity contract](./data/multiplier2_js/verifier.sol). The [test suite](./src/test.rs) demonstrates off-chain parsing of the proof and verification key, along with successful contract execution.
+
+This example was presented at the [Stellar Developer Meeting - 12/19/2024](https://www.youtube.com/watch?v=51SitOUZySk&list=PLmr3tp_7-7Gg5IAsJ0VlgfMoh-aTmbQmh&index=4) to demonstrate the BLS12-381 features.
+
+## β οΈ WARNING: Demonstration Use Only
+
+**This project is for demonstration purposes only.**
+- It has **not** undergone security auditing
+- It is **not** safe for use in production environments
+
+**Use at your own risk.**
\ No newline at end of file
diff --git a/zk/soroban/tools/groth16_verifier/data/auxiliary/input.json b/zk/soroban/tools/groth16_verifier/data/auxiliary/input.json
new file mode 100644
index 0000000..c7e0fc6
--- /dev/null
+++ b/zk/soroban/tools/groth16_verifier/data/auxiliary/input.json
@@ -0,0 +1 @@
+{"a": 3, "b": 11}
diff --git a/zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2.circom b/zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2.circom
new file mode 100644
index 0000000..080377d
--- /dev/null
+++ b/zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2.circom
@@ -0,0 +1,16 @@
+pragma circom 2.0.0;
+
+/*This circuit template checks that c is the multiplication of a and b.*/
+
+template Multiplier2 () {
+
+ // Declaration of signals.
+ signal input a;
+ signal input b;
+ signal output c;
+
+ // Constraints.
+ c <== a * b;
+}
+
+component main = Multiplier2();
diff --git a/zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2_0000.zkey b/zk/soroban/tools/groth16_verifier/data/auxiliary/multiplier2_0000.zkey
new file mode 100644
index 0000000000000000000000000000000000000000..7d9b5b09d467f810c63792b03a6b145aeff84353
GIT binary patch
literal 3652
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
literal 0
HcmV?d00001
diff --git a/zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_0000.ptau b/zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_0000.ptau
new file mode 100644
index 0000000000000000000000000000000000000000..a7bd6041277aec189d341c410e14c6b46ba37c7e
GIT binary patch
literal 2359552
zcmeI&-Ahzy0Knm?EiE5+1Zp6wg
za;Z=&Hcg{2jV)o#h$t*#BZ595DrrLsO^MXpvHcr12%ZDy%$0*P%zMuJKJV}6Up5ww
z2m}I=;dA&kC43Ga^TX%4`l0ag`Ol%DH5We*o%{ZWz6*WTf6veRYhr27Z!30gdf2dH
zY0Do8D}I0d>yQ6T7!iyK|IP3@GJIAKMTf6}z?7IZg9rCFW%my4sLC6dT6C=@dGgI8
ztK*h+-s`!OfBt>yhsQHIw%+Y3?2kT~wsXY9?K3-L9vp7CQa%`891P7YyPFvK)1;iN
zrwOes{Gt@!k8vy8Dr@9_=nEAKV*Qe__+}
zih;JqCmScvi<(m(U;XxFa(+YOzJ;e2-CC8MUfgv%<#fi{sh!;k&q6ir^P>I#zJI?T
z3}7?r+NO9okWqH!!v6T21ogn@3j1E$h73b0`1&`_vDQXLM}6+f~>feKKw5h>6>0
zcE&t7+;F9QFuph#npt)?G4iKLIayCDGgC9>u5HL{%L+6uDVr9XUpppaU~y}-_xJty
z{TN^F5AL6yFP@L)59U|qhvv`L7uHACkJi_GfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^
z1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(LgfDiD2Z`TJ#2ZoP`FIQvPST>fw-LY)^
z8o$P`@yqI2J*#K+te(}gdREWsSv{*~^?ZO2@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1AKrF@Bu!+2lxOV-~)Vs5AXp#zz6sMAK(Lg
zfDiBiKEMa~03YB3e1H$|0Y1P7_y8Z^1OK-VL<9nXw(vQ8jE|}uS$m+nH+b~Y{@MM#
zO}k$uEp9%1w&uwOes{Gt@!k8vy8Dr@9_=nEAKV*Qe__+}ih;JqCmScvi<(m(U;XxF
sa(+YOzJ;e2-CC8MUfgv%<#fi{sh!;k&q6ir^P(fepJCLOPx9a8Uq8^Qng9R*
literal 0
HcmV?d00001
diff --git a/zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_0001.ptau b/zk/soroban/tools/groth16_verifier/data/auxiliary/pot12_0001.ptau
new file mode 100644
index 0000000000000000000000000000000000000000..262ae1b4c073c4be00d459c8fbcdc9faa8374d5c
GIT binary patch
literal 2361684
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
z
zVeYp)K1jk`Y^e(|!&mR50;qq{Zi=bcg1CogC2%cb1Mr*|9-xUu{mIj27n*Tb&N+h=8d}F3cyA1#iyFFI<0i{uomMjC
zVdzE9q7iFWX(kG3JzD(WS(rM<3G6jMF}77k6mJNFMUC3-E99)kWjCUoQaD-0Jkw;o
z=jW2GG9L^Eh3Yc^Q}^5SHaV4eR>LKnilr!-eJ&SN!JNS4MF!SaL@A&Sa |