mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-01 18:27:43 +02:00
multi: Fix final hop payload size for AMP payments.
This commit is contained in:
@@ -104,6 +104,10 @@ func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest,
|
|||||||
// expect an extra invoice to appear in the ListInvoices response, since
|
// expect an extra invoice to appear in the ListInvoices response, since
|
||||||
// a new invoice will be JIT inserted under a different payment address
|
// a new invoice will be JIT inserted under a different payment address
|
||||||
// than the one in the invoice.
|
// than the one in the invoice.
|
||||||
|
//
|
||||||
|
// NOTE: This will only work when the peer has spontaneous AMP payments
|
||||||
|
// enabled otherwise no invoice under a different payment_addr will be
|
||||||
|
// found.
|
||||||
var (
|
var (
|
||||||
expNumInvoices = 1
|
expNumInvoices = 1
|
||||||
externalPayAddr []byte
|
externalPayAddr []byte
|
||||||
|
@@ -967,6 +967,9 @@ func (r *RouterBackend) extractIntentFromSendRequest(
|
|||||||
// pseudo-reusable, e.g. the invoice parameters are
|
// pseudo-reusable, e.g. the invoice parameters are
|
||||||
// reused (amt, cltv, hop hints, etc) even though the
|
// reused (amt, cltv, hop hints, etc) even though the
|
||||||
// payments will share different payment hashes.
|
// payments will share different payment hashes.
|
||||||
|
//
|
||||||
|
// NOTE: This will only work when the peer has
|
||||||
|
// spontaneous AMP payments enabled.
|
||||||
if len(rpcPayReq.PaymentAddr) > 0 {
|
if len(rpcPayReq.PaymentAddr) > 0 {
|
||||||
var addr [32]byte
|
var addr [32]byte
|
||||||
copy(addr[:], rpcPayReq.PaymentAddr)
|
copy(addr[:], rpcPayReq.PaymentAddr)
|
||||||
|
@@ -19,6 +19,16 @@ type AMP struct {
|
|||||||
childIndex uint32
|
childIndex uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MaxAmpPayLoadSize is an AMP Record which when serialized to a tlv record uses
|
||||||
|
// the maximum payload size. The `childIndex` is created randomly and is a
|
||||||
|
// 4 byte `varint` type so we make sure we use an index which will be encoded in
|
||||||
|
// 4 bytes.
|
||||||
|
var MaxAmpPayLoadSize = AMP{
|
||||||
|
rootShare: [32]byte{},
|
||||||
|
setID: [32]byte{},
|
||||||
|
childIndex: 0x80000000,
|
||||||
|
}
|
||||||
|
|
||||||
// NewAMP generate a new AMP record with the given root_share, set_id, and
|
// NewAMP generate a new AMP record with the given root_share, set_id, and
|
||||||
// child_index.
|
// child_index.
|
||||||
func NewAMP(rootShare, setID [32]byte, childIndex uint32) *AMP {
|
func NewAMP(rootShare, setID [32]byte, childIndex uint32) *AMP {
|
||||||
|
@@ -408,6 +408,11 @@ type RestrictParams struct {
|
|||||||
// invoices.
|
// invoices.
|
||||||
PaymentAddr *[32]byte
|
PaymentAddr *[32]byte
|
||||||
|
|
||||||
|
// Amp signals to the pathfinder that this payment is an AMP payment
|
||||||
|
// and therefore it needs to account for additional AMP data in the
|
||||||
|
// final hop payload size calculation.
|
||||||
|
Amp *AMPOptions
|
||||||
|
|
||||||
// Metadata is additional data that is sent along with the payment to
|
// Metadata is additional data that is sent along with the payment to
|
||||||
// the payee.
|
// the payee.
|
||||||
Metadata []byte
|
Metadata []byte
|
||||||
@@ -1134,12 +1139,21 @@ func lastHopPayloadSize(r *RestrictParams, finalHtlcExpiry int32,
|
|||||||
mpp = record.NewMPP(amount, *r.PaymentAddr)
|
mpp = record.NewMPP(amount, *r.PaymentAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var amp *record.AMP
|
||||||
|
if r.Amp != nil {
|
||||||
|
// The AMP payload is not easy accessible at this point but we
|
||||||
|
// are only interested in the size of the payload so we just use
|
||||||
|
// the AMP record dummy.
|
||||||
|
amp = &record.MaxAmpPayLoadSize
|
||||||
|
}
|
||||||
|
|
||||||
finalHop := route.Hop{
|
finalHop := route.Hop{
|
||||||
AmtToForward: amount,
|
AmtToForward: amount,
|
||||||
OutgoingTimeLock: uint32(finalHtlcExpiry),
|
OutgoingTimeLock: uint32(finalHtlcExpiry),
|
||||||
CustomRecords: r.DestCustomRecords,
|
CustomRecords: r.DestCustomRecords,
|
||||||
LegacyPayload: legacy,
|
LegacyPayload: legacy,
|
||||||
MPP: mpp,
|
MPP: mpp,
|
||||||
|
AMP: amp,
|
||||||
Metadata: r.Metadata,
|
Metadata: r.Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3469,6 +3469,7 @@ func TestLastHopPayloadSize(t *testing.T) {
|
|||||||
)
|
)
|
||||||
_, blindedPoint = btcec.PrivKeyFromBytes([]byte{5})
|
_, blindedPoint = btcec.PrivKeyFromBytes([]byte{5})
|
||||||
paymentAddr = &[32]byte{1}
|
paymentAddr = &[32]byte{1}
|
||||||
|
ampOptions = &Options{}
|
||||||
amtToForward = lnwire.MilliSatoshi(10000)
|
amtToForward = lnwire.MilliSatoshi(10000)
|
||||||
finalHopExpiry int32 = 144
|
finalHopExpiry int32 = 144
|
||||||
|
|
||||||
@@ -3510,6 +3511,7 @@ func TestLastHopPayloadSize(t *testing.T) {
|
|||||||
PaymentAddr: paymentAddr,
|
PaymentAddr: paymentAddr,
|
||||||
DestCustomRecords: customRecords,
|
DestCustomRecords: customRecords,
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
|
Amp: ampOptions,
|
||||||
},
|
},
|
||||||
amount: amtToForward,
|
amount: amtToForward,
|
||||||
finalHopExpiry: finalHopExpiry,
|
finalHopExpiry: finalHopExpiry,
|
||||||
@@ -3524,6 +3526,7 @@ func TestLastHopPayloadSize(t *testing.T) {
|
|||||||
PaymentAddr: paymentAddr,
|
PaymentAddr: paymentAddr,
|
||||||
DestCustomRecords: customRecords,
|
DestCustomRecords: customRecords,
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
|
Amp: ampOptions,
|
||||||
},
|
},
|
||||||
amount: amtToForward,
|
amount: amtToForward,
|
||||||
finalHopExpiry: finalHopExpiry,
|
finalHopExpiry: finalHopExpiry,
|
||||||
@@ -3560,6 +3563,13 @@ func TestLastHopPayloadSize(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case it's an AMP payment we use the max AMP record
|
||||||
|
// size to estimate the final hop size.
|
||||||
|
var amp *record.AMP
|
||||||
|
if tc.restrictions.Amp != nil {
|
||||||
|
amp = &record.MaxAmpPayLoadSize
|
||||||
|
}
|
||||||
|
|
||||||
var finalHop route.Hop
|
var finalHop route.Hop
|
||||||
if tc.restrictions.BlindedPayment != nil {
|
if tc.restrictions.BlindedPayment != nil {
|
||||||
blindedPath := tc.restrictions.BlindedPayment.
|
blindedPath := tc.restrictions.BlindedPayment.
|
||||||
@@ -3586,6 +3596,7 @@ func TestLastHopPayloadSize(t *testing.T) {
|
|||||||
OutgoingTimeLock: uint32(tc.finalHopExpiry),
|
OutgoingTimeLock: uint32(tc.finalHopExpiry),
|
||||||
Metadata: tc.restrictions.Metadata,
|
Metadata: tc.restrictions.Metadata,
|
||||||
MPP: mpp,
|
MPP: mpp,
|
||||||
|
AMP: amp,
|
||||||
CustomRecords: tc.restrictions.DestCustomRecords,
|
CustomRecords: tc.restrictions.DestCustomRecords,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -628,7 +628,7 @@ func (p *paymentLifecycle) createNewPaymentAttempt(rt *route.Route,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// It this shard carries MPP or AMP options, add them to the last hop
|
// If this shard carries MPP or AMP options, add them to the last hop
|
||||||
// on the route.
|
// on the route.
|
||||||
hop := rt.Hops[len(rt.Hops)-1]
|
hop := rt.Hops[len(rt.Hops)-1]
|
||||||
if shard.MPP() != nil {
|
if shard.MPP() != nil {
|
||||||
|
@@ -258,6 +258,7 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
|
|||||||
DestCustomRecords: p.payment.DestCustomRecords,
|
DestCustomRecords: p.payment.DestCustomRecords,
|
||||||
DestFeatures: p.payment.DestFeatures,
|
DestFeatures: p.payment.DestFeatures,
|
||||||
PaymentAddr: p.payment.PaymentAddr,
|
PaymentAddr: p.payment.PaymentAddr,
|
||||||
|
Amp: p.payment.amp,
|
||||||
Metadata: p.payment.Metadata,
|
Metadata: p.payment.Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user