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

lightningnetwork / lnd / 13980275562

20 Mar 2025 10:06PM UTC coverage: 58.6% (-10.2%) from 68.789%
13980275562

Pull #9623

github

web-flow
Merge b9b960345 into 09b674508
Pull Request #9623: Size msg test msg

0 of 1518 new or added lines in 42 files covered. (0.0%)

26603 existing lines in 443 files now uncovered.

96807 of 165200 relevant lines covered (58.6%)

1.82 hits per line

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

48.0
/lnwire/update_add_htlc.go
1
package lnwire
2

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

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

12
const (
13
        // OnionPacketSize is the size of the serialized Sphinx onion packet
14
        // included in each UpdateAddHTLC message. The breakdown of the onion
15
        // packet is as follows: 1-byte version, 33-byte ephemeral public key
16
        // (for ECDH), 1300-bytes of per-hop data, and a 32-byte HMAC over the
17
        // entire packet.
18
        OnionPacketSize = 1366
19

20
        // ExperimentalEndorsementType is the TLV type used for a custom
21
        // record that sets an experimental endorsement value.
22
        ExperimentalEndorsementType tlv.Type = 106823
23

24
        // ExperimentalUnendorsed is the value that the experimental endorsement
25
        // field contains when a htlc is not endorsed.
26
        ExperimentalUnendorsed = 0
27

28
        // ExperimentalEndorsed is the value that the experimental endorsement
29
        // field contains when a htlc is endorsed. We're using a single byte
30
        // to represent our endorsement value, but limit the value to using
31
        // the first three bits (max value = 00000111). Interpreted as a uint8
32
        // (an alias for byte in go), we can just define this constant as 7.
33
        ExperimentalEndorsed = 7
34
)
35

36
type (
37
        // BlindingPointTlvType is the type for ephemeral pubkeys used in
38
        // route blinding.
39
        BlindingPointTlvType = tlv.TlvType0
40

41
        // BlindingPointRecord holds an optional blinding point on update add
42
        // htlc.
43
        //nolint:ll
44
        BlindingPointRecord = tlv.OptionalRecordT[BlindingPointTlvType, *btcec.PublicKey]
45
)
46

47
// UpdateAddHTLC is the message sent by Alice to Bob when she wishes to add an
48
// HTLC to his remote commitment transaction. In addition to information
49
// detailing the value, the ID, expiry, and the onion blob is also included
50
// which allows Bob to derive the next hop in the route. The HTLC added by this
51
// message is to be added to the remote node's "pending" HTLCs.  A subsequent
52
// CommitSig message will move the pending HTLC to the newly created commitment
53
// transaction, marking them as "staged".
54
type UpdateAddHTLC struct {
55
        // ChanID is the particular active channel that this UpdateAddHTLC is
56
        // bound to.
57
        ChanID ChannelID
58

59
        // ID is the identification server for this HTLC. This value is
60
        // explicitly included as it allows nodes to survive single-sided
61
        // restarts. The ID value for this sides starts at zero, and increases
62
        // with each offered HTLC.
63
        ID uint64
64

65
        // Amount is the amount of millisatoshis this HTLC is worth.
66
        Amount MilliSatoshi
67

68
        // PaymentHash is the payment hash to be included in the HTLC this
69
        // request creates. The pre-image to this HTLC must be revealed by the
70
        // upstream peer in order to fully settle the HTLC.
71
        PaymentHash [32]byte
72

73
        // Expiry is the number of blocks after which this HTLC should expire.
74
        // It is the receiver's duty to ensure that the outgoing HTLC has a
75
        // sufficient expiry value to allow her to redeem the incoming HTLC.
76
        Expiry uint32
77

78
        // OnionBlob is the raw serialized mix header used to route an HTLC in
79
        // a privacy-preserving manner. The mix header is defined currently to
80
        // be parsed as a 4-tuple: (groupElement, routingInfo, headerMAC,
81
        // body).  First the receiving node should use the groupElement, and
82
        // its current onion key to derive a shared secret with the source.
83
        // Once the shared secret has been derived, the headerMAC should be
84
        // checked FIRST. Note that the MAC only covers the routingInfo field.
85
        // If the MAC matches, and the shared secret is fresh, then the node
86
        // should strip off a layer of encryption, exposing the next hop to be
87
        // used in the subsequent UpdateAddHTLC message.
88
        OnionBlob [OnionPacketSize]byte
89

90
        // BlindingPoint is the ephemeral pubkey used to optionally blind the
91
        // next hop for this htlc.
92
        BlindingPoint BlindingPointRecord
93

94
        // CustomRecords maps TLV types to byte slices, storing arbitrary data
95
        // intended for inclusion in the ExtraData field of the UpdateAddHTLC
96
        // message.
97
        CustomRecords CustomRecords
98

99
        // ExtraData is the set of data that was appended to this message to
100
        // fill out the full maximum transport message size. These fields can
101
        // be used to specify optional data such as custom TLV fields.
102
        ExtraData ExtraOpaqueData
103
}
104

105
// NewUpdateAddHTLC returns a new empty UpdateAddHTLC message.
106
func NewUpdateAddHTLC() *UpdateAddHTLC {
×
107
        return &UpdateAddHTLC{}
×
108
}
×
109

110
// A compile time check to ensure UpdateAddHTLC implements the lnwire.Message
111
// interface.
112
var _ Message = (*UpdateAddHTLC)(nil)
113

114
// Decode deserializes a serialized UpdateAddHTLC message stored in the passed
115
// io.Reader observing the specified protocol version.
116
//
117
// This is part of the lnwire.Message interface.
118
func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
3✔
119
        // msgExtraData is a temporary variable used to read the message extra
3✔
120
        // data field from the reader.
3✔
121
        var msgExtraData ExtraOpaqueData
3✔
122

3✔
123
        if err := ReadElements(r,
3✔
124
                &c.ChanID,
3✔
125
                &c.ID,
3✔
126
                &c.Amount,
3✔
127
                c.PaymentHash[:],
3✔
128
                &c.Expiry,
3✔
129
                c.OnionBlob[:],
3✔
130
                &msgExtraData,
3✔
131
        ); err != nil {
3✔
UNCOV
132
                return err
×
UNCOV
133
        }
×
134

135
        // Extract TLV records from the extra data field.
136
        blindingRecord := c.BlindingPoint.Zero()
3✔
137

3✔
138
        customRecords, parsed, extraData, err := ParseAndExtractCustomRecords(
3✔
139
                msgExtraData, &blindingRecord,
3✔
140
        )
3✔
141
        if err != nil {
3✔
UNCOV
142
                return err
×
UNCOV
143
        }
×
144

145
        // Assign the parsed records back to the message.
146
        if parsed.Contains(blindingRecord.TlvType()) {
6✔
147
                c.BlindingPoint = tlv.SomeRecordT(blindingRecord)
3✔
148
        }
3✔
149

150
        c.CustomRecords = customRecords
3✔
151
        c.ExtraData = extraData
3✔
152

3✔
153
        return nil
3✔
154
}
155

156
// Encode serializes the target UpdateAddHTLC into the passed io.Writer
157
// observing the protocol version specified.
158
//
159
// This is part of the lnwire.Message interface.
160
func (c *UpdateAddHTLC) Encode(w *bytes.Buffer, pver uint32) error {
3✔
161
        if err := WriteChannelID(w, c.ChanID); err != nil {
3✔
162
                return err
×
163
        }
×
164

165
        if err := WriteUint64(w, c.ID); err != nil {
3✔
166
                return err
×
167
        }
×
168

169
        if err := WriteMilliSatoshi(w, c.Amount); err != nil {
3✔
170
                return err
×
171
        }
×
172

173
        if err := WriteBytes(w, c.PaymentHash[:]); err != nil {
3✔
174
                return err
×
175
        }
×
176

177
        if err := WriteUint32(w, c.Expiry); err != nil {
3✔
178
                return err
×
179
        }
×
180

181
        if err := WriteBytes(w, c.OnionBlob[:]); err != nil {
3✔
182
                return err
×
183
        }
×
184

185
        // Only include blinding point in extra data if present.
186
        var records []tlv.RecordProducer
3✔
187
        c.BlindingPoint.WhenSome(
3✔
188
                func(b tlv.RecordT[BlindingPointTlvType, *btcec.PublicKey]) {
6✔
189
                        records = append(records, &b)
3✔
190
                },
3✔
191
        )
192

193
        extraData, err := MergeAndEncode(records, c.ExtraData, c.CustomRecords)
3✔
194
        if err != nil {
3✔
UNCOV
195
                return err
×
UNCOV
196
        }
×
197

198
        return WriteBytes(w, extraData)
3✔
199
}
200

201
// MsgType returns the integer uniquely identifying this message type on the
202
// wire.
203
//
204
// This is part of the lnwire.Message interface.
205
func (c *UpdateAddHTLC) MsgType() MessageType {
3✔
206
        return MsgUpdateAddHTLC
3✔
207
}
3✔
208

209
// TargetChanID returns the channel id of the link for which this message is
210
// intended.
211
//
212
// NOTE: Part of peer.LinkUpdater interface.
213
func (c *UpdateAddHTLC) TargetChanID() ChannelID {
3✔
214
        return c.ChanID
3✔
215
}
3✔
216

217
// SerializedSize returns the serialized size of the message in bytes.
218
//
219
// This is part of the lnwire.SizeableMessage interface.
NEW
220
func (c *UpdateAddHTLC) SerializedSize() (uint32, error) {
×
NEW
221
        return MessageSerializedSize(c)
×
NEW
222
}
×
223

224
// RandTestMessage returns an UpdateAddHTLC message populated with random data.
225
//
226
// This is part of the TestMessage interface.
NEW
227
func (c *UpdateAddHTLC) RandTestMessage(t *rapid.T) Message {
×
NEW
228
        msg := &UpdateAddHTLC{
×
NEW
229
                ChanID: RandChannelID(t),
×
NEW
230
                ID:     rapid.Uint64().Draw(t, "id"),
×
NEW
231
                Amount: MilliSatoshi(rapid.Uint64().Draw(t, "amount")),
×
NEW
232
                Expiry: rapid.Uint32().Draw(t, "expiry"),
×
NEW
233
        }
×
NEW
234

×
NEW
235
        hashBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "paymentHash")
×
NEW
236
        copy(msg.PaymentHash[:], hashBytes)
×
NEW
237

×
NEW
238
        onionBytes := rapid.SliceOfN(
×
NEW
239
                rapid.Byte(), OnionPacketSize, OnionPacketSize,
×
NEW
240
        ).Draw(t, "onionBlob")
×
NEW
241
        copy(msg.OnionBlob[:], onionBytes)
×
NEW
242

×
NEW
243
        numRecords := rapid.IntRange(0, 5).Draw(t, "numRecords")
×
NEW
244
        if numRecords > 0 {
×
NEW
245
                msg.CustomRecords, _ = RandCustomRecords(t, nil, true)
×
NEW
246
        }
×
247

248
        // 50/50 chance to add a blinding point
NEW
249
        if rapid.Bool().Draw(t, "includeBlindingPoint") {
×
NEW
250
                pubKey := RandPubKey(t)
×
NEW
251

×
NEW
252
                msg.BlindingPoint = tlv.SomeRecordT(
×
NEW
253
                        tlv.NewPrimitiveRecord[BlindingPointTlvType](pubKey),
×
NEW
254
                )
×
NEW
255
        }
×
256

NEW
257
        return msg
×
258
}
259

260
// A compile time check to ensure UpdateAddHTLC implements the
261
// lnwire.SizeableMessage interface.
262
var _ SizeableMessage = (*UpdateAddHTLC)(nil)
263

264
// A compile time check to ensure UpdateAddHTLC implements the
265
// lnwire.TestMessage interface.
266
var _ TestMessage = (*UpdateAddHTLC)(nil)
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