Pleb5 / satshoot

Freelancing on nostr
https://satshoot.com
13 stars 3 forks source link

Protect User from losing money #61

Open Pleb5 opened 1 day ago

Pleb5 commented 1 day ago

The scenario

  1. User wants to pay with ecash so swaps Token to have the right Proofs available
  2. Mint responds with the swapped Token - the newly minted ecash: Some is P2PK locked to payment Recipient, some remains in User's possession
  3. We fail to publish new Token to Relays for any reason
  4. We run another Mint operation like 'Checking Proofs' or 'Swap' or 'Melt'. This will cause NDK to use the last Token event that was published successfully WHILE ignoring User's actual money that could NOT be synchronized with relays
  5. The Mint will not allow this operation because those outdated Proofs are already spent so reponds with 400-bad request "Token already spent" message
  6. On failing, NDK will then run 'Check Proofs' on these outdated Proofs and Mint will return 'Spent' reponse on most Proofs. Still we can have some unspent Proofs at this point but we have NEW unspent Proofs NOT included in this validity check
  7. NDK gets rid of spent Proofs but it also publishes an OUTDATED Token state. This is where ALL newly minted BUT NOT SYNCED MONEY COULD GET LOST

This is because Mint operations are atomic while nostr operations are NOT. So payment is actually NOT an atomic operation with NIP60 wallets.

To tackle this we need workarounds:

  1. Alert User of the Token publish failure
  2. Save unspent money in Local Storage as well as an exported file(JSON, tags encrypted)
  3. On the Toast message where we alert User we have a 'Retry' button that will try again to publish(uses memory)
  4. Have ways for the User to recover the ecash on wallet page from file OR try from Local storage. We cross-examine Proofs with current wallet state, 'Check Proof validity' of new unique Proofs and try to publish new Token event. We delete successfully published Proofs from local storage
  5. Additionally, when we run 'Check valid Proofs' operation with the Mints OR we are setting up the User's wallet, we could load unspent Proofs and try rollover again from Local storage AUTOMATICALLY too. UX improvement
Pleb5 commented 8 hours ago

Solution implementation:

The goal is to keep ecash in persistent storage besides relays AND have multiple ways to REsync ecash automatically and/or manually

Backup methods (Token event with encrypted tags):

AUTOMATIC Backup Triggers in PERSISTENT STORAGE AND MEMORY(svelte store):

  1. On EVERY Swap and Deposit operation

Manual FILE Backup Triggers:

  1. Button on Wallet page
  2. On FAILED Proof rollOver operation (Toast with action btn)

Resync operation:

  1. Either: Look for event in Memory(svelte store) OR persistent storage OR file OR a new unseen Token event was fetched. This depends on context
  2. Cross-check with existing latest wallet state. Find new unique Proofs and add them to latest Token event
  3. IF new Proofs were added, Try rollover operation

MANUAL Resync attempt triggers:

  1. "Recover ecash from File" option on Wallet page

AUTOMATIC Resync attempt triggers:

  1. On Wallet load (from persistent storage)
  2. On FAILED Swap / Melt operation (from memory)
  3. On NEW Token event with unspent but yet-unseen Proofs

More about outdated Tokens:

This way:

  1. The money is very hard to lose
  2. Payments and Withdrawals can be retried with increased chance of success
  3. We have automatic and manual ecash recovery options available from multiple locations in the app