What changed, and why it matters
This commit adds a new optional 'inbound fee' field to an experimental Lightning Network message type called ChannelUpdate2. The commit message explicitly states this message type is not used in production, and the field uses a temporary placeholder type number (55555) with a TODO to pick the correct one later. There is no security issue visible in the change itself.
No security action required. Treat as a normal feature/refactoring commit. Monitor the follow-up spec discussion for the final TLV type assignment.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends lnwire.ChannelUpdate2 with an optional TLV record InboundFee (tlv.TlvType55555) of type Fee, plus decode/encode logic and a rapid test generator. The commit message notes the TLV type is intentionally incorrect pending a spec discussion, and that ChannelUpdate2 is not yet used in production. No parsing bounds, signature handling, or memory safety issues are introduced by the diff.
Changed components
lnwire/channel_update_2.golnwire/test_message.goInspect captured patch +28 / −1
diff --git a/lnwire/channel_update_2.go b/lnwire/channel_update_2.go
index b832bc5..7fe7670 100644
--- a/lnwire/channel_update_2.go
+++ b/lnwire/channel_update_2.go
@@ -70,6 +70,11 @@ type ChannelUpdate2 struct {
// millionth of a satoshi.
FeeProportionalMillionths tlv.RecordT[tlv.TlvType18, uint32]
+ // InboundFee is an optional TLV record that contains the fee
+ // information for incoming HTLCs.
+ // TODO(elle): assign normal tlv type?
+ InboundFee tlv.OptionalRecordT[tlv.TlvType55555, Fee]
+
// Signature is used to validate the announced data and prove the
// ownership of node id.
Signature tlv.RecordT[tlv.TlvType160, Sig]
@@ -102,12 +107,13 @@ func (c *ChannelUpdate2) Decode(r io.Reader, _ uint32) error {
var (
chainHash = tlv.ZeroRecordT[tlv.TlvType0, [32]byte]()
secondPeer = tlv.ZeroRecordT[tlv.TlvType8, TrueBoolean]()
+ inboundFee = tlv.ZeroRecordT[tlv.TlvType55555, Fee]()
)
typeMap, err := tlvRecords.ExtractRecords(
&chainHash, &c.ShortChannelID, &c.BlockHeight, &c.DisabledFlags,
&secondPeer, &c.CLTVExpiryDelta, &c.HTLCMinimumMsat,
&c.HTLCMaximumMsat, &c.FeeBaseMsat,
- &c.FeeProportionalMillionths,
+ &c.FeeProportionalMillionths, &inboundFee,
&c.Signature,
)
if err != nil {
@@ -149,6 +155,11 @@ func (c *ChannelUpdate2) Decode(r io.Reader, _ uint32) error {
c.FeeProportionalMillionths.Val = defaultFeeProportionalMillionths //nolint:ll
}
+ // If the inbound fee was encoded, set it.
+ if _, ok := typeMap[c.InboundFee.TlvType()]; ok {
+ c.InboundFee = tlv.SomeRecordT(inboundFee)
+ }
+
c.ExtraSignedFields = ExtraSignedFieldsFromTypeMap(typeMap)
return nil
@@ -207,6 +218,10 @@ func (c *ChannelUpdate2) AllRecords() []tlv.Record {
)
}
+ c.InboundFee.WhenSome(func(r tlv.RecordT[tlv.TlvType55555, Fee]) {
+ recordProducers = append(recordProducers, &r)
+ })
+
recordProducers = append(recordProducers, RecordsAsProducers(
tlv.MapToRecords(c.ExtraSignedFields),
)...)
diff --git a/lnwire/test_message.go b/lnwire/test_message.go
index dc55ef5..fd0d1d6 100644
--- a/lnwire/test_message.go
+++ b/lnwire/test_message.go
@@ -569,6 +569,18 @@ func (c *ChannelUpdate2) RandTestMessage(t *rapid.T) Message {
ExtraSignedFields: make(map[uint64][]byte),
}
+ if rapid.Bool().Draw(t, "includeInboundFee") {
+ base := rapid.IntRange(-1000, 1000).Draw(t, "inFeeBase")
+ rate := rapid.IntRange(-1000, 1000).Draw(t, "inFeeProp")
+ fee := Fee{
+ BaseFee: int32(base),
+ FeeRate: int32(rate),
+ }
+ msg.InboundFee = tlv.SomeRecordT(
+ tlv.NewRecordT[tlv.TlvType55555](fee),
+ )
+ }
+
msg.Signature.Val = RandSignature(t)
msg.Signature.Val.ForceSchnorr()
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.