Relay first double-spend as alert, notify wallet #4570

pull dgenr8 wants to merge 4 commits into bitcoin:master from dgenr8:relay_first_respend changing 23 files +429 −62
  1. dgenr8 commented at 6:58 AM on July 22, 2014: contributor

    Relay at most one double-spend per unspent output, subject to anti-DoS provisions.

    Unconfirmed double-spends carry information that is time-critical to the payee of the first spend, but today, they are silently dropped.

    Add a -respendnotify option that can immediately notify a user-supplied command when a double-spend affecting the wallet is received.

    Change the GUI wallet to highlight a transaction in red when a transaction that double-spends it has been seen. When the conflict first occurs, display a warning dialog.

    alertshot

    This change has been running on mainnet since 2014-05-02. Relayable double-spends seen by the change are recorded here in realtime.

  2. dgenr8 commented at 7:13 AM on July 22, 2014: contributor

    Prior development work subsumed in this request: #3883 #4450 #4484 Guidance and contributions so far from the following: @gavinandresen @mikehearn @petertodd @SergioDemianLerner @laanwj @sipa @jgarzik @gmaxwell @drak @Diapolo

  3. dgenr8 renamed this:
    Relay first double-spend as alert, and notify
    Relay first double-spend as alert, notify wallet
    on Jul 22, 2014
  4. petertodd commented at 8:45 PM on July 22, 2014: contributor

    UI needs to have a more restrictive idea of what is a double-spend. Make it only trigger the UI display of a double-spend if the double-spend doesn't pay you at least as much as the previous tx.

    Right now this warning will be set off by accident in many cases, for instance wallets like GreenAddress.it where dual-factor controls expire after some time period, allowing the txouts to be spent with more than one scriptSig.

  5. jgarzik commented at 8:57 PM on July 22, 2014: contributor

    Also there are valid double spend cases employed in contract protocols. For example, payment channels rely on only-A-or-B-is-valid protocol property to guarantee that the payment channel refund transaction OR the payment channel payment transaction is valid, but not both.

  6. dgenr8 commented at 11:42 PM on July 22, 2014: contributor

    @jgarzik Are there double-spend cases where an alert would be undesirable?

    For a payment channel, merchant would get an alert for the known attack where merchant claims payment close to the refund unlock time, then customer broadcasts the refund transaction as a double-spend as soon as it unlocks.

  7. dgenr8 commented at 1:13 AM on July 23, 2014: contributor

    @petertodd That is a bit of a minefield. Consider these 3 transactions

     In       Paysme
    tx1-1
     coin1      1
    
    tx1-2
     coin2      1
    
    tx2
     coin1      1
     coin2
    

    tx2 double-spends both tx1-1 and tx1-2. It pays as much as either one alone, but is not innocuous because it can stop both of them from confirming. What the UI currently does is highlight both tx1-1 and tx1-2 (conflict seen). tx2 is displayed (only because it pays us), and is also highlighted because it is a non-clone conflict.

    Re: GreenAddress can you connect the dots for me? How does the script getting more permissive imply it's not important to alert if the coin is spent twice?

  8. luke-jr commented at 1:16 AM on July 23, 2014: member

    @dgenr8 I don't think anyone said implementing this correctly would be easy ;)

  9. dgenr8 commented at 2:50 AM on July 23, 2014: contributor

    @luke-jr It wasn't ;P The example can be made arbitrarily complex by making overlapping groups of conflicts. The wording is careful -- another transaction was seen spending the money you think you're getting [unsaid -- there may be a third that you haven't seen]. Best to wait for confirmation.

  10. petertodd commented at 3:41 AM on July 23, 2014: contributor

    @dgenr8 You've also forgotten the case there tx2 spends tx1 and tx1 is double-spent. You're code doesn't right now warn users if they're only paid by tx2. Probably better to remove the UI stuff in this patch for now; make it a separate patch.

  11. luke-jr commented at 3:53 AM on July 23, 2014: member

    @dgenr8 Warning users about perfectly reasonable behaviour is not appropriate. And you should always wait for confirmation if you need confirmation, period.

  12. dgenr8 commented at 10:32 PM on July 23, 2014: contributor

    @petertodd Thank you. Proper alerts for a double-spend of an unconfirmed parent will require adding the branch of unconfirmed parents to the wallet at the time the child is first added.

    I'd like to get feedback on whether anyone sees a problem with this. These parents would be persistent like all wallet txes, and would not be displayed unless they are IsMine/IsFromMe themselves. They were already allowed into the mempool.

  13. laanwj added the label P2P on Jul 31, 2014
  14. laanwj added the label Wallet on Jul 31, 2014
  15. dgenr8 commented at 1:22 AM on August 23, 2014: contributor

    Lately, miners are pretty consistently not mining respends if they occur quickly, apparently up to a day or so after the first spend.

    That is nice, but the network still buries respends. Accepting 0-conf payments is still susceptible to the following attack, even if all miners are nice:

    When ready to "pay," attacker first transmits a bunch of transactions tx1 paying self, each from a different coin cX. Then, at a succession of time offsets, he transmits a respend of each coin to the target.

    The goal is for at least one tx2 to be seen by the target first, but the eventual miner second. An additional constant input c0 is included in all the tx2 to ensure that in an adverse scenario for attacker, the target can only be paid once at most. Change is not shown:

    respends=20  offset=.40s  offset increment=.05s
    
    tx1               elapsed        tx2
    c1 -> self          .40s         c1 + c0 -> target
    c2 -> self          .45s         c2 + c0 -> target
    ...
    c20 -> self        1.35s         c20 + c0 -> target
    
    Worst-case value to attacker: -20*fee
    Best-case value to attacker: (value of goods or services) - 19*fee
    

    Respend relay, with a properly monitored alert, is an effective countermeasure to this attack. Target would be alerted almost immediately to withhold goods or services.

    In addition to tuning the parameters, the attacker can use diverse nodes to gain variability in the timings, helping at least one pair to achieve the goal.

  16. dgenr8 force-pushed on Aug 26, 2014
  17. dgenr8 force-pushed on Aug 26, 2014
  18. dgenr8 force-pushed on Aug 30, 2014
  19. dgenr8 force-pushed on Sep 20, 2014
  20. BitcoinPullTester commented at 9:09 PM on September 20, 2014: none

    Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/p4570_d17d9ccf44625207415e6450171579ce8351c99d/ for binaries and test log. This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/ Contact BlueMatt on freenode if something looks broken.

  21. dgenr8 force-pushed on Oct 8, 2014
  22. dgenr8 referenced this in commit 91ad0d62df on Dec 6, 2014
  23. dgenr8 force-pushed on Dec 27, 2014
  24. dgenr8 force-pushed on Feb 10, 2015
  25. dgenr8 force-pushed on Feb 20, 2015
  26. dgenr8 force-pushed on Feb 26, 2015
  27. jonasschnelli commented at 12:56 PM on March 11, 2015: contributor

    needs rebase.

  28. dgenr8 force-pushed on Mar 12, 2015
  29. luke-jr commented at 4:50 PM on March 13, 2015: member

    Some serious problems with this still: respend checking is performed after IsStandard , so a fraudster need only craft his transactions carefully to defeat this entirely; if the order of this is inverted, you then create a situation where it encourages people who want to send real non-IsStandard transactions to do so as a double spend. I think the only way to resolve this is to remove IsStandard from the policy entirely (and hope enough nodes continue to run with this policy). This is potentially very dangerous.

    Furthermore, it appears an attacker can flood the network with double-spends in order to rate limit relaying of some of them. I also see no efforts made to consider the relay costs: since these are double spends, only one or the other will confirm, and thus the fee from the non-confirming one is never paid.

  30. dgenr8 commented at 4:09 PM on March 16, 2015: contributor

    @luke-jr First to catch up, the "wait for confirmation" part of the alert dialog message was removed. You're right, it's best to stick to the facts.

    You are also correct that this change does not secure unconfirmed spends, and as currently written, does not help in the construction of a system that does.

    What this change claims to do, and does, is to stop delaying the moment when interested parties can discover relayable double-spends. The wallet portion also serves the important function of notifying the user of successful double-spends.

    Even people with diametrically opposite views on whether unconfirmed transactions can ever gain more reliability agree that relaying double-spends, when possible, is an improvement. The reason is that they happened, and that is useful information.

  31. Relay double-spends, subject to anti-DOS
    As an alert, relay at most one transaction that respends a prevout already
    spent in an unconfirmed transaction in this node's mempool.
    
    As before, respends are not added to the mempool.
    
    Anti-Denial-of-Service-Attack provisions:
     - Use a bloom filter to relay only one respend per mempool prevout
     - Rate-limit respend relays to a default of 100 thousand bytes/minute
     - Define tx2.IsEquivalentTo(tx1): equality when scriptSigs are not considered
     - Do not relay these equivalent transactions
     - Do not allow relayed respends into our wallet unless they conflict with it,
       even if they pay us.  This addresses a resource exhaustion attack
    
    CWallet::SyncMetaData is changed to sync only to equivalent transactions.
    
    Remove an unused variable declaration in txmempool.cpp.
    6a62da9214
  32. UI to alert of respend attempt affecting wallet.
    Respend transactions that conflict with transactions already in the
    wallet are added to it.  They are not displayed unless they also involve
    the wallet, or get into a block.  If they do not involve the wallet,
    they continue not to affect balance.
    
    Transactions that involve the wallet, and have conflicting non-equivalent
    transactions, are highlighted in red.  When the conflict first occurs, a
    modal dialog is thrown.
    
    When a conflict is added to the wallet, counter nConflictsReceived is
    incremented.  This acts like a change in active block height for the
    purpose of triggering UI updates.
    58c5bb791c
  33. Add -respendnotify option, new RPC data, reg tests
    -respendnotify=<cmd> Execute command when a network tx respends wallet
    tx input (%s=respend TxID, %t=wallet TxID)
    
    Add respendsobserved array to gettransaction, listtransactions, and
    listsinceblock RPCs.  This omits the malleability clones that are included
    in the walletconflicts array.
    
    Add RPC help for respendsobserved and walletconflicts (help was missing
    for the latter).
    
    New test txn_doublespendrelay.py uses a 4-node network to test 5 relay
    scenarios.
    
    New test txn_clone does what the old txnmall.sh test did. It creates
    an equivalent malleated clone and tests that SyncMetaData syncs the
    accounting effects from the original transaction to the confirmed clone.
    
    Existing test txn_doublespend.py is changed to remove reliance on
    accounting "move" ledger entries and on broken SyncMetaData.  Instead,
    expect double-spend amount to be debited from the default "" account.
    2439d0a424
  34. Release notes d9351eee74
  35. dgenr8 force-pushed on Jul 13, 2015
  36. dgenr8 commented at 12:48 AM on July 13, 2015: contributor

    Rebased. There is a question of where to put the equivalent-tx-check function. At the moment there are identical versions in CTransaction and CWalletTx. See #6365.

  37. jgarzik commented at 5:58 PM on July 23, 2015: contributor

    Observations on this pull request:

    • Zero ACKs after a year
    • Discussion on mailing list, here and IRC indicates concerns remain

    Going to close. That is perhaps mildly controversial given the current core/xt code fork debates, but it seems within bounds of reasonable project management.

    We can re-open if ACKs suddenly appear or concerns are alleviated, etc. The overall motivation is simply janitorial, closing pull requests that aren't moving after a long time.

  38. jgarzik closed this on Jul 23, 2015

  39. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 18:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me