From d40cf6b59256be1ef3b03ea3c7b9ef7cf2547d26 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 2 Oct 2020 13:56:43 +0200 Subject: [PATCH] autopilot: split channel definition into LocalChannel/ChannelEdge Since non-local channels won't have a balance field, we split the definitions in anticipation of adding one. --- autopilot/agent.go | 30 +++++++++++++-------------- autopilot/agent_constraints.go | 4 ++-- autopilot/agent_constraints_test.go | 12 +++++------ autopilot/agent_test.go | 14 ++++++------- autopilot/combinedattach.go | 2 +- autopilot/externalscoreattach.go | 2 +- autopilot/graph.go | 32 ++++++++++------------------- autopilot/interface.go | 18 +++++++++------- autopilot/manager.go | 6 +++--- autopilot/prefattach.go | 2 +- autopilot/prefattach_test.go | 4 ++-- autopilot/top_centrality.go | 2 +- autopilot/top_centrality_test.go | 4 ++-- pilot.go | 6 +++--- 14 files changed, 66 insertions(+), 72 deletions(-) diff --git a/autopilot/agent.go b/autopilot/agent.go index a7e34fa9..fbe62026 100644 --- a/autopilot/agent.go +++ b/autopilot/agent.go @@ -65,11 +65,11 @@ type Config struct { // channelState is a type that represents the set of active channels of the // backing LN node that the Agent should be aware of. This type contains a few // helper utility methods. -type channelState map[lnwire.ShortChannelID]Channel +type channelState map[lnwire.ShortChannelID]LocalChannel // Channels returns a slice of all the active channels. -func (c channelState) Channels() []Channel { - chans := make([]Channel, 0, len(c)) +func (c channelState) Channels() []LocalChannel { + chans := make([]LocalChannel, 0, len(c)) for _, channel := range c { chans = append(chans, channel) } @@ -163,7 +163,7 @@ type Agent struct { // initiated, but haven't yet been confirmed as being fully opened. // This state is required as otherwise, we may go over our allotted // channel limit, or open multiple channels to the same node. - pendingOpens map[NodeID]Channel + pendingOpens map[NodeID]LocalChannel pendingMtx sync.Mutex quit chan struct{} @@ -174,10 +174,10 @@ type Agent struct { // configuration and initial channel state. The initial channel state slice // should be populated with the set of Channels that are currently opened by // the backing Lightning Node. -func New(cfg Config, initialState []Channel) (*Agent, error) { +func New(cfg Config, initialState []LocalChannel) (*Agent, error) { a := &Agent{ cfg: cfg, - chanState: make(map[lnwire.ShortChannelID]Channel), + chanState: make(map[lnwire.ShortChannelID]LocalChannel), quit: make(chan struct{}), stateUpdates: make(chan interface{}), balanceUpdates: make(chan *balanceUpdate, 1), @@ -187,7 +187,7 @@ func New(cfg Config, initialState []Channel) (*Agent, error) { pendingOpenUpdates: make(chan *chanPendingOpenUpdate, 1), failedNodes: make(map[NodeID]struct{}), pendingConns: make(map[NodeID]struct{}), - pendingOpens: make(map[NodeID]Channel), + pendingOpens: make(map[NodeID]LocalChannel), } for _, c := range initialState { @@ -249,7 +249,7 @@ type nodeUpdates struct{} // channel has been opened, either by the Agent itself (within the main // controller loop), or by an external user to the system. type chanOpenUpdate struct { - newChan Channel + newChan LocalChannel } // chanPendingOpenUpdate is a type of external state update that indicates a new @@ -294,7 +294,7 @@ func (a *Agent) OnNodeUpdates() { // OnChannelOpen is a callback that should be executed each time a new channel // is manually opened by the user or any system outside the autopilot agent. -func (a *Agent) OnChannelOpen(c Channel) { +func (a *Agent) OnChannelOpen(c LocalChannel) { a.wg.Add(1) go func() { defer a.wg.Done() @@ -356,7 +356,7 @@ func (a *Agent) OnHeuristicUpdate(h AttachmentHeuristic) { // channels open to, with the other sets of nodes that should be removed from // consideration during heuristic selection. This ensures that the Agent doesn't // attempt to open any "duplicate" channels to the same node. -func mergeNodeMaps(c map[NodeID]Channel, +func mergeNodeMaps(c map[NodeID]LocalChannel, skips ...map[NodeID]struct{}) map[NodeID]struct{} { numNodes := len(c) @@ -380,11 +380,11 @@ func mergeNodeMaps(c map[NodeID]Channel, // mergeChanState merges the Agent's set of active channels, with the set of // channels awaiting confirmation. This ensures that the agent doesn't go over // the prescribed channel limit or fund allocation limit. -func mergeChanState(pendingChans map[NodeID]Channel, - activeChans channelState) []Channel { +func mergeChanState(pendingChans map[NodeID]LocalChannel, + activeChans channelState) []LocalChannel { numChans := len(pendingChans) + len(activeChans) - totalChans := make([]Channel, 0, numChans) + totalChans := make([]LocalChannel, 0, numChans) totalChans = append(totalChans, activeChans.Channels()...) @@ -549,7 +549,7 @@ func (a *Agent) controller() { // openChans queries the agent's heuristic for a set of channel candidates, and // attempts to open channels to them. func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32, - totalChans []Channel) error { + totalChans []LocalChannel) error { // As channel size we'll use the maximum channel size available. chanSize := a.cfg.Constraints.MaxChanSize() @@ -828,7 +828,7 @@ func (a *Agent) executeDirective(directive AttachmentDirective) { // opens. We do this here to ensure we don't stall on selecting new // peers if the connection attempt happens to take too long. delete(a.pendingConns, nodeID) - a.pendingOpens[nodeID] = Channel{ + a.pendingOpens[nodeID] = LocalChannel{ Capacity: directive.ChanAmt, Node: nodeID, } diff --git a/autopilot/agent_constraints.go b/autopilot/agent_constraints.go index 2b084e45..fc80b2af 100644 --- a/autopilot/agent_constraints.go +++ b/autopilot/agent_constraints.go @@ -13,7 +13,7 @@ type AgentConstraints interface { // the first return value will represent the amount of additional funds // available towards creating channels. The second return value is the // exact *number* of additional channels available. - ChannelBudget(chans []Channel, balance btcutil.Amount) ( + ChannelBudget(chans []LocalChannel, balance btcutil.Amount) ( btcutil.Amount, uint32) // MaxPendingOpens returns the maximum number of pending channel @@ -82,7 +82,7 @@ func NewConstraints(minChanSize, maxChanSize btcutil.Amount, chanLimit, // additional channels available. // // Note: part of the AgentConstraints interface. -func (h *agentConstraints) ChannelBudget(channels []Channel, +func (h *agentConstraints) ChannelBudget(channels []LocalChannel, funds btcutil.Amount) (btcutil.Amount, uint32) { // If we're already over our maximum allowed number of channels, then diff --git a/autopilot/agent_constraints_test.go b/autopilot/agent_constraints_test.go index 4ce78245..19cdd5d6 100644 --- a/autopilot/agent_constraints_test.go +++ b/autopilot/agent_constraints_test.go @@ -37,7 +37,7 @@ func TestConstraintsChannelBudget(t *testing.T) { } testCases := []struct { - channels []Channel + channels []LocalChannel walletAmt btcutil.Amount needMore bool @@ -47,7 +47,7 @@ func TestConstraintsChannelBudget(t *testing.T) { // Many available funds, but already have too many active open // channels. { - []Channel{ + []LocalChannel{ { ChanID: randChanID(), Capacity: btcutil.Amount(prand.Int31()), @@ -70,7 +70,7 @@ func TestConstraintsChannelBudget(t *testing.T) { // Ratio of funds in channels and total funds meets the // threshold. { - []Channel{ + []LocalChannel{ { ChanID: randChanID(), Capacity: btcutil.Amount(btcutil.SatoshiPerBitcoin), @@ -93,7 +93,7 @@ func TestConstraintsChannelBudget(t *testing.T) { // recommended. We should also request 2 more channels as the // limit is 3. { - []Channel{ + []LocalChannel{ { ChanID: randChanID(), Capacity: btcutil.Amount(btcutil.SatoshiPerBitcoin), @@ -113,7 +113,7 @@ func TestConstraintsChannelBudget(t *testing.T) { // to be committed. We should only request a single additional // channel as the limit is 3. { - []Channel{ + []LocalChannel{ { ChanID: randChanID(), Capacity: btcutil.Amount(btcutil.SatoshiPerBitcoin), @@ -132,7 +132,7 @@ func TestConstraintsChannelBudget(t *testing.T) { // Ratio of funds in channels and total funds is above the // threshold. { - []Channel{ + []LocalChannel{ { ChanID: randChanID(), Capacity: btcutil.Amount(btcutil.SatoshiPerBitcoin), diff --git a/autopilot/agent_test.go b/autopilot/agent_test.go index 4828e7d5..1e842018 100644 --- a/autopilot/agent_test.go +++ b/autopilot/agent_test.go @@ -19,7 +19,7 @@ type moreChansResp struct { } type moreChanArg struct { - chans []Channel + chans []LocalChannel balance btcutil.Amount } @@ -29,7 +29,7 @@ type mockConstraints struct { quit chan struct{} } -func (m *mockConstraints) ChannelBudget(chans []Channel, +func (m *mockConstraints) ChannelBudget(chans []LocalChannel, balance btcutil.Amount) (btcutil.Amount, uint32) { if m.moreChanArgs != nil { @@ -76,7 +76,7 @@ type mockHeuristic struct { type directiveArg struct { graph ChannelGraph amt btcutil.Amount - chans []Channel + chans []LocalChannel nodes map[NodeID]struct{} } @@ -84,7 +84,7 @@ func (m *mockHeuristic) Name() string { return "mock" } -func (m *mockHeuristic) NodeScores(g ChannelGraph, chans []Channel, +func (m *mockHeuristic) NodeScores(g ChannelGraph, chans []LocalChannel, chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*NodeScore, error) { @@ -154,7 +154,7 @@ type testContext struct { sync.Mutex } -func setup(t *testing.T, initialChans []Channel) (*testContext, func()) { +func setup(t *testing.T, initialChans []LocalChannel) (*testContext, func()) { t.Helper() // First, we'll create all the dependencies that we'll need in order to @@ -291,7 +291,7 @@ func TestAgentChannelOpenSignal(t *testing.T) { // Next we'll signal a new channel being opened by the backing LN node, // with a capacity of 1 BTC. - newChan := Channel{ + newChan := LocalChannel{ ChanID: randChanID(), Capacity: btcutil.SatoshiPerBitcoin, } @@ -432,7 +432,7 @@ func TestAgentChannelFailureSignal(t *testing.T) { func TestAgentChannelCloseSignal(t *testing.T) { t.Parallel() // We'll start the agent with two channels already being active. - initialChans := []Channel{ + initialChans := []LocalChannel{ { ChanID: randChanID(), Capacity: btcutil.SatoshiPerBitcoin, diff --git a/autopilot/combinedattach.go b/autopilot/combinedattach.go index 80d32e65..56041d08 100644 --- a/autopilot/combinedattach.go +++ b/autopilot/combinedattach.go @@ -70,7 +70,7 @@ func (c *WeightedCombAttachment) Name() string { // is the maximum possible improvement in connectivity. // // NOTE: This is a part of the AttachmentHeuristic interface. -func (c *WeightedCombAttachment) NodeScores(g ChannelGraph, chans []Channel, +func (c *WeightedCombAttachment) NodeScores(g ChannelGraph, chans []LocalChannel, chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*NodeScore, error) { diff --git a/autopilot/externalscoreattach.go b/autopilot/externalscoreattach.go index 2ac9814e..01549218 100644 --- a/autopilot/externalscoreattach.go +++ b/autopilot/externalscoreattach.go @@ -80,7 +80,7 @@ func (s *ExternalScoreAttachment) SetNodeScores(targetHeuristic string, // not known will get a score of 0. // // NOTE: This is a part of the AttachmentHeuristic interface. -func (s *ExternalScoreAttachment) NodeScores(g ChannelGraph, chans []Channel, +func (s *ExternalScoreAttachment) NodeScores(g ChannelGraph, chans []LocalChannel, chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*NodeScore, error) { diff --git a/autopilot/graph.go b/autopilot/graph.go index 8ea45495..72c1b091 100644 --- a/autopilot/graph.go +++ b/autopilot/graph.go @@ -99,11 +99,8 @@ func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error { } edge := ChannelEdge{ - Channel: Channel{ - ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID), - Capacity: ei.Capacity, - Node: NodeID(ep.Node.PubKeyBytes), - }, + ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID), + Capacity: ei.Capacity, Peer: dbNode{ tx: tx, node: ep.Node, @@ -264,19 +261,15 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, } return &ChannelEdge{ - Channel: Channel{ - ChanID: chanID, - Capacity: capacity, - }, + ChanID: chanID, + Capacity: capacity, Peer: dbNode{ node: vertex1, }, }, &ChannelEdge{ - Channel: Channel{ - ChanID: chanID, - Capacity: capacity, - }, + ChanID: chanID, + Capacity: capacity, Peer: dbNode{ node: vertex2, }, @@ -424,20 +417,17 @@ func (m *memChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, } } - channel := Channel{ + edge1 := ChannelEdge{ ChanID: randChanID(), Capacity: capacity, - } - - edge1 := ChannelEdge{ - Channel: channel, - Peer: vertex2, + Peer: vertex2, } vertex1.chans = append(vertex1.chans, edge1) edge2 := ChannelEdge{ - Channel: channel, - Peer: vertex1, + ChanID: randChanID(), + Capacity: capacity, + Peer: vertex1, } vertex2.chans = append(vertex2.chans, edge2) diff --git a/autopilot/interface.go b/autopilot/interface.go index a443a471..2b7b5509 100644 --- a/autopilot/interface.go +++ b/autopilot/interface.go @@ -36,10 +36,10 @@ type Node interface { 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 { +// LocalChannel is a simple struct which contains relevant details of a +// particular channel the local node has. The fields in this struct may be used +// a signals for various AttachmentHeuristic implementations. +type LocalChannel struct { // ChanID is the short channel ID for this channel as defined within // BOLT-0007. ChanID lnwire.ShortChannelID @@ -59,8 +59,12 @@ type Channel struct { // 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 + // 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 // Peer is the peer that this channel creates an edge to in the channel // graph. @@ -136,7 +140,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, + NodeScores(g ChannelGraph, chans []LocalChannel, chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*NodeScore, error) } diff --git a/autopilot/manager.go b/autopilot/manager.go index 88f6c37d..f1bdff87 100644 --- a/autopilot/manager.go +++ b/autopilot/manager.go @@ -23,7 +23,7 @@ type ManagerCfg struct { // ChannelState is a function closure that returns the current set of // channels managed by this node. - ChannelState func() ([]Channel, error) + ChannelState func() ([]LocalChannel, error) // SubscribeTransactions is used to get a subscription for transactions // relevant to this node's wallet. @@ -200,7 +200,7 @@ func (m *Manager) StartAgent() error { chanID := lnwire.NewShortChanIDFromInt( edgeUpdate.ChanID, ) - edge := Channel{ + edge := LocalChannel{ ChanID: chanID, Capacity: edgeUpdate.Capacity, Node: chanNode, @@ -292,7 +292,7 @@ func (m *Manager) queryHeuristics(nodes map[NodeID]struct{}, localState bool) ( // If we want to take the local state into action when querying the // heuristics, we fetch it. If not we'll just pass an emply slice to // the heuristic. - var totalChans []Channel + var totalChans []LocalChannel var err error if localState { // Fetch the current set of channels. diff --git a/autopilot/prefattach.go b/autopilot/prefattach.go index 4068fe10..c25009d1 100644 --- a/autopilot/prefattach.go +++ b/autopilot/prefattach.go @@ -78,7 +78,7 @@ func (p *PrefAttachment) Name() string { // given to nodes already having high connectivity in the graph. // // NOTE: This is a part of the AttachmentHeuristic interface. -func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []Channel, +func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []LocalChannel, chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*NodeScore, error) { diff --git a/autopilot/prefattach_test.go b/autopilot/prefattach_test.go index a680fffa..24934592 100644 --- a/autopilot/prefattach_test.go +++ b/autopilot/prefattach_test.go @@ -422,10 +422,10 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) { // We'll simulate a channel update by adding the nodes // to our set of channels. - var chans []Channel + var chans []LocalChannel for _, candidate := range scores { chans = append(chans, - Channel{ + LocalChannel{ Node: candidate.NodeID, }, ) diff --git a/autopilot/top_centrality.go b/autopilot/top_centrality.go index da6dcf38..354b20ff 100644 --- a/autopilot/top_centrality.go +++ b/autopilot/top_centrality.go @@ -50,7 +50,7 @@ func (g *TopCentrality) Name() string { // As our current implementation of betweenness centrality is non-incremental, // NodeScores will recalculate the centrality values on every call, which is // slow for large graphs. -func (g *TopCentrality) NodeScores(graph ChannelGraph, chans []Channel, +func (g *TopCentrality) NodeScores(graph ChannelGraph, chans []LocalChannel, chanSize btcutil.Amount, nodes map[NodeID]struct{}) ( map[NodeID]*NodeScore, error) { diff --git a/autopilot/top_centrality_test.go b/autopilot/top_centrality_test.go index 6069200c..dbc627e5 100644 --- a/autopilot/top_centrality_test.go +++ b/autopilot/top_centrality_test.go @@ -16,9 +16,9 @@ func testTopCentrality(t *testing.T, graph testGraph, topCentrality := NewTopCentrality() - var channels []Channel + var channels []LocalChannel for _, ch := range channelsWith { - channels = append(channels, Channel{ + channels = append(channels, LocalChannel{ Node: NewNodeID(graphNodes[ch]), }) } diff --git a/pilot.go b/pilot.go index 03ef225f..34ba0e81 100644 --- a/pilot.go +++ b/pilot.go @@ -249,7 +249,7 @@ func initAutoPilot(svr *server, cfg *lncfg.AutoPilot, return &autopilot.ManagerCfg{ Self: self, PilotCfg: &pilotCfg, - ChannelState: func() ([]autopilot.Channel, error) { + ChannelState: func() ([]autopilot.LocalChannel, error) { // We'll fetch the current state of open // channels from the database to use as initial // state for the auto-pilot agent. @@ -257,10 +257,10 @@ func initAutoPilot(svr *server, cfg *lncfg.AutoPilot, if err != nil { return nil, err } - chanState := make([]autopilot.Channel, + chanState := make([]autopilot.LocalChannel, len(activeChannels)) for i, channel := range activeChannels { - chanState[i] = autopilot.Channel{ + chanState[i] = autopilot.LocalChannel{ ChanID: channel.ShortChanID(), Capacity: channel.Capacity, Node: autopilot.NewNodeID(