Configurable level of confirmations needed before a coin can be spent #1428

issue sgornick opened this issue on June 6, 2012
  1. sgornick commented at 7:40 PM on June 6, 2012: none

    I believe the vector76 attack (also referred to as the "one confirmation attack", which is a variation of the Finney attack) can easily lead to a subsequent situation that is, at best, an annoyance but to some degree it may result in causing a denial of service for Bitcoin users.

    The problem is that coin selection in the client can choose a coin that only has only one confirmation. At the same time though, the vector76 attack makes it possible that a transaction will exist with at least one confirmation but will never confirm. The result is that the spend transaction chooses a coin from a transaction whose block will eventually be orphaned and that spend transaction will never confirm.

    This is an annoyance to the user because the client does not (yet) have a mechanism to clear these 0/unconfirmed spend transactions that will never confirm. How this could result in a denial of service though is because there is a period of time that the user believes a spend transaction has been made but because the transaction for that payment won't get relayed by any other nodes, as it is invalid, the recipient will not receive payment.

    How this occurs:

    Bob's bitcoin node is left configured using the default settings and receives incoming traffic on the default port 8333. Evil miner creates a transaction (Trx A) to Bob's address but does not broadcast it. As soon as Evil miner solves a block he waits for a block at the same height to be solved. Immediately on learning this, Evil miner sends his block directly to (and only to) Bob's node. Evil miner then immediately creates another transaction (Trx B) that double spends the coin used in Trx A and broadcasts Trx B to well connected nodes. Shortly after, Bob then makes a payment to Alice (Trx C). Bob doesn't keep much of a balance, so the coin that was chosen by the client happened to be from Trx A which came from Evil miner and has one confirmation yet. Because Trx B got a head start by being sent through a well connected node, Trx A from Bob's node won't get propagated. Eventually the blockchain will include Trx B in the next block and Bob's node will drop Trx A back to 0/unconfirmed. Bob's Trx C to Alice will never confirm then. Alice might think Bob is a scammer as the payment that Bob claims to have made doesn't arrive and will not get included in any blocks.

    It is ironic that only Bob's node is either the sole ignorant node (or one of the few nodes) that doesn't realize that Trx A is invalid. It will be in this state until next block gets mined, -- so on average there will be a ten minute span that Bob's client remains ignorant and is willing to spend that invalid coin.

    Bob could have lessened the chance of this occurring by following the recommended step of not listening (-nolisten) and explicitly connecting only to a well connected node (-connect=) but if even Bob didn't do that the Bitcoin client could handle this situation a little better.

    Apparently the future plans for how the Bitcoin.org client deals with these 0/unconfirmed spend transactions is to have the client temporarily disable them and eventually to delete them when the conflict is buried deep in the chain. There could, however, be a configurable option added to prevent the spend transaction from occurring in the first place.

    If there was a configuration setting that added a restriction to coin selection (i.e., only choose coins with N or more confirmations), then this situation could be averted entirely. Another approach, I suppose, would be to for the client to retain in the memory pool any transactions that it rejected (e.g., Trx B) and to then not consider using any coins where it knows there is at least one conflict until after the coin with a conflict has confirmed.

    Now the normal situation where Evil miner might be motivated to do this is if Bob delivers the goods after seeing just one confirmation (or on 0/unconfirmed even). This is not the recommended practice, of course, as six confirmations is the recommended level for merchants who transact with untrusted parties or where there is no recourse (e.g., exchange for Dwolla or Liberty Reserve, for example).

    But if Evil miner's intention is to be disruptive to Bob such that Bob's service is harmed, then this attack is effective. (And inexpensive, say if the transaction is an exchange where little or no value is lost -- such as a deposit of bitcoins to an account on Bob's service and then a later withdrawal in which Bob assesses no fees.)

    If Bob could configure the client to only spend coins that have confirmed (e.g., those with six confirmations or more), the scenario where Bob makes spend transactions that will not confirm he could prevent this scenario of him creating invalid payments from occurring.

    The vector76 attack is described here: http://bitcointalk.org/index.php?topic=36788.msg463391#msg463391 and further here http://sourceforge.net/mailarchive/message.php?msg_id=27963970

  2. gmaxwell commented at 8:00 PM on June 6, 2012: contributor

    "Because the first transaction seen by most miners is Trx B, they will reject the block from Evil miner for being invalid and eventually the blockchain will confirm Trx B."

    I stopped reading here. This isn't how bitcoin works. Blocks always superseed hearing transactions not in blocks.

    Also I suspect you think a txn will still show confirmation 1 when its no longer in the longest chain. This isn't so, if the block the txn was confirmed in falls out of the longest chain the confirms will go back to zero.

    Also, the client will not spend inputs with less than 6 confirms if it has a choice.

  3. sgornick commented at 4:38 AM on June 7, 2012: none

    Blocks always superseed hearing transactions not in blocks.

    Yup, after re-reading vector76's post I see where I goofed on the details. But the problem is still there.

    So now Evil miner holds off on broadcasting his block which includes Trx A until he learns that a block at the same height has been mined elsewhere. Immediately then Evil miner races his block with Trx A directly to Bob and then at the same time broadcasts Trx B to well connected nodes.

    So the problem remains. Bob sees the block with Trx A, rejects the block which has the same height when it finally arrives from elsewhere and rejects Trx B when that arrives as well.

    I've edited the report above to reflect this missing detail of Evil miner holding onto the block until it has been solved elsewhere.

    As far as the client will not spend inputs with less than 6 confirms, that's why I clarified that "Bob doesn't keep much of a balance". With security fears keeping coins in cold storage, the online (hot) wallet will frequently be completely spent. If the intent is to grief Bob, Evil miner can withdraw coins to cause the hot wallet to run low or out, so it isn't like this scenario is one that won't ever occur. There is no risk to Evil miner too If Bob learns of the block from the network before Evil miner's block arrives, then simply Bob will never see Trx A. Or if Evil miner's block to Bob propagates and is the one that gets built instead of being orphaned, the Trx B is rejected and Evil miner's transaction with Bob gets processed as a normal transaction. So there's no risk to Evil miner to keep doing this over and over until Bob gets harmed.

  4. laanwj commented at 10:19 AM on September 25, 2014: member

    Closing this.

    The wallet will not spend recent outputs (<6 confirms) unless there is no other choice. So this is just a matter of waiting until there is enough balance 'old enough'.

  5. laanwj closed this on Sep 25, 2014

  6. lateminer referenced this in commit 1ba03cc688 on May 6, 2020
  7. DrahtBot 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-29 03:16 UTC

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