Stellar testnetCircom · Groth16 · BN254Soroban

Veil

Pago privado no rastreable. A deposita 10 XLM en un pool y entrega una nota secreta; C retira esos 10 XLM presentando una prueba de conocimiento cero. Nadie puede vincular on-chain el depósito con el retiro, y la misma nota no se puede usar dos veces.

Depósitos
…
Retiros
…
XLM en el pool
…
Contrato

Cómo funciona

1
Depósito. Alice genera nullifier y secret, calcula commitment = Poseidon(nullifier, secret) y lo inserta en un Merkle tree on-chain pagando 10 XLM. Guarda la nota off-chain.
2
Retiro. Carol reconstruye el árbol desde los eventos, genera una prueba Groth16 de que conoce una hoja del árbol, y el contrato la verifica con las host functions BN254 de Soroban. Paga 10 XLM a Dave.
3
Sin doble gasto. La prueba expone nullifierHash = Poseidon(nullifier). El contrato lo marca como gastado y rechaza cualquier segundo intento.

Demo ejecutada en testnet

PasoTransacción
init (SAC de XLM, 10 XLM)528f08c2…c3c6a9
deposit · alice → pool4b1a171b…cff213
withdraw · carol firma, dave recibe (prueba ZK)188ac2f9…268347
corrida 2 (con OpenRouter en el flujo) · deposit / withdrawb54d05bb… / b5297ecc… · IA: "riesgo medio, esperar más depósitos"
withdraw con la misma notarechazado · Error(Contract, #5) NullifierSpent

Actividad on-chain cargando…

LedgerEventoDatoTx

Verifícalo tú

1
Sin instalar nada (2 min). Abre el contrato en stellar.expert: cada withdraw lleva la prueba Groth16 como argumento y solo tuvo éxito porque el pairing_check BN254 pasó on-chain. Quien deposita (alice) y quien retira (carol) no tienen relación.
2
Tests del contrato (5 min, solo Rust). cd contracts && cargo test: Poseidon == circomlib, una prueba real de snarkjs verifica y una alterada no, y el flujo completo con doble gasto rechazado.
3
Demo contra el contrato (10 min). Node + Stellar CLI + 3 cuentas de testnet. Tu propio depósito, tu propia prueba, tu propio retiro. Pasos exactos en el README.
git clone https://github.com/NovaCorpAI/veil && cd veil && npm i
stellar keys generate alice --network testnet --fund   # idem carol y dave
STELLAR=$(which stellar) bash scripts/demo.sh         # deposit → nota → withdraw con ZK → doble retiro rechazado
EntregaLink
Pull request al repo del tallerviniciorm/zk-pay-starter#1
Fork con la solución (veil/ + SOLUTION.md)NovaCorpAI/zk-pay-starter
Repo de desarrollo con historialNovaCorpAI/veil
Cobertura de los 8 GAPs y checklist de unlinkabilitySOLUTION.md
ContratoCA4D3V4D…CL6QQ

Lo que había que acertar: Poseidon on-chain idéntico a circomlib (Poseidon(1,2) verificado), y el orden c1‖c0 de las coordenadas G2 entre snarkjs y las host functions. Las dos cosas se validaron con tests antes del deploy.