Merge pull request #8735 from ellemouton/rb-receives

[2/4] Route Blinding Receives: Receive and send to a single blinded path in an invoice.
This commit is contained in:
Olaoluwa Osuntokun
2024-07-29 19:00:06 -07:00
committed by GitHub
49 changed files with 5634 additions and 1884 deletions

View File

@ -75,6 +75,7 @@ import (
"github.com/lightningnetwork/lnd/peernotifier"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/routing/blindedpath"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/rpcperms"
"github.com/lightningnetwork/lnd/signal"
@ -5104,6 +5105,7 @@ type rpcPaymentIntent struct {
paymentAddr *[32]byte
payReq []byte
metadata []byte
blindedPayment *routing.BlindedPayment
destCustomRecords record.CustomSet
@ -5239,6 +5241,32 @@ func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPayme
payIntent.paymentAddr = payReq.PaymentAddr
payIntent.metadata = payReq.Metadata
if len(payReq.BlindedPaymentPaths) > 0 {
// NOTE: Currently we only choose a single payment path.
// This will be updated in a future PR to handle
// multiple blinded payment paths.
path := payReq.BlindedPaymentPaths[0]
if len(path.Hops) == 0 {
return payIntent, fmt.Errorf("a blinded " +
"payment must have at least 1 hop")
}
finalHop := path.Hops[len(path.Hops)-1]
payIntent.blindedPayment =
routerrpc.MarshalBlindedPayment(path)
// Replace the target node with the blinded public key
// of the blinded path's final node.
copy(
payIntent.dest[:],
finalHop.BlindedNodePub.SerializeCompressed(),
)
if !payReq.BlindedPaymentPaths[0].Features.IsEmpty() {
payIntent.destFeatures = path.Features.Clone()
}
}
if err := validateDest(payIntent.dest); err != nil {
return payIntent, err
}
@ -5393,6 +5421,7 @@ func (r *rpcServer) dispatchPaymentIntent(
DestFeatures: payIntent.destFeatures,
PaymentAddr: payIntent.paymentAddr,
Metadata: payIntent.metadata,
BlindedPayment: payIntent.blindedPayment,
// Don't enable multi-part payments on the main rpc.
// Users need to use routerrpc for that.
@ -5737,6 +5766,13 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
defaultDelta := r.cfg.Bitcoin.TimeLockDelta
blindingRestrictions := &routing.BlindedPathRestrictions{
MinDistanceFromIntroNode: r.server.cfg.Routing.BlindedPaths.
MinNumRealHops,
NumHops: r.server.cfg.Routing.BlindedPaths.NumHops,
MaxNumPaths: r.server.cfg.Routing.BlindedPaths.MaxNumPaths,
}
addInvoiceCfg := &invoicesrpc.AddInvoiceConfig{
AddInvoice: r.server.invoices.AddInvoice,
IsChannelActive: r.server.htlcSwitch.HasActiveLink,
@ -5746,12 +5782,56 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
ChanDB: r.server.chanStateDB,
Graph: r.server.graphDB,
GenInvoiceFeatures: func() *lnwire.FeatureVector {
return r.server.featureMgr.Get(feature.SetInvoice)
v := r.server.featureMgr.Get(feature.SetInvoice)
if invoice.Blind {
// If an invoice includes blinded paths, then a
// payment address is not required since we use
// the PathID in the final hop's encrypted data
// as equivalent to the payment address
v.Unset(lnwire.PaymentAddrRequired)
v.Set(lnwire.PaymentAddrOptional)
// The invoice payer will also need to
// understand the new BOLT 11 tagged field
// containing the blinded path, so we switch
// the bit to required.
v.Unset(lnwire.Bolt11BlindedPathsOptional)
v.Set(lnwire.Bolt11BlindedPathsRequired)
}
return v
},
GenAmpInvoiceFeatures: func() *lnwire.FeatureVector {
return r.server.featureMgr.Get(feature.SetInvoiceAmp)
},
GetAlias: r.server.aliasMgr.GetPeerAlias,
GetAlias: r.server.aliasMgr.GetPeerAlias,
BestHeight: r.server.cc.BestBlockTracker.BestHeight,
BlindedRoutePolicyIncrMultiplier: r.server.cfg.Routing.
BlindedPaths.PolicyIncreaseMultiplier,
BlindedRoutePolicyDecrMultiplier: r.server.cfg.Routing.
BlindedPaths.PolicyDecreaseMultiplier,
QueryBlindedRoutes: func(amt lnwire.MilliSatoshi) (
[]*route.Route, error) {
return r.server.chanRouter.FindBlindedPaths(
r.selfNode, amt,
r.server.missionControl.GetProbability,
blindingRestrictions,
)
},
MinNumBlindedPathHops: r.server.cfg.Routing.BlindedPaths.
NumHops,
DefaultDummyHopPolicy: &blindedpath.BlindedHopPolicy{
CLTVExpiryDelta: uint16(defaultDelta),
FeeRate: uint32(r.server.cfg.Bitcoin.FeeRate),
BaseFee: r.server.cfg.Bitcoin.BaseFee,
MinHTLCMsat: r.server.cfg.Bitcoin.MinHTLCIn,
// MaxHTLCMsat will be calculated on the fly by using
// the introduction node's channel's capacities.
MaxHTLCMsat: 0,
},
}
value, err := lnrpc.UnmarshallAmt(invoice.Value, invoice.ValueMsat)
@ -5774,6 +5854,7 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
Private: invoice.Private,
RouteHints: routeHints,
Amp: invoice.IsAmp,
Blind: invoice.Blind,
}
if invoice.RPreimage != nil {