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.
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.nullifierHash = Poseidon(nullifier). El contrato lo marca como gastado y rechaza cualquier segundo intento.| Paso | Transacción |
|---|---|
| init (SAC de XLM, 10 XLM) | 528f08c2…c3c6a9 |
| deposit · alice → pool | 4b1a171b…cff213 |
| withdraw · carol firma, dave recibe (prueba ZK) | 188ac2f9…268347 |
| withdraw con la misma nota | rechazado · Error(Contract, #5) NullifierSpent |
| Ledger | Evento | Dato | Tx |
|---|
git clone https://github.com/NovaCorpAI/veil && cd veil && npm i bash scripts/demo.sh # deposit (alice) → nota → withdraw (carol → dave) → doble retiro rechazado
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.