0

Let’s have 2 transactions. The second one is duplicating Input of the first one.
Both have very high fees so they are selected by miner to be included in the same block but before passing validation (because it makes no sense to validate transactions if they aren’t included in the block after because the fee is too low).

Which is the transaction is going to be rejected by not being included in the block ? The first one with a slightly lower fee than the second or as it’s the same block, the second one ?

And where is the code in Bitcoin core handling this ? I mean which source files and lines ?

user2284570
  • 286
  • 2
  • 14

3 Answers3

3

Which is the transaction is going to be rejected ? The first one with a slightly lower fee than the second or as it’s the same block, the second one ?

Generally speaking, miners will choose the transaction that has the highest fee, but they are not obliged to. In fact they don't need to mine any of your transactions if they don't want to.

Both have very high fees so they are selected by miner to be included in the same block.

No, the miner must choose 1 or zero not both, otherwise the block they create will be invalid if it contains a double-spend. Invalid blocks will waste the miners time and money as they will be rejected by the network.

And where is the code in Bitcoin core handling this ?

Sorry, can't help with specific location.

Jonathan Cross
  • 1,410
  • 10
  • 30
  • `Both have very high fees so they are selected by miner to be included in the same block.` Before being validated of course. Because it makes no sense to validate inputs if they aren’t included in the block after. – user2284570 Apr 23 '19 at 21:57
  • 2
    @user2284570 no, a transaction is validated before it is added to a block, that is how blocks are built: From transactions that are known to be valid, as a whole. It makes no sense to only check to see if they are valid after mining a block, that would be a waste of resources. – chytrik Apr 23 '19 at 22:00
  • @chytrik I’m talking about fees. Transactions are validated by the miner only if they pay enough fees to be included in next block. – user2284570 Apr 24 '19 at 00:25
  • 1
    @user2284570 that is incorrect. I think you're mixing up what 'validate' means. Every node on the network that hears about a new tx will *validate* it before relaying it to network peers. Likewise, miners will *validate* each transaction before the add it to a block template that they will mine one. Once the miner finds a valid block, the transactions they added to it are said to be *confirmed*. So there is a difference between *valid* and *confirmed*. In fact, an otherwise valid transaction may never be confirmed (perhaps it paid too low a fee, or was not seen by miners, etc). – chytrik Apr 24 '19 at 01:19
  • @chytrik what I mean is miners don’t process the whole mempool and then includes transactions with the best fees in the block : they only check those which pay enough fees to be included. – user2284570 Apr 24 '19 at 12:44
  • 1
    @user2284570 if a transaction is in the miner’s mempool, that means they have *already validated it*. So yes, miners do ‘process the whole mempool’ first – chytrik Apr 24 '19 at 16:09
  • @chytrik no! The mempool don t check for double spends which are in the mempool. And as the process of nodes is not serialized unlike the block generation process this wouldn t makes sense. So in the case of the mempool double spending checking is performed only against coins in the ledger not on transactions not yet mined. – user2284570 Apr 24 '19 at 16:41
  • 2
    @user2284570 Just repeating this claim does not make it true. As everyone is already telling you: all transactions in the mempool are already validated, or they wouldn't be in the mempool. Miners typically select from this set of valid transactions that maximizes feerate. – Pieter Wuille Apr 24 '19 at 16:45
  • 2
    Regarding double-spend checking: Bitcoin Core maintains two "views" of the UTXO set; one from just confirmed blocks, and one from blocks + everything in the mempool. New incoming transactions are fully validated against the latter (they're allowed to spend unconfirmed outputs). When a new block comes in, the mempool is reconciled with it (removing transactions that were confirmed or now conflict with the new block). – Pieter Wuille Apr 24 '19 at 16:47
  • @PieterWuille but I m not merely repeateating, this is you who are wrong. But said otherwise, checktxinputs in validation.cpp uses haveInput which only read from disk cache or from disk directly not in the mempool. And for reference https://bitcoin.stackexchange.com/a/37534 – user2284570 Apr 24 '19 at 17:09
  • 2
    @user2284570 CheckTxInputs is passed a CCoinsViewCache object in AcceptToMemoryPoolWorker, which is backed by a CCoinsViewMemPool object, which in its turn looks up transactions in the mempool. – Pieter Wuille Apr 24 '19 at 17:43
  • @PieterWuille this is nonsense. Even then what happens when submitting 2 new transactions using the same inputs to 2 different unconnected nodes considering network latency ? There are several nodes, this block generation which serializes the process. – user2284570 Apr 24 '19 at 17:47
  • 2
    @user2284570 If you can't have a civil conversation about this, I'm done explaining. There are lots of interesting details to learn about how all of this works, but you seem to reject everything knowledgeable people try to explain. – Pieter Wuille Apr 24 '19 at 17:51
  • @PieterWuille and finally [an example](https://www.reddit.com/r/Bitcoin/comments/239bj1/doublespending_unconfirmed_transactions_is_a_lot/) of what I’m saying. – user2284570 Apr 24 '19 at 17:55
  • 1
    @user2284570 that example involves situations in which some miners would *not accept certain transactions into their mempool*, it does not show more than one tx in a certain miner’s mempool spending the same inputs. As people here have attempted to explain to you, such a situation is not possible. Note that each node maintains its own mempool, and that is part of how double spend txs can be published. Double spent inputs can **not** exist validly in a single node’s/miner’s mempool. – chytrik Apr 24 '19 at 20:43
2

Every transaction included in a block must be valid in order for the block to be valid. An input can only be spent once, any attempt to spend it again would be invalid.

So in your example, the entire block would be invalid and thus rejected by the network. Nodes that hear about and attempt to validate the block would get to the second transaction, see it is invalid (because one of its inputs was already spent), and reject the entire block.

Generally, miners will choose the transaction that pays them the most. The bitcoin-core rules for relaying transactions are separate from this, so they aren’t of much consequence in the real world. A miner could easily run their own modified software that builds blocks in a way they like. Even if a transaction isn’t marked RBF, there is nothing stopping a miner from including a higher paying transaction they heard about instead.

chytrik
  • 17,910
  • 3
  • 18
  • 47
  • No, I was meaning which is the block the miner will reject if he/she uses Bitcoin core. Because of course miners rejects transactions that attempt to double spend. – user2284570 Apr 23 '19 at 21:52
  • I added a bit to my answer, hopefully that helps. – chytrik Apr 23 '19 at 21:58
1

I am going to interpret this question from a different angle: If a node were to receive a block with two transactions that spend the same input, which transaction will it return to the mempool and which will it discard?


When a node receives a block that contains two or more transactions that spend the same inputs, the block would be marked invalid and thrown away entirely. None of the transactions in that block would be considered confirmed and any transaction that was already in the mempool will remain there. A transaction was not in the mempool but was in the block will not be added to the mempool.

As such, when the node receives this invalid block and validates it, when it determines it to be invalid, it throws away the block and does nothing. It does not change the UTXO set and it does not change the mempool. This means that if any of the conflicting transactions were in the mempool when the block is received, it will remain there. If none were, none of those transactions will be added to the mempool.

So if one of the conflicting transactions paid a higher fee, but the lower fee transaction was already in the node's mempool, the lower fee transaction would stay in the mempool and the higher fee one thrown away with the block.

The code for this behavior is here. ConnectBlock takes a CCoinsViewCache which is a cache for the UTXO set. This cache only writes out the changes made to it when its Flush() function is called. ConnectBlock will return false because the block is invalid and as such, this function will return here before Flush() can be called here. So no changes will be made to the UTXO set.

Furthermore, that early return due to an invalid block means that the mempool update will not occur either. The call for the mempool update here will not be reached because of the early return and thus the the transactions that were in the mempool at the time the block was received will remain there, and the ones that weren't in the mempool will be thrown out along with the block.

Andrew Chow
  • 67,209
  • 5
  • 76
  • 149
  • I’m talking about rejection done by miner which I don’t know because if I’m correct such invalid block rejection is performed in CChainState::ConnectBlock in validation.cpp at `UpdateCoin` which ensure next input check will take into account coins spent by transactions in the same block. – user2284570 Apr 24 '19 at 10:18
  • 2
    The check for whether an input exists is done in `CheckTxInputs` which is called in multiple places, including `ConnectBlock` as well as `AcceptToMemoryPoolWorker`. It is not just checked when a block received; it is always checked whenever a transaction is received, whether that is in a block or over the network as an unconfirmed transaction. – Andrew Chow Apr 24 '19 at 17:46