OLD wallet seed secret/local
The compromised 24 words are the witness. They are used locally to build the proof witness and are never sent to a wallet, server, or network endpoint.
Prove ownership of the compromised wallet without revealing its seed. The recovered entitlement arrives at a fresh recovery wallet you control — never back to the wallet that was breached.
This page visualizes the Redeemer role for a Plutus V3 recovery contract. All wallet, proof, and chain interactions are mocked. No real proving occurs, no real keys are derived, and this file makes no runtime network calls.
CIP-30 wallets only operate on their own managed keys. The old seed and new recovery wallet are handled by this page's local code; the connected wallet only funds and submits the claim.
The compromised 24 words are the witness. They are used locally to build the proof witness and are never sent to a wallet, server, or network endpoint.
This page generates a fresh 24-word recovery wallet in the prototype and displays destination address D. Recovered funds go here.
A separate funded CIP-30 wallet pays fee and collateral, signs only those inputs, and submits the transaction. It cannot prove for old or new seeds.
Optional lookup against the public fixed eligibility snapshot. No secret is required for this step.
The connected wallet pays transaction fees and collateral and submits the claim. It is not the old wallet and not the new recovery wallet.
Enter the compromised wallet seed locally. This prototype validates only that 24 words are present.
It is used locally to build the proof witness and is never sent anywhere. In this prototype, the seed is not copied into persistent browser storage, a wallet, or a network request.
Recovered funds land at this fresh address, isolated from the compromised wallet. Back up the new seed before continuing.
This is where recovered funds will be sent. In the real system this seed must be backed up before submission. This prototype seed is fake and not a valid wallet.
Framed as heavy local computation: about 43s and about 7GB RAM in reality. This mock runs for a few seconds.
Low-RAM device? Use the native helper fallback. The system must never fall back to a remote prover.
local onlyMock 336-byte proof:
Only the proof and destination D leave the local proof boundary. The old seed, master key, derivation path, Merkle path, and witness remain local.
The claim transaction spends the custody UTxO and pays exactly the committed entitlement to D. Redeemer data is (proof, D, role).
The recovery relation proves control of the compromised wallet without revealing the seed. The on-chain verifier sees one public field element and the claim transaction; the private witness stays on the user's device.
The client queries the public eligibility snapshot, a Merkle tree over (credential C, entitlement) leaves whose root is pinned on-chain, and shows the entitlement for the user's credential.
The 24 words are converted via BIP39 to entropy, then to a Cardano CIP-1852 / BIP32-Ed25519 Icarus master extended private key (kL || kR || chain code, 96 bytes). This stays in memory on the device.
The client walks the CIP-1852 path m/1852'/1815'/account'/role/index to the leaf scalar kL, computes the leaf public key A = compress(kL * B) on Ed25519, and sets credential C = Blake2b-224(A). It confirms C equals the eligible snapshot leaf.
The client generates fresh entropy, a new 24-word seed, a new master key, and a fresh base address D (header || payment-credential-28 || stake-credential-28, 57 bytes). The new seed is shown for backup.
The witness includes the old master key, the Merkle inclusion path (siblings and directions) for C, the entitlement, snapshot_version, scriptHash, root, destination D, and role.
The digest is read little-endian and reduced modulo the BLS12-381 scalar field order: pub = Fr(Blake2b-256(domain_sep || scriptHash || snapshot_version || root || C || entitlement || D || role)).
The client runs the about 3.45M-constraint recovery circuit prover in WASM, or in the downloadable native helper, about 43s and about 7GB RAM in reality. The proof carries a Pedersen (BSB22) commitment forced by the circuit's lookup-table hashing. Only the about 336-byte proof and public destination D leave the device; the seed and witness never do.
Input is the custody UTxO at the contract. Output is exactly the entitlement to D. Redeemer data is (336-byte proof, D, role). Fee and collateral come from the connected CIP-30 wallet.
The connected wallet partial-signs only the fee and collateral inputs with signTx(tx, true) and submits with submitTx(tx), or the operator relayer submits if chosen.
This animation shows what happens when the claim transaction reaches the redemption smart contract. Toggle the rejected branch to see a tampered proof fail without moving funds.
Claim transaction leaves with the 336-byte proof plus destination D.
It arrives at the redemption contract's locked custody UTxO.
Authenticated on-chain data plus D and role converge into one field element.
Commitment-aware verification checks the proof, commitment point, and final pairing.
Output credentials match D and value equals the committed entitlement.
The nullifier for C is marked spent, preventing another claim.
1,250 ADA + 3 SUNDAE flow to the fresh recovery wallet.
Ready to play.
Plain English first, then the same role requirements in EARS notation.
| ID | Type | Requirement |
|---|---|---|
| REQ-RD-01 | ubiquitous | The redeemer client shall let a user look up a credential's eligibility and committed entitlement from the published snapshot without entering any secret. |
| REQ-RD-02 | ubiquitous | The redeemer client shall hold the old wallet's 24-word seed only in local device memory and shall never transmit it to any server, wallet, or network endpoint. |
| REQ-RD-03 | event-driven | When the user submits the old seed, the client shall derive the master key and credential C locally and confirm C matches an eligible snapshot leaf. |
| REQ-RD-04 | event-driven | When the old seed is accepted, the client shall generate a fresh 24-word recovery wallet, derive the destination address D, and display the new seed for backup before proceeding. |
| REQ-RD-05 | event-driven | When the user requests proof generation, the client shall generate the zk recovery proof locally, binding C, the entitlement, and D into the single public input. |
| REQ-RD-06 | state-driven | While no funded wallet is connected, the client shall prevent submission and prompt the user to connect a CIP-30 wallet or choose the relayer. |
| REQ-RD-07 | event-driven | When the proof is ready, the client shall build the claim transaction that spends the custody UTxO and pays exactly the committed entitlement to D, with redeemer = (proof, D, role). |
| REQ-RD-08 | event-driven | When the user submits, the client shall submit via the connected CIP-30 wallet by default, or via the operator relayer when selected. |
| REQ-RD-09 | unwanted | If the device cannot complete in-browser proving, then the client shall offer the downloadable native helper and shall never send the seed off-device for remote proving. |
| REQ-RD-10 | unwanted | If a credential's nullifier is already spent, then the claim shall be rejected and no funds released. |
| REQ-RD-11 | ubiquitous | The payout shall be cryptographically bound to the proven destination D so it cannot be redirected or front-run. |
| REQ-RD-12 | optional | Where the user requests it, the client shall verify snapshot inclusion of C and that the payout equals the committed entitlement. |
| REQ-RD-13 | ubiquitous | The redeemer client shall display, at all times, which of the three key materials each field concerns: old seed = secret/local; new wallet = destination; connected wallet = fees/submit. |
This simulates window.cardano.{wallet}.enable() and read-only funding calls. It cannot import old or new seeds.