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

lightningnetwork / lnd / 14358372723

09 Apr 2025 01:26PM UTC coverage: 56.696% (-12.3%) from 69.037%
14358372723

Pull #9696

github

web-flow
Merge e2837e400 into 867d27d68
Pull Request #9696: Add `development_guidelines.md` for both human and machine

107055 of 188823 relevant lines covered (56.7%)

22721.56 hits per line

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

0.0
/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
type linkNetworkController interface {
57
        // RequestDisable disables a channel by its channel point.
58
        RequestDisable(wire.OutPoint, bool) error
59
}
60

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

69
// newChanObserver creates a new instance of a chanObserver from an active
70
// channelView.
71
func newChanObserver(chanView channelView,
72
        link linkController, linkNetwork linkNetworkController) *chanObserver {
×
73

×
74
        return &chanObserver{
×
75
                chanView:    chanView,
×
76
                link:        link,
×
77
                linkNetwork: linkNetwork,
×
78
        }
×
79
}
×
80

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

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

96
        disabled := l.link.DisableAdds(htlcswitch.Incoming)
×
97
        if disabled {
×
98
                chanPoint := l.chanView.StateSnapshot().ChannelPoint
×
99
                peerLog.Debugf("ChannelPoint(%v): link already disabled",
×
100
                        chanPoint)
×
101
        }
×
102

103
        return nil
×
104
}
105

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

114
        _ = l.link.DisableAdds(htlcswitch.Outgoing)
×
115

×
116
        return nil
×
117
}
118

119
// MarkCoopBroadcasted persistently marks that the channel close transaction
120
// has been broadcast.
121
func (l *chanObserver) MarkCoopBroadcasted(tx *wire.MsgTx, local bool) error {
×
122
        return l.chanView.MarkCoopBroadcasted(tx, lntypes.Local)
×
123
}
×
124

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

×
131
        shutdownInfo := channeldb.NewShutdownInfo(deliveryAddr, isInitiator)
×
132
        return l.chanView.MarkShutdownSent(shutdownInfo)
×
133
}
×
134

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

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

×
147
                fallthrough
×
148

149
        // If we don't have a link, then this is a restart case, so the
150
        // balances are final.
151
        case l.link == nil:
×
152
                snapshot := l.chanView.StateSnapshot()
×
153

×
154
                return fn.Some(chancloser.ShutdownBalances{
×
155
                        LocalBalance:  snapshot.LocalBalance,
×
156
                        RemoteBalance: snapshot.RemoteBalance,
×
157
                })
×
158

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

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

172
// A compile-time assertion to ensure that chanObserver meets the
173
// chancloser.ChanStateObserver interface.
174
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