invoicesrpc: add HopHintInfo decoupling hop hint from channel internals

This commit is contained in:
carla committed 2022-01-27 15:09:18 +02:00
1 parent 8d3d8580f9
commit 56e83de9ef
1 file changed
+66 -22
+66 -22
View File
@@ -9,6 +9,7 @@ import (
"math" "math"
"time" "time"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
@@ -379,12 +380,21 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
if len(openChannels) > 0 { if len(openChannels) > 0 {
// We filter the channels by excluding the ones that were specified by // We filter the channels by excluding the ones that were specified by
// the caller and were already added. // the caller and were already added.
var filteredChannels []*channeldb.OpenChannel var filteredChannels []*HopHintInfo
for _, c := range openChannels { for _, c := range openChannels {
if _, ok := forcedHints[c.ShortChanID().ToUint64()]; ok { if _, ok := forcedHints[c.ShortChanID().ToUint64()]; ok {
continue continue
} }
filteredChannels = append(filteredChannels, c)
chanID := lnwire.NewChanIDFromOutPoint(
&c.FundingOutpoint,
)
isActive := cfg.IsChannelActive(chanID)
hopHintInfo := newHopHintInfo(c, isActive)
filteredChannels = append(
filteredChannels, hopHintInfo,
)
} }
// We'll restrict the number of individual route hints // We'll restrict the number of individual route hints
@@ -466,24 +476,20 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
// chanCanBeHopHint returns true if the target channel is eligible to be a hop // chanCanBeHopHint returns true if the target channel is eligible to be a hop
// hint. // hint.
func chanCanBeHopHint(channel *channeldb.OpenChannel, cfg *AddInvoiceConfig) ( func chanCanBeHopHint(channel *HopHintInfo, cfg *AddInvoiceConfig) (
*channeldb.ChannelEdgePolicy, bool) { *channeldb.ChannelEdgePolicy, bool) {
// Since we're only interested in our private channels, we'll skip // Since we're only interested in our private channels, we'll skip
// public ones. // public ones.
isPublic := channel.ChannelFlags&lnwire.FFAnnounceChannel != 0 if channel.IsPublic {
if isPublic {
return nil, false return nil, false
} }
// Make sure the channel is active. // Make sure the channel is active.
chanPoint := lnwire.NewChanIDFromOutPoint( if !channel.IsActive {
&channel.FundingOutpoint,
)
if !cfg.IsChannelActive(chanPoint) {
log.Debugf("Skipping channel %v due to not "+ log.Debugf("Skipping channel %v due to not "+
"being eligible to forward payments", "being eligible to forward payments",
chanPoint) channel.ShortChannelID)
return nil, false return nil, false
} }
@@ -493,7 +499,7 @@ func chanCanBeHopHint(channel *channeldb.OpenChannel, cfg *AddInvoiceConfig) (
// unadvertised, like in the case of a node only having private // unadvertised, like in the case of a node only having private
// channels. // channels.
var remotePub [33]byte var remotePub [33]byte
copy(remotePub[:], channel.IdentityPub.SerializeCompressed()) copy(remotePub[:], channel.RemotePubkey.SerializeCompressed())
isRemoteNodePublic, err := cfg.Graph.IsPublicNode(remotePub) isRemoteNodePublic, err := cfg.Graph.IsPublicNode(remotePub)
if err != nil { if err != nil {
log.Errorf("Unable to determine if node %x "+ log.Errorf("Unable to determine if node %x "+
@@ -504,17 +510,18 @@ func chanCanBeHopHint(channel *channeldb.OpenChannel, cfg *AddInvoiceConfig) (
if !isRemoteNodePublic { if !isRemoteNodePublic {
log.Debugf("Skipping channel %v due to "+ log.Debugf("Skipping channel %v due to "+
"counterparty %x being unadvertised", "counterparty %x being unadvertised",
chanPoint, remotePub) channel.ShortChannelID, remotePub)
return nil, false return nil, false
} }
// Fetch the policies for each end of the channel. // Fetch the policies for each end of the channel.
chanID := channel.ShortChanID().ToUint64() info, p1, p2, err := cfg.Graph.FetchChannelEdgesByID(
info, p1, p2, err := cfg.Graph.FetchChannelEdgesByID(chanID) channel.ShortChannelID,
)
if err != nil { if err != nil {
log.Errorf("Unable to fetch the routing "+ log.Errorf("Unable to fetch the routing "+
"policies for the edges of the channel "+ "policies for the edges of the channel "+
"%v: %v", chanPoint, err) "%v: %v", channel.ShortChannelID, err)
return nil, false return nil, false
} }
@@ -533,11 +540,11 @@ func chanCanBeHopHint(channel *channeldb.OpenChannel, cfg *AddInvoiceConfig) (
// addHopHint creates a hop hint out of the passed channel and channel policy. // addHopHint creates a hop hint out of the passed channel and channel policy.
// The new hop hint is appended to the passed slice. // The new hop hint is appended to the passed slice.
func addHopHint(hopHints *[]func(*zpay32.Invoice), func addHopHint(hopHints *[]func(*zpay32.Invoice),
channel *channeldb.OpenChannel, chanPolicy *channeldb.ChannelEdgePolicy) { channel *HopHintInfo, chanPolicy *channeldb.ChannelEdgePolicy) {
hopHint := zpay32.HopHint{ hopHint := zpay32.HopHint{
NodeID: channel.IdentityPub, NodeID: channel.RemotePubkey,
ChannelID: channel.ShortChanID().ToUint64(), ChannelID: channel.ShortChannelID,
FeeBaseMSat: uint32(chanPolicy.FeeBaseMSat), FeeBaseMSat: uint32(chanPolicy.FeeBaseMSat),
FeeProportionalMillionths: uint32( FeeProportionalMillionths: uint32(
chanPolicy.FeeProportionalMillionths, chanPolicy.FeeProportionalMillionths,
@@ -549,13 +556,50 @@ func addHopHint(hopHints *[]func(*zpay32.Invoice),
) )
} }
// HopHintInfo contains the channel information required to create a hop hint.
type HopHintInfo struct {
// IsPublic indicates whether a channel is advertised to the network.
IsPublic bool
// IsActive indicates whether the channel is online and available for
// use.
IsActive bool
// FundingOutpoint is the funding txid:index for the channel.
FundingOutpoint wire.OutPoint
// RemotePubkey is the public key of the remote party that this channel
// is in.
RemotePubkey *btcec.PublicKey
// RemoteBalance is the remote party's balance (our current incoming
// capacity).
RemoteBalance lnwire.MilliSatoshi
// ShortChannelID is the short channel ID of the channel.
ShortChannelID uint64
}
func newHopHintInfo(c *channeldb.OpenChannel, isActive bool) *HopHintInfo {
isPublic := c.ChannelFlags&lnwire.FFAnnounceChannel != 0
return &HopHintInfo{
IsPublic: isPublic,
IsActive: isActive,
FundingOutpoint: c.FundingOutpoint,
RemotePubkey: c.IdentityPub,
RemoteBalance: c.LocalCommitment.RemoteBalance,
ShortChannelID: c.ShortChannelID.ToUint64(),
}
}
// SelectHopHints will select up to numMaxHophints from the set of passed open // SelectHopHints will select up to numMaxHophints from the set of passed open
// channels. The set of hop hints will be returned as a slice of functional // channels. The set of hop hints will be returned as a slice of functional
// options that'll append the route hint to the set of all route hints. // options that'll append the route hint to the set of all route hints.
// //
// TODO(roasbeef): do proper sub-set sum max hints usually << numChans // TODO(roasbeef): do proper sub-set sum max hints usually << numChans
func SelectHopHints(amtMSat lnwire.MilliSatoshi, cfg *AddInvoiceConfig, func SelectHopHints(amtMSat lnwire.MilliSatoshi, cfg *AddInvoiceConfig,
openChannels []*channeldb.OpenChannel, openChannels []*HopHintInfo,
numMaxHophints int) []func(*zpay32.Invoice) { numMaxHophints int) []func(*zpay32.Invoice) {
// We'll add our hop hints in two passes, first we'll add all channels // We'll add our hop hints in two passes, first we'll add all channels
@@ -573,7 +617,7 @@ func SelectHopHints(amtMSat lnwire.MilliSatoshi, cfg *AddInvoiceConfig,
// Similarly, in this first pass, we'll ignore all channels in // Similarly, in this first pass, we'll ignore all channels in
// isolation can't satisfy this payment. // isolation can't satisfy this payment.
if channel.LocalCommitment.RemoteBalance < amtMSat { if channel.RemoteBalance < amtMSat {
continue continue
} }
@@ -582,7 +626,7 @@ func SelectHopHints(amtMSat lnwire.MilliSatoshi, cfg *AddInvoiceConfig,
addHopHint(&hopHints, channel, edgePolicy) addHopHint(&hopHints, channel, edgePolicy)
hopHintChans[channel.FundingOutpoint] = struct{}{} hopHintChans[channel.FundingOutpoint] = struct{}{}
totalHintBandwidth += channel.LocalCommitment.RemoteBalance totalHintBandwidth += channel.RemoteBalance
} }
// If we have enough hop hints at this point, then we'll exit early. // If we have enough hop hints at this point, then we'll exit early.
@@ -629,7 +673,7 @@ func SelectHopHints(amtMSat lnwire.MilliSatoshi, cfg *AddInvoiceConfig,
// available balance now to update our tally. // available balance now to update our tally.
// //
// TODO(roasbeef): have a cut off based on min bandwidth? // TODO(roasbeef): have a cut off based on min bandwidth?
totalHintBandwidth += channel.LocalCommitment.RemoteBalance totalHintBandwidth += channel.RemoteBalance
} }
return hopHints return hopHints