Skip to content

Integrate package context into fee and weight calculations; add absolute fee target#38

Draft
evanlinjin wants to merge 3 commits intobitcoindevkit:masterfrom
evanlinjin:feat/package-fee-and-weight
Draft

Integrate package context into fee and weight calculations; add absolute fee target#38
evanlinjin wants to merge 3 commits intobitcoindevkit:masterfrom
evanlinjin:feat/package-fee-and-weight

Conversation

@evanlinjin
Copy link
Member

@evanlinjin evanlinjin commented Feb 8, 2026

Package context for CPFP

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.

Absolute fee target

Adds a TargetFee::absolute field that acts as a minimum absolute fee floor, checked independently alongside the existing feerate and replacement constraints.

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.

Changes:

  • TargetFee::absolute: u64 — minimum absolute fee the transaction must pay
  • CoinSelector::absolute_excess() — how much the selection overshoots the absolute fee requirement
  • absolute_excess integrated into excess() via .min() so the most binding constraint wins
  • implied_fee() accounts for absolute via .max()
  • LowestFee::bound() handles the absolute constraint for correct branch-and-bound behavior

Note: 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.

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>
@evanlinjin evanlinjin force-pushed the feat/package-fee-and-weight branch from 6b6a402 to ee587da Compare February 8, 2026 09:45
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>
Copy link
Contributor

@aagbotemi aagbotemi left a comment

Choose a reason for hiding this comment

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

The approach of adding Package to CoinSelector is good one and works well for the UTXO selection for CPFP use case.

@evanlinjin
Copy link
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
@evanlinjin evanlinjin changed the title Integrate package context into fee and weight calculations Integrate package context into fee and weight calculations; add absolute fee target Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments