Add follower-side soft check for below-floor sweep fees#4194
Add follower-side soft check for below-floor sweep fees#4194piotr-roslaniec wants to merge 4 commits into
Conversation
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 #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 on-chain WalletProposalValidator bounds the sweep fee only from above, so a misbehaving or unpatched coordination leader can propose a sweep at the ~1 sat/vByte relay floor that patched followers would still sign - the same underpricing that jams the wallet (#4171). ValidateDepositSweepProposal now recomputes the safe minimum and warns if the proposed fee is below it. The check is intentionally log-only, not a rejection: rejecting a below-floor proposal during a mixed-version rollout would split signers and could stall signing. Hard enforcement belongs on-chain in the WalletProposalValidator or behind a coordinated all-nodes upgrade. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The follower-side soft check in pkg/tbtc hand-copies the safe minimum sweep-fee rate and worst-case deposit script size from pkg/tbtcpg, because pkg/tbtcpg imports pkg/tbtc and the canonical constants cannot be imported back without a dependency cycle. Only sync comments kept them aligned, so silent drift would make the check compute a wrong floor. Export the canonical constants (MinWalletTxSatPerVByteFee, DepositScriptByteSize) and add a guard test in an external tbtc_test package - which can import pkg/tbtcpg without a cycle - that fails if the canonical values drift from the pkg/tbtc mirrors.
Address review on the follower-side below-floor sweep-fee check: - Warn when SweepTxFee is nil instead of silently skipping the check; a missing fee gets its own distinct log line. - Compare the proposed fee with big.Int.Cmp instead of Int64(), which is undefined above MaxInt64. - Replace the literal-pinned drift guard with a direct comparison of the exported pkg/tbtc mirrors against the canonical pkg/tbtcpg constants, so drift is caught regardless of which side changes. The constants are exported for this cross-package comparison.
📝 WalkthroughWalkthroughChangesThe PR adds a shared 5 sat/vByte wallet fee floor with 25% buffering and maximum-fee handling. Deposit, moved-funds, moving-funds, and redemption estimators use it, while follower deposit validation logs below-floor proposals. Wallet fee-floor enforcement
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Proposal
participant FeeEstimator
participant applyWalletTxFeeFloor
participant BridgeParameters
Proposal->>FeeEstimator: request transaction fee estimate
FeeEstimator->>BridgeParameters: read maximum total fee
BridgeParameters-->>FeeEstimator: txMaxTotalFee
FeeEstimator->>applyWalletTxFeeFloor: estimated fee, vsize, and cap
applyWalletTxFeeFloor-->>FeeEstimator: buffered fee or error
FeeEstimator-->>Proposal: adjusted transaction fee
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
pkg/tbtcpg/redemptions.go (1)
516-521: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMissing test coverage for the new raw-estimate-exceeds-cap branch.
This newly-added check has no corresponding test case in
redemptions_test.go'sTestEstimateRedemptionFeetable, unlike the analogous branch already covered for deposit sweeps ("raw estimate above the cap returns an error"indeposit_sweep_fee_test.go) and moved funds/moving funds sweeps (ErrSweepTxFeeTooHigh/ErrFeeTooHightests).Suggested test case addition
"raw estimate above the cap returns an error": { estimateSatPerVByte: 30, txMaxTotalFee: uint64(10 * vsize), expectErrorContains: "estimated fee exceeds the maximum fee", },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/tbtcpg/redemptions.go` around lines 516 - 521, Add a table case named “raw estimate above the cap returns an error” to TestEstimateRedemptionFee, configuring estimateSatPerVByte and txMaxTotalFee so the raw totalFee exceeds the cap, and assert the error contains “estimated fee exceeds the maximum fee.”
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@pkg/tbtcpg/redemptions.go`:
- Around line 516-521: Add a table case named “raw estimate above the cap
returns an error” to TestEstimateRedemptionFee, configuring estimateSatPerVByte
and txMaxTotalFee so the raw totalFee exceeds the cap, and assert the error
contains “estimated fee exceeds the maximum fee.”
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 0fa2afe2-6a98-40a5-94a1-2784619bd8f4
📒 Files selected for processing (12)
pkg/tbtc/deposit_sweep.gopkg/tbtc/sweep_fee_sync_test.gopkg/tbtcpg/deposit_sweep.gopkg/tbtcpg/deposit_sweep_fee_test.gopkg/tbtcpg/fee.gopkg/tbtcpg/fee_test.gopkg/tbtcpg/moved_funds_sweep.gopkg/tbtcpg/moved_funds_sweep_test.gopkg/tbtcpg/moving_funds.gopkg/tbtcpg/moving_funds_test.gopkg/tbtcpg/redemptions.gopkg/tbtcpg/redemptions_test.go
Summary
Adds a follower-side soft (log-only) check that the leader's proposed deposit
sweep fee is not below the safe minimum. The on-chain
WalletProposalValidatoronly bounds the sweep fee from above, so a misbehaving or unpatched leader can
propose a fee at the ~1 sat/vByte relay floor that would otherwise be signed -
the same underpricing that jams the wallet (#4171).
Each node recomputes the safe minimum and logs a warning when the proposal is
below it.
The check is intentionally log-only, not a rejection: rejecting a
below-floor proposal would, during a mixed-version rollout, split signers
(patched nodes reject, unpatched nodes sign) and could stall signing. Hard
enforcement belongs on-chain in the
WalletProposalValidatoror behind acoordinated all-nodes upgrade.
Contents
This branch is rebased on current
mainand, in addition to the soft check,carries the safe-minimum sweep-fee floor applied to all wallet transactions
(the
feat/floor-all-wallet-tx-feeswork, also open as #4179 / #4192). Thefloor commit is bundled here so the branch builds and passes CI against
main;if the floor lands separately first, this branch should be rebased to drop it.
Review follow-ups addressed
Incorporates the multi-agent review of the soft check:
SweepTxFeeisnilinstead of silently skipping the check; amissing fee gets its own distinct log line.
big.Int.Cmpinstead ofInt64(), which isundefined above
MaxInt64.the (now exported)
pkg/tbtcmirrors against the canonicalpkg/tbtcpgconstants, so drift is caught regardless of which side changes. A
literal-based guard could be defeated by updating
tbtcpgand the literaltogether while forgetting the mirror; comparing the live values closes that
gap.
Supersedes
Replaces #4180, whose head lived on a fork branch that had drifted onto an old
mainand becomeCONFLICTING. This PR is the same work rebased clean ontocurrent
main.Summary by CodeRabbit