Repository navigation
Protect eCash (ECX) wallets split from Bitcoin - #749
Conversation
|
|
||
| // The protection waits for the wallet to sync, so it runs in the background: | ||
| if (protectEcx) { | ||
| protectEcxWallet(ai, wallet).catch((error: unknown) => |
There was a problem hiding this comment.
Critical: the sweep exists only as this in-memory promise. split() resolves before the ECX wallet syncs, and nothing persists or retries the protection. If the app is killed, backgrounded until the OS reaps it, or logged out before totalRatio reaches 1, the sweep never runs in any later session. The ECX coins keep sharing UTXOs with BTC. The next BTC spend then replays on ECX and moves them. The GUI card in EdgeApp/edge-react-gui#6294 then says "wait for it to confirm" for a transaction that will never be sent. The only recovery is deleting and re-splitting the ECX wallet.
Suggest a durable marker (wallet otherData / a disklet flag on the ECX wallet) set at split time and cleared after saveTx, with the sweep resumed on login whenever the marker is present.
There was a problem hiding this comment.
Fixed. The ECX wallet's synced storage now holds EcxProtection.json: pending from the split, then sent with the sweep's txid, or empty. Each load of a pending wallet resumes the sweep, so logging out or closing the app before the wallet syncs leaves it to the next login, on any device. Calls re-read the status under a per-wallet lock before sweeping, so only one sweep goes out. The GUI reads the same file.
| wallet: EdgeCurrencyWallet | ||
| ): Promise<void> { | ||
| // Wait until the wallet has found every coin it shares with Bitcoin: | ||
| await ai.waitFor((props: RootProps): true | undefined => { |
There was a problem hiding this comment.
Warning: this wait has no exit besides totalRatio >= 1 or a throw from checkCurrencyWallet. An archived/paused ECX wallet, or an engine reset (CURRENCY_ENGINE_CLEARED sets the ratio back to 0), leaves it pending for the rest of the session and silently skips protection. On logout or wallet deletion it throws Wallet id ... does not exist, which reaches onError as an error the user did nothing to cause. Consider treating a missing wallet as a quiet cancel, and logging when protection is abandoned.
There was a problem hiding this comment.
A wallet that goes away (logout, archive, delete) now ends the wait quietly with a log line, and its pending status resumes the sweep at its next load. Engine failures still reach onError. An engine reset does not skip the protection: the wait continues until the resync reaches 1. A paused wallet waits until it is unpaused.
ECX has no automatic replay protection. After a Bitcoin wallet splits into ECX, the new wallet sweeps itself once it syncs. The ECX plugin's magic nLockTime keeps the sweep off Bitcoin, so the swept coins exist only on ECX and later Bitcoin spends cannot replay there. The sweep runs in the background so the split does not wait for the sync, and a wallet with nothing spendable skips it, so empty wallets still split. The wallet's synced storage records the protection in EcxProtection.json: pending from the split, then sent with the sweep's txid, or empty. Each load of a pending wallet resumes the sweep, so a session that ends before the wallet syncs (logout, app exit, archiving) leaves the sweep to the next load instead of dropping it, and the GUI reads the status instead of searching transaction names. A wallet that goes away while waiting cancels quietly.
795c5f2 to
e102af5
Compare
CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none. The sweep only protects anything once the ECX plugins from EdgeApp/edge-currency-plugins#466 exist, since their magic nLockTime is what keeps it off Bitcoin.
Description
Asana task
eCash (ECX) is a Bitcoin hard fork with no automatic replay protection. After a Bitcoin wallet splits into ECX, the new ECX wallet sends its whole balance to itself once it syncs. The ECX plugin's magic nLockTime makes this sweep invalid on Bitcoin, so afterwards the ECX sits on UTXOs that exist only on ECX, and later Bitcoin spends cannot replay onto them.
splitreturns without waiting for the sync.EcxProtection.json:pendingfrom the split, thensentwith the sweep's txid, orempty. The GUI reads this file.Testing: unit tests for the sweep, the empty-wallet split, and a sweep resumed on the next login after logging out before the wallet synced. In the simulator, a betanet split signed the sweep, which was logged instead of broadcast and checked by hand.