9f52372cd2
In this commit, we fix a regression introduced by a recent change which would allow the agent to detect a channel as failed, and blacklist the node, promising faster convergence with the ideal state of the heuristic. The source of this bug is that we would use the set of blacklisted nodes in order to compute how many additional channels we should open. If 10 failures happened, then we would think that we had opened up 10 channels, and stop much earlier than we actually should. To fix this, while ensuring we don’t retry to failed peers, the NeedMoreChans method will now return *how* anymore channels to open, and the Select method will take in how many channels it should try to open *exactly*.
157 lines
6.3 KiB
Go
157 lines
6.3 KiB
Go
package autopilot
|
|
|
|
import (
|
|
"net"
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
"github.com/roasbeef/btcd/btcec"
|
|
"github.com/roasbeef/btcd/wire"
|
|
"github.com/roasbeef/btcutil"
|
|
)
|
|
|
|
// Node node is an interface which represents n abstract vertex within the
|
|
// channel graph. All nodes should have at least a single edge to/from them
|
|
// within the graph.
|
|
//
|
|
// TODO(roasbeef): combine with routing.ChannelGraphSource
|
|
type Node interface {
|
|
// PubKey is the identity public key of the node. This will be used to
|
|
// attempt to target a node for channel opening by the main autopilot
|
|
// agent.
|
|
PubKey() *btcec.PublicKey
|
|
|
|
// Addrs returns a slice of publicly reachable public TCP addresses
|
|
// that the peer is known to be listening on.
|
|
Addrs() []net.Addr
|
|
|
|
// ForEachChannel is a higher-order function that will be used to
|
|
// iterate through all edges emanating from/to the target node. For
|
|
// each active channel, this function should be called with the
|
|
// populated ChannelEdge that describes the active channel.
|
|
ForEachChannel(func(ChannelEdge) error) error
|
|
}
|
|
|
|
// Channel is a simple struct which contains relevant details of a particular
|
|
// channel within the channel graph. The fields in this struct may be used a
|
|
// signals for various AttachmentHeuristic implementations.
|
|
type Channel struct {
|
|
// ChanID is the short channel ID for this channel as defined within
|
|
// BOLT-0007.
|
|
ChanID lnwire.ShortChannelID
|
|
|
|
// Capacity is the capacity of the channel expressed in satoshis.
|
|
Capacity btcutil.Amount
|
|
|
|
// FundedAmt is the amount the local node funded into the target
|
|
// channel.
|
|
//
|
|
// TODO(roasbeef): need this?
|
|
FundedAmt btcutil.Amount
|
|
|
|
// Node is the peer that this channel has been established with.
|
|
Node NodeID
|
|
|
|
// TODO(roasbeef): also add other traits?
|
|
// * fee, timelock, etc
|
|
}
|
|
|
|
// ChannelEdge is a struct that holds details concerning a channel, but also
|
|
// contains a reference to the Node that this channel connects to as a directed
|
|
// edge within the graph. The existence of this reference to the connected node
|
|
// will allow callers to traverse the graph in an object-oriented manner.
|
|
type ChannelEdge struct {
|
|
// Channel contains the attributes of this channel.
|
|
Channel
|
|
|
|
// Peer is the peer that this channel creates an edge to in the channel
|
|
// graph.
|
|
Peer Node
|
|
}
|
|
|
|
// ChannelGraph in an interface that represents a traversable channel graph.
|
|
// The autopilot agent will use this interface as its source of graph traits in
|
|
// order to make decisions concerning which channels should be opened, and to
|
|
// whom.
|
|
//
|
|
// TODO(roasbeef): abstract??
|
|
type ChannelGraph interface {
|
|
// ForEachNode is a higher-order function that should be called once
|
|
// for each connected node within the channel graph. If the passed
|
|
// callback returns an error, then execution should be terminated.
|
|
ForEachNode(func(Node) error) error
|
|
}
|
|
|
|
// AttachmentDirective describes a channel attachment proscribed by an
|
|
// AttachmentHeuristic. It details to which node a channel should be created
|
|
// to, and also the parameters which should be used in the channel creation.
|
|
type AttachmentDirective struct {
|
|
// PeerKey is the target node for this attachment directive. It can be
|
|
// identified by its public key, and therefore can be used along with
|
|
// a ChannelOpener implementation to execute the directive.
|
|
PeerKey *btcec.PublicKey
|
|
|
|
// ChanAmt is the size of the channel that should be opened, expressed
|
|
// in satoshis.
|
|
ChanAmt btcutil.Amount
|
|
|
|
// Addrs is a list of addresses that the target peer may be reachable
|
|
// at.
|
|
Addrs []net.Addr
|
|
}
|
|
|
|
// AttachmentHeuristic is one of the primary interfaces within this package.
|
|
// Implementations of this interface will be used to implement a control system
|
|
// which automatically regulates channels of a particular agent, attempting to
|
|
// optimize channels opened/closed based on various heuristics. The purpose of
|
|
// 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 {
|
|
// NeedMoreChans is a predicate that should return true if, given the
|
|
// passed parameters, and its internal state, more channels should be
|
|
// opened within the channel graph. If the heuristic decides that we do
|
|
// indeed need more channels, then the second argument returned will
|
|
// represent the amount of additional funds to be used towards creating
|
|
// channels. This method should also return the exact *number* of
|
|
// additional channels that are needed in order to converge towards our
|
|
// ideal state.
|
|
NeedMoreChans(chans []Channel, balance btcutil.Amount) (btcutil.Amount, uint32, bool)
|
|
|
|
// Select is a method that given the current state of the channel
|
|
// graph, a set of nodes to ignore, and an amount of available funds,
|
|
// should return a set of attachment directives which describe which
|
|
// additional channels should be opened within the graph to push the
|
|
// heuristic back towards its equilibrium state. The numNewChans
|
|
// argument represents the additional number of channels that should be
|
|
// open.
|
|
Select(self *btcec.PublicKey, graph ChannelGraph,
|
|
amtToUse btcutil.Amount, numNewChans uint32,
|
|
skipNodes map[NodeID]struct{}) ([]AttachmentDirective, error)
|
|
}
|
|
|
|
// ChannelController is a simple interface that allows an auto-pilot agent to
|
|
// open a channel within the graph to a target peer, close targeted channels,
|
|
// or add/remove funds from existing channels via a splice in/out mechanisms.
|
|
type ChannelController interface {
|
|
// OpenChannel opens a channel to a target peer, with a capacity of the
|
|
// specified amount. This function should un-block immediately after
|
|
// the funding transaction that marks the channel open has been
|
|
// broadcast.
|
|
OpenChannel(target *btcec.PublicKey, amt btcutil.Amount,
|
|
addrs []net.Addr) error
|
|
|
|
// CloseChannel attempts to close out the target channel.
|
|
//
|
|
// TODO(roasbeef): add force option?
|
|
CloseChannel(chanPoint *wire.OutPoint) error
|
|
|
|
// SpliceIn attempts to add additional funds to the target channel via
|
|
// a splice in mechanism. The new channel with an updated capacity
|
|
// should be returned.
|
|
SpliceIn(chanPoint *wire.OutPoint, amt btcutil.Amount) (*Channel, error)
|
|
|
|
// SpliceOut attempts to remove funds from an existing channels using a
|
|
// splice out mechanism. The removed funds from the channel should be
|
|
// returned to an output under the control of the backing wallet.
|
|
SpliceOut(chanPoint *wire.OutPoint, amt btcutil.Amount) (*Channel, error)
|
|
}
|