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

lightningnetwork / lnd / 16983297902

15 Aug 2025 04:58AM UTC coverage: 66.777% (+0.02%) from 66.758%
16983297902

Pull #10140

github

web-flow
Merge 33b9b55dc into 3841d5554
Pull Request #10140: [2/3] lnwire: fix encoding customized TLV records

178 of 191 new or added lines in 8 files covered. (93.19%)

79 existing lines in 13 files now uncovered.

136014 of 203685 relevant lines covered (66.78%)

21511.77 hits per line

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

68.91
/lnwire/accept_channel.go
1
package lnwire
2

3
import (
4
        "bytes"
5
        "io"
6

7
        "github.com/btcsuite/btcd/btcec/v2"
8
        "github.com/btcsuite/btcd/btcutil"
9
        "github.com/lightningnetwork/lnd/tlv"
10
)
11

12
// AcceptChannel is the message Bob sends to Alice after she initiates the
13
// single funder channel workflow via an AcceptChannel message. Once Alice
14
// receives Bob's response, then she has all the items necessary to construct
15
// the funding transaction, and both commitment transactions.
16
type AcceptChannel struct {
17
        // PendingChannelID serves to uniquely identify the future channel
18
        // created by the initiated single funder workflow.
19
        PendingChannelID [32]byte
20

21
        // DustLimit is the specific dust limit the sender of this message
22
        // would like enforced on their version of the commitment transaction.
23
        // Any output below this value will be "trimmed" from the commitment
24
        // transaction, with the amount of the HTLC going to dust.
25
        DustLimit btcutil.Amount
26

27
        // MaxValueInFlight represents the maximum amount of coins that can be
28
        // pending within the channel at any given time. If the amount of funds
29
        // in limbo exceeds this amount, then the channel will be failed.
30
        MaxValueInFlight MilliSatoshi
31

32
        // ChannelReserve is the amount of BTC that the receiving party MUST
33
        // maintain a balance above at all times. This is a safety mechanism to
34
        // ensure that both sides always have skin in the game during the
35
        // channel's lifetime.
36
        ChannelReserve btcutil.Amount
37

38
        // HtlcMinimum is the smallest HTLC that the sender of this message
39
        // will accept.
40
        HtlcMinimum MilliSatoshi
41

42
        // MinAcceptDepth is the minimum depth that the initiator of the
43
        // channel should wait before considering the channel open.
44
        MinAcceptDepth uint32
45

46
        // CsvDelay is the number of blocks to use for the relative time lock
47
        // in the pay-to-self output of both commitment transactions.
48
        CsvDelay uint16
49

50
        // MaxAcceptedHTLCs is the total number of incoming HTLC's that the
51
        // sender of this channel will accept.
52
        //
53
        // TODO(roasbeef): acks the initiator's, same with max in flight?
54
        MaxAcceptedHTLCs uint16
55

56
        // FundingKey is the key that should be used on behalf of the sender
57
        // within the 2-of-2 multi-sig output that it contained within the
58
        // funding transaction.
59
        FundingKey *btcec.PublicKey
60

61
        // RevocationPoint is the base revocation point for the sending party.
62
        // Any commitment transaction belonging to the receiver of this message
63
        // should use this key and their per-commitment point to derive the
64
        // revocation key for the commitment transaction.
65
        RevocationPoint *btcec.PublicKey
66

67
        // PaymentPoint is the base payment point for the sending party. This
68
        // key should be combined with the per commitment point for a
69
        // particular commitment state in order to create the key that should
70
        // be used in any output that pays directly to the sending party, and
71
        // also within the HTLC covenant transactions.
72
        PaymentPoint *btcec.PublicKey
73

74
        // DelayedPaymentPoint is the delay point for the sending party. This
75
        // key should be combined with the per commitment point to derive the
76
        // keys that are used in outputs of the sender's commitment transaction
77
        // where they claim funds.
78
        DelayedPaymentPoint *btcec.PublicKey
79

80
        // HtlcPoint is the base point used to derive the set of keys for this
81
        // party that will be used within the HTLC public key scripts.  This
82
        // value is combined with the receiver's revocation base point in order
83
        // to derive the keys that are used within HTLC scripts.
84
        HtlcPoint *btcec.PublicKey
85

86
        // FirstCommitmentPoint is the first commitment point for the sending
87
        // party. This value should be combined with the receiver's revocation
88
        // base point in order to derive the revocation keys that are placed
89
        // within the commitment transaction of the sender.
90
        FirstCommitmentPoint *btcec.PublicKey
91

92
        // NOTE: The following fields are TLV records.
93
        //
94
        // UpfrontShutdownScript is the script to which the channel funds should
95
        // be paid when mutually closing the channel. This field is optional, and
96
        // and has a length prefix, so a zero will be written if it is not set
97
        // and its length followed by the script will be written if it is set.
98
        UpfrontShutdownScript DeliveryAddress
99

100
        // ChannelType is the explicit channel type the initiator wishes to
101
        // open.
102
        ChannelType *ChannelType
103

104
        // LeaseExpiry represents the absolute expiration height of a channel
105
        // lease. This is a custom TLV record that will only apply when a leased
106
        // channel is being opened using the script enforced lease commitment
107
        // type.
108
        LeaseExpiry *LeaseExpiry
109

110
        // LocalNonce is an optional field that transmits the
111
        // local/verification nonce for a party. This nonce will be used to
112
        // verify the very first commitment transaction signature.
113
        // This will only be populated if the simple taproot channels type was
114
        // negotiated.
115
        LocalNonce OptMusig2NonceTLV
116

117
        // ExtraData is the set of data that was appended to this message to
118
        // fill out the full maximum transport message size. These fields can
119
        // be used to specify optional data such as custom TLV fields.
120
        //
121
        // NOTE: Since the upfront shutdown script MUST be present (though can
122
        // be zero-length) if any TLV data is available, the script will be
123
        // extracted and removed from this blob when decoding. ExtraData will
124
        // contain all TLV records _except_ the DeliveryAddress record in that
125
        // case.
126
        ExtraData ExtraOpaqueData
127
}
128

129
// A compile time check to ensure AcceptChannel implements the lnwire.Message
130
// interface.
131
var _ Message = (*AcceptChannel)(nil)
132

133
// A compile time check to ensure AcceptChannel implements the
134
// lnwire.SizeableMessage interface.
135
var _ SizeableMessage = (*AcceptChannel)(nil)
136

137
// Encode serializes the target AcceptChannel into the passed io.Writer
138
// implementation. Serialization will observe the rules defined by the passed
139
// protocol version.
140
//
141
// This is part of the lnwire.Message interface.
142
func (a *AcceptChannel) Encode(w *bytes.Buffer, pver uint32) error {
141✔
143
        // Get producers from extra data.
141✔
144
        producers, err := a.ExtraData.RecordProducers()
141✔
145
        if err != nil {
141✔
NEW
146
                return err
×
NEW
147
        }
×
148

149
        // Append known producers.
150
        producers = append(producers, &a.UpfrontShutdownScript)
141✔
151
        if a.ChannelType != nil {
209✔
152
                producers = append(producers, a.ChannelType)
68✔
153
        }
68✔
154
        if a.LeaseExpiry != nil {
197✔
155
                producers = append(producers, a.LeaseExpiry)
56✔
156
        }
56✔
157
        a.LocalNonce.WhenSome(func(localNonce Musig2NonceTLV) {
189✔
158
                producers = append(producers, &localNonce)
48✔
159
        })
48✔
160

161
        // Pack all records into a new TLV stream.
162
        var tlvData ExtraOpaqueData
141✔
163
        err = tlvData.PackRecords(producers...)
141✔
164
        if err != nil {
141✔
165
                return err
×
166
        }
×
167

168
        if err := WriteBytes(w, a.PendingChannelID[:]); err != nil {
141✔
169
                return err
×
170
        }
×
171

172
        if err := WriteSatoshi(w, a.DustLimit); err != nil {
141✔
173
                return err
×
174
        }
×
175

176
        if err := WriteMilliSatoshi(w, a.MaxValueInFlight); err != nil {
141✔
177
                return err
×
178
        }
×
179

180
        if err := WriteSatoshi(w, a.ChannelReserve); err != nil {
141✔
181
                return err
×
182
        }
×
183

184
        if err := WriteMilliSatoshi(w, a.HtlcMinimum); err != nil {
141✔
185
                return err
×
186
        }
×
187

188
        if err := WriteUint32(w, a.MinAcceptDepth); err != nil {
141✔
189
                return err
×
190
        }
×
191

192
        if err := WriteUint16(w, a.CsvDelay); err != nil {
141✔
193
                return err
×
194
        }
×
195

196
        if err := WriteUint16(w, a.MaxAcceptedHTLCs); err != nil {
141✔
197
                return err
×
198
        }
×
199

200
        if err := WritePublicKey(w, a.FundingKey); err != nil {
141✔
201
                return err
×
202
        }
×
203

204
        if err := WritePublicKey(w, a.RevocationPoint); err != nil {
141✔
205
                return err
×
206
        }
×
207

208
        if err := WritePublicKey(w, a.PaymentPoint); err != nil {
141✔
209
                return err
×
210
        }
×
211

212
        if err := WritePublicKey(w, a.DelayedPaymentPoint); err != nil {
141✔
213
                return err
×
214
        }
×
215

216
        if err := WritePublicKey(w, a.HtlcPoint); err != nil {
141✔
217
                return err
×
218
        }
×
219

220
        if err := WritePublicKey(w, a.FirstCommitmentPoint); err != nil {
141✔
221
                return err
×
222
        }
×
223

224
        return WriteBytes(w, tlvData)
141✔
225
}
226

227
// Decode deserializes the serialized AcceptChannel stored in the passed
228
// io.Reader into the target AcceptChannel using the deserialization rules
229
// defined by the passed protocol version.
230
//
231
// This is part of the lnwire.Message interface.
232
func (a *AcceptChannel) Decode(r io.Reader, pver uint32) error {
237✔
233
        // Read all the mandatory fields in the accept message.
237✔
234
        err := ReadElements(r,
237✔
235
                a.PendingChannelID[:],
237✔
236
                &a.DustLimit,
237✔
237
                &a.MaxValueInFlight,
237✔
238
                &a.ChannelReserve,
237✔
239
                &a.HtlcMinimum,
237✔
240
                &a.MinAcceptDepth,
237✔
241
                &a.CsvDelay,
237✔
242
                &a.MaxAcceptedHTLCs,
237✔
243
                &a.FundingKey,
237✔
244
                &a.RevocationPoint,
237✔
245
                &a.PaymentPoint,
237✔
246
                &a.DelayedPaymentPoint,
237✔
247
                &a.HtlcPoint,
237✔
248
                &a.FirstCommitmentPoint,
237✔
249
        )
237✔
250
        if err != nil {
255✔
251
                return err
18✔
252
        }
18✔
253

254
        // For backwards compatibility, the optional extra data blob for
255
        // AcceptChannel must contain an entry for the upfront shutdown script.
256
        // We'll read it out and attempt to parse it.
257
        var tlvRecords ExtraOpaqueData
219✔
258
        if err := ReadElements(r, &tlvRecords); err != nil {
219✔
259
                return err
×
260
        }
×
261

262
        // Next we'll parse out the set of known records, keeping the raw tlv
263
        // bytes untouched to ensure we don't drop any bytes erroneously.
264
        var (
219✔
265
                chanType    ChannelType
219✔
266
                leaseExpiry LeaseExpiry
219✔
267
                localNonce  = a.LocalNonce.Zero()
219✔
268
        )
219✔
269
        knownRecords, extraData, err := ParseAndExtractExtraData(
219✔
270
                tlvRecords, &a.UpfrontShutdownScript, &chanType, &leaseExpiry,
219✔
271
                &localNonce,
219✔
272
        )
219✔
273
        if err != nil {
263✔
274
                return err
44✔
275
        }
44✔
276

277
        // Set the corresponding TLV types if they were included in the stream.
278
        if _, ok := knownRecords[ChannelTypeRecordType]; ok {
261✔
279
                a.ChannelType = &chanType
86✔
280
        }
86✔
281
        if _, ok := knownRecords[LeaseExpiryRecordType]; ok {
233✔
282
                a.LeaseExpiry = &leaseExpiry
58✔
283
        }
58✔
284
        if _, ok := knownRecords[a.LocalNonce.TlvType()]; ok {
224✔
285
                a.LocalNonce = tlv.SomeRecordT(localNonce)
49✔
286
        }
49✔
287

288
        a.ExtraData = extraData
175✔
289

175✔
290
        return nil
175✔
291
}
292

293
// MsgType returns the MessageType code which uniquely identifies this message
294
// as an AcceptChannel on the wire.
295
//
296
// This is part of the lnwire.Message interface.
297
func (a *AcceptChannel) MsgType() MessageType {
140✔
298
        return MsgAcceptChannel
140✔
299
}
140✔
300

301
// SerializedSize returns the serialized size of the message in bytes.
302
//
303
// This is part of the lnwire.SizeableMessage interface.
304
func (a *AcceptChannel) SerializedSize() (uint32, error) {
×
305
        return MessageSerializedSize(a)
×
306
}
×
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