Skip to content
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

Merged
merged 4 commits into from
Oct 7, 2021

Conversation

darosior
Copy link
Member

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.

@ghost
Copy link

ghost commented Jul 23, 2021

Concept ACK

image

@darosior
Copy link
Member Author

Asking the mempool statistics reference on IRC, @0xB10C pointed out to me there are between 2000 and 6000 replacements per day at the moment.

Copy link
Member

@maflcko maflcko left a 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

src/validation.cpp Outdated Show resolved Hide resolved
@ghost
Copy link

ghost commented Jul 23, 2021

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:

  1. Fee estimation is a meme IMO or maybe helps in UX for newbies. You cannot predict if a fee rate will confirm the transaction in next N blocks. Context: https://bitcoin.stackexchange.com/questions/105860/what-are-we-trying-to-predict-in-fee-estimation-and-why/106129
  2. If fee estimates are used, they should be available for all type of transactions and not based on % of txs per day. Rationale in PR Exclude RBF replacement txs from fee estimation #9519 was not good enough to change something. Not sure about the ACKs in that PR.
  3. If any % still matters to document in PR, it should be RBF per day because if a user did transaction with RBF enabled, fee estimate may be required by replacement tx. Total transaction per day around 200k so 20% is 40k RBF transactions. We shouldn't wait for usage or other node implementations/wallets to do better before doing things that make sense.

@0xB10C
Copy link
Contributor

0xB10C commented Jul 23, 2021

Out of interest, did anyone collect stats on how many txs are replacements? Edit: see previous comment

image

@Rspigler
Copy link
Contributor

Concept ACK, due to reasons stated in OP

Copy link
Contributor

@benthecarman benthecarman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 4abe6aa

@darosior
Copy link
Member Author

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.

Copy link
Contributor

@tryphe tryphe left a 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).

Copy link
Contributor

@theStack theStack left a 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

src/validation.cpp Outdated Show resolved Hide resolved
@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 10, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #23075 (refactoring: Fee estimation functional test cleanups by darosior)
  • #22674 (validation: mempool validation and submission for packages of 1 child + parents by glozow)

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.

Copy link
Member

@josibake josibake left a 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.

Copy link
Contributor

@Zero-1729 Zero-1729 left a 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.

Copy link
Member

@glozow glozow left a 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.

@darosior
Copy link
Member Author

Rebased on master after #22796 merge and addressed @theStack 's nit.

Copy link
Contributor

@theStack theStack left a 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).

@darosior
Copy link
Member Author

transaction is RBF'ed in our mempool, but the original transaction is included in a block

That's a very good point. I think with this patch we would keep the replacement tx in the buckets until it expires..

@glozow
Copy link
Member

glozow commented Sep 30, 2021

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 removeForBlock() calls removeConflicts here since it's conflicted out of the mempool. So that's fine, we'd just lose a data point.

I ask because in some cases we keep the original transaction (e.g. we'll put it in vExtraTxnForCompact for reconstructing compact blocks), so I wondered if that's something we want here.

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 3b61372

Thanks for patiently answering my questions! Verified that 053415b is move-only, and the added functional test looks correct to me. Will take my test improvement-related comments to #23075.

@darosior
Copy link
Member Author

darosior commented Oct 1, 2021

Actually, I think it would be removed here when removeForBlock() calls removeConflicts here since it's conflicted out of the mempool. So that's fine, we'd just lose a data point.

So at first i did not think it was fine. We in this case call removeTx with inBlock set to false, ie counting this removal as a failure to confirm. This could have led to wrecked estimations because we would count a higher fee tx as failed.

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!

@darosior
Copy link
Member Author

darosior commented Oct 1, 2021

@tryphe @theStack @josibake do you mind re-[reviewing-and-]ACKing? I think we are getting close to merge and no other conflicting PR reported by Drahbot seem closer to merge.

Comment on lines +162 to +168
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)]
Copy link
Contributor

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.

Suggested change
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

Copy link
Member Author

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 ?

Comment on lines +327 to +332
while True:
try:
u = utxos_to_respend.pop(0)
send_tx(node, u, high_feerate)
except IndexError:
break
Copy link
Contributor

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:

Suggested change
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)

Copy link
Member Author

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

Copy link
Contributor

@theStack theStack left a 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.

@laanwj laanwj merged commit 6f0cbc7 into bitcoin:master Oct 7, 2021
@@ -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)
Copy link
Member

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?

Copy link
Member Author

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?

Copy link
Member

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

Copy link
Member Author

@darosior darosior Oct 8, 2021

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.

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Oct 7, 2021
Notable changes
===============

P2P and network changes
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done here #23284

darosior added a commit to darosior/bitcoin that referenced this pull request Oct 15, 2021
darosior added a commit to darosior/bitcoin that referenced this pull request Oct 15, 2021
Followups to bitcoin#22539

Co-Atuhored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
darosior added a commit to darosior/bitcoin that referenced this pull request Oct 15, 2021
@darosior darosior deleted the fee_est_rbf branch October 15, 2021 11:01
@darosior
Copy link
Member Author

For what it's worth here is again another diagram for last ~2 wee
702743_705101
ks

maflcko pushed a commit to bitcoin-core/gui that referenced this pull request Oct 15, 2021
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
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Oct 15, 2021
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
glozow added a commit to glozow/bitcoin that referenced this pull request Oct 28, 2021
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.
glozow added a commit to glozow/bitcoin that referenced this pull request Oct 28, 2021
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.
glozow added a commit to glozow/bitcoin that referenced this pull request Oct 28, 2021
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.
janus pushed a commit to BitgesellOfficial/bitgesell that referenced this pull request Nov 11, 2021
darosior added a commit to darosior/bitcoin that referenced this pull request Nov 15, 2021
Followups to bitcoin#22539

Co-Atuhored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
darosior added a commit to darosior/bitcoin that referenced this pull request Dec 9, 2021
Followups to bitcoin#22539

Co-Atuhored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
darosior added a commit to darosior/bitcoin that referenced this pull request Dec 9, 2021
Followups to bitcoin#22539

Co-Authored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
maflcko pushed a commit that referenced this pull request Jan 6, 2022
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
mzumsande pushed a commit to mzumsande/bitcoin that referenced this pull request Jan 17, 2022
Followups to bitcoin#22539

Co-Authored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
rebroad pushed a commit to rebroad/bitcoin that referenced this pull request Feb 3, 2022
Followups to bitcoin#22539

Co-Authored-By: Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
@bitcoin bitcoin locked and limited conversation to collaborators Oct 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.