-
Notifications
You must be signed in to change notification settings - Fork 36.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-include RBF replacement txs in fee estimation #22539
Conversation
Asking the mempool statistics reference on IRC, @0xB10C pointed out to me there are between 2000 and 6000 replacements per day at the moment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of interest, did anyone collect stats on how many txs are replacements? Edit: see previous comment
Although 0xb10c shared there are 2000-6000 replacement tx per day , I don't think it matters for few reasons:
|
Concept ACK, due to reasons stated in OP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 4abe6aa
For what it's worth, I've been comparing running this on 2 pretty similar nodes for the past week. This didn't affect estimates, it must be because we are currently in a pretty low fee period. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
untested ACK 4abe6aa (edited hash, sorry clipboard was bugged)
Concept is simple and code changes are very straightforward (only one line is effectively changed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept and code review ACK 4abe6aa
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 4abe6aa
reading through #9519 , the general consensus seemed to be "this will be trivial to and should be reverted once RBF is widely adopted by miners."
i didn't get the sense anyone was arguing to never include RBF in fee estimation, so given that RBF is widely adopted, this change makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
crACK 4abe6aa
Change makes sense given the wide adoption of RBF txs. Plus, as stated above, the original PR that excluded RBFs did state a potential revert in the future once there's increased use in the wild (when widely adopted as "miner policy").
Note: I am leaning towards the code suggestion here, specifically if (setConflicts.size() > 0) {
, to make the condition more explicit about the expected value of setConflicts.size()
(as was similarly done here in the same file). It's a non-blocking nit, so feel free to ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code review ACK 4abe6aa
If we're at the point where most of the network and miners support RBF, this makes our fee estimates more accurate. My concern correctness-wise was making sure that only the new transaction is considered in fee estimation (I don't have much knowledge of CBlockPolicyEstimator
). I've checked that when Finalize()
calls RemoveStaged()
which calls removeUnchecked()
for each transaction, the mempool will call minerPolicyEstimator->removeTx()
for the removed transactions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK 5b29258 🌴
Verified via git range-diff 4abe6aab...5b292580
that changes since my last ACK are only rebase-related, plus the slight improvement in the if condition (avoiding implicit int-to-bool cast).
That's a very good point. I think with this patch we would keep the replacement tx in the buckets until it expires.. |
Actually, I think it would be removed here when I ask because in some cases we keep the original transaction (e.g. we'll put it in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So at first i did not think it was fine. We in this case call But actually, we'd only count it as a failure if it didn't confirm for at least 12 blocks (for short stats, 24 and 42 for med and long). It's plenty of time for the replacement to have propagated and makes this type of race so unlikely that i think it's fine. Thank you for raising this point! |
overhead, op, scriptsig, nseq, value, spk = 10, 36, 5, 4, 8, 24 | ||
tx_size = overhead + op + scriptsig + nseq + value + spk | ||
fee = tx_size * feerate | ||
|
||
tx = CTransaction() | ||
tx.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), SCRIPT_SIG[utxo["vout"]])] | ||
tx.vout = [CTxOut(int(utxo["amount"] * COIN) - fee, P2SH_1)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid manual tx size calculation with magic numbers, you could simply create the CTransaction
first (without the fee), determine tx size via len(tx.serialize())
and then subtract the fee.
overhead, op, scriptsig, nseq, value, spk = 10, 36, 5, 4, 8, 24 | |
tx_size = overhead + op + scriptsig + nseq + value + spk | |
fee = tx_size * feerate | |
tx = CTransaction() | |
tx.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), SCRIPT_SIG[utxo["vout"]])] | |
tx.vout = [CTxOut(int(utxo["amount"] * COIN) - fee, P2SH_1)] | |
tx = CTransaction() | |
tx.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), SCRIPT_SIG[utxo["vout"]])] | |
tx.vout = [CTxOut(int(utxo["amount"] * COIN), P2SH_1)] | |
fee = len(tx.serialize()) * feerate | |
tx.vout[0].nValue -= fee |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right since we use legacy txs in this test it's indeed much cleaner. However i'd like to not invalidate 4 ACKs on a cosmetic change. Do you mind if i make it a follow-up in #23075 ?
while True: | ||
try: | ||
u = utxos_to_respend.pop(0) | ||
send_tx(node, u, high_feerate) | ||
except IndexError: | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be a bit shorter and more pythonic without exception:
while True: | |
try: | |
u = utxos_to_respend.pop(0) | |
send_tx(node, u, high_feerate) | |
except IndexError: | |
break | |
while utxos_to_respond: | |
u = utxos_to_respend.pop(0) | |
send_tx(node, u, high_feerate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed 🤦♂️ but same rationale as above, as ugly as it is i'd rather address it in #23075
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK 3b61372 🍪
Verified that since my last ACK a rebase was done and a test was added which LGTM. Being extra-paranoid, I also checked that the test fails on the master branch on the estimated fee assertion at the end of sanity_check_rbf_estimates
.
@darosior: I agree that the proposed fixups can be done in a follow-up, was not intending to block a merge (I kind of missed reading previous comments about fixups and PR #23075 that is already prepared for that purpose). BTW I also support the idea of using MiniWallet for creating txs, as suggested by gloria.
@@ -998,11 +993,10 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws) | |||
m_pool.RemoveStaged(allConflicting, false, MemPoolRemovalReason::REPLACED); | |||
|
|||
// This transaction should only count for fee estimation if: | |||
// - it isn't a BIP 125 replacement transaction (may not be widely supported) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One risk I could see is that someone running with a full-rbf patch might pay a higher fee now. So I am wondering if this needs to be re-introduced with a full-rbf patch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can only increase the fees for anyone, but if it does it means that it was necessary (a higher feerate was needed in order to have this transaction go through). How could a full-rbf patch wrongly increase estimates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High-fee non-miner-policy txs (In this case full-rbf'ed) might fill your mempool, but never get confirmed, thus raising your estimates.
This is a general problem and I was just wondering if the patch should be re-introduced for full-rbf (or other similar policy changes in the future).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh for people running it without knowing that some miners do as well.
I think stopping (again) to consider replacement transactions would be a step backward. However it could make sense for a full-RBF patch to stop considering replacement to not-opted-in transactions for fee estimation until the full-RBF policy is reasonably deployed on the network. Since we only implement explicit signaling it sounds like the complexity of doing so would be reasonable.
Notable changes | ||
=============== | ||
|
||
P2P and network changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something that should be mentioned in the release notes at all? Given that less than 25% of txs are opt-in-rbf and way less than that are conflicts, this shouldn't have any significant effect on real-world fee estimation. See also your findings: #22539 (comment)
Also, it doesn't change the P2P protocol or is a network change. At most it would affect your local estimates, so if the notes are kept, the section headline could be adjusted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See also your findings: #22539 (comment)
I expect this to be very different with a not so low fee market (replacement-aware fee estimation to constantly be slightly higher).
the section headline could be adjusted
Sure, what do you suggest? To be honest i was not sure what headline to use and since fee estimation is ubiquitous i figured it was a notable change, but happy to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will show up in the section "Policy" (example: https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-22.0.md#policy), but I think we never had a "notable change" policy section. Maybe "Fee estimation changes"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done here #23284
Following Marcofalke's feedback at bitcoin#22539 (comment)
Followups to bitcoin#22539 Co-Atuhored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
Following Marcofalke's feedback at bitcoin#22539 (comment)
5307351 doc: update release notes for 22539 (Antoine Poinsot) Pull request description: Following Marcofalke's feedback at bitcoin/bitcoin#22539 (comment) ACKs for top commit: shaavan: ACK 5307351 Tree-SHA512: 91ea3e6c7fc06a4f40723217735e3d3f12812dc5adafa4f8c505ae4df5bd91345133099a9c158a7f15f01313c3128c8c15455c24256d76cd93033c0b5ce2c64f
5307351 doc: update release notes for 22539 (Antoine Poinsot) Pull request description: Following Marcofalke's feedback at bitcoin#22539 (comment) ACKs for top commit: shaavan: ACK 5307351 Tree-SHA512: 91ea3e6c7fc06a4f40723217735e3d3f12812dc5adafa4f8c505ae4df5bd91345133099a9c158a7f15f01313c3128c8c15455c24256d76cd93033c0b5ce2c64f
This bool was originally part of Workspace and was removed in bitcoin#22539 when it was no longer needed in Finalize(). Re-introducing it because, once again, multiple functions will need to know whether we're doing an RBF. Member of MemPoolAccept so that we can use this to inform package RBF in the future.
This bool was originally part of Workspace and was removed in bitcoin#22539 when it was no longer needed in Finalize(). Re-introducing it because, once again, multiple functions will need to know whether we're doing an RBF. Member of MemPoolAccept so that we can use this to inform package RBF in the future.
This bool was originally part of Workspace and was removed in bitcoin#22539 when it was no longer needed in Finalize(). Re-introducing it because, once again, multiple functions will need to know whether we're doing an RBF. Member of MemPoolAccept so that we can use this to inform package RBF in the future.
Following Marcofalke's feedback at bitcoin/bitcoin#22539 (comment)
Followups to bitcoin#22539 Co-Atuhored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
Followups to bitcoin#22539 Co-Atuhored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
Followups to bitcoin#22539 Co-Authored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
60ae116 qa: replace assert with test framework assertion helpers in fee estimation test (Antoine Poinsot) e502139 qa: fee estimation with RBF test cleanups (Antoine Poinsot) 15f5fd6 qa: don't mine non standard txs in fee estimation test (Antoine Poinsot) eae52dd qa: pass scriptsig directly to txins constructor in fee estimation test (Antoine Poinsot) 1fc0315 qa: split coins in a single tx in fee estimation test (Antoine Poinsot) cc204b8 qa: use a single p2sh script in fee estimation test (Antoine Poinsot) 19dd91a qa: remove a redundant condition in fee estimation test (Antoine Poinsot) Pull request description: Some cleanups that i noticed would be desirable while working on #23074 and #22539, which are intentionally not based on it. Mainly simplifications and a slight speedup. - Use a single tx to create the `2**9` coins instead of creating `2**8` 2-outputs transactions - Use a single P2SH script - Avoid the use of non-standard transactions - Misc style nits (happy to take more) ACKs for top commit: pg156: I ACK all commits up to 60ae116 (except 1fc0315, where I have a question more for my own learning than actually questioning the PR). I built and ran the test successfully. I agree after the changes, the behavior is kept the same and the code is shorter and easier to reason. glozow: utACK 60ae116 Tree-SHA512: 57ae2294eb68961ced30f32448c4a530ba1cdee17881594eecb97e1b9ba8927d58c25022b847eb07fb67d676bf436108c416c2f2174864d258fcca5b528b8bbd
Followups to bitcoin#22539 Co-Authored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
Followups to bitcoin#22539 Co-Authored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
This effectively reverts #9519.
RBF is now largely in use on the network (signaled for by around 20% of
all transactions on average) and replacement logic is implemented in
most end-user wallets. The rate of replaced transactions is also
expected to rise as fee-bumping techniques are being developed for
pre-signed transaction ("L2") protocols.