mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-28 14:40:51 +02:00
autopilot: update AttachmentHeuristics with context
Continue threading context through the autopilot system and remove the remaining context.TODOs.
This commit is contained in:
@@ -648,7 +648,7 @@ func (a *Agent) openChans(ctx context.Context, availableFunds btcutil.Amount,
|
|||||||
// graph.
|
// graph.
|
||||||
log.Debugf("Scoring %d nodes for chan_size=%v", len(nodes), chanSize)
|
log.Debugf("Scoring %d nodes for chan_size=%v", len(nodes), chanSize)
|
||||||
scores, err := a.cfg.Heuristic.NodeScores(
|
scores, err := a.cfg.Heuristic.NodeScores(
|
||||||
a.cfg.Graph, totalChans, chanSize, nodes,
|
ctx, a.cfg.Graph, totalChans, chanSize, nodes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to calculate node scores : %w", err)
|
return fmt.Errorf("unable to calculate node scores : %w", err)
|
||||||
|
@@ -86,9 +86,9 @@ func (m *mockHeuristic) Name() string {
|
|||||||
return "mock"
|
return "mock"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockHeuristic) NodeScores(g ChannelGraph, chans []LocalChannel,
|
func (m *mockHeuristic) NodeScores(_ context.Context, g ChannelGraph,
|
||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chans []LocalChannel, chanSize btcutil.Amount,
|
||||||
map[NodeID]*NodeScore, error) {
|
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
|
||||||
|
|
||||||
if m.nodeScoresArgs != nil {
|
if m.nodeScoresArgs != nil {
|
||||||
directive := directiveArg{
|
directive := directiveArg{
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package autopilot
|
package autopilot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
@@ -70,9 +71,9 @@ func (c *WeightedCombAttachment) Name() string {
|
|||||||
// is the maximum possible improvement in connectivity.
|
// is the maximum possible improvement in connectivity.
|
||||||
//
|
//
|
||||||
// NOTE: This is a part of the AttachmentHeuristic interface.
|
// NOTE: This is a part of the AttachmentHeuristic interface.
|
||||||
func (c *WeightedCombAttachment) NodeScores(g ChannelGraph, chans []LocalChannel,
|
func (c *WeightedCombAttachment) NodeScores(ctx context.Context, g ChannelGraph,
|
||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chans []LocalChannel, chanSize btcutil.Amount,
|
||||||
map[NodeID]*NodeScore, error) {
|
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
|
||||||
|
|
||||||
// We now query each heuristic to determine the score they give to the
|
// We now query each heuristic to determine the score they give to the
|
||||||
// nodes for the given channel size.
|
// nodes for the given channel size.
|
||||||
@@ -81,7 +82,7 @@ func (c *WeightedCombAttachment) NodeScores(g ChannelGraph, chans []LocalChannel
|
|||||||
log.Tracef("Getting scores from sub heuristic %v", h.Name())
|
log.Tracef("Getting scores from sub heuristic %v", h.Name())
|
||||||
|
|
||||||
s, err := h.NodeScores(
|
s, err := h.NodeScores(
|
||||||
g, chans, chanSize, nodes,
|
ctx, g, chans, chanSize, nodes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to get sub score: %w",
|
return nil, fmt.Errorf("unable to get sub score: %w",
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package autopilot
|
package autopilot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -80,9 +81,9 @@ func (s *ExternalScoreAttachment) SetNodeScores(targetHeuristic string,
|
|||||||
// not known will get a score of 0.
|
// not known will get a score of 0.
|
||||||
//
|
//
|
||||||
// NOTE: This is a part of the AttachmentHeuristic interface.
|
// NOTE: This is a part of the AttachmentHeuristic interface.
|
||||||
func (s *ExternalScoreAttachment) NodeScores(g ChannelGraph, chans []LocalChannel,
|
func (s *ExternalScoreAttachment) NodeScores(_ context.Context, g ChannelGraph,
|
||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chans []LocalChannel, chanSize btcutil.Amount,
|
||||||
map[NodeID]*NodeScore, error) {
|
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
|
||||||
|
|
||||||
existingPeers := make(map[NodeID]struct{})
|
existingPeers := make(map[NodeID]struct{})
|
||||||
for _, c := range chans {
|
for _, c := range chans {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package autopilot_test
|
package autopilot_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
@@ -22,6 +23,7 @@ func randKey() (*btcec.PublicKey, error) {
|
|||||||
// ExternalScoreAttachment correctly reflects the scores we set last.
|
// ExternalScoreAttachment correctly reflects the scores we set last.
|
||||||
func TestSetNodeScores(t *testing.T) {
|
func TestSetNodeScores(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
const name = "externalscore"
|
const name = "externalscore"
|
||||||
|
|
||||||
@@ -62,7 +64,7 @@ func TestSetNodeScores(t *testing.T) {
|
|||||||
q[nID] = struct{}{}
|
q[nID] = struct{}{}
|
||||||
}
|
}
|
||||||
resp, err := h.NodeScores(
|
resp, err := h.NodeScores(
|
||||||
nil, nil, btcutil.Amount(btcutil.SatoshiPerBitcoin), q,
|
ctx, nil, nil, btcutil.Amount(btcutil.SatoshiPerBitcoin), q,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@@ -144,7 +144,7 @@ type AttachmentHeuristic interface {
|
|||||||
//
|
//
|
||||||
// NOTE: A NodeID not found in the returned map is implicitly given a
|
// NOTE: A NodeID not found in the returned map is implicitly given a
|
||||||
// score of 0.
|
// score of 0.
|
||||||
NodeScores(g ChannelGraph, chans []LocalChannel,
|
NodeScores(ctx context.Context, g ChannelGraph, chans []LocalChannel,
|
||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
||||||
map[NodeID]*NodeScore, error)
|
map[NodeID]*NodeScore, error)
|
||||||
}
|
}
|
||||||
|
@@ -276,8 +276,8 @@ func (m *Manager) StopAgent() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryHeuristics queries the available autopilot heuristics for node scores.
|
// QueryHeuristics queries the available autopilot heuristics for node scores.
|
||||||
func (m *Manager) QueryHeuristics(nodes []NodeID, localState bool) (
|
func (m *Manager) QueryHeuristics(ctx context.Context, nodes []NodeID,
|
||||||
HeuristicScores, error) {
|
localState bool) (HeuristicScores, error) {
|
||||||
|
|
||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
@@ -288,7 +288,8 @@ func (m *Manager) QueryHeuristics(nodes []NodeID, localState bool) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Querying heuristics for %d nodes", len(n))
|
log.Debugf("Querying heuristics for %d nodes", len(n))
|
||||||
return m.queryHeuristics(n, localState)
|
|
||||||
|
return m.queryHeuristics(ctx, n, localState)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeuristicScores is an alias for a map that maps heuristic names to a map of
|
// HeuristicScores is an alias for a map that maps heuristic names to a map of
|
||||||
@@ -299,8 +300,8 @@ type HeuristicScores map[string]map[NodeID]float64
|
|||||||
// the agent's current active heuristic.
|
// the agent's current active heuristic.
|
||||||
//
|
//
|
||||||
// NOTE: Must be called with the manager's lock.
|
// NOTE: Must be called with the manager's lock.
|
||||||
func (m *Manager) queryHeuristics(nodes map[NodeID]struct{}, localState bool) (
|
func (m *Manager) queryHeuristics(ctx context.Context,
|
||||||
HeuristicScores, error) {
|
nodes map[NodeID]struct{}, localState bool) (HeuristicScores, error) {
|
||||||
|
|
||||||
// If we want to take the local state into action when querying the
|
// If we want to take the local state into action when querying the
|
||||||
// heuristics, we fetch it. If not we'll just pass an empty slice to
|
// heuristics, we fetch it. If not we'll just pass an empty slice to
|
||||||
@@ -348,7 +349,7 @@ func (m *Manager) queryHeuristics(nodes map[NodeID]struct{}, localState bool) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
s, err := h.NodeScores(
|
s, err := h.NodeScores(
|
||||||
m.cfg.PilotCfg.Graph, totalChans, chanSize, nodes,
|
ctx, m.cfg.PilotCfg.Graph, totalChans, chanSize, nodes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to get sub score: %w",
|
return nil, fmt.Errorf("unable to get sub score: %w",
|
||||||
|
@@ -79,11 +79,9 @@ func (p *PrefAttachment) Name() string {
|
|||||||
// given to nodes already having high connectivity in the graph.
|
// given to nodes already having high connectivity in the graph.
|
||||||
//
|
//
|
||||||
// NOTE: This is a part of the AttachmentHeuristic interface.
|
// NOTE: This is a part of the AttachmentHeuristic interface.
|
||||||
func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []LocalChannel,
|
func (p *PrefAttachment) NodeScores(ctx context.Context, g ChannelGraph,
|
||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chans []LocalChannel, chanSize btcutil.Amount,
|
||||||
map[NodeID]*NodeScore, error) {
|
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
|
||||||
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
// We first run though the graph once in order to find the median
|
// We first run though the graph once in order to find the median
|
||||||
// channel size.
|
// channel size.
|
||||||
|
@@ -88,6 +88,8 @@ var chanGraphs = []struct {
|
|||||||
// TestPrefAttachmentSelectEmptyGraph ensures that when passed an
|
// TestPrefAttachmentSelectEmptyGraph ensures that when passed an
|
||||||
// empty graph, the NodeSores function always returns a score of 0.
|
// empty graph, the NodeSores function always returns a score of 0.
|
||||||
func TestPrefAttachmentSelectEmptyGraph(t *testing.T) {
|
func TestPrefAttachmentSelectEmptyGraph(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
ctx := context.Background()
|
||||||
prefAttach := NewPrefAttachment()
|
prefAttach := NewPrefAttachment()
|
||||||
|
|
||||||
// Create a random public key, which we will query to get a score for.
|
// Create a random public key, which we will query to get a score for.
|
||||||
@@ -108,7 +110,7 @@ func TestPrefAttachmentSelectEmptyGraph(t *testing.T) {
|
|||||||
// attempt to get the score for this one node.
|
// attempt to get the score for this one node.
|
||||||
const walletFunds = btcutil.SatoshiPerBitcoin
|
const walletFunds = btcutil.SatoshiPerBitcoin
|
||||||
scores, err := prefAttach.NodeScores(
|
scores, err := prefAttach.NodeScores(
|
||||||
graph, nil, walletFunds, nodes,
|
ctx, graph, nil, walletFunds, nodes,
|
||||||
)
|
)
|
||||||
require.NoError(t1, err)
|
require.NoError(t1, err)
|
||||||
|
|
||||||
@@ -172,7 +174,7 @@ func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
|
|||||||
// attempt to get our candidates channel score given
|
// attempt to get our candidates channel score given
|
||||||
// the current state of the graph.
|
// the current state of the graph.
|
||||||
candidates, err := prefAttach.NodeScores(
|
candidates, err := prefAttach.NodeScores(
|
||||||
graph, nil, maxChanSize, nodes,
|
ctx, graph, nil, maxChanSize, nodes,
|
||||||
)
|
)
|
||||||
require.NoError(t1, err)
|
require.NoError(t1, err)
|
||||||
|
|
||||||
@@ -280,7 +282,7 @@ func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
|
|||||||
// result, the heuristic should try to greedily
|
// result, the heuristic should try to greedily
|
||||||
// allocate funds to channels.
|
// allocate funds to channels.
|
||||||
scores, err := prefAttach.NodeScores(
|
scores, err := prefAttach.NodeScores(
|
||||||
graph, nil, maxChanSize, nodes,
|
ctx, graph, nil, maxChanSize, nodes,
|
||||||
)
|
)
|
||||||
require.NoError(t1, err)
|
require.NoError(t1, err)
|
||||||
|
|
||||||
@@ -298,7 +300,7 @@ func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
|
|||||||
// candidates of that size.
|
// candidates of that size.
|
||||||
const remBalance = btcutil.SatoshiPerBitcoin * 0.5
|
const remBalance = btcutil.SatoshiPerBitcoin * 0.5
|
||||||
scores, err = prefAttach.NodeScores(
|
scores, err = prefAttach.NodeScores(
|
||||||
graph, nil, remBalance, nodes,
|
ctx, graph, nil, remBalance, nodes,
|
||||||
)
|
)
|
||||||
require.NoError(t1, err)
|
require.NoError(t1, err)
|
||||||
|
|
||||||
@@ -358,7 +360,7 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
|
|||||||
// With our graph created, we'll now get the scores for
|
// With our graph created, we'll now get the scores for
|
||||||
// all nodes in the graph.
|
// all nodes in the graph.
|
||||||
scores, err := prefAttach.NodeScores(
|
scores, err := prefAttach.NodeScores(
|
||||||
graph, nil, maxChanSize, nodes,
|
ctx, graph, nil, maxChanSize, nodes,
|
||||||
)
|
)
|
||||||
require.NoError(t1, err)
|
require.NoError(t1, err)
|
||||||
|
|
||||||
@@ -386,7 +388,7 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
|
|||||||
// then all nodes should have a score of zero, since we
|
// then all nodes should have a score of zero, since we
|
||||||
// already got channels to them.
|
// already got channels to them.
|
||||||
scores, err = prefAttach.NodeScores(
|
scores, err = prefAttach.NodeScores(
|
||||||
graph, chans, maxChanSize, nodes,
|
ctx, graph, chans, maxChanSize, nodes,
|
||||||
)
|
)
|
||||||
require.NoError(t1, err)
|
require.NoError(t1, err)
|
||||||
|
|
||||||
|
@@ -51,11 +51,9 @@ func (g *TopCentrality) Name() string {
|
|||||||
// As our current implementation of betweenness centrality is non-incremental,
|
// As our current implementation of betweenness centrality is non-incremental,
|
||||||
// NodeScores will recalculate the centrality values on every call, which is
|
// NodeScores will recalculate the centrality values on every call, which is
|
||||||
// slow for large graphs.
|
// slow for large graphs.
|
||||||
func (g *TopCentrality) NodeScores(graph ChannelGraph, chans []LocalChannel,
|
func (g *TopCentrality) NodeScores(ctx context.Context, graph ChannelGraph,
|
||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chans []LocalChannel, chanSize btcutil.Amount,
|
||||||
map[NodeID]*NodeScore, error) {
|
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
|
||||||
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
// Calculate betweenness centrality for the whole graph.
|
// Calculate betweenness centrality for the whole graph.
|
||||||
if err := g.centralityMetric.Refresh(ctx, graph); err != nil {
|
if err := g.centralityMetric.Refresh(ctx, graph); err != nil {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package autopilot
|
package autopilot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
@@ -58,7 +59,7 @@ func testTopCentrality(t *testing.T, graph testGraph,
|
|||||||
// Attempt to get centrality scores and expect
|
// Attempt to get centrality scores and expect
|
||||||
// that the result equals with the expected set.
|
// that the result equals with the expected set.
|
||||||
scores, err := topCentrality.NodeScores(
|
scores, err := topCentrality.NodeScores(
|
||||||
graph, channels, chanSize, nodes,
|
context.Background(), graph, channels, chanSize, nodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@@ -236,7 +236,7 @@ func (s *Server) QueryScores(ctx context.Context, in *QueryScoresRequest) (
|
|||||||
|
|
||||||
// Query the heuristics.
|
// Query the heuristics.
|
||||||
heuristicScores, err := s.manager.QueryHeuristics(
|
heuristicScores, err := s.manager.QueryHeuristics(
|
||||||
nodes, !in.IgnoreLocalState,
|
ctx, nodes, !in.IgnoreLocalState,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Reference in New Issue
Block a user