chancloser: remove dead ChannelFlushed.FreshFlush field
What changed, and why it matters
This commit removes an unused data field called FreshFlush from the cooperative channel-closing logic. The field was always set to true and never actually checked by any code, so deleting it is a cleanup change with no security effect.
No security action needed; this is a routine refactoring/cleanup commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch deletes the FreshFlush bool field from the ChannelFlushed event struct in lnwallet/chancloser/rbf_coop_states.go, removes the unconditional FreshFlush: true assignment in peer/brontide.go, and simplifies the related tests in rbf_coop_test.go by collapsing loops that previously iterated over {true, false}. No transition handler reads this field, so the change is purely dead-code removal.
Changed components
lnwallet/chancloser/rbf_coop_states.golnwallet/chancloser/rbf_coop_test.gopeer/brontide.goInspect captured patch +54 / −69
diff --git a/lnwallet/chancloser/rbf_coop_states.go b/lnwallet/chancloser/rbf_coop_states.go
index e359e53..554dca0 100644
--- a/lnwallet/chancloser/rbf_coop_states.go
+++ b/lnwallet/chancloser/rbf_coop_states.go
@@ -175,10 +175,6 @@ var unknownBalance = ShutdownBalances{}
// - fromState: ChannelFlushing
// - toState: ClosingNegotiation
type ChannelFlushed struct {
- // FreshFlush indicates if this is the first time the channel has been
- // flushed, or if this is a flush as part of an RBF iteration.
- FreshFlush bool
-
// ShutdownBalances is the balances of the channel once it has been
// flushed. We tie this to the ChannelFlushed state as this may not be
// the same as the starting value.
diff --git a/lnwallet/chancloser/rbf_coop_test.go b/lnwallet/chancloser/rbf_coop_test.go
index 05d44f7..0c4b937 100644
--- a/lnwallet/chancloser/rbf_coop_test.go
+++ b/lnwallet/chancloser/rbf_coop_test.go
@@ -1780,84 +1780,74 @@ func TestRbfChannelFlushingTransitions(t *testing.T) {
},
}
- // If send in the channel flushed event, but the local party can't pay
- // for fees, then we should just head to the negotiation state.
- for _, isFreshFlush := range []bool{true, false} {
+ // When the channel is flushed but the local party cannot cover
+ // the closing fee, we should transition directly to
+ // ClosingNegotiation without any further intermediate state
+ // transitions.
+ t.Run("local_cannot_pay_for_fee", func(t *testing.T) {
+ firstState := *startingState
chanFlushedEvent := *flushTemplate
- chanFlushedEvent.FreshFlush = isFreshFlush
- testName := fmt.Sprintf("local_cannot_pay_for_fee/"+
- "fresh_flush=%v", isFreshFlush)
+ closeHarness := newCloser(t, &harnessCfg{
+ initialState: fn.Some[ProtocolState](
+ &firstState,
+ ),
+ })
+ defer closeHarness.stopAndAssert()
- t.Run(testName, func(t *testing.T) {
- firstState := *startingState
+ // As part of the set up for this state, we'll have the
+ // final absolute fee required be greater than the
+ // balance of the local party.
+ closeHarness.expectFeeEstimate(absoluteFee, 1)
- closeHarness := newCloser(t, &harnessCfg{
- initialState: fn.Some[ProtocolState](
- &firstState,
- ),
- })
- defer closeHarness.stopAndAssert()
-
- // As part of the set up for this state, we'll have the
- // final absolute fee required be greater than the
- // balance of the local party.
- closeHarness.expectFeeEstimate(absoluteFee, 1)
-
- // We'll now send in the event which should trigger
- // this code path.
- closeHarness.chanCloser.SendEvent(
- ctx, &chanFlushedEvent,
- )
+ // We'll now send in the event which should trigger
+ // this code path.
+ closeHarness.chanCloser.SendEvent(
+ ctx, &chanFlushedEvent,
+ )
- // With the event sent, we should now transition
- // straight to the ClosingNegotiation state, with no
- // further state transitions.
- closeHarness.assertStateTransitions(
- &ClosingNegotiation{},
- )
- })
- }
+ // With the event sent, we should now transition
+ // straight to the ClosingNegotiation state, with no
+ // further state transitions.
+ closeHarness.assertStateTransitions(
+ &ClosingNegotiation{},
+ )
+ })
- for _, isFreshFlush := range []bool{true, false} {
+ // When the local party can cover the closing fee,
+ // ChannelFlushed drives a normal half-signer iteration: we
+ // move to ClosingNegotiation and send a ClosingComplete
+ // message.
+ t.Run("local_can_pay_for_fee", func(t *testing.T) {
+ firstState := *startingState
flushEvent := *flushTemplate
- flushEvent.FreshFlush = isFreshFlush
- // We'll modify the starting balance to be 3x the required fee
- // to ensure that we can pay for the fee.
+ // We'll modify the starting balance to be 3x the required
+ // fee to ensure that we can pay for the fee.
flushEvent.ShutdownBalances.LocalBalance = lnwire.NewMSatFromSatoshis( //nolint:ll
absoluteFee * 3,
)
- testName := fmt.Sprintf("local_can_pay_for_fee/"+
- "fresh_flush=%v", isFreshFlush)
+ closeHarness := newCloser(t, &harnessCfg{
+ initialState: fn.Some[ProtocolState](
+ &firstState,
+ ),
+ })
+ defer closeHarness.stopAndAssert()
- // This scenario, we'll have the local party be able to pay for
- // the fees, which will trigger additional state transitions.
- t.Run(testName, func(t *testing.T) {
- firstState := *startingState
+ localBalance := flushEvent.ShutdownBalances.LocalBalance
+ balanceAfterClose := localBalance.ToSatoshis() - absoluteFee
- closeHarness := newCloser(t, &harnessCfg{
- initialState: fn.Some[ProtocolState](
- &firstState,
- ),
- })
- defer closeHarness.stopAndAssert()
-
- localBalance := flushEvent.ShutdownBalances.LocalBalance
- balanceAfterClose := localBalance.ToSatoshis() - absoluteFee //nolint:ll
-
- // From here, we expect the state transition to go
- // back to closing negotiated, for a ClosingComplete
- // message to be sent and then for us to terminate at
- // that state. This is 1/2 of the normal RBF signer
- // flow.
- closeHarness.expectHalfSignerIteration(
- &flushEvent, balanceAfterClose, absoluteFee,
- noDustExpect, false,
- )
- })
- }
+ // From here, we expect the state transition to go
+ // back to closing negotiated, for a ClosingComplete
+ // message to be sent and then for us to terminate at
+ // that state. This is 1/2 of the normal RBF signer
+ // flow.
+ closeHarness.expectHalfSignerIteration(
+ &flushEvent, balanceAfterClose, absoluteFee,
+ noDustExpect, false,
+ )
+ })
// This tests that if we receive an `OfferReceivedEvent` while in the
// flushing state, then we'll cache that, and once we receive
diff --git a/peer/brontide.go b/peer/brontide.go
index 5f6cbe5..2a06e6f 100644
--- a/peer/brontide.go
+++ b/peer/brontide.go
@@ -4131,7 +4131,6 @@ func (p *Brontide) chanFlushEventSentinel(chanCloser *chancloser.RbfChanCloser,
ctx := context.Background()
chanCloser.SendEvent(ctx, &chancloser.ChannelFlushed{
ShutdownBalances: chanBalances,
- FreshFlush: true,
})
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.