Loading
fix: never reuse an output address across coinjoin pools
Prevents address reuse in coinjoins across the Electrum plugin, the cli daemon and the web GUI. Invariant: an address (scriptPubKey) appears at most once, in at most one coinjoin, on either side of the transaction, as far as the local client can see.
Within one coinjoin transaction
| Reuse case | Plugin | CLI daemon | Web GUI |
|---|---|---|---|
| Two outputs share an address | equal-value and output-count validation aborts the round | register-output rejects an address another peer registered, combine_psbts rejects duplicate output scriptPubKeys | combine_psbts rejects duplicate output scriptPubKeys |
| Two inputs spend from the same address | finalize_coinjoin rejects duplicate spent-UTXO addresses | combine_psbts rejects two inputs spending UTXOs with the same scriptPubKey | combine_psbts, same check as the daemon |
| Input spends from an output address | input validation and finalize_coinjoin reject | registration endpoints and combine_psbts reject | register-input and combine_psbts reject |
Across coinjoins
| Reuse case | Plugin | CLI daemon | Web GUI |
|---|---|---|---|
| Same output address in two pools | fresh address helper skips addresses reserved by active sessions, creator address persisted so resume re-registers the same one | register-output checks all active pools | fresh address from getnewaddress each round |
| Same address funds inputs of two pools | input validation checks other sessions' pending coins | register-input compares spent-UTXO scriptPubKeys across all active pools | not applicable, one pool per session |
| Output in one pool, input in another | input validation checks other sessions' output lists | register-output checks other pools' inputs, register-input checks other pools' output addresses | not applicable |
| Previously used wallet address offered as output | only unused addresses are picked | getreceivedbyaddress rejects addresses that already received funds, covers the user supplied --address path | getnewaddress is always fresh |
Closes #43 (closed)
Edited by /dev/fd0