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

lightningnetwork / lnd / 13586005509

28 Feb 2025 10:14AM UTC coverage: 68.629% (+9.9%) from 58.77%
13586005509

Pull #9521

github

web-flow
Merge 37d3a70a5 into 8532955b3
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

129950 of 189351 relevant lines covered (68.63%)

23726.46 hits per line

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

90.53
/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 {
340✔
16

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

30
                        var ok bool
377✔
31
                        curUpdate, ok = nextMsg.(*wtwire.StateUpdate)
377✔
32
                        if !ok {
377✔
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)
714✔
40
                if err != nil {
937✔
41
                        return err
223✔
42
                }
223✔
43

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

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

383✔
54
                select {
383✔
55
                case <-s.quit:
×
56
                        return ErrServerExiting
×
57
                default:
383✔
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 {
714✔
69

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

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

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

708✔
90
                failCode = wtwire.CodeOK
708✔
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

97
        case err == wtdb.ErrSeqNumAlreadyApplied:
2✔
98
                failCode = wtwire.CodePermanentFailure
2✔
99

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

104
        case err == wtdb.ErrLastAppliedReversion:
1✔
105
                failCode = wtwire.StateUpdateCodeClientBehind
1✔
106

107
        case err == wtdb.ErrSessionConsumed:
1✔
108
                failCode = wtwire.StateUpdateCodeMaxUpdatesExceeded
1✔
109

110
        case err == wtdb.ErrUpdateOutOfOrder:
2✔
111
                failCode = wtwire.StateUpdateCodeSeqNumOutOfOrder
2✔
112

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

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

124
        return s.replyStateUpdate(
498✔
125
                peer, id, failCode, lastApplied,
498✔
126
        )
498✔
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 {
498✔
135

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

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

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

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