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

lightningnetwork / lnd / 13236757158

10 Feb 2025 08:39AM UTC coverage: 57.649% (-1.2%) from 58.815%
13236757158

Pull #9493

github

ziggie1984
lncli: for some cmds we don't replace the data of the response.

For some cmds it is not very practical to replace the json output
because we might pipe it into other commands. For example when
creating the route we want to pipe it into sendtoRoute.
Pull Request #9493: For some lncli cmds we should not replace the content with other data

0 of 9 new or added lines in 2 files covered. (0.0%)

19535 existing lines in 252 files now uncovered.

103517 of 179563 relevant lines covered (57.65%)

24878.49 hits per line

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

45.99
/brontide/conn.go
1
package brontide
2

3
import (
4
        "bytes"
5
        "io"
6
        "math"
7
        "net"
8
        "time"
9

10
        "github.com/btcsuite/btcd/btcec/v2"
11
        "github.com/lightningnetwork/lnd/keychain"
12
        "github.com/lightningnetwork/lnd/lnwire"
13
        "github.com/lightningnetwork/lnd/tor"
14
)
15

16
// Conn is an implementation of net.Conn which enforces an authenticated key
17
// exchange and message encryption protocol dubbed "Brontide" after initial TCP
18
// connection establishment. In the case of a successful handshake, all
19
// messages sent via the .Write() method are encrypted with an AEAD cipher
20
// along with an encrypted length-prefix. See the Machine struct for
21
// additional details w.r.t to the handshake and encryption scheme.
22
type Conn struct {
23
        conn net.Conn
24

25
        noise *Machine
26

27
        readBuf bytes.Buffer
28
}
29

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

33
// Dial attempts to establish an encrypted+authenticated connection with the
34
// remote peer located at address which has remotePub as its long-term static
35
// public key. In the case of a handshake failure, the connection is closed and
36
// a non-nil error is returned.
37
func Dial(local keychain.SingleKeyECDH, netAddr *lnwire.NetAddress,
38
        timeout time.Duration, dialer tor.DialFunc) (*Conn, error) {
3✔
39

3✔
40
        ipAddr := netAddr.Address.String()
3✔
41
        var conn net.Conn
3✔
42
        var err error
3✔
43
        conn, err = dialer("tcp", ipAddr, timeout)
3✔
44
        if err != nil {
3✔
UNCOV
45
                return nil, err
×
UNCOV
46
        }
×
47

48
        b := &Conn{
3✔
49
                conn:  conn,
3✔
50
                noise: NewBrontideMachine(true, local, netAddr.IdentityKey),
3✔
51
        }
3✔
52

3✔
53
        // Initiate the handshake by sending the first act to the receiver.
3✔
54
        actOne, err := b.noise.GenActOne()
3✔
55
        if err != nil {
3✔
56
                b.conn.Close()
×
57
                return nil, err
×
58
        }
×
59
        if _, err := conn.Write(actOne[:]); err != nil {
3✔
60
                b.conn.Close()
×
61
                return nil, err
×
62
        }
×
63

64
        // We'll ensure that we get ActTwo from the remote peer in a timely
65
        // manner. If they don't respond within handshakeReadTimeout, then
66
        // we'll kill the connection.
67
        err = conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
3✔
68
        if err != nil {
3✔
69
                b.conn.Close()
×
70
                return nil, err
×
71
        }
×
72

73
        // If the first act was successful (we know that address is actually
74
        // remotePub), then read the second act after which we'll be able to
75
        // send our static public key to the remote peer with strong forward
76
        // secrecy.
77
        var actTwo [ActTwoSize]byte
3✔
78
        if _, err := io.ReadFull(conn, actTwo[:]); err != nil {
3✔
UNCOV
79
                b.conn.Close()
×
UNCOV
80
                return nil, err
×
UNCOV
81
        }
×
82
        if err := b.noise.RecvActTwo(actTwo); err != nil {
3✔
83
                b.conn.Close()
×
84
                return nil, err
×
85
        }
×
86

87
        // Finally, complete the handshake by sending over our encrypted static
88
        // key and execute the final ECDH operation.
89
        actThree, err := b.noise.GenActThree()
3✔
90
        if err != nil {
3✔
91
                b.conn.Close()
×
92
                return nil, err
×
93
        }
×
94
        if _, err := conn.Write(actThree[:]); err != nil {
3✔
95
                b.conn.Close()
×
96
                return nil, err
×
97
        }
×
98

99
        // We'll reset the deadline as it's no longer critical beyond the
100
        // initial handshake.
101
        err = conn.SetReadDeadline(time.Time{})
3✔
102
        if err != nil {
3✔
103
                b.conn.Close()
×
104
                return nil, err
×
105
        }
×
106

107
        return b, nil
3✔
108
}
109

110
// ReadNextMessage uses the connection in a message-oriented manner, instructing
111
// it to read the next _full_ message with the brontide stream. This function
112
// will block until the read of the header and body succeeds.
113
//
114
// NOTE: This method SHOULD NOT be used in the case that the connection may be
115
// adversarial and induce long delays. If the caller needs to set read deadlines
116
// appropriately, it is preferred that they use the split ReadNextHeader and
117
// ReadNextBody methods so that the deadlines can be set appropriately on each.
UNCOV
118
func (c *Conn) ReadNextMessage() ([]byte, error) {
×
UNCOV
119
        return c.noise.ReadMessage(c.conn)
×
UNCOV
120
}
×
121

122
// ReadNextHeader uses the connection to read the next header from the brontide
123
// stream. This function will block until the read of the header succeeds and
124
// return the packet length (including MAC overhead) that is expected from the
125
// subsequent call to ReadNextBody.
UNCOV
126
func (c *Conn) ReadNextHeader() (uint32, error) {
×
UNCOV
127
        return c.noise.ReadHeader(c.conn)
×
UNCOV
128
}
×
129

130
// ReadNextBody uses the connection to read the next message body from the
131
// brontide stream. This function will block until the read of the body succeeds
132
// and return the decrypted payload. The provided buffer MUST be the packet
133
// length returned by the preceding call to ReadNextHeader.
UNCOV
134
func (c *Conn) ReadNextBody(buf []byte) ([]byte, error) {
×
UNCOV
135
        return c.noise.ReadBody(c.conn, buf)
×
UNCOV
136
}
×
137

138
// Read reads data from the connection.  Read can be made to time out and
139
// return an Error with Timeout() == true after a fixed time limit; see
140
// SetDeadline and SetReadDeadline.
141
//
142
// Part of the net.Conn interface.
143
func (c *Conn) Read(b []byte) (n int, err error) {
21✔
144
        // In order to reconcile the differences between the record abstraction
21✔
145
        // of our AEAD connection, and the stream abstraction of TCP, we
21✔
146
        // maintain an intermediate read buffer. If this buffer becomes
21✔
147
        // depleted, then we read the next record, and feed it into the
21✔
148
        // buffer. Otherwise, we read directly from the buffer.
21✔
149
        if c.readBuf.Len() == 0 {
41✔
150
                plaintext, err := c.noise.ReadMessage(c.conn)
20✔
151
                if err != nil {
20✔
152
                        return 0, err
×
153
                }
×
154

155
                if _, err := c.readBuf.Write(plaintext); err != nil {
20✔
156
                        return 0, err
×
157
                }
×
158
        }
159

160
        return c.readBuf.Read(b)
21✔
161
}
162

163
// Write writes data to the connection.  Write can be made to time out and
164
// return an Error with Timeout() == true after a fixed time limit; see
165
// SetDeadline and SetWriteDeadline.
166
//
167
// Part of the net.Conn interface.
168
func (c *Conn) Write(b []byte) (n int, err error) {
12✔
169
        // If the message doesn't require any chunking, then we can go ahead
12✔
170
        // with a single write.
12✔
171
        if len(b) <= math.MaxUint16 {
23✔
172
                err = c.noise.WriteMessage(b)
11✔
173
                if err != nil {
11✔
174
                        return 0, err
×
175
                }
×
176
                return c.noise.Flush(c.conn)
11✔
177
        }
178

179
        // If we need to split the message into fragments, then we'll write
180
        // chunks which maximize usage of the available payload.
181
        chunkSize := math.MaxUint16
1✔
182

1✔
183
        bytesToWrite := len(b)
1✔
184
        bytesWritten := 0
1✔
185
        for bytesWritten < bytesToWrite {
10✔
186
                // If we're on the last chunk, then truncate the chunk size as
9✔
187
                // necessary to avoid an out-of-bounds array memory access.
9✔
188
                if bytesWritten+chunkSize > len(b) {
9✔
189
                        chunkSize = len(b) - bytesWritten
×
190
                }
×
191

192
                // Slice off the next chunk to be written based on our running
193
                // counter and next chunk size.
194
                chunk := b[bytesWritten : bytesWritten+chunkSize]
9✔
195
                if err := c.noise.WriteMessage(chunk); err != nil {
9✔
196
                        return bytesWritten, err
×
197
                }
×
198

199
                n, err := c.noise.Flush(c.conn)
9✔
200
                bytesWritten += n
9✔
201
                if err != nil {
9✔
202
                        return bytesWritten, err
×
203
                }
×
204
        }
205

206
        return bytesWritten, nil
1✔
207
}
208

209
// WriteMessage encrypts and buffers the next message p for the connection. The
210
// ciphertext of the message is prepended with an encrypt+auth'd length which
211
// must be used as the AD to the AEAD construction when being decrypted by the
212
// other side.
213
//
214
// NOTE: This DOES NOT write the message to the wire, it should be followed by a
215
// call to Flush to ensure the message is written.
UNCOV
216
func (c *Conn) WriteMessage(b []byte) error {
×
UNCOV
217
        return c.noise.WriteMessage(b)
×
UNCOV
218
}
×
219

220
// Flush attempts to write a message buffered using WriteMessage to the
221
// underlying connection. If no buffered message exists, this will result in a
222
// NOP. Otherwise, it will continue to write the remaining bytes, picking up
223
// where the byte stream left off in the event of a partial write. The number of
224
// bytes returned reflects the number of plaintext bytes in the payload, and
225
// does not account for the overhead of the header or MACs.
226
//
227
// NOTE: It is safe to call this method again iff a timeout error is returned.
UNCOV
228
func (c *Conn) Flush() (int, error) {
×
UNCOV
229
        return c.noise.Flush(c.conn)
×
UNCOV
230
}
×
231

232
// Close closes the connection. Any blocked Read or Write operations will be
233
// unblocked and return errors.
234
//
235
// Part of the net.Conn interface.
236
func (c *Conn) Close() error {
6✔
237
        // TODO(roasbeef): reset brontide state?
6✔
238
        return c.conn.Close()
6✔
239
}
6✔
240

241
// LocalAddr returns the local network address.
242
//
243
// Part of the net.Conn interface.
UNCOV
244
func (c *Conn) LocalAddr() net.Addr {
×
UNCOV
245
        return c.conn.LocalAddr()
×
UNCOV
246
}
×
247

248
// RemoteAddr returns the remote network address.
249
//
250
// Part of the net.Conn interface.
UNCOV
251
func (c *Conn) RemoteAddr() net.Addr {
×
UNCOV
252
        return c.conn.RemoteAddr()
×
UNCOV
253
}
×
254

255
// SetDeadline sets the read and write deadlines associated with the
256
// connection. It is equivalent to calling both SetReadDeadline and
257
// SetWriteDeadline.
258
//
259
// Part of the net.Conn interface.
260
func (c *Conn) SetDeadline(t time.Time) error {
×
261
        return c.conn.SetDeadline(t)
×
262
}
×
263

264
// SetReadDeadline sets the deadline for future Read calls. A zero value for t
265
// means Read will not time out.
266
//
267
// Part of the net.Conn interface.
UNCOV
268
func (c *Conn) SetReadDeadline(t time.Time) error {
×
UNCOV
269
        return c.conn.SetReadDeadline(t)
×
UNCOV
270
}
×
271

272
// SetWriteDeadline sets the deadline for future Write calls. Even if write
273
// times out, it may return n > 0, indicating that some of the data was
274
// successfully written. A zero value for t means Write will not time out.
275
//
276
// Part of the net.Conn interface.
UNCOV
277
func (c *Conn) SetWriteDeadline(t time.Time) error {
×
UNCOV
278
        return c.conn.SetWriteDeadline(t)
×
UNCOV
279
}
×
280

281
// RemotePub returns the remote peer's static public key.
UNCOV
282
func (c *Conn) RemotePub() *btcec.PublicKey {
×
UNCOV
283
        return c.noise.remoteStatic
×
UNCOV
284
}
×
285

286
// LocalPub returns the local peer's static public key.
287
func (c *Conn) LocalPub() *btcec.PublicKey {
×
288
        return c.noise.localStatic.PubKey()
×
289
}
×
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