<p>Yes, we check unconfirmed transactions to the full extent of what’s possible to do before they are included in the block, including that the scripts are valid and input scripts resolve the spending conditions defined in the corresponding output scripts. Anything that we have in our mempool is valid to be included in the next block. We even cache script validation, so when we get a new block, we do not need to check the scripts again for transactions that were in our mempool, we just need to ensure that the block is well-formed, no conflicting transactions are included in the block, and check any previously unseen transactions in full.</p>
<p>As to what checks are performed on transactions when they are submitted to the mempool, I have been poking around a bit in the function calls that follow a <code>ProcessTransaction</code> call. This is just a quick rundown from stepping through the functions and may be incomplete or not completely in order.</p>
<p>It seems to me that via <code>AcceptToMemoryPool</code> and <code>AcceptSingleTransaction</code> first <a href="https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/consensus/tx_check.cpp#L11" rel="noreferrer"><code>CheckTransaction</code></a> does some basic context-free checks:</p>
<ul>
<li>The transaction has at least one input and one output</li>
<li>The transaction is not bigger than the block size</li>
<li>Each output amount is at least 0</li>
<li>The outputs are in in sum less than 21 M₿</li>
<li>There are no duplicate inputs</li>
<li>That outpoints referenced in inputs are not undefined</li>
<li>If it‘s a coinbase, the coinbase field is not too long</li>
</ul>
<p>After that <a href="https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/validation.cpp#L770" rel="noreferrer"><code>PreChecks</code></a> continues with:</p>
<ul>
<li>Checking that the transaction is not a loose coinbase transaction</li>
<li>Rejecting outputs with excessive amounts of null data, bare multisig, or dust outputs that cause transaction to be non-standard</li>
<li>Rejecting transactions shorter than 65 bytes of non-witness data</li>
<li>Refusing immature timelocked transactions</li>
<li>Skipping transactions that are already in the mempool with the same wtxid or txid</li>
<li>Scanning for conflicting inputs and rejecting conflicts with non-replaceable transactions (otherwise teeing up a replacement attempt evaluation)</li>
<li><strong>Checking whether the UTXOs spent by the inputs are in our UTXO set</strong>, placing any transaction with unknown inputs into the orphanage</li>
<li>Checking whether any CSV-locked inputs are mature for mining</li>
</ul>
<p>At this point, <code>PreChecks</code> calls <a href="https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/consensus/tx_verify.cpp#L164" rel="noreferrer"><code>CheckTxInputs</code></a>:</p>
<ul>
<li>Checking that any coinbase outputs are mature</li>
<li>Checking that input amounts are in range</li>
<li>Checking that the input amounts can pay for the new outputs created</li>
<li>Checking that the transaction fee is in range</li>
</ul>
<p>Back in <code>PreChecks</code>, it now checks:</p>
<ul>
<li>That the inputs are standard</li>
<li>That the inputs have standard witnesses if applicable</li>
<li>That the SigOps limits are met</li>
<li>That the transaction meets the minimum feerate</li>
<li>That any replacement attempts do not exceed the conflict limits</li>
<li>That any transactions do not exceed ancestor or descendant limits</li>
</ul>
<p>After the <code>PreChecks</code>, <a href="https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/validation.cpp#L1436" rel="noreferrer"><code>AcceptSingleTransaction</code></a>:</p>
<ul>
<li>Checks that the maximum feerate is not exceeded</li>
<li>That a replacement would succeed</li>
<li>and finally <strong>that the transaction passes policy script checks and consensus script checks</strong></li>
</ul>
<p><strong>So, in fact, any transaction that lands in our mempool is eligible to be picked into the next block.</strong></p>

CC BY-SA 4.0
2024-09-11T15:59:36.417Z
2024-09-11T17:00:30.343Z
2024-09-11T17:00:30.343Z
Murch
<p>I suspect the low-resource basic checks are done 1st to prevent spam attacks, then the node would prolly check against the UTXO set, and before adding the TX to its own mempool and relay it further, check against conflicts in the current mempool.</p>
<p>At some point the spending conditions have to be checked, but not sure if this is done here or before being added in a block.
I can't imagine a miner not doing this check, and risking adding bad stuff in the blockchain, so does it make sense to check this also at this step?</p>
<p>This is how I intuitively imagine it would work, but I'm sure I'm missing quite a lot of stuff.</p>

CC BY-SA 4.0
2024-09-10T20:51:10.963Z
Related: https://bitcoin.stackexchange.com/q/77934/5406
Murch
<unconfirmed-transactions><transaction-verification><utxo-set>
What specific verifications are done on a fresh Bitcoin TX and in what order?
Alex Waltz
# What specific verifications are done on a fresh Bitcoin TX and in what order?

(Asked by: username_0 on 2024-09-10)

I suspect the low-resource basic checks are done 1st to prevent spam attacks, then the node would prolly check against the UTXO set, and before adding the TX to its own mempool and relay it further, check against conflicts in the current mempool.

At some point the spending conditions have to be checked, but not sure if this is done here or before being added in a block.
I can't imagine a miner not doing this check, and risking adding bad stuff in the blockchain, so does it make sense to check this also at this step?

This is how I intuitively imagine it would work, but I'm sure I'm missing quite a lot of stuff.

**Tags:** unconfirmed-transactions, transaction-verification, utxo-set

> **Comments:**
> **username_1**: Related: https://bitcoin.stackexchange.com/q/77934/5406  

---

## 1 answers

### Answer by username_1 on 2024-09-11. Score: 7 | Accepted answer

Yes, we check unconfirmed transactions to the full extent of what’s possible to do before they are included in the block, including that the scripts are valid and input scripts resolve the spending conditions defined in the corresponding output scripts. Anything that we have in our mempool is valid to be included in the next block. We even cache script validation, so when we get a new block, we do not need to check the scripts again for transactions that were in our mempool, we just need to ensure that the block is well-formed, no conflicting transactions are included in the block, and check any previously unseen transactions in full.

As to what checks are performed on transactions when they are submitted to the mempool, I have been poking around a bit in the function calls that follow a `ProcessTransaction` call. This is just a quick rundown from stepping through the functions and may be incomplete or not completely in order.

It seems to me that via `AcceptToMemoryPool` and `AcceptSingleTransaction` first [`CheckTransaction`](https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/consensus/tx_check.cpp#L11) does some basic context-free checks:

* The transaction has at least one input and one output
* The transaction is not bigger than the block size
* Each output amount is at least 0
* The outputs are in in sum less than 21 M₿
* There are no duplicate inputs
* That outpoints referenced in inputs are not undefined
* If it‘s a coinbase, the coinbase field is not too long

After that [`PreChecks`](https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/validation.cpp#L770) continues with:

* Checking that the transaction is not a loose coinbase transaction
* Rejecting outputs with excessive amounts of null data, bare multisig, or dust outputs that cause transaction to be non-standard
* Rejecting transactions shorter than 65 bytes of non-witness data
* Refusing immature timelocked transactions
* Skipping transactions that are already in the mempool with the same wtxid or txid
* Scanning for conflicting inputs and rejecting conflicts with non-replaceable transactions (otherwise teeing up a replacement attempt evaluation)
* **Checking whether the UTXOs spent by the inputs are in our UTXO set**, placing any transaction with unknown inputs into the orphanage
* Checking whether any CSV-locked inputs are mature for mining

At this point, `PreChecks` calls [`CheckTxInputs`](https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/consensus/tx_verify.cpp#L164):

* Checking that any coinbase outputs are mature
* Checking that input amounts are in range
* Checking that the input amounts can pay for the new outputs created
* Checking that the transaction fee is in range

Back in `PreChecks`, it now checks:

* That the inputs are standard
* That the inputs have standard witnesses if applicable
* That the SigOps limits are met
* That the transaction meets the minimum feerate
* That any replacement attempts do not exceed the conflict limits
* That any transactions do not exceed ancestor or descendant limits

After the `PreChecks`, [`AcceptSingleTransaction`](https://github.com/bitcoin/bitcoin/blob/0725a374941355349bb4bc8a79dad1affb27d3b9/src/validation.cpp#L1436):

* Checks that the maximum feerate is not exceeded
* That a replacement would succeed
* and finally **that the transaction passes policy script checks and consensus script checks**

**So, in fact, any transaction that lands in our mempool is eligible to be picked into the next block.**


---

