Key Concepts
Commitments
A commitment is a cryptographic hash that represents a deposit in the pool. It is computed as:
commitment = Poseidon2(amount, publicKey, blinding, domainSeparator=0x01)The commitment is inserted into the pool’s Merkle tree on-chain. Anyone can see that a commitment exists, but no one can determine the amount, owner, or blinding factor without the preimage.
Nullifiers
A nullifier is a unique, deterministic value derived from a commitment that prevents double-spending:
nullifier = Poseidon2(commitment, pathIndices, privateKey, domainSeparator=0x02)When you withdraw or spend, the nullifier is published on-chain. The contract checks that the nullifier hasn’t been used before. Because the nullifier is derived differently from the commitment, they cannot be linked — an observer cannot determine which commitment was spent.
Notes
A note is the private data you need to spend a commitment: the amount, blinding factor, and leaf index in the Merkle tree. Notes are stored encrypted (AES-256-GCM) in the proxy’s SQLite database.
Merkle Tree
The pool maintains a 10-level binary Merkle tree of commitments (max 1,024 leaves). When generating a ZK proof, you prove that your commitment exists in this tree without revealing which leaf it is.
Association Set Providers (ASPs)
ASPs are compliance-compatible membership lists. Before generating a proof, the prover must demonstrate membership in the ASP (or non-membership in an exclusion set). This implements the Privacy Pools model: privacy for honest users, transparency for regulators.
Groth16
Groth16 is a zero-knowledge proof system with:
- Constant proof size: 256 bytes regardless of circuit complexity
- Constant verification time: ~3ms with BN254 pairing check
- Trusted setup required: One-time ceremony to generate proving and verification keys
Lateo uses Groth16 over the BN254 curve, verified on-chain using Stellar Protocol 25’s native host functions (bn254_g1_add, bn254_g1_mul, bn254_pairing_check).
x402
x402 is a pay-per-request protocol for HTTP. When an AI agent hits a paywalled endpoint, it receives a 402 status code, signs a payment authorization, and retries. The service verifies payment on-chain and returns the data. Lateo interposes a privacy pool so the payment comes from the pool, not the agent’s wallet.
Batch Operator
The batch operator accumulates x402 payment requests from multiple agents and executes them in temporal batches from the pool wallet. An on-chain observer sees “Pool paid Service” N times in a burst — but cannot determine which of the N agents requested which payment.