lnwallet: add TLV blob to PaymentDescriptor + htlc add

In this commit, we add a TLV blob to the PaymentDescriptor struct. We also now thread through this value from the UpdateAddHTLC message to the PaymentDescriptor mapping, and the other way around.
This commit is contained in:
Olaoluwa Osuntokun 2024-04-01 19:56:50 -07:00 committed by Oliver Gugger
parent d95c1f93f3
commit c1e641e9d9
No known key found for this signature in database
GPG key ID: 8E4256593F177720
5 changed files with 78 additions and 7 deletions

View file

@ -2580,6 +2580,12 @@ type HTLC struct {
// HTLC. It is stored in the ExtraData field, which is used to store
// a TLV stream of additional information associated with the HTLC.
BlindingPoint lnwire.BlindingPointRecord
// CustomRecords is a set of custom TLV records that are associated with
// this HTLC. These records are used to store additional information
// about the HTLC that is not part of the standard HTLC fields. This
// field is encoded within the ExtraData field.
CustomRecords lnwire.CustomRecords
}
// serializeExtraData encodes a TLV stream of extra data to be stored with a
@ -2598,6 +2604,11 @@ func (h *HTLC) serializeExtraData() error {
records = append(records, &b)
})
records, err := h.CustomRecords.ExtendRecordProducers(records)
if err != nil {
return err
}
return h.ExtraData.PackRecords(records...)
}
@ -2619,8 +2630,19 @@ func (h *HTLC) deserializeExtraData() error {
if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
// Remove the entry from the TLV map. Anything left in the map
// will be included in the custom records field.
delete(tlvMap, h.BlindingPoint.TlvType())
}
// Set the custom records field to the remaining TLV records.
customRecords, err := lnwire.NewCustomRecords(tlvMap)
if err != nil {
return err
}
h.CustomRecords = customRecords
return nil
}
@ -2758,6 +2780,8 @@ func (h *HTLC) Copy() HTLC {
copy(clone.Signature[:], h.Signature)
copy(clone.RHash[:], h.RHash[:])
copy(clone.ExtraData, h.ExtraData)
clone.BlindingPoint = h.BlindingPoint
clone.CustomRecords = h.CustomRecords.Copy()
return clone
}

View file

@ -1657,6 +1657,24 @@ func TestHTLCsExtraData(t *testing.T) {
),
}
// Custom channel data htlc with a blinding point.
customDataHTLC := HTLC{
Signature: testSig.Serialize(),
Incoming: false,
Amt: 10,
RHash: key,
RefundTimeout: 1,
OnionBlob: lnmock.MockOnion(),
BlindingPoint: tlv.SomeRecordT(
tlv.NewPrimitiveRecord[lnwire.BlindingPointTlvType](
pubKey,
),
),
CustomRecords: map[uint64][]byte{
uint64(lnwire.MinCustomRecordsTlvType + 3): {1, 2, 3},
},
}
testCases := []struct {
name string
htlcs []HTLC
@ -1678,6 +1696,7 @@ func TestHTLCsExtraData(t *testing.T) {
mockHtlc,
blindingPointHTLC,
mockHtlc,
customDataHTLC,
},
},
}

View file

@ -529,6 +529,7 @@ func (c *commitment) toDiskCommit(
LogIndex: htlc.LogIndex,
Incoming: false,
BlindingPoint: htlc.BlindingPoint,
CustomRecords: htlc.CustomRecords.Copy(),
}
copy(h.OnionBlob[:], htlc.OnionBlob)
@ -554,8 +555,10 @@ func (c *commitment) toDiskCommit(
LogIndex: htlc.LogIndex,
Incoming: true,
BlindingPoint: htlc.BlindingPoint,
CustomRecords: htlc.CustomRecords.Copy(),
}
copy(h.OnionBlob[:], htlc.OnionBlob)
if whoseCommit.IsLocal() && htlc.sig != nil {
h.Signature = htlc.sig.Serialize()
}
@ -653,6 +656,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
theirPkScript: theirP2WSH,
theirWitnessScript: theirWitnessScript,
BlindingPoint: htlc.BlindingPoint,
CustomRecords: htlc.CustomRecords.Copy(),
}, nil
}
@ -5727,6 +5731,9 @@ func (lc *LightningChannel) htlcAddDescriptor(htlc *lnwire.UpdateAddHTLC,
OnionBlob: htlc.OnionBlob[:],
OpenCircuitKey: openKey,
BlindingPoint: htlc.BlindingPoint,
// TODO(guggero): Add custom records from HTLC here once we have
// the custom records in the HTLC struct (later commits in this
// PR).
}
}
@ -5767,7 +5774,9 @@ func (lc *LightningChannel) validateAddHtlc(pd *PaymentDescriptor,
// ReceiveHTLC adds an HTLC to the state machine's remote update log. This
// method should be called in response to receiving a new HTLC from the remote
// party.
func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, error) {
func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64,
error) {
lc.Lock()
defer lc.Unlock()
@ -5785,6 +5794,9 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64, err
HtlcIndex: lc.remoteUpdateLog.htlcCounter,
OnionBlob: htlc.OnionBlob[:],
BlindingPoint: htlc.BlindingPoint,
// TODO(guggero): Add custom records from HTLC here once we have
// the custom records in the HTLC struct (later commits in this
// PR).
}
localACKedIndex := lc.remoteCommitChain.tail().ourMessageIndex

View file

@ -2,6 +2,7 @@ package lnwallet
import (
"bytes"
crand "crypto/rand"
"crypto/sha256"
"fmt"
"math/rand"
@ -10431,19 +10432,26 @@ func assertPayDescMatchHTLC(t *testing.T, pd PaymentDescriptor,
// the `Incoming`.
func createRandomHTLC(t *testing.T, incoming bool) channeldb.HTLC {
var onionBlob [lnwire.OnionPacketSize]byte
_, err := rand.Read(onionBlob[:])
_, err := crand.Read(onionBlob[:])
require.NoError(t, err)
var rHash [lntypes.HashSize]byte
_, err = rand.Read(rHash[:])
_, err = crand.Read(rHash[:])
require.NoError(t, err)
sig := make([]byte, 64)
_, err = rand.Read(sig)
_, err = crand.Read(sig)
require.NoError(t, err)
randCustomData := make([]byte, 32)
_, err = crand.Read(randCustomData)
require.NoError(t, err)
randCustomType := rand.Intn(255) + lnwire.MinCustomRecordsTlvType
blinding, err := pubkeyFromHex(
"0228f2af0abe322403480fb3ee172f7f1601e67d1da6cad40b54c4468d48236c39", //nolint:lll
"0228f2af0abe322403480fb3ee172f7f1601e67d1da6cad40b54c4468d48" +
"236c39",
)
require.NoError(t, err)
@ -10458,9 +10466,13 @@ func createRandomHTLC(t *testing.T, incoming bool) channeldb.HTLC {
HtlcIndex: rand.Uint64(),
LogIndex: rand.Uint64(),
BlindingPoint: tlv.SomeRecordT(
//nolint:lll
tlv.NewPrimitiveRecord[lnwire.BlindingPointTlvType](blinding),
tlv.NewPrimitiveRecord[lnwire.BlindingPointTlvType](
blinding,
),
),
CustomRecords: map[uint64][]byte{
uint64(randCustomType): randCustomData,
},
}
}

View file

@ -221,4 +221,8 @@ type PaymentDescriptor struct {
// blinded route (ie, not the introduction node) from update_add_htlc's
// TLVs.
BlindingPoint lnwire.BlindingPointRecord
// CustomRecords also stores the set of optional custom records that
// may have been attached to a sent HTLC.
CustomRecords lnwire.CustomRecords
}