Skip to content

Commit

Permalink
multi: report blinded path receives to Mission Control
Browse files Browse the repository at this point in the history
in the new "blinded-paths" namespace.
  • Loading branch information
ellemouton committed Aug 15, 2024
1 parent f23b847 commit 0eb2638
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 20 deletions.
5 changes: 5 additions & 0 deletions invoices/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"time"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/lntypes"
Expand Down Expand Up @@ -114,6 +115,10 @@ type Payload interface {
// TotalAmtMsat returns the total amount sent to the final hop, as set
// by the payee.
TotalAmtMsat() lnwire.MilliSatoshi

// BlindingPoint returns the route blinding point parsed from the onion
// payload.
BlindingPoint() *btcec.PublicKey
}

// InvoiceQuery represents a query to the invoice database. The query allows a
Expand Down
42 changes: 42 additions & 0 deletions invoices/invoiceregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import (
"sync/atomic"
"time"

"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/queue"
"github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route"
)

var (
Expand Down Expand Up @@ -74,6 +76,11 @@ type RegistryConfig struct {
// KeysendHoldTime indicates for how long we want to accept and hold
// spontaneous keysend payments.
KeysendHoldTime time.Duration

// ReportBlindedPathReceive can be used to indicate the successful
// receive along a chosen blinded path.
ReportBlindedPathReceive func(invoiceAddIndex uint64,
rt *models.MCRoute) error
}

// htlcReleaseEvent describes an htlc auto-release event. It is used to release
Expand Down Expand Up @@ -931,6 +938,7 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
metadata: payload.Metadata(),
pathID: payload.PathID(),
totalAmtMsat: payload.TotalAmtMsat(),
blindingPoint: payload.BlindingPoint(),
}

switch {
Expand Down Expand Up @@ -1024,9 +1032,13 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
var (
resolution HtlcResolution
updateSubscribers bool
blindedPath *models.BlindedPathInfo
addIndex uint64
)

callback := func(inv *Invoice) (*InvoiceUpdateDesc, error) {
addIndex = inv.AddIndex

updateDesc, res, err := updateInvoice(ctx, inv)
if err != nil {
return nil, err
Expand All @@ -1039,6 +1051,24 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
// Assign resolution to outer scope variable.
resolution = res

if ctx.blindingPoint == nil {
return updateDesc, nil
}

// If this invoice was created before we started persisting the
// blinded path info for an invoice, exit.
if inv.BlindedPaths == nil {
return updateDesc, nil
}

path, ok := inv.BlindedPaths[route.NewVertex(ctx.blindingPoint)]
if !ok {
return nil, fmt.Errorf("expected a blinding path " +
"matching the received ephemeral key")
}

blindedPath = path

return updateDesc, nil
}

Expand Down Expand Up @@ -1078,6 +1108,18 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
return nil, nil, err
}

if blindedPath != nil {
// Regardless of what we will do with the HTLC, we want to
// report to mission control that the blinded path route it
// chose successfully reached us.
err = i.cfg.ReportBlindedPathReceive(
addIndex, blindedPath.Route,
)
if err != nil {
return nil, nil, err
}
}

var invoiceToExpire invoiceExpiry

switch res := resolution.(type) {
Expand Down
4 changes: 4 additions & 0 deletions invoices/test_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ func (p *mockPayload) PathID() *chainhash.Hash {
return p.pathID
}

func (p *mockPayload) BlindingPoint() *btcec.PublicKey {
return nil
}

func (p *mockPayload) TotalAmtMsat() lnwire.MilliSatoshi {
return p.totalAmtMsat
}
Expand Down
2 changes: 2 additions & 0 deletions invoices/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/hex"
"errors"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/lightningnetwork/lnd/amp"
"github.com/lightningnetwork/lnd/lntypes"
Expand All @@ -27,6 +28,7 @@ type invoiceUpdateCtx struct {
metadata []byte
pathID *chainhash.Hash
totalAmtMsat lnwire.MilliSatoshi
blindingPoint *btcec.PublicKey
}

// invoiceRef returns an identifier that can be used to lookup or update the
Expand Down
4 changes: 3 additions & 1 deletion routing/missioncontrol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ func (ctx *mcTestContext) reportFailure(amt lnwire.MilliSatoshi,

// reportSuccess reports a success by using a test route.
func (ctx *mcTestContext) reportSuccess() {
err := ctx.mc.ReportPaymentSuccess(ctx.pid, mcTestRoute)
err := ctx.mc.ReportPaymentSuccess(
ctx.pid, mcTestRoute,
)
if err != nil {
ctx.t.Fatal(err)
}
Expand Down
47 changes: 28 additions & 19 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,17 +559,6 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
return nil, err
}

registryConfig := invoices.RegistryConfig{
FinalCltvRejectDelta: lncfg.DefaultFinalCltvRejectDelta,
HtlcHoldDuration: invoices.DefaultHtlcHoldDuration,
Clock: clock.NewDefaultClock(),
AcceptKeySend: cfg.AcceptKeySend,
AcceptAMP: cfg.AcceptAMP,
GcCanceledInvoicesOnStartup: cfg.GcCanceledInvoicesOnStartup,
GcCanceledInvoicesOnTheFly: cfg.GcCanceledInvoicesOnTheFly,
KeysendHoldTime: cfg.KeysendHoldTime,
}

s := &server{
cfg: cfg,
graphDB: dbs.GraphDB.ChannelGraph(),
Expand Down Expand Up @@ -628,14 +617,6 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
return nil, err
}

expiryWatcher := invoices.NewInvoiceExpiryWatcher(
clock.NewDefaultClock(), cfg.Invoices.HoldExpiryDelta,
uint32(currentHeight), currentHash, cc.ChainNotifier,
)
s.invoices = invoices.NewRegistry(
dbs.InvoiceDB, expiryWatcher, &registryConfig,
)

s.htlcNotifier = htlcswitch.NewHtlcNotifier(time.Now)

thresholdSats := btcutil.Amount(cfg.MaxFeeExposure)
Expand Down Expand Up @@ -950,6 +931,34 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
"default namespace: %w", err)
}

blindedPathMC, err := s.missionController.GetNamespacedStore(
"blinded-path",
)
if err != nil {
return nil, fmt.Errorf("can't create mission control in the "+
"blinded path namespace: %w", err)
}

registryConfig := invoices.RegistryConfig{
FinalCltvRejectDelta: lncfg.DefaultFinalCltvRejectDelta,
HtlcHoldDuration: invoices.DefaultHtlcHoldDuration,
Clock: clock.NewDefaultClock(),
AcceptKeySend: cfg.AcceptKeySend,
AcceptAMP: cfg.AcceptAMP,
GcCanceledInvoicesOnStartup: cfg.GcCanceledInvoicesOnStartup,
GcCanceledInvoicesOnTheFly: cfg.GcCanceledInvoicesOnTheFly,
KeysendHoldTime: cfg.KeysendHoldTime,
ReportBlindedPathReceive: blindedPathMC.ReportPaymentSuccess,
}

expiryWatcher := invoices.NewInvoiceExpiryWatcher(
clock.NewDefaultClock(), cfg.Invoices.HoldExpiryDelta,
uint32(currentHeight), currentHash, cc.ChainNotifier,
)
s.invoices = invoices.NewRegistry(
dbs.InvoiceDB, expiryWatcher, &registryConfig,
)

srvrLog.Debugf("Instantiating payment session source with config: "+
"AttemptCost=%v + %v%%, MinRouteProbability=%v",
int64(routingConfig.AttemptCost),
Expand Down

0 comments on commit 0eb2638

Please sign in to comment.