Integrate package context into fee and weight calculations; add absolute fee target#38
Closed
evanlinjin wants to merge 3 commits intobitcoindevkit:masterfrom
Closed
Integrate package context into fee and weight calculations; add absolute fee target#38evanlinjin wants to merge 3 commits intobitcoindevkit:masterfrom
evanlinjin wants to merge 3 commits intobitcoindevkit:masterfrom
Conversation
When a Package is set via with_package(), all fee and weight calculations now automatically include parent transaction context: - weight() returns child_weight + parent_weight - fee() returns child_fee + parent_fee - implied_feerate() returns package feerate New methods for when child-only values are needed: - weight_without_package() - fee_without_package() - package() accessor RBF calculations (replacement_excess) use child weight only since Bitcoin's RBF rule 4 applies to the replacing transaction, not the package. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6b6a402 to
ee587da
Compare
Tests cover: - weight() includes parent_weight when package is set - weight_without_package() returns child weight only - fee() includes parent_fee when package is set - fee_without_package() returns child fee only - implied_feerate() returns package feerate - package() accessor - with_package() auto-selects link indices - No package behaves normally (backwards compatible) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
aagbotemi
reviewed
Feb 16, 2026
Contributor
aagbotemi
left a comment
There was a problem hiding this comment.
The approach of adding Package to CoinSelector is good one and works well for the UTXO selection for CPFP use case.
Member
Author
|
I also want to add an absolute fee target. Payjoin (BIP 78): The payjoin proposal MUST NOT decrease the absolute fee of the original transaction. Some users may want to select their fee based on an absolute value (not sure why, but some wallets provide this feature). |
Add a `TargetFee::absolute` field that acts as a minimum absolute fee floor, checked independently alongside the existing feerate and replacement constraints. This supports use cases like Payjoin (BIP 78), where the receiver must not decrease the original transaction's absolute fee, and application-level policy minimums. Changes: - Add `absolute: u64` field to `TargetFee` - Add `CoinSelector::absolute_excess()` method - Integrate absolute excess into `CoinSelector::excess()` via `.min()` - Account for absolute fee in `CoinSelector::implied_fee()` - Handle absolute constraint in `LowestFee::bound()` for correct branch-and-bound behavior
8 tasks
aagbotemi
reviewed
Mar 24, 2026
| /// How much the current selection overshoots the value need to satisfy `target.fee.rate` and | ||
| /// `target.value` (while ignoring `target.min_fee`). | ||
| /// `target.value` (while ignoring `target.fee.absolute`). | ||
| pub fn rate_excess(&self, target: Target, drain: Drain) -> i64 { |
Contributor
There was a problem hiding this comment.
rate_excess includes parent_weight in the required fee via implied_fee_from_feerate() -> weight() but doesn't include parent_fee in the actual fee, so the excess is parent_fee sats too low.
This was referenced Mar 30, 2026
Member
Author
|
Closing in favor of #43. |
3 tasks
evanlinjin
added a commit
that referenced
this pull request
Apr 24, 2026
b8db9e9 feat: Add absolute fee target to TargetFee (志宇) Pull request description: ## Summary - Adds `TargetFee::absolute` field as a minimum absolute fee floor, checked independently alongside the existing feerate and replacement constraints - Adds `CoinSelector::absolute_excess()` method and integrates it into `excess()` via `.min()` so the most binding constraint wins - Handles the absolute constraint in `LowestFee::bound()` for correct branch-and-bound behavior **Use cases:** - **Payjoin (BIP 78):** The receiver must not decrease the original transaction's absolute fee when adding inputs - **Application-level policy minimums:** Supports `bdk_wallet`'s `TxBuilder::fee_absolute()` API where users set a fee floor regardless of feerate Extracted from #38 (package context changes excluded). ## Test plan - [x] `cargo test` — all existing tests pass - [x] `cargo test --no-default-features` — no_std builds pass - [x] `cargo clippy` — clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Top commit has no ACKs. Tree-SHA512: a2465c64a73a09b533f2f6d103137846684daad95e6019fbc34f663e4493fbb4ea2e4ad9cb764a4ec5febf041157c9a539e08b343fc5c291de58cb19f7bd6c1b
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Package context for CPFP
When a
Packageis set viawith_package(), all fee and weight calculations now automatically include parent transaction context:weight()returnschild_weight + parent_weightfee()returnschild_fee + parent_feeimplied_feerate()returns package feerateNew methods for when child-only values are needed:
weight_without_package()fee_without_package()package()accessorRBF calculations (
replacement_excess) use child weight only since Bitcoin's RBF rule 4 applies to the replacing transaction, not the package.Absolute fee target
Adds a
TargetFee::absolutefield that acts as a minimum absolute fee floor, checked independently alongside the existing feerate and replacement constraints.Use cases:
bdk_wallet'sTxBuilder::fee_absolute()API where users set a fee floor regardless of feerate.Changes:
TargetFee::absolute: u64— minimum absolute fee the transaction must payCoinSelector::absolute_excess()— how much the selection overshoots the absolute fee requirementabsolute_excessintegrated intoexcess()via.min()so the most binding constraint winsimplied_fee()accounts forabsolutevia.max()LowestFee::bound()handles the absolute constraint for correct branch-and-bound behaviorNote: absolute fee is complementary to package context, not a replacement. Package context changes how the feerate constraint itself scales with child weight (the parent's fee/weight are inside the feerate calculation). An absolute fee floor is an independent constraint for cases where a fixed sat minimum comes from an external source.