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

lightningnetwork / lnd / 15736109134

18 Jun 2025 02:46PM UTC coverage: 58.197% (-10.1%) from 68.248%
15736109134

Pull #9752

github

web-flow
Merge d2634a68c into 31c74f20f
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

6 of 13 new or added lines in 2 files covered. (46.15%)

28331 existing lines in 455 files now uncovered.

97860 of 168153 relevant lines covered (58.2%)

1.81 hits per line

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

45.28
/watchtower/wtserver/create_session.go
1
package wtserver
2

3
import (
4
        "github.com/btcsuite/btcd/txscript"
5
        "github.com/lightningnetwork/lnd/watchtower/blob"
6
        "github.com/lightningnetwork/lnd/watchtower/wtdb"
7
        "github.com/lightningnetwork/lnd/watchtower/wtpolicy"
8
        "github.com/lightningnetwork/lnd/watchtower/wtwire"
9
)
10

11
// handleCreateSession processes a CreateSession message from the peer, and returns
12
// a CreateSessionReply in response. This method will only succeed if no existing
13
// session info is known about the session id. If an existing session is found,
14
// the reward address is returned in case the client lost our reply.
15
func (s *Server) handleCreateSession(peer Peer, id *wtdb.SessionID,
16
        req *wtwire.CreateSession) error {
3✔
17

3✔
18
        // TODO(conner): validate accept against policy
3✔
19

3✔
20
        // Query the db for session info belonging to the client's session id.
3✔
21
        existingInfo, err := s.cfg.DB.GetSessionInfo(id)
3✔
22
        switch {
3✔
23

24
        // We already have a session, though it is currently unused. We'll allow
25
        // the client to recommit the session if it wanted to change the policy.
UNCOV
26
        case err == nil && existingInfo.LastApplied == 0:
×
27

28
        // We already have a session corresponding to this session id, return an
29
        // error signaling that it already exists in our database. We return the
30
        // reward address to the client in case they were not able to process
31
        // our reply earlier.
UNCOV
32
        case err == nil && existingInfo.LastApplied > 0:
×
UNCOV
33
                log.Debugf("Already have session for %s", id)
×
UNCOV
34
                return s.replyCreateSession(
×
UNCOV
35
                        peer, id, wtwire.CreateSessionCodeAlreadyExists,
×
UNCOV
36
                        existingInfo.LastApplied, existingInfo.RewardAddress,
×
UNCOV
37
                )
×
38

39
        // Some other database error occurred, return a temporary failure.
40
        case err != wtdb.ErrSessionNotFound:
×
41
                log.Errorf("unable to load session info for %s", id)
×
42
                return s.replyCreateSession(
×
43
                        peer, id, wtwire.CodeTemporaryFailure, 0, nil,
×
44
                )
×
45
        }
46

47
        // Ensure that the requested blob type is supported by our tower.
48
        if !blob.IsSupportedType(req.BlobType) {
3✔
UNCOV
49
                log.Debugf("Rejecting CreateSession from %s, unsupported blob "+
×
UNCOV
50
                        "type %s", id, req.BlobType)
×
UNCOV
51
                return s.replyCreateSession(
×
UNCOV
52
                        peer, id, wtwire.CreateSessionCodeRejectBlobType, 0,
×
UNCOV
53
                        nil,
×
UNCOV
54
                )
×
UNCOV
55
        }
×
56

57
        // If the request asks for a reward session and the tower has them
58
        // disabled, we will reject the request.
59
        if s.cfg.DisableReward && req.BlobType.Has(blob.FlagReward) {
3✔
60
                log.Debugf("Rejecting CreateSession from %s, reward "+
×
61
                        "sessions disabled", id)
×
62
                return s.replyCreateSession(
×
63
                        peer, id, wtwire.CreateSessionCodeRejectBlobType, 0,
×
64
                        nil,
×
65
                )
×
66
        }
×
67

68
        // Now that we've established that this session does not exist in the
69
        // database, retrieve the sweep address that will be given to the
70
        // client. This address is to be included by the client when signing
71
        // sweep transactions destined for this tower, if its negotiated output
72
        // is not dust.
73
        var rewardScript []byte
3✔
74
        if req.BlobType.Has(blob.FlagReward) {
3✔
UNCOV
75
                rewardAddress, err := s.cfg.NewAddress()
×
UNCOV
76
                if err != nil {
×
77
                        log.Errorf("Unable to generate reward addr for %s: %v",
×
78
                                id, err)
×
79
                        return s.replyCreateSession(
×
80
                                peer, id, wtwire.CodeTemporaryFailure, 0, nil,
×
81
                        )
×
82
                }
×
83

84
                // Construct the pkscript the client should pay to when signing
85
                // justice transactions for this session.
UNCOV
86
                rewardScript, err = txscript.PayToAddrScript(rewardAddress)
×
UNCOV
87
                if err != nil {
×
88
                        log.Errorf("Unable to generate reward script for "+
×
89
                                "%s: %v", id, err)
×
90
                        return s.replyCreateSession(
×
91
                                peer, id, wtwire.CodeTemporaryFailure, 0, nil,
×
92
                        )
×
93
                }
×
94
        }
95

96
        // TODO(conner): create invoice for upfront payment
97

98
        // Assemble the session info using the agreed upon parameters, reward
99
        // address, and session id.
100
        info := wtdb.SessionInfo{
3✔
101
                ID: *id,
3✔
102
                Policy: wtpolicy.Policy{
3✔
103
                        TxPolicy: wtpolicy.TxPolicy{
3✔
104
                                BlobType:     req.BlobType,
3✔
105
                                RewardBase:   req.RewardBase,
3✔
106
                                RewardRate:   req.RewardRate,
3✔
107
                                SweepFeeRate: req.SweepFeeRate,
3✔
108
                        },
3✔
109
                        MaxUpdates: req.MaxUpdates,
3✔
110
                },
3✔
111
                RewardAddress: rewardScript,
3✔
112
        }
3✔
113

3✔
114
        // Insert the session info into the watchtower's database. If
3✔
115
        // successful, the session will now be ready for use.
3✔
116
        err = s.cfg.DB.InsertSessionInfo(&info)
3✔
117
        if err != nil {
3✔
118
                log.Errorf("Unable to create session for %s: %v", id, err)
×
119
                return s.replyCreateSession(
×
120
                        peer, id, wtwire.CodeTemporaryFailure, 0, nil,
×
121
                )
×
122
        }
×
123

124
        log.Infof("Accepted session for %s", id)
3✔
125

3✔
126
        return s.replyCreateSession(
3✔
127
                peer, id, wtwire.CodeOK, 0, rewardScript,
3✔
128
        )
3✔
129
}
130

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

3✔
138
        if s.cfg.NoAckCreateSession {
3✔
UNCOV
139
                return &connFailure{
×
UNCOV
140
                        ID:   *id,
×
UNCOV
141
                        Code: code,
×
UNCOV
142
                }
×
UNCOV
143
        }
×
144

145
        msg := &wtwire.CreateSessionReply{
3✔
146
                Code:        code,
3✔
147
                LastApplied: lastApplied,
3✔
148
                Data:        data,
3✔
149
        }
3✔
150

3✔
151
        err := s.sendMessage(peer, msg)
3✔
152
        if err != nil {
3✔
UNCOV
153
                log.Errorf("unable to send CreateSessionReply to %s", id)
×
UNCOV
154
        }
×
155

156
        // Return the write error if the request succeeded.
157
        if code == wtwire.CodeOK {
6✔
158
                return err
3✔
159
        }
3✔
160

161
        // Otherwise the request failed, return a connection failure to
162
        // disconnect the client.
UNCOV
163
        return &connFailure{
×
UNCOV
164
                ID:   *id,
×
UNCOV
165
                Code: code,
×
UNCOV
166
        }
×
167
}
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