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
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
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
:
- 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
:
- 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.