routing: Use NUMS point for blinded paths

To be able to do MPP payment to multiple blinded routes we need
to add a constant dummy hop as a final hop to every blined path.
This is used when sending or querying a blinded path, to let the
pathfinder be able to send MPP payments over different blinded
routes. For this dummy final hop we use a NUMS key so that we
are sure no other node can use this blinded pubkey either in a
normal or blinded route.
Moreover this helps us handling the mission control data for
blinded paths correctly because we always consider the blinded
pubkey pairs which are registered with mission control when
a payment to a blinded path fails.
This commit is contained in:
ziggie
2024-12-09 22:08:43 +01:00
parent df30b481c6
commit e47024b790
4 changed files with 259 additions and 60 deletions

View File

@@ -2,11 +2,11 @@ package routing
import (
"bytes"
"reflect"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
@@ -129,7 +129,7 @@ func TestBlindedPaymentToHints(t *testing.T) {
HtlcMaximum: htlcMax,
Features: features,
}
hints, err := blindedPayment.toRouteHints(fn.None[*btcec.PublicKey]())
hints, err := blindedPayment.toRouteHints()
require.NoError(t, err)
require.Nil(t, hints)
@@ -184,7 +184,7 @@ func TestBlindedPaymentToHints(t *testing.T) {
},
}
actual, err := blindedPayment.toRouteHints(fn.None[*btcec.PublicKey]())
actual, err := blindedPayment.toRouteHints()
require.NoError(t, err)
require.Equal(t, len(expected), len(actual))
@@ -218,3 +218,63 @@ func TestBlindedPaymentToHints(t *testing.T) {
require.Equal(t, expectedHint[0], actualHint[0])
}
}
// TestBlindedPaymentDeepCopy tests the deep copy method of the BLindedPayment
// struct.
//
// TODO(ziggie): Make this a property test instead.
func TestBlindedPaymentDeepCopy(t *testing.T) {
_, pkBlind1 := btcec.PrivKeyFromBytes([]byte{1})
_, blindingPoint := btcec.PrivKeyFromBytes([]byte{2})
_, pkBlind2 := btcec.PrivKeyFromBytes([]byte{3})
// Create a test BlindedPayment with non-nil fields
original := &BlindedPayment{
BaseFee: 1000,
ProportionalFeeRate: 2000,
CltvExpiryDelta: 144,
HtlcMinimum: 1000,
HtlcMaximum: 1000000,
Features: lnwire.NewFeatureVector(nil, nil),
BlindedPath: &sphinx.BlindedPath{
IntroductionPoint: pkBlind1,
BlindingPoint: blindingPoint,
BlindedHops: []*sphinx.BlindedHopInfo{
{
BlindedNodePub: pkBlind2,
CipherText: []byte("test cipher"),
},
},
},
}
// Make a deep copy
cpyPayment := original.deepCopy()
// Test 1: Verify the copy is not the same pointer
if cpyPayment == original {
t.Fatal("deepCopy returned same pointer")
}
// Verify all fields are equal
if !reflect.DeepEqual(original, cpyPayment) {
t.Fatal("copy is not equal to original")
}
// Modify the copy and verify it doesn't affect the original
cpyPayment.BaseFee = 2000
cpyPayment.BlindedPath.BlindedHops[0].CipherText = []byte("modified")
require.NotEqual(t, original.BaseFee, cpyPayment.BaseFee)
require.NotEqual(
t,
original.BlindedPath.BlindedHops[0].CipherText,
cpyPayment.BlindedPath.BlindedHops[0].CipherText,
)
// Verify nil handling.
var nilPayment *BlindedPayment
nilCopy := nilPayment.deepCopy()
require.Nil(t, nilCopy)
}