invoicerpc: Allow user specify routing hints.

This commit is contained in:
Roei Erez authored and Roei Erez committed 2020-11-06 17:54:20 +02:00
1 parent 1c96cc7e10
commit 4463a4ce17
5 files changed
+141 -2

No files matched your search

+37 -2
View File
@@ -94,6 +94,10 @@ type AddInvoiceData struct {
// HodlInvoice signals that this invoice shouldn't be settled
// immediately upon receiving the payment.
HodlInvoice bool
// RouteHints are optional route hints that can each be individually used
// to assist in reaching the invoice's destination.
RouteHints [][]zpay32.HopHint
}
// AddInvoice attempts to add a new invoice to the invoice database. Any
@@ -246,6 +250,27 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta)))
}
// We make sure that the given invoice routing hints number is within the
// valid range
if len(invoice.RouteHints) > 20 {
return nil, nil, fmt.Errorf("number of routing hints must not exceed " +
"maximum of 20")
}
// We continue by populating the requested routing hints indexing their
// corresponding channels so we won't duplicate them.
forcedHints := make(map[uint64]struct{})
for _, h := range invoice.RouteHints {
if len(h) == 0 {
return nil, nil, fmt.Errorf("number of hop hint within a route must " +
"be positive")
}
options = append(options, zpay32.RouteHint(h))
// Only this first hop is our direct channel.
forcedHints[h[0].ChannelID] = struct{}{}
}
// If we were requested to include routing hints in the invoice, then
// we'll fetch all of our available private channels and create routing
// hints for them.
@@ -256,11 +281,21 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
}
if len(openChannels) > 0 {
// We filter the channels by excluding the ones that were specified by
// the caller and were already added.
var filteredChannels []*channeldb.OpenChannel
for _, c := range openChannels {
if _, ok := forcedHints[c.ShortChanID().ToUint64()]; ok {
continue
}
filteredChannels = append(filteredChannels, c)
}
// We'll restrict the number of individual route hints
// to 20 to avoid creating overly large invoices.
const numMaxHophints = 20
numMaxHophints := 20 - len(forcedHints)
hopHints := selectHopHints(
amtMSat, cfg, openChannels, numMaxHophints,
amtMSat, cfg, filteredChannels, numMaxHophints,
)
options = append(options, hopHints...)
+6
View File
@@ -289,6 +289,11 @@ func (s *Server) AddHoldInvoice(ctx context.Context,
return nil, err
}
// Convert the passed routing hints to the required format.
routeHints, err := CreateZpay32HopHints(invoice.RouteHints)
if err != nil {
return nil, err
}
addInvoiceData := &AddInvoiceData{
Memo: invoice.Memo,
Hash: &hash,
@@ -300,6 +305,7 @@ func (s *Server) AddHoldInvoice(ctx context.Context,
Private: invoice.Private,
HodlInvoice: true,
Preimage: nil,
RouteHints: routeHints,
}
_, dbInvoice, err := AddInvoice(ctx, addInvoiceCfg, addInvoiceData)
+29
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnrpc"
@@ -204,3 +205,31 @@ func CreateRPCRouteHints(routeHints [][]zpay32.HopHint) []*lnrpc.RouteHint {
return res
}
// CreateZpay32HopHints takes in the lnrpc form of route hints and converts them
// into an invoice decoded form.
func CreateZpay32HopHints(routeHints []*lnrpc.RouteHint) ([][]zpay32.HopHint, error) {
var res [][]zpay32.HopHint
for _, route := range routeHints {
hopHints := make([]zpay32.HopHint, 0, len(route.HopHints))
for _, hop := range route.HopHints {
pubKeyBytes, err := hex.DecodeString(hop.NodeId)
if err != nil {
return nil, err
}
p, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256())
if err != nil {
return nil, err
}
hopHints = append(hopHints, zpay32.HopHint{
NodeID: p,
ChannelID: hop.ChanId,
FeeBaseMSat: hop.FeeBaseMsat,
FeeProportionalMillionths: hop.FeeProportionalMillionths,
CLTVExpiryDelta: uint16(hop.CltvExpiryDelta),
})
}
res = append(res, hopHints)
}
return res, nil
}