lnwire: add blinding point to update_add_htlc TLVs

Add blinding points to update_add_htlc. This TLV will be set for
nodes that are relaying payments in blinded routes that are _not_
the introduction node.
This commit is contained in:
Carla Kirk-Cohen 2024-03-27 09:38:50 -04:00
parent d8979d3086
commit e4f90ec593
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91
5 changed files with 111 additions and 17 deletions

View File

@ -651,8 +651,7 @@ func TestChannelStateTransition(t *testing.T) {
{
LogIndex: 2,
UpdateMsg: &lnwire.UpdateAddHTLC{
ChanID: lnwire.ChannelID{1, 2, 3},
ExtraData: make([]byte, 0),
ChanID: lnwire.ChannelID{1, 2, 3},
},
},
}
@ -710,25 +709,22 @@ func TestChannelStateTransition(t *testing.T) {
wireSig,
wireSig,
},
ExtraData: make([]byte, 0),
},
LogUpdates: []LogUpdate{
{
LogIndex: 1,
UpdateMsg: &lnwire.UpdateAddHTLC{
ID: 1,
Amount: lnwire.NewMSatFromSatoshis(100),
Expiry: 25,
ExtraData: make([]byte, 0),
ID: 1,
Amount: lnwire.NewMSatFromSatoshis(100),
Expiry: 25,
},
},
{
LogIndex: 2,
UpdateMsg: &lnwire.UpdateAddHTLC{
ID: 2,
Amount: lnwire.NewMSatFromSatoshis(200),
Expiry: 50,
ExtraData: make([]byte, 0),
ID: 2,
Amount: lnwire.NewMSatFromSatoshis(200),
Expiry: 50,
},
},
},

View File

@ -3037,7 +3037,6 @@ func TestChanSyncOweCommitment(t *testing.T) {
Amount: htlcAmt,
Expiry: uint32(10),
OnionBlob: fakeOnionBlob,
ExtraData: make([]byte, 0),
}
htlcIndex, err := bobChannel.AddHTLC(h, nil)
@ -3082,7 +3081,6 @@ func TestChanSyncOweCommitment(t *testing.T) {
Amount: htlcAmt,
Expiry: uint32(10),
OnionBlob: fakeOnionBlob,
ExtraData: make([]byte, 0),
}
aliceHtlcIndex, err := aliceChannel.AddHTLC(aliceHtlc, nil)
require.NoError(t, err, "unable to add alice's htlc")

View File

@ -1337,6 +1337,42 @@ func TestLightningWireProtocol(t *testing.T) {
v[0] = reflect.ValueOf(req)
},
MsgUpdateAddHTLC: func(v []reflect.Value, r *rand.Rand) {
req := &UpdateAddHTLC{
ID: r.Uint64(),
Amount: MilliSatoshi(r.Uint64()),
Expiry: r.Uint32(),
}
_, err := r.Read(req.ChanID[:])
require.NoError(t, err)
_, err = r.Read(req.PaymentHash[:])
require.NoError(t, err)
_, err = r.Read(req.OnionBlob[:])
require.NoError(t, err)
// Generate a blinding point 50% of the time, since not
// all update adds will use route blinding.
if r.Int31()%2 == 0 {
pubkey, err := randPubKey()
if err != nil {
t.Fatalf("unable to generate key: %v",
err)
return
}
req.BlindingPoint = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[tlv.TlvType0](
pubkey,
),
)
}
v[0] = reflect.ValueOf(*req)
},
}
// With the above types defined, we'll now generate a slice of

View File

@ -3,6 +3,9 @@ package lnwire
import (
"bytes"
"io"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/tlv"
)
// OnionPacketSize is the size of the serialized Sphinx onion packet included
@ -11,6 +14,17 @@ import (
// of per-hop data, and a 32-byte HMAC over the entire packet.
const OnionPacketSize = 1366
type (
// BlindingPointTlvType is the type for ephemeral pubkeys used in
// route blinding.
BlindingPointTlvType = tlv.TlvType0
// BlindingPointRecord holds an optional blinding point on update add
// htlc.
//nolint:lll
BlindingPointRecord = tlv.OptionalRecordT[BlindingPointTlvType, *btcec.PublicKey]
)
// UpdateAddHTLC is the message sent by Alice to Bob when she wishes to add an
// HTLC to his remote commitment transaction. In addition to information
// detailing the value, the ID, expiry, and the onion blob is also included
@ -54,6 +68,10 @@ type UpdateAddHTLC struct {
// used in the subsequent UpdateAddHTLC message.
OnionBlob [OnionPacketSize]byte
// BlindingPoint is the ephemeral pubkey used to optionally blind the
// next hop for this htlc.
BlindingPoint BlindingPointRecord
// ExtraData is the set of data that was appended to this message to
// fill out the full maximum transport message size. These fields can
// be used to specify optional data such as custom TLV fields.
@ -74,7 +92,7 @@ var _ Message = (*UpdateAddHTLC)(nil)
//
// This is part of the lnwire.Message interface.
func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
return ReadElements(r,
if err := ReadElements(r,
&c.ChanID,
&c.ID,
&c.Amount,
@ -82,7 +100,27 @@ func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
&c.Expiry,
c.OnionBlob[:],
&c.ExtraData,
)
); err != nil {
return err
}
blindingRecord := c.BlindingPoint.Zero()
tlvMap, err := c.ExtraData.ExtractRecords(&blindingRecord)
if err != nil {
return err
}
if val, ok := tlvMap[c.BlindingPoint.TlvType()]; ok && val == nil {
c.BlindingPoint = tlv.SomeRecordT(blindingRecord)
}
// Set extra data to nil if we didn't parse anything out of it so that
// we can use assert.Equal in tests.
if len(tlvMap) == 0 {
c.ExtraData = nil
}
return nil
}
// Encode serializes the target UpdateAddHTLC into the passed io.Writer
@ -114,6 +152,20 @@ func (c *UpdateAddHTLC) Encode(w *bytes.Buffer, pver uint32) error {
return err
}
// Only include blinding point in extra data if present.
var records []tlv.RecordProducer
c.BlindingPoint.WhenSome(func(b tlv.RecordT[BlindingPointTlvType,
*btcec.PublicKey]) {
records = append(records, &b)
})
err := EncodeMessageExtraData(&c.ExtraData, records...)
if err != nil {
return err
}
return WriteBytes(w, c.ExtraData)
}

View File

@ -45,6 +45,7 @@ import (
"github.com/lightningnetwork/lnd/queue"
"github.com/lightningnetwork/lnd/subscribe"
"github.com/lightningnetwork/lnd/ticker"
"github.com/lightningnetwork/lnd/tlv"
"github.com/lightningnetwork/lnd/watchtower/wtclient"
)
@ -1985,8 +1986,19 @@ func messageSummary(msg lnwire.Message) string {
msg.FeeSatoshis)
case *lnwire.UpdateAddHTLC:
return fmt.Sprintf("chan_id=%v, id=%v, amt=%v, expiry=%v, hash=%x",
msg.ChanID, msg.ID, msg.Amount, msg.Expiry, msg.PaymentHash[:])
var blindingPoint []byte
msg.BlindingPoint.WhenSome(
func(b tlv.RecordT[lnwire.BlindingPointTlvType,
*btcec.PublicKey]) {
blindingPoint = b.Val.SerializeCompressed()
},
)
return fmt.Sprintf("chan_id=%v, id=%v, amt=%v, expiry=%v, "+
"hash=%x, blinding_point=%x", msg.ChanID, msg.ID,
msg.Amount, msg.Expiry, msg.PaymentHash[:],
blindingPoint)
case *lnwire.UpdateFailHTLC:
return fmt.Sprintf("chan_id=%v, id=%v, reason=%x", msg.ChanID,