From cfd237bf1f2670dca4daf2f8c0898abbb2d0e1b0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 19 Dec 2018 14:54:53 +0100 Subject: [PATCH] autopilot: move determining chanSize from heuristic to agent Since we want to combine scores from multiple heuristics, things get complicated if the heuristics report their own individual channel sizes. Therefore we change the NodeScores interface slightly, letting the agent specify the wanted channel size, and let the heuristic score the nodes accordingly. --- autopilot/agent.go | 8 +++++++- autopilot/interface.go | 12 ++++++------ autopilot/prefattach.go | 18 ++++-------------- autopilot/prefattach_test.go | 21 ++++++++++----------- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/autopilot/agent.go b/autopilot/agent.go index 86ce85e11..5a7ca0c01 100644 --- a/autopilot/agent.go +++ b/autopilot/agent.go @@ -547,10 +547,16 @@ func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32, return fmt.Errorf("unable to get graph nodes: %v", err) } + // As channel size we'll use the maximum channel size available. + chanSize := a.cfg.Constraints.MaxChanSize() + if availableFunds-chanSize < 0 { + chanSize = availableFunds + } + // Use the heuristic to calculate a score for each node in the // graph. scores, err := a.cfg.Heuristic.NodeScores( - a.cfg.Graph, totalChans, availableFunds, nodes, + a.cfg.Graph, totalChans, chanSize, nodes, ) if err != nil { return fmt.Errorf("unable to calculate node scores : %v", err) diff --git a/autopilot/interface.go b/autopilot/interface.go index a612914a6..cb9ff9abd 100644 --- a/autopilot/interface.go +++ b/autopilot/interface.go @@ -111,11 +111,11 @@ type AttachmentDirective struct { // the interface is to allow an auto-pilot agent to decide if it needs more // channels, and if so, which exact channels should be opened. type AttachmentHeuristic interface { - // NodeScores is a method that given the current channel graph, current - // set of local channels and funds available, scores the given nodes - // according to the preference of opening a channel with them. The - // returned channel candidates maps the NodeID to an attachemnt - // directive containing a score and a channel size. + // NodeScores is a method that given the current channel graph and + // current set of local channels, scores the given nodes according to + // the preference of opening a channel of the given size with them. The + // returned channel candidates maps the NodeID to an attachment + // directive containing a score. // // The scores will be in the range [0, M], where 0 indicates no // improvement in connectivity if a channel is opened to this node, @@ -126,7 +126,7 @@ type AttachmentHeuristic interface { // NOTE: A NodeID not found in the returned map is implicitly given a // score of 0. NodeScores(g ChannelGraph, chans []Channel, - fundsAvailable btcutil.Amount, nodes map[NodeID]struct{}) ( + chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*AttachmentDirective, error) } diff --git a/autopilot/prefattach.go b/autopilot/prefattach.go index 55587cd0a..b71ca8f95 100644 --- a/autopilot/prefattach.go +++ b/autopilot/prefattach.go @@ -53,9 +53,9 @@ func NewNodeID(pub *btcec.PublicKey) NodeID { return n } -// NodeScores is a method that given the current channel graph, current set of -// local channels and funds available, scores the given nodes according the the -// preference of opening a channel with them. +// NodeScores is a method that given the current channel graph and +// current set of local channels, scores the given nodes according to +// the preference of opening a channel of the given size with them. // // The heuristic employed by this method is one that attempts to promote a // scale-free network globally, via local attachment preferences for new nodes @@ -71,7 +71,7 @@ func NewNodeID(pub *btcec.PublicKey) NodeID { // // NOTE: This is a part of the AttachmentHeuristic interface. func (p *ConstrainedPrefAttachment) NodeScores(g ChannelGraph, chans []Channel, - fundsAvailable btcutil.Amount, nodes map[NodeID]struct{}) ( + chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*AttachmentDirective, error) { // Count the number of channels in the graph. We'll also count the @@ -124,11 +124,6 @@ func (p *ConstrainedPrefAttachment) NodeScores(g ChannelGraph, chans []Channel, // in the graph, and use that as the score. candidates := make(map[NodeID]*AttachmentDirective) for nID, nodeChans := range nodeChanNum { - // As channel size we'll use the maximum channel size available. - chanSize := p.constraints.MaxChanSize() - if fundsAvailable-chanSize < 0 { - chanSize = fundsAvailable - } _, ok := existingPeers[nID] addrs := addresses[nID] @@ -140,11 +135,6 @@ func (p *ConstrainedPrefAttachment) NodeScores(g ChannelGraph, chans []Channel, case ok: continue - // If the amount is too small, we don't want to attempt opening - // another channel. - case chanSize == 0 || chanSize < p.constraints.MinChanSize(): - continue - // If the node has no addresses, we cannot connect to it, so we // skip it for now, which implicitly gives it a score of 0. case len(addrs) == 0: diff --git a/autopilot/prefattach_test.go b/autopilot/prefattach_test.go index 94d021238..2c5f15148 100644 --- a/autopilot/prefattach_test.go +++ b/autopilot/prefattach_test.go @@ -241,9 +241,8 @@ func TestConstrainedPrefAttachmentSelectTwoVertexes(t *testing.T) { // With the necessary state initialized, we'll now // attempt to get our candidates channel score given // the current state of the graph. - const walletFunds = btcutil.SatoshiPerBitcoin * 10 candidates, err := prefAttach.NodeScores(graph, nil, - walletFunds, nodes) + maxChanSize, nodes) if err != nil { t1.Fatalf("unable to select attachment "+ "directives: %v", err) @@ -351,7 +350,7 @@ func TestConstrainedPrefAttachmentSelectInsufficientFunds(t *testing.T) { // With the necessary state initialized, we'll now // attempt to get the score for our list of nodes, // passing zero for the amount of wallet funds. This - // should return an all-zero score set. + // should return candidates with zero-value channels. scores, err := prefAttach.NodeScores(graph, nil, 0, nodes) if err != nil { @@ -361,9 +360,11 @@ func TestConstrainedPrefAttachmentSelectInsufficientFunds(t *testing.T) { // Since all should be given a score of 0, the map // should be empty. - if len(scores) != 0 { - t1.Fatalf("expected empty score map, "+ - "instead got %v ", len(scores)) + for _, s := range scores { + if s.ChanAmt != 0 { + t1.Fatalf("expected zero channel, "+ + "instead got %v ", s.ChanAmt) + } } }) if !success { @@ -466,9 +467,8 @@ func TestConstrainedPrefAttachmentSelectGreedyAllocation(t *testing.T) { // 50/50 allocation, and have 3 BTC in channels. As a // result, the heuristic should try to greedily // allocate funds to channels. - const availableBalance = btcutil.SatoshiPerBitcoin * 2.5 scores, err := prefAttach.NodeScores(graph, nil, - availableBalance, nodes) + maxChanSize, nodes) if err != nil { t1.Fatalf("unable to select attachment "+ "directives: %v", err) @@ -598,9 +598,8 @@ func TestConstrainedPrefAttachmentSelectSkipNodes(t *testing.T) { // With our graph created, we'll now get the scores for // all nodes in the graph. - const availableBalance = btcutil.SatoshiPerBitcoin * 2.5 scores, err := prefAttach.NodeScores(graph, nil, - availableBalance, nodes) + maxChanSize, nodes) if err != nil { t1.Fatalf("unable to select attachment "+ "directives: %v", err) @@ -646,7 +645,7 @@ func TestConstrainedPrefAttachmentSelectSkipNodes(t *testing.T) { // then all nodes should have a score of zero, since we // already got channels to them. scores, err = prefAttach.NodeScores(graph, chans, - availableBalance, nodes) + maxChanSize, nodes) if err != nil { t1.Fatalf("unable to select attachment "+ "directives: %v", err)