Skip to content

Commit

Permalink
preliminary commit to check CI.
Browse files Browse the repository at this point in the history
  • Loading branch information
ziggie1984 committed Dec 3, 2024
1 parent fd31bbc commit 28168e0
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 65 deletions.
6 changes: 3 additions & 3 deletions input/script_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ var (
SequenceLockTimeSeconds = uint32(1 << 22)
)

// mustParsePubKey parses a hex encoded public key string into a public key and
// MustParsePubKey parses a hex encoded public key string into a public key and
// panic if parsing fails.
func mustParsePubKey(pubStr string) btcec.PublicKey {
func MustParsePubKey(pubStr string) btcec.PublicKey {
pubBytes, err := hex.DecodeString(pubStr)
if err != nil {
panic(err)
Expand All @@ -55,7 +55,7 @@ var (
// https://github.com/lightninglabs/lightning-node-connect/tree/
// master/mailbox/numsgen, with the seed phrase "Lightning Simple
// Taproot".
TaprootNUMSKey = mustParsePubKey(TaprootNUMSHex)
TaprootNUMSKey = MustParsePubKey(TaprootNUMSHex)
)

// Signature is an interface for objects that can populate signatures during
Expand Down
80 changes: 50 additions & 30 deletions routing/blinding.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package routing

import (
"bytes"
"errors"
"fmt"

"github.com/btcsuite/btcd/btcec/v2"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)

// BlindedPathNUMSHex is the hex encoded version of the blinded path target
// NUMs key (in compressed format).
const BlindedPathNUMSHex = "02667a98ef82ecb522f803b17a74f14508a48b25258f9831" +
"dd6e95f5e299dfd54e"

var (
// ErrNoBlindedPath is returned when the blinded path in a blinded
// payment is missing.
Expand All @@ -25,6 +31,13 @@ var (
// ErrHTLCRestrictions is returned when a blinded path has invalid
// HTLC maximum and minimum values.
ErrHTLCRestrictions = errors.New("invalid htlc minimum and maximum")

// BlindedPathNUMSKey is a NUMS key (nothing up my sleeves number) that
// has no known private key. This was generated using the following
// script:
// https://github.com/lightninglabs/lightning-node-connect/tree/master/
// mailbox/numsgen, with the seed phrase "Lightning Blinded Path".
BlindedPathNUMSKey = input.MustParsePubKey(BlindedPathNUMSHex)
)

// BlindedPaymentPathSet groups the data we need to handle sending to a set of
Expand Down Expand Up @@ -103,13 +116,9 @@ func NewBlindedPaymentPathSet(paths []*BlindedPayment) (*BlindedPaymentPathSet,
}
}

// Derive an ephemeral target priv key that will be injected into each
// blinded path final hop.
targetPriv, err := btcec.NewPrivateKey()
if err != nil {
return nil, err
}
targetPub := targetPriv.PubKey()
// For blinded paths we use the NUMS key as a target if the blinded
// path has more hops than just the introduction node.
targetPub := &BlindedPathNUMSKey

var (
pathSet = paths
Expand All @@ -124,15 +133,33 @@ func NewBlindedPaymentPathSet(paths []*BlindedPayment) (*BlindedPaymentPathSet,
// replacement, so our target pub key in this case just remains the
// real introduction node ID.
for _, path := range paths {
if len(path.BlindedPath.BlindedHops) != 1 {
continue
}
pathLength := len(path.BlindedPath.BlindedHops)

pathSet = []*BlindedPayment{path}
finalCLTVDelta = path.CltvExpiryDelta
targetPub = path.BlindedPath.IntroductionPoint
if pathLength == 1 {
pathSet = []*BlindedPayment{path}
finalCLTVDelta = path.CltvExpiryDelta
targetPub = path.BlindedPath.IntroductionPoint

break
}

break
// We add a dummy hop to the end of the path so that
// we can do MPP path finding taking all the blinded
// routes into account. Moreover we need to use a
// dummy hop here because we still want to be able to
// penalize the last hop in case the payment fails.
// We need to set the cipher text because it is used for the
// payload size estimation.
lastHopCipherText := path.BlindedPath.BlindedHops[pathLength-1].
CipherText

path.BlindedPath.BlindedHops = append(
path.BlindedPath.BlindedHops,
&sphinx.BlindedHopInfo{
BlindedNodePub: &BlindedPathNUMSKey,
CipherText: lastHopCipherText,
},
)
}

return &BlindedPaymentPathSet{
Expand Down Expand Up @@ -222,7 +249,7 @@ func (s *BlindedPaymentPathSet) ToRouteHints() (RouteHints, error) {
hints := make(RouteHints)

for _, path := range s.paths {
pathHints, err := path.toRouteHints(fn.Some(s.targetPubKey))
pathHints, err := path.toRouteHints()
if err != nil {
return nil, err
}
Expand All @@ -239,6 +266,12 @@ func (s *BlindedPaymentPathSet) ToRouteHints() (RouteHints, error) {
return hints, nil
}

// isBlindedRouteNUMSTargetKey returns true if the given public key is the
// NUMS key used as a target for blinded path final hops.
func isBlindedRouteNUMSTargetKey(pk []byte) bool {
return bytes.Equal(pk, BlindedPathNUMSKey.SerializeCompressed())
}

// BlindedPayment provides the path and payment parameters required to send a
// payment along a blinded path.
type BlindedPayment struct {
Expand Down Expand Up @@ -303,9 +336,7 @@ func (b *BlindedPayment) Validate() error {
// hints (both for intermediate hops and the final_cltv_delta for the receiving
// node). The pseudoTarget, if provided, will be used to override the pub key
// of the destination node in the path.
func (b *BlindedPayment) toRouteHints(
pseudoTarget fn.Option[*btcec.PublicKey]) (RouteHints, error) {

func (b *BlindedPayment) toRouteHints() (RouteHints, error) {
// If we just have a single hop in our blinded route, it just contains
// an introduction node (this is a valid path according to the spec).
// Since we have the un-blinded node ID for the introduction node, we
Expand Down Expand Up @@ -393,16 +424,5 @@ func (b *BlindedPayment) toRouteHints(
hints[fromNode] = []AdditionalEdge{lastEdge}
}

pseudoTarget.WhenSome(func(key *btcec.PublicKey) {
// For the very last hop on the path, switch out the ToNodePub
// for the pseudo target pub key.
lastEdge.policy.ToNodePubKey = func() route.Vertex {
return route.NewVertex(key)
}

// Then override the final hint with this updated edge.
hints[fromNode] = []AdditionalEdge{lastEdge}
})

return hints, nil
}
5 changes: 2 additions & 3 deletions routing/blinding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/btcsuite/btcd/btcec/v2"
sphinx "github.com/lightningnetwork/lightning-onion"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
Expand Down Expand Up @@ -129,7 +128,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)

Expand Down Expand Up @@ -184,7 +183,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))
Expand Down
29 changes: 20 additions & 9 deletions routing/pathfind.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,26 @@ func newRoute(sourceVertex route.Vertex,
)

pathLength := len(pathEdges)

for _, edge := range pathEdges {
log.Debugf("edge: %v", edge.policy.ToNodePubKey())
}

// When paying to a blinded route we might have appened a dummy hop at
// the end to make MPP payment possible via the whole path. Before
// sending out the onion payload we make sure we remove this hop again.
if blindedPathSet != nil && pathLength > 1 {
finalBlinedPubKey := pathEdges[pathLength-2].policy.
ToNodePubKey()

if isBlindedRouteNUMSTargetKey(finalBlinedPubKey[:]) {
// If the last hop is the NUMS key for blinded paths, we
// remove the dummy hop from the route.
pathEdges = pathEdges[:pathLength-1]
pathLength--
}
}

for i := pathLength - 1; i >= 0; i-- {
// Now we'll start to calculate the items within the per-hop
// payload for the hop this edge is leading to.
Expand Down Expand Up @@ -319,10 +339,6 @@ func newRoute(sourceVertex route.Vertex,
dataIndex = 0

blindedPath = blindedPayment.BlindedPath
numHops = len(blindedPath.BlindedHops)
realFinal = blindedPath.BlindedHops[numHops-1].
BlindedNodePub

introVertex = route.NewVertex(
blindedPath.IntroductionPoint,
)
Expand Down Expand Up @@ -350,11 +366,6 @@ func newRoute(sourceVertex route.Vertex,
if i != len(hops)-1 {
hop.AmtToForward = 0
hop.OutgoingTimeLock = 0
} else {
// For the final hop, we swap out the pub key
// bytes to the original destination node pub
// key for that payment path.
hop.PubKeyBytes = route.NewVertex(realFinal)
}

dataIndex++
Expand Down
8 changes: 2 additions & 6 deletions routing/pathfind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1336,9 +1336,7 @@ func runPathFindingWithBlindedPathDuplicateHop(t *testing.T, useCache bool) {
CltvExpiryDelta: 140,
}

blindedPath, err := blindedPayment.toRouteHints(
fn.None[*btcec.PublicKey](),
)
blindedPath, err := blindedPayment.toRouteHints()
require.NoError(t, err)

find := func(r *RestrictParams) (
Expand Down Expand Up @@ -3380,9 +3378,7 @@ func TestBlindedRouteConstruction(t *testing.T) {
// that make up the graph we'll give to route construction. The hints
// map is keyed by source node, so we can retrieve our blinded edges
// accordingly.
blindedEdges, err := blindedPayment.toRouteHints(
fn.None[*btcec.PublicKey](),
)
blindedEdges, err := blindedPayment.toRouteHints()
require.NoError(t, err)

carolDaveEdge := blindedEdges[carolVertex][0]
Expand Down
24 changes: 12 additions & 12 deletions routing/result_interpretation.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,25 +517,25 @@ func (i *interpretedResult) processPaymentOutcomeIntermediate(route *mcRoute,
if introIdx == len(route.hops.Val)-1 {
i.finalFailureReason = &reasonError
} else {
// Penalize the first hop after the introduction node.
// This makes sure we do not retry this blinded path
// in our path finding logic with the same amount.
// In the pathfinding logic for blinded routes we swap
// the target pubkey for a general one so that
// multi-path payment can be attempted, so the last
// hop is not the one that we are considering during
// pathfinding. The case where the next hop after the
// introduction node is the final recipient is handled
// above, where we punish nothing but abort the payment
// by reporting a final failure reason.
// We penalize the final hop of the blinded route which
// is sufficient to not reuse this route again and is
// also more memory efficient because the other hops
// of the blinded path are ephemeral and will only be
// used in conjunction with the final hop. Moreover we
// don't want to punish the introduction node because
// the blinded failure does not necessarily mean that
// the introduction node was at fault. Penalizing the
// final hop does work here because we add a dummy hop
// when sending to a blinded route so that we can be
// sure this MC data is considered during path finding.
//
// TODO(ziggie): Make sure we only keep mc data for
// blinded paths, in both the success and failure case,
// in memory during the time of the payment and remove
// it afterwards. Blinded paths and their blinded hop
// keys are always changing per blinded route so there
// is no point in persisting this data.
i.failPairBalance(route, introIdx)
i.failPairBalance(route, len(route.hops.Val)-1)
}

// In all other cases, we penalize the reporting node. These are all
Expand Down
4 changes: 2 additions & 2 deletions routing/result_interpretation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ var resultTestCases = []resultTestCase{
pairResults: map[DirectedNodePair]pairResult{
getTestPair(0, 1): successPairResult(100),
getTestPair(1, 2): successPairResult(99),
getTestPair(2, 3): failPairResult(95),
getTestPair(3, 4): failPairResult(88),
},
},
},
Expand All @@ -567,7 +567,7 @@ var resultTestCases = []resultTestCase{
expectedResult: &interpretedResult{
pairResults: map[DirectedNodePair]pairResult{
getTestPair(0, 1): successPairResult(100),
getTestPair(1, 2): failPairResult(90),
getTestPair(2, 3): failPairResult(75),
},
},
},
Expand Down

0 comments on commit 28168e0

Please sign in to comment.