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

lightningnetwork / lnd / 13157733617

05 Feb 2025 12:49PM UTC coverage: 57.712% (-1.1%) from 58.82%
13157733617

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19472 existing lines in 252 files now uncovered.

103634 of 179570 relevant lines covered (57.71%)

24840.31 hits per line

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

66.67
/brontide/listener.go
1
package brontide
2

3
import (
4
        "errors"
5
        "fmt"
6
        "io"
7
        "net"
8
        "time"
9

10
        "github.com/lightningnetwork/lnd/keychain"
11
)
12

13
// defaultHandshakes is the maximum number of handshakes that can be done in
14
// parallel.
15
const defaultHandshakes = 1000
16

17
// Listener is an implementation of a net.Conn which executes an authenticated
18
// key exchange and message encryption protocol dubbed "Machine" after
19
// initial connection acceptance. See the Machine struct for additional
20
// details w.r.t the handshake and encryption scheme used within the
21
// connection.
22
type Listener struct {
23
        localStatic keychain.SingleKeyECDH
24

25
        tcp *net.TCPListener
26

27
        handshakeSema chan struct{}
28
        conns         chan maybeConn
29
        quit          chan struct{}
30
}
31

32
// A compile-time assertion to ensure that Conn meets the net.Listener interface.
33
var _ net.Listener = (*Listener)(nil)
34

35
// NewListener returns a new net.Listener which enforces the Brontide scheme
36
// during both initial connection establishment and data transfer.
37
func NewListener(localStatic keychain.SingleKeyECDH,
38
        listenAddr string) (*Listener, error) {
3✔
39

3✔
40
        addr, err := net.ResolveTCPAddr("tcp", listenAddr)
3✔
41
        if err != nil {
3✔
42
                return nil, err
×
43
        }
×
44

45
        l, err := net.ListenTCP("tcp", addr)
3✔
46
        if err != nil {
3✔
47
                return nil, err
×
48
        }
×
49

50
        brontideListener := &Listener{
3✔
51
                localStatic:   localStatic,
3✔
52
                tcp:           l,
3✔
53
                handshakeSema: make(chan struct{}, defaultHandshakes),
3✔
54
                conns:         make(chan maybeConn),
3✔
55
                quit:          make(chan struct{}),
3✔
56
        }
3✔
57

3✔
58
        for i := 0; i < defaultHandshakes; i++ {
3,003✔
59
                brontideListener.handshakeSema <- struct{}{}
3,000✔
60
        }
3,000✔
61

62
        go brontideListener.listen()
3✔
63

3✔
64
        return brontideListener, nil
3✔
65
}
66

67
// listen accepts connection from the underlying tcp conn, then performs
68
// the brontinde handshake procedure asynchronously. A maximum of
69
// defaultHandshakes will be active at any given time.
70
//
71
// NOTE: This method must be run as a goroutine.
72
func (l *Listener) listen() {
3✔
73
        for {
21✔
74
                select {
18✔
75
                case <-l.handshakeSema:
15✔
76
                case <-l.quit:
3✔
77
                        return
3✔
78
                }
79

80
                conn, err := l.tcp.Accept()
15✔
81
                if err != nil {
22✔
82
                        l.rejectConn(err)
7✔
83
                        l.handshakeSema <- struct{}{}
7✔
84
                        continue
7✔
85
                }
86

87
                go l.doHandshake(conn)
8✔
88
        }
89
}
90

91
// rejectedConnErr is a helper function that prepends the remote address of the
92
// failed connection attempt to the original error message.
93
func rejectedConnErr(err error, remoteAddr string) error {
5✔
94
        return fmt.Errorf("unable to accept connection from %v: %w", remoteAddr,
5✔
95
                err)
5✔
96
}
5✔
97

98
// doHandshake asynchronously performs the brontide handshake, so that it does
99
// not block the main accept loop. This prevents peers that delay writing to the
100
// connection from block other connection attempts.
101
func (l *Listener) doHandshake(conn net.Conn) {
8✔
102
        defer func() { l.handshakeSema <- struct{}{} }()
16✔
103

104
        select {
8✔
105
        case <-l.quit:
×
106
                return
×
107
        default:
8✔
108
        }
109

110
        remoteAddr := conn.RemoteAddr().String()
8✔
111

8✔
112
        brontideConn := &Conn{
8✔
113
                conn:  conn,
8✔
114
                noise: NewBrontideMachine(false, l.localStatic, nil),
8✔
115
        }
8✔
116

8✔
117
        // We'll ensure that we get ActOne from the remote peer in a timely
8✔
118
        // manner. If they don't respond within handshakeReadTimeout, then
8✔
119
        // we'll kill the connection.
8✔
120
        err := conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
8✔
121
        if err != nil {
8✔
122
                brontideConn.conn.Close()
×
123
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
124
                return
×
125
        }
×
126

127
        // Attempt to carry out the first act of the handshake protocol. If the
128
        // connecting node doesn't know our long-term static public key, then
129
        // this portion will fail with a non-nil error.
130
        var actOne [ActOneSize]byte
8✔
131
        if _, err := io.ReadFull(conn, actOne[:]); err != nil {
13✔
132
                brontideConn.conn.Close()
5✔
133
                l.rejectConn(rejectedConnErr(err, remoteAddr))
5✔
134
                return
5✔
135
        }
5✔
136
        if err := brontideConn.noise.RecvActOne(actOne); err != nil {
3✔
137
                brontideConn.conn.Close()
×
138
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
139
                return
×
140
        }
×
141

142
        // Next, progress the handshake processes by sending over our ephemeral
143
        // key for the session along with an authenticating tag.
144
        actTwo, err := brontideConn.noise.GenActTwo()
3✔
145
        if err != nil {
3✔
146
                brontideConn.conn.Close()
×
147
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
148
                return
×
149
        }
×
150
        if _, err := conn.Write(actTwo[:]); err != nil {
3✔
151
                brontideConn.conn.Close()
×
152
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
153
                return
×
154
        }
×
155

156
        select {
3✔
157
        case <-l.quit:
×
158
                return
×
159
        default:
3✔
160
        }
161

162
        // We'll ensure that we get ActTwo from the remote peer in a timely
163
        // manner. If they don't respond within handshakeReadTimeout, then
164
        // we'll kill the connection.
165
        err = conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
3✔
166
        if err != nil {
3✔
167
                brontideConn.conn.Close()
×
168
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
169
                return
×
170
        }
×
171

172
        // Finally, finish the handshake processes by reading and decrypting
173
        // the connection peer's static public key. If this succeeds then both
174
        // sides have mutually authenticated each other.
175
        var actThree [ActThreeSize]byte
3✔
176
        if _, err := io.ReadFull(conn, actThree[:]); err != nil {
3✔
177
                brontideConn.conn.Close()
×
178
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
179
                return
×
180
        }
×
181
        if err := brontideConn.noise.RecvActThree(actThree); err != nil {
3✔
182
                brontideConn.conn.Close()
×
183
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
184
                return
×
185
        }
×
186

187
        // We'll reset the deadline as it's no longer critical beyond the
188
        // initial handshake.
189
        err = conn.SetReadDeadline(time.Time{})
3✔
190
        if err != nil {
3✔
191
                brontideConn.conn.Close()
×
192
                l.rejectConn(rejectedConnErr(err, remoteAddr))
×
193
                return
×
194
        }
×
195

196
        l.acceptConn(brontideConn)
3✔
197
}
198

199
// maybeConn holds either a brontide connection or an error returned from the
200
// handshake.
201
type maybeConn struct {
202
        conn *Conn
203
        err  error
204
}
205

206
// acceptConn returns a connection that successfully performed a handshake.
207
func (l *Listener) acceptConn(conn *Conn) {
3✔
208
        select {
3✔
209
        case l.conns <- maybeConn{conn: conn}:
3✔
210
        case <-l.quit:
×
211
        }
212
}
213

214
// rejectConn returns any errors encountered during connection or handshake.
215
func (l *Listener) rejectConn(err error) {
12✔
216
        select {
12✔
217
        case l.conns <- maybeConn{err: err}:
×
218
        case <-l.quit:
12✔
219
        }
220
}
221

222
// Accept waits for and returns the next connection to the listener. All
223
// incoming connections are authenticated via the three act Brontide
224
// key-exchange scheme. This function will fail with a non-nil error in the
225
// case that either the handshake breaks down, or the remote peer doesn't know
226
// our static public key.
227
//
228
// Part of the net.Listener interface.
229
func (l *Listener) Accept() (net.Conn, error) {
3✔
230
        select {
3✔
231
        case result := <-l.conns:
3✔
232
                return result.conn, result.err
3✔
UNCOV
233
        case <-l.quit:
×
UNCOV
234
                return nil, errors.New("brontide connection closed")
×
235
        }
236
}
237

238
// Close closes the listener.  Any blocked Accept operations will be unblocked
239
// and return errors.
240
//
241
// Part of the net.Listener interface.
242
func (l *Listener) Close() error {
3✔
243
        select {
3✔
244
        case <-l.quit:
×
245
        default:
3✔
246
                close(l.quit)
3✔
247
        }
248

249
        return l.tcp.Close()
3✔
250
}
251

252
// Addr returns the listener's network address.
253
//
254
// Part of the net.Listener interface.
255
func (l *Listener) Addr() net.Addr {
8✔
256
        return l.tcp.Addr()
8✔
257
}
8✔
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