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.
This commit is contained in:
Johan T. Halseth 2018-12-19 14:54:53 +01:00
parent d5f3714f86
commit cfd237bf1f
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
4 changed files with 27 additions and 32 deletions

@ -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)

@ -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)
}

@ -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:

@ -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)