Skip to Content
Getting StartedArchitecture Overview

Architecture Overview

System Components

lateo/ ├── contracts/ Soroban smart contracts (Rust) │ ├── pool/ Privacy pool — transact(), disburse() │ ├── circom-groth16-verifier/ On-chain Groth16 verification │ ├── asp-membership/ Binary Merkle tree for inclusion proofs │ └── asp-non-membership/ Sparse Merkle tree for exclusion proofs ├── circuits/ Circom circuits (Groth16, BN254) │ └── src/policyTransaction.circom ├── proxy/ Privacy proxy server (TypeScript) │ ├── zk-pool-service.ts ZK proof generation + on-chain submission │ ├── batch-operator.ts Temporal batching for x402 payments │ ├── witness-builder.ts Circuit witness construction │ └── storage.ts SQLite + AES-256-GCM encryption ├── dashboard/ React dashboard ├── landing/ Landing page ├── zksearch/ x402-protected search service ├── mcp-server/ MCP server for AI agent integration └── target/wasm-prover-nodejs/ ark-groth16 compiled to WASM

Transaction Flows

Deposit (Atomic ZK)

1. Frontend → POST /api/deposit/prepare { amount, publicKey } 2. Proxy: generates Groth16 proof + builds unsigned transact() XDR 3. Frontend → Freighter signTransaction(XDR) → user approves 4. Frontend → POST /api/deposit/submit { signedTransactionXDR } 5. Proxy → submits signed tx to Stellar 6. ON-CHAIN (atomic): ├── pool.transact() verifies Groth16 proof ├── pool.transact() transfers USDC from sender to pool ├── pool.transact() inserts commitments into Merkle tree └── If ANY step fails → entire tx reverts → no USDC moves 7. Proxy → credits balance ONLY after on-chain confirmation

x402 Payment (Batched)

1. Agent → POST /api/pay { serviceUrl } 2. Proxy: verifies agent balance 3. Proxy: enqueues in BatchOperator 4. BatchOperator: accumulates payments for batch window (15s) 5. BatchOperator: executes x402 payments from pool wallet 6. On-chain: Pool → Service (individual agent not identifiable)

Withdrawal (Atomic ZK)

1. User → POST /api/withdraw { amount, destination } 2. Proxy: selects unspent notes for the withdrawal amount 3. Proxy: generates Groth16 proof with nullifiers 4. Proxy: operator signs transact() with negative ext_amount 5. ON-CHAIN (atomic): ├── pool.transact() verifies Groth16 proof ├── pool.transact() verifies nullifiers not already spent ├── pool.transact() marks nullifiers as spent ├── pool.transact() transfers USDC from pool to recipient ├── pool.transact() inserts change commitments └── If ANY step fails → entire tx reverts → no USDC moves 6. Proxy → debits balance ONLY after on-chain confirmation

Smart Contracts

ContractPurposeKey Functions
PoolPrivacy pool with atomic ZK transactionstransact(proof, extData, sender), disburse(), get_root()
Groth16 VerifierOn-chain BN254 pairing checkverify(proof, publicInputs)
ASP MembershipBinary Merkle tree of verified participantsinsert_leaf(), get_root()
ASP Non-MembershipSparse Merkle tree for exclusion proofsinsert(), delete(), verify_non_membership()

Trust Model

ComponentWhat it knowsTrust assumption
On-chain contractsCommitments, nullifiers, Merkle rootsTrustless — verified by Stellar validators
Proxy serverAgent identities, notes, payment requestsTrusted operator (mitigated by encrypted storage)
Freighter walletUser’s private keyUser’s device
x402 FacilitatorTransaction authorizationThird-party (Coinbase/OpenZeppelin)
Batch operatorWhich agent requested which paymentSame trust as proxy
Last updated on