An orphan transaction is a transaction with missing inputs. The p2p code uses a TxOrphanage to store orphan
transactions, to be reconsidered later if/when its parent transaction(s) are submitted to mempool.
There are two ways this can happen:
ProcessOrphanTx, which is called at the start of each ProcessMessages, pops orphans from a
work set that is updated whenever a parent transaction is accepted to mempool.
When a low-feerate parent is paired with its child in the
orphanage to be submitted together as a package. This happens in two locations:
If it is found to be invalid for some reason other than missing inputs. For example, a
transaction may be missing two parents, and we have only accepted one of them to mempool so
far. In that case, we keep the orphan and will reconsider it again after the second parent is submitted.
Different transactions can have the same txid but different witnesses, i.e. different wtxids. For
example, a same-txid-different-witness transaction can have an invalid signature (and thus be
invalid) or a larger witness (but same fee and thus lower feerate).
We also covered adding Txid vs Wtxid type-safety to TxOrphanage in a previous review club.
Prior to this PR, the TxOrphanage is indexed by Txid and, when considering a new transaction
in AddTx, immediately fails if the new transactionâs txid matches that of an existing entry.
TxOrphanage::HaveTx takes a GenTxid to query the data structure by either txid or wtxid.
HaveTx is primarily called by AlreadyHaveTx which also accepts a GenTxid.
Why would we want to allow multiple transactions with the same txid to exist in the TxOrphanage
at the same time? What kind of situation does this prevent?
What are some examples of same-txid-different-witness orphans? (Bonus points if you can write a test case in the functional test for your example).
Letâs consider the effects of only allowing 1 entry per txid. What happens if a malicious peer sends us a mutated version of the orphan transaction, where the parent is not low feerate? What needs to happen for us to end up accepting this child to mempool? (There are multiple answers).
Letâs consider the effects if we have a 1p1c package (where the parent is low feerate and must be submitted with its child). What needs to happen for us to end up accepting the correct parent+child package to mempool?
Instead of allowing multiple transactions with the same txid (where we are obviously wasting some space on a version we will not accept), should we allow a transaction to replace an existing entry in the TxOrphanage? What would be the requirements for replacement?
Where in the code do we check whether the orphanage contains a transaction? Is the query done by wtxid, txid, or both? (Hint: there are at least 5).
This PR removes the ability to query the orphanage by txid, since the TxOrphanage no longer has an index by txid. Is that okay, and why or why not?
<glozow> Let's dive into the questions. Why would we want to allow multiple transactions with the same txid to exist in the TxOrphanage at the same time? What kind of situation does this prevent?
<maxedw_> When a parent comes in that a valid orphaned child can be combined with it to form a package. Prevents an attacker from preventing us getting our package in the mempool and confirmed
<angusp> I'm not super sure, my guess is malleability, if a messed-with tx was seen first and in the orphanage and you're indexing by txid, the honest one can't be included
<glozow> maxedw_: great! let's look at that a bit more closely. let's say an attacker has the parent tx and the child tx. what should they do / send to you?
<glozow> okay so the attacker sent you a malleated version of the child, and nobody has sent you the parent yet. what happens if an honest peer sends you the real child tx?
<angusp> so then the honest peer would have to rebroadcast the real child later when it's not an orphan? (Or is there a mechanism for my peer to re-request it later?)
<glozow> Ok! We covered the next question "What are some examples of same-txid-different-witness orphans?", we mentioned a bad signature and a really large witness for a lower feerate
<glozow> Ok next question. Instead of allowing multiple transactions with the same txid (where we are obviously wasting some space on a version we will not accept), should we allow a transaction to replace an existing entry in the TxOrphanage?
<angusp> Also think no, because you know nothing about the parent tx, you can't really pick which will be valid or not (between an honest tx and a maleated one)
<maxedw_> the only reason I could think to replace would be if it was a higher fee but you would also have to know it was valid which you couldn't do without the parent
<glozow> doesn't that make it easier? an honest peer will only send 1 tx. an attacker can send many, and has a 1/2 chance of displacing the tx each time
<glozow> Next question: Where in the code do we check whether the orphanage contains a transaction? Is the query done by wtxid, txid, or both? (Hint: there are at least 5).
<angusp> Presumably it was done by both Txid and Wtxid as the existing code also had m_wtxid_to_orphan_it -- I'm not really familiar enough to know where other than doing a code search!
<glozow> "This PR removes the ability to query the orphanage by txid, since the TxOrphanage no longer has an index by txid. Is that okay, and why or why not?"