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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

66.32
/watchtower/wtserver/state_update.go
1
package wtserver
2

3
import (
4
        "fmt"
5

6
        "github.com/lightningnetwork/lnd/watchtower/wtdb"
7
        "github.com/lightningnetwork/lnd/watchtower/wtwire"
8
)
9

10
// handleStateUpdates processes a stream of StateUpdate requests from the
11
// client. The provided update should be the first such update read, subsequent
12
// updates will be consumed if the peer does not signal IsComplete on a
13
// particular update.
14
func (s *Server) handleStateUpdates(peer Peer, id *wtdb.SessionID,
15
        update *wtwire.StateUpdate) error {
3✔
16

3✔
17
        // Set the current update to the first update read off the wire.
3✔
18
        // Additional updates will be read if this value is set to nil after
3✔
19
        // processing the first.
3✔
20
        var curUpdate = update
3✔
21
        for {
6✔
22
                // If this is not the first update, read the next state update
3✔
23
                // from the peer.
3✔
24
                if curUpdate == nil {
6✔
25
                        nextMsg, err := s.readMessage(peer)
3✔
26
                        if err != nil {
3✔
UNCOV
27
                                return err
×
UNCOV
28
                        }
×
29

30
                        var ok bool
3✔
31
                        curUpdate, ok = nextMsg.(*wtwire.StateUpdate)
3✔
32
                        if !ok {
3✔
33
                                return fmt.Errorf("client sent %T after "+
×
34
                                        "StateUpdate", nextMsg)
×
35
                        }
×
36
                }
37

38
                // Try to accept the state update from the client.
39
                err := s.handleStateUpdate(peer, id, curUpdate)
3✔
40
                if err != nil {
3✔
UNCOV
41
                        return err
×
UNCOV
42
                }
×
43

44
                // If the client signals that this is last StateUpdate
45
                // message, we can disconnect the client.
46
                if curUpdate.IsComplete == 1 {
6✔
47
                        return nil
3✔
48
                }
3✔
49

50
                // Reset the current update to read subsequent updates in the
51
                // stream.
52
                curUpdate = nil
3✔
53

3✔
54
                select {
3✔
55
                case <-s.quit:
×
56
                        return ErrServerExiting
×
57
                default:
3✔
58
                }
59
        }
60
}
61

62
// handleStateUpdate processes a StateUpdate message request from a client. An
63
// attempt will be made to insert the update into the db, where it is validated
64
// against the client's session. The possible errors are then mapped back to
65
// StateUpdateCodes specified by the watchtower wire protocol, and sent back
66
// using a StateUpdateReply message.
67
func (s *Server) handleStateUpdate(peer Peer, id *wtdb.SessionID,
68
        update *wtwire.StateUpdate) error {
3✔
69

3✔
70
        var (
3✔
71
                lastApplied uint16
3✔
72
                failCode    wtwire.ErrorCode
3✔
73
                err         error
3✔
74
        )
3✔
75

3✔
76
        sessionUpdate := wtdb.SessionStateUpdate{
3✔
77
                ID:            *id,
3✔
78
                Hint:          update.Hint,
3✔
79
                SeqNum:        update.SeqNum,
3✔
80
                LastApplied:   update.LastApplied,
3✔
81
                EncryptedBlob: update.EncryptedBlob,
3✔
82
        }
3✔
83

3✔
84
        lastApplied, err = s.cfg.DB.InsertStateUpdate(&sessionUpdate)
3✔
85
        switch {
3✔
86
        case err == nil:
3✔
87
                log.Debugf("State update %d accepted for %s",
3✔
88
                        update.SeqNum, id)
3✔
89

3✔
90
                failCode = wtwire.CodeOK
3✔
91

92
        // Return a permanent failure if a client tries to send an update for
93
        // which we have no session.
94
        case err == wtdb.ErrSessionNotFound:
×
95
                failCode = wtwire.CodePermanentFailure
×
96

UNCOV
97
        case err == wtdb.ErrSeqNumAlreadyApplied:
×
UNCOV
98
                failCode = wtwire.CodePermanentFailure
×
99

100
                // TODO(conner): remove session state for protocol
101
                // violation. Could also double as clean up method for
102
                // session-related state.
103

UNCOV
104
        case err == wtdb.ErrLastAppliedReversion:
×
UNCOV
105
                failCode = wtwire.StateUpdateCodeClientBehind
×
106

UNCOV
107
        case err == wtdb.ErrSessionConsumed:
×
UNCOV
108
                failCode = wtwire.StateUpdateCodeMaxUpdatesExceeded
×
109

UNCOV
110
        case err == wtdb.ErrUpdateOutOfOrder:
×
UNCOV
111
                failCode = wtwire.StateUpdateCodeSeqNumOutOfOrder
×
112

113
        default:
×
114
                failCode = wtwire.CodeTemporaryFailure
×
115
        }
116

117
        if s.cfg.NoAckUpdates {
3✔
UNCOV
118
                return &connFailure{
×
UNCOV
119
                        ID:   *id,
×
UNCOV
120
                        Code: failCode,
×
UNCOV
121
                }
×
UNCOV
122
        }
×
123

124
        return s.replyStateUpdate(
3✔
125
                peer, id, failCode, lastApplied,
3✔
126
        )
3✔
127
}
128

129
// replyStateUpdate sends a response to a StateUpdate from a client. If the
130
// status code in the reply is OK, the error from the write will be bubbled up.
131
// Otherwise, this method returns a connection error to ensure we don't continue
132
// communication with the client.
133
func (s *Server) replyStateUpdate(peer Peer, id *wtdb.SessionID,
134
        code wtwire.StateUpdateCode, lastApplied uint16) error {
3✔
135

3✔
136
        msg := &wtwire.StateUpdateReply{
3✔
137
                Code:        code,
3✔
138
                LastApplied: lastApplied,
3✔
139
        }
3✔
140

3✔
141
        err := s.sendMessage(peer, msg)
3✔
142
        if err != nil {
3✔
UNCOV
143
                log.Errorf("unable to send StateUpdateReply to %s", id)
×
UNCOV
144
        }
×
145

146
        // Return the write error if the request succeeded.
147
        if code == wtwire.CodeOK {
6✔
148
                return err
3✔
149
        }
3✔
150

151
        // Otherwise the request failed, return a connection failure to
152
        // disconnect the client.
UNCOV
153
        return &connFailure{
×
UNCOV
154
                ID:   *id,
×
UNCOV
155
                Code: code,
×
UNCOV
156
        }
×
157
}
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