• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13558005087

27 Feb 2025 03:04AM UTC coverage: 58.834% (-0.001%) from 58.835%
13558005087

Pull #8453

github

Roasbeef
lnwallet/chancloser: increase test coverage of state machine
Pull Request #8453: [4/4] - multi: integrate new rbf coop close FSM into the existing peer flow

1079 of 1370 new or added lines in 23 files covered. (78.76%)

578 existing lines in 40 files now uncovered.

137063 of 232965 relevant lines covered (58.83%)

19205.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.49
/peer/chan_observer.go
1
package peer
2

3
import (
4
        "github.com/btcsuite/btcd/wire"
5
        "github.com/lightningnetwork/lnd/channeldb"
6
        "github.com/lightningnetwork/lnd/fn/v2"
7
        "github.com/lightningnetwork/lnd/htlcswitch"
8
        "github.com/lightningnetwork/lnd/lntypes"
9
        "github.com/lightningnetwork/lnd/lnwallet/chancloser"
10
)
11

12
// channelView is a view into the current active/global channel state machine
13
// for a given link.
14
type channelView interface {
15
        // OweCommitment returns a boolean value reflecting whether we need to
16
        // send out a commitment signature because there are outstanding local
17
        // updates and/or updates in the local commit tx that aren't reflected
18
        // in the remote commit tx yet.
19
        OweCommitment() bool
20

21
        // IsChannelClean returns true if neither side has pending commitments,
22
        // neither side has HTLC's, and all updates are locked in irrevocably.
23
        IsChannelClean() bool
24

25
        // MarkCoopBroadcasted persistently marks that the channel close
26
        // transaction has been broadcast.
27
        MarkCoopBroadcasted(*wire.MsgTx, lntypes.ChannelParty) error
28

29
        // StateSnapshot returns a snapshot of the current fully committed
30
        // state within the channel.
31
        StateSnapshot() *channeldb.ChannelSnapshot
32

33
        // MarkShutdownSent persists the given ShutdownInfo. The existence of
34
        // the ShutdownInfo represents the fact that the Shutdown message has
35
        // been sent by us and so should be re-sent on re-establish.
36
        MarkShutdownSent(info *channeldb.ShutdownInfo) error
37
}
38

39
// linkController is capable of controlling the flow out incoming/outgoing
40
// HTLCs to/from the link.
41
type linkController interface {
42
        // DisableAdds sets the ChannelUpdateHandler state to allow/reject
43
        // UpdateAddHtlc's in the specified direction. It returns true if the
44
        // state was changed and false if the desired state was already set
45
        // before the method was called.
46
        DisableAdds(outgoing bool) bool
47

48
        // IsFlushing returns true when UpdateAddHtlc's are disabled in the
49
        // direction of the argument.
50
        IsFlushing(direction bool) bool
51
}
52

53
// linkNetworkController is an interface that represents an object capable of
54
// managing interactions with the active channel links from the PoV of the
55
// gossip network.
56
//
57
//nolint:iface
58
type linkNetworkController interface {
59
        // RequestDisable disables a channel by its channel point.
60
        RequestDisable(wire.OutPoint, bool) error
61
}
62

63
// chanObserver implements the chancloser.ChanObserver interface for the
64
// existing LightningChannel struct/instance.
65
type chanObserver struct {
66
        chanView    channelView
67
        link        linkController
68
        linkNetwork linkNetworkController
69
}
70

71
// newChanObserver creates a new instance of a chanObserver from an active
72
// channelView.
73
func newChanObserver(chanView channelView,
74
        link linkController, linkNetwork linkNetworkController) *chanObserver {
1✔
75

1✔
76
        return &chanObserver{
1✔
77
                chanView:    chanView,
1✔
78
                link:        link,
1✔
79
                linkNetwork: linkNetwork,
1✔
80
        }
1✔
81
}
1✔
82

83
// NoDanglingUpdates returns true if there are no dangling updates in the
84
// channel. In other words, there are no active update messages that haven't
85
// already been covered by a commit sig.
86
func (l *chanObserver) NoDanglingUpdates() bool {
1✔
87
        return !l.chanView.OweCommitment()
1✔
88
}
1✔
89

90
// DisableIncomingAdds instructs the channel link to disable process new
91
// incoming add messages.
92
func (l *chanObserver) DisableIncomingAdds() error {
1✔
93
        // If there's no link, then we don't need to disable any adds.
1✔
94
        if l.link == nil {
2✔
95
                return nil
1✔
96
        }
1✔
97

98
        _ = l.link.DisableAdds(htlcswitch.Incoming)
1✔
99

1✔
100
        return nil
1✔
101
}
102

103
// DisableOutgoingAdds instructs the channel link to disable process new
104
// outgoing add messages.
105
func (l *chanObserver) DisableOutgoingAdds() error {
1✔
106
        // If there's no link, then we don't need to disable any adds.
1✔
107
        if l.link == nil {
1✔
NEW
108
                return nil
×
NEW
109
        }
×
110

111
        _ = l.link.DisableAdds(htlcswitch.Outgoing)
1✔
112

1✔
113
        return nil
1✔
114
}
115

116
// MarkCoopBroadcasted persistently marks that the channel close transaction
117
// has been broadcast.
118
func (l *chanObserver) MarkCoopBroadcasted(tx *wire.MsgTx, local bool) error {
1✔
119
        return l.chanView.MarkCoopBroadcasted(tx, lntypes.Local)
1✔
120
}
1✔
121

122
// MarkShutdownSent persists the given ShutdownInfo. The existence of the
123
// ShutdownInfo represents the fact that the Shutdown message has been sent by
124
// us and so should be re-sent on re-establish.
125
func (l *chanObserver) MarkShutdownSent(deliveryAddr []byte,
126
        isInitiator bool) error {
1✔
127

1✔
128
        shutdownInfo := channeldb.NewShutdownInfo(deliveryAddr, isInitiator)
1✔
129
        return l.chanView.MarkShutdownSent(shutdownInfo)
1✔
130
}
1✔
131

132
// FinalBalances is the balances of the channel once it has been flushed. If
133
// Some, then this indicates that the channel is now in a state where it's
134
// always flushed, so we can accelerate the state transitions.
135
func (l *chanObserver) FinalBalances() fn.Option[chancloser.ShutdownBalances] {
1✔
136
        chanClean := l.chanView.IsChannelClean()
1✔
137

1✔
138
        switch {
1✔
139
        // If we have a link, then the balances are final if both the incoming
140
        // and outgoing adds are disabled _and_ the channel is clean.
141
        case l.link != nil && l.link.IsFlushing(htlcswitch.Incoming) &&
142
                l.link.IsFlushing(htlcswitch.Outgoing) && chanClean:
1✔
143

1✔
144
                fallthrough
1✔
145

146
        // If we don't have a link, then this is a restart case, so the
147
        // balances are final.
148
        case l.link == nil:
1✔
149
                snapshot := l.chanView.StateSnapshot()
1✔
150

1✔
151
                return fn.Some[chancloser.ShutdownBalances](
1✔
152
                        chancloser.ShutdownBalances{
1✔
153
                                LocalBalance:  snapshot.LocalBalance,
1✔
154
                                RemoteBalance: snapshot.RemoteBalance,
1✔
155
                        },
1✔
156
                )
1✔
157

158
        // Otherwise, the link is still active and not flushed, so the balances
159
        // aren't yet final.
160
        default:
1✔
161
                return fn.None[chancloser.ShutdownBalances]()
1✔
162
        }
163
}
164

165
// DisableChannel disables the target channel.
166
func (l *chanObserver) DisableChannel() error {
1✔
167
        op := l.chanView.StateSnapshot().ChannelPoint
1✔
168
        return l.linkNetwork.RequestDisable(op, false)
1✔
169
}
1✔
170

171
// A compile-time assertion to ensure that chanObserver meets the
172
// chancloser.ChanStateObserver interface.
173
var _ chancloser.ChanStateObserver = (*chanObserver)(nil)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc