Apply the safe minimum fee floor to all wallet transactions - #4179
Apply the safe minimum fee floor to all wallet transactions#4179mswilkison wants to merge 2 commits into
Conversation
|
Warning Review limit reached
Next review available in: 8 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (10)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
af7c525 to
9785c88
Compare
Fixes part **A** of #4171: a deposit sweep could be broadcast at the ~1 sat/vByte relay floor (a low-but-valid oracle estimate in an uncongested mempool), and since sweeps are not RBF-enabled it could get stuck and jam the wallet. Observed live on mainnet. ## Change `estimateDepositsSweepFee`: - **Errors** (instead of silently lowering the fee) if the raw estimate exceeds the Bridge maximum (uneconomical), or if the minimum safe fee (`minSweepTxSatPerVByteFee`, 5 sat/vByte) exceeds the maximum — so a sweep is never broadcast below the intended floor. - Otherwise applies `max(floor, ceil(rate × 1.25))`: a 25% buffer over the oracle estimate to keep a margin during the estimate-to-broadcast delay and stay adaptive under congestion (per the #4171 reference design), floored at 5 sat/vByte, bounded above by the Bridge maximum. The floor constant documents that it (and the buffer) is a stopgap for the current non-RBF path and should be revisited when RBF lands; the P2SH-vsize interaction is noted at the floor site. ## Tests Unit test asserts a low estimate is floored to 5, an estimate above the floor is buffered by 25%, and a Bridge maximum below the floor returns an error (message-pinned to the floor branch). The deposit-sweep scenario testdata is updated for the buffered fee. `go test ./pkg/tbtcpg/...` passes. ## Follow-ups - **#4179** — applies the same floor to redemptions, moving funds, and moved funds sweeps via a shared helper (stacked on this PR). - **#4180** — follower-side soft check that a leader's proposed sweep fee is not below the floor (log-only; full enforcement belongs on-chain in `WalletProposalValidator`). Stacked on #4179. - **Part B of #4171 (RBF + fee-bumping)** — the durable recovery fix; a stuck sweep should be replaceable rather than jamming the wallet. Larger change, targeted at FROST/ROAST. The static floor + buffer here is a stopgap and should be revisited when RBF lands. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved deposit sweep fee estimation to avoid underpriced, non-RBF-able sweeps stalling in the mempool. - Introduced a minimum safe fee-rate floor and updated failure behavior when safe fees can’t fit within the Bridge maximum. - Added a 25% buffered fee-rate (rounded up), enforced minimum/maximum caps, and updated informational sat/vByte reporting. - Enhanced proposal-time warning logs when minimum-safe-fee behavior prevents fee selection. - **Tests** - Added coverage for minimum-floor, buffer, and maximum-cap fee behaviors, including rounding and error cases. - Updated the expected sweep fee in the proposal scenario test data. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Extract the 25% buffer + minimum floor + Bridge-max bound into a shared applyWalletTxFeeFloor helper and a shared minWalletTxSatPerVByteFee const, then apply it to redemptions, moving funds, and moved funds sweeps in addition to deposit sweeps. These are all non-RBF wallet transactions that jam the wallet if they get stuck at the relay floor, so the same protection applies (per lrsaturnino review on threshold-network#4172). EstimateRedemptionFee now takes the redemption tx max total fee so the floor can be bounded by it; the caller fetches it from GetRedemptionParameters. deposit sweep fee estimation is refactored onto the shared helper with no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The redemption fee estimator bounds the floored/buffered fee by the total cap (txMaxTotalFee) only. The prior comment claimed this made the floor unable to produce a fee the Bridge would reject, which is inaccurate: the per-request TxMaxFee (snapshotted per request) is a separate cap enforced only by on-chain validation, and the floor can raise a request's fee share above it while the total stays within bounds. Correct the ProposeRedemption and EstimateRedemptionFee comments, document that applyWalletTxFeeFloor bounds only the total fee (and its caller precondition), and note why the final clamp is floor-safe. Comments only; no behavior change.
e55ec08 to
4be8129
Compare
|
Closing in favor of #4192, which carries this work forward rebased cleanly onto current
#4192 is on a |
Follows up on #4172 (lrsaturnino review): the fee floor there covers deposit sweeps only.
EstimateRedemptionFee,EstimateMovingFundsFee, andEstimateMovedFundsSweepFeestill returned the raw oracle fee, so a redemption, moving-funds, or moved-funds-sweep transaction could be broadcast at the ~1 sat/vByte relay floor and jam the wallet the same way a sweep can.Change
applyWalletTxFeeFloorhelper and a sharedminWalletTxSatPerVByteFeeconstant (pkg/tbtcpg/fee.go).EstimateRedemptionFeenow takes the redemption tx max total fee so the floor can be bounded by it; the caller fetches it fromGetRedemptionParameters.Note on redemption scope
Redemption fee estimation previously deferred the fee cap entirely to on-chain validation. To apply a client-side floor safely, it now also bounds the fee by the max total fee (clamp, not reject) so the floor cannot produce a fee the Bridge would reject, and errors if the raw estimate already exceeds the cap (consistent with the other transaction types) rather than broadcasting an underpriced transaction. The per-request max fee is still validated on-chain.
Tests
TestApplyWalletTxFeeFloorcovers buffer / floor / cap-clamp / floor-over-cap error / invalid-vsize.go test ./pkg/tbtcpg/...passes;go build ./...andgo vetclean.Follow-ups still open from the #4172 review