Skip to content

Bump unconfirmed ancestor transactions to target feerate#26152

Merged
achow101 merged 8 commits intobitcoin:masterfrom
murchandamus:2022-09-ancestor-aware-funding
Sep 14, 2023
Merged

Bump unconfirmed ancestor transactions to target feerate#26152
achow101 merged 8 commits intobitcoin:masterfrom
murchandamus:2022-09-ancestor-aware-funding

Conversation

@murchandamus
Copy link
Member

@murchandamus murchandamus commented Sep 21, 2022

Includes some commits to address follow-ups from #27021: #27021 (comment)

Reduces the effective value of unconfirmed UTXOs by the fees necessary to bump their ancestor transactions to the same feerate.

While the individual UTXOs always account for their full ancestry before coin-selection, we can correct potential overestimates with a second pass where we establish the ancestry and bump fee for the whole input set collectively.

Fixes #9645
Fixes #9864
Fixes #15553

@murchandamus murchandamus force-pushed the 2022-09-ancestor-aware-funding branch from db2c0f7 to 54fd46b Compare September 21, 2022 21:16
@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 21, 2022

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

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK S3RK, brunoerg, ismaelsadeeq, t-bast, achow101
Concept ACK fanquake, glozow, jonatack, ishaanam, andrewtoth, stickies-v, LarryRuane, josibake

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #28391 (refactor: Simplify CTxMempool/BlockAssembler fields, remove some external mapTx access by TheCharlatan)
  • #28335 (RFC: Remove boost usage from kernel api / headers by TheCharlatan)
  • #27865 (wallet: Track no-longer-spendable TXOs separately by achow101)
  • #27601 (wallet: don't duplicate change output if already exist by furszy)
  • #27286 (wallet: Keep track of the wallet's own transaction outputs in memory by achow101)

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

@fanquake fanquake left a comment

Choose a reason for hiding this comment

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

Concept ACK

@murchandamus
Copy link
Member Author

Thanks @fanquake, I fixed the two issues.

I also added a test for a transaction using subtractfeefromamount

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.

HUGE Concept ACK obviously 🥳 🥳

This needs to obey -maxtxfee, so I'd suggest that coin selection keeps track of what ancestors the tx has and how much of the fees is ancestors vs this transaction. And we'd want a test where the target feerate is just below maxtxfee and there are low-feerate ancestors to bump, and so total fees paid / size of this tx is higher than maxtxfee, but actually you're just paying to bump.

Also, given that there is a (small) chance of overpayment, it would be good to check that -maxtxfee protects against something drastic. For example, a test where all the coins share 1 large parent? It will overestimate and -maxtxfee should make sure the tx isn't sent? edit: this is totally wrong

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

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

Concept ACK

Copy link
Contributor

@t-bast t-bast left a comment

Choose a reason for hiding this comment

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

Concept ACK, thanks a lot for working on this, it will be very helpful!
And this set of internal utility functions will very likely be useful for many things in the future.
I'll create a set of E2E tests in eclair to run against this branch when I have a bit more time, I'll let you know the results.

@glozow glozow added the Wallet label Sep 23, 2022
@t-bast
Copy link
Contributor

t-bast commented Sep 23, 2022

I ran a first set of tests from within eclair against a07ac02, and everything is looking good 👍

Copy link
Contributor

@ishaanam ishaanam left a comment

Choose a reason for hiding this comment

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

Concept ACK

@murchandamus murchandamus force-pushed the 2022-09-ancestor-aware-funding branch from a07ac02 to a720b50 Compare September 27, 2022 19:15
@murchandamus
Copy link
Member Author

murchandamus commented Sep 27, 2022

@jonatack, @t-bast: Thanks for the review and testing. I made an attempt of getting rid of the getters on MockMempoolEntry, but what I did interfered with the calls made on properties of actual mempool entries. Will have to shift my approach.

@murchandamus murchandamus force-pushed the 2022-09-ancestor-aware-funding branch from a720b50 to 337a24e Compare September 27, 2022 20:25
@murchandamus
Copy link
Member Author

murchandamus commented Sep 27, 2022

@glozow: Maybe for

This needs to obey -maxtxfee

Maybe we can add a maxtxfee check to the filter introduced in #25729 for max weight after input sets are produced for different subsets of the available coins. Perhaps a separate PR that builds both on this one here and #25729.

@jonatack, @t-bast:
Fixed whitespace issues, applied the propose change to a class for the struct MockMempoolEntry, amended comments in Chain interface. Thanks!

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.

This needs to obey -maxtxfee

Maybe we can add a maxtxfee check to the filter introduced in #25729 for max weight after input sets are produced for different subsets of the available coins. Perhaps a separate PR that builds both on this one here and #25729.

Not sure if this is scope creep, but seems like breaking maxtxfee would be a bug and should probably be done in the same PR? Why not build this on top of #25729? ignore

@murchandamus murchandamus force-pushed the 2022-09-ancestor-aware-funding branch from 970c848 to f9979ef Compare October 27, 2022 18:53
@murchandamus
Copy link
Member Author

  • Reordered members vs initialization
  • Removed special casing of UTXOs without relatives in CalculateBumpFee
  • Call CalculateBumpFee once for the whole UTXO pool instead of introducing chain-interface dependency on every UTXO

Todos:

  • Prevent exceeding maxtxfee
  • Add test for bumpfee RPC
  • Add secondary modus for CalculateBumpFee that treats the provided UTXOs as being spent together. This allows us to recalculate the bumpfee of all inputs together to resolve our overpayment caveat.

@murchandamus
Copy link
Member Author

@glozow: looking more into this, I realized that the maxtxfee refers to an absolute fee, not a feerate. maxtxfee is checked after a transaction is built, so I don't see how ancestor aware funding changes anything in regard to maxtxfee—we still check at the end whether the amount of fee is allowed, regardless how we calculated the fee. If you meant maxtxfeerate, that is used to check raw transactions on submission in sendrawtx, so it doesn't apply here either.

@glozow
Copy link
Member

glozow commented Nov 2, 2022

maxtxfee refers to an absolute fee, not a feerate. maxtxfee is checked after a transaction is built, so I don't see how ancestor aware funding changes anything in regard to maxtxfee

Ah for some reason I thought it was a feerate, apologies. Question: is it better to only enforce -maxtxfee on the fees paid for the tx itself and not on the fees used to bump its ancestors? Or would the user expect that it's applied to any tx, bumping or not?

@achow101
Copy link
Member

achow101 commented Nov 2, 2022

Question: is it better to only enforce -maxtxfee on the fees paid for the tx itself and not on the fees used to bump its ancestors? Or would the user expect that it's applied to any tx, bumping or not?

I think that -maxtxfee should be expected to behave the same regardless of bumping, it's a context-free check.

@murchandamus
Copy link
Member Author

murchandamus commented Aug 30, 2023

Rebased, and fixed comment to mollify tidy. (Ready for review.)

Copy link
Contributor

@t-bast t-bast left a comment

Choose a reason for hiding this comment

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

ACK 1b2fb54, I ran my e2e lightning tests on top of that branch and everything is looking good 👍

@ismaelsadeeq
Copy link
Member

re ACK 1b2fb54d5c18579e013b1dfd061c2b29d8cffdc2

Reviewed up to acb6aaeac49dd4543280653f19d2377ffb175c9e and functional test
As I am not really familiar with the coinselection part of the PR, I lightly review the commits.
I rebased latest master a4e0bcb on this PR, the tests failed and passed after making the branch.

@achow101
Copy link
Member

achow101 commented Sep 6, 2023

ACK 1b2fb54d5c18579e013b1dfd061c2b29d8cffdc2

Copy link
Contributor

@S3RK S3RK left a comment

Choose a reason for hiding this comment

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

Started re-review. Besides few nits, I have a doubt about waste calculation with bump fee and excess. Could you take a look, please?

Copy link
Member Author

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

Addressed @S3RK’s review

murchandamus and others added 7 commits September 13, 2023 14:33
Follow-up from bitcoin#27021: In the prior commit, the vector started counting
at 0, but the transaction names started with 1. This commit matches the
names to the transactions’ vector indices for better readability.

Co-authored-by: theStack <[email protected]>
Follow-up from bitcoin#27021.
Also included is an ASCII art visualization of the test’s transaction
topology by theStack.

Co-authored-by: theStack <[email protected]>
Follow-up from bitcoin#27021: accessing of fields in MiniMinerMempoolEntry was
done inconsistently. Even though we had a getter, we would directly
write to the fields when we needed to update them.
This commits sets the fields to private and introduces a method for
updating the ancestor information in transactions using the same method
name as used for Mempool Entries.
GetSelectionWaste will need to access more context within a selection
result, and so should be a private member function rather than a static
function. It's only use outside of SelectionResult was for tests which
have now been updated to just make a SelectionResult.

Co-authored-by: Murch <[email protected]>
When a transaction uses an unconfirmed input, preceding this commit it
would not consider the feerate of the parent transaction. Given a parent
transaction with a lower ancestor feerate, this resulted in the new
transaction's ancestor feerate undershooting the target feerate.

This commit changes how we calculate the effective value of unconfirmed UTXOs.
The effective value of unconfirmed UTXOs is decreased by the fee
necessary to bump its ancestry to the target feerate. This also impacts
the calculation of the waste metric: since the estimate for the current
fee is increased by the bump fees, unconfirmed UTXOs current fees appear less
favorable compared to their unchanged long term fees.

This has one caveat: if multiple UTXOs have overlapping ancestries, each
of their individual estimates will account for bumping all ancestors.
Copy link
Member Author

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

I pulled the part of the waste test that dealt with bump fees without group discount into the earlier commit and fixed an issue in the waste calculation in that commit. The final code is unchanged.

@murchandamus
Copy link
Member Author

I had forgotten to update the AttemptSelection call in src/bench/coin_selection.cpp to the new function header that takes the chain instead of the wallet.

I should have now addressed all feedback from @brunoerg and @S3RK, and be ready for review again.

At the end of coin selection reduce the fees by the difference between
the individual bump fee estimates and the collective bump fee estimate.
@murchandamus
Copy link
Member Author

@S3RK noticed that SelectionResult::GetBumpFeeDiscount() was now obsolete and no longer used. (AFAIR, this would have been a bi-product of moving GetSelectionWaste into SelectionResult.)

I removed the obsolete method.

@S3RK
Copy link
Contributor

S3RK commented Sep 13, 2023

ACK f18f9ef

Great work! This PR not only makes our wallet work properly with unconfirmed inputs, but it also improved the factoring of the code. Happy to see waste calculations as a member function of SelectionResult

@murchandamus
Copy link
Member Author

murchandamus commented Sep 13, 2023

@t-bast, @ismaelsadeeq, @achow101: Changes since 1b2fb54d5c18579e013b1dfd061c2b29d8cffdc2

  • Pass chain interface to AttemptSelection(…) instead of whole wallet
  • Remove obsolete method SelectionResult::GetBumpFeeDiscount()
  • Add waste calculation test for changeless transactions with bump fees
  • Fix typo

Copy link
Contributor

@brunoerg brunoerg left a comment

Choose a reason for hiding this comment

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

crACK f18f9ef

code lgtm, nice improvement!

@ismaelsadeeq
Copy link
Member

ACK f18f9ef

Copy link
Contributor

@t-bast t-bast left a comment

Choose a reason for hiding this comment

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

ACK f18f9ef, I reviewed the latest changes and run e2e tests against eclair, everything looks good 👍

@achow101
Copy link
Member

ACK f18f9ef

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet