From 4a1e06b2041a8ec365c3c4e020b68eb4509438c0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 12 Feb 2019 12:40:25 +0100 Subject: [PATCH] autopilot/agent: distribute available funds among channels This commit fixes a regression in how we allocate funds to attempted channels. We would earlier stay within the channel size limits, but we wouldn't account for funds consumed by other channels being opened in parallel. We fix this by introducing a loop which greadily tries to distribute the funds among the channels to open, and reduces the number of channels to open in case not enough funds are available to satisfy the channel size limits. --- autopilot/agent.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/autopilot/agent.go b/autopilot/agent.go index 2ff5cf0b..2f257173 100644 --- a/autopilot/agent.go +++ b/autopilot/agent.go @@ -567,10 +567,15 @@ func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32, // As channel size we'll use the maximum channel size available. chanSize := a.cfg.Constraints.MaxChanSize() - if availableFunds-chanSize < 0 { + if availableFunds < chanSize { chanSize = availableFunds } + if chanSize < a.cfg.Constraints.MinChanSize() { + return fmt.Errorf("not enough funds available to open a " + + "single channel") + } + // Use the heuristic to calculate a score for each node in the // graph. scores, err := a.cfg.Heuristic.NodeScores( @@ -601,6 +606,17 @@ func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32, continue } + // Track the available funds we have left. + if availableFunds < chanSize { + chanSize = availableFunds + } + availableFunds -= chanSize + + // If we run out of funds, we can break early. + if chanSize < a.cfg.Constraints.MinChanSize() { + break + } + chanCandidates[nID] = &AttachmentDirective{ NodeID: nID, ChanAmt: chanSize, @@ -725,8 +741,7 @@ func (a *Agent) executeDirective(directive AttachmentDirective) { // fewer slots were available, and other successful attempts finished // first. a.pendingMtx.Lock() - if uint16(len(a.pendingOpens)) >= - a.cfg.Constraints.MaxPendingOpens() { + if uint16(len(a.pendingOpens)) >= a.cfg.Constraints.MaxPendingOpens() { // Since we've reached our max number of pending opens, we'll // disconnect this peer and exit. However, if we were // previously connected to them, then we'll make sure to @@ -799,6 +814,9 @@ func (a *Agent) executeDirective(directive AttachmentDirective) { // Since the channel open was successful and is currently pending, // we'll trigger the autopilot agent to query for more peers. + // TODO(halseth): this triggers a new loop before all the new channels + // are added to the pending channels map. Should add before executing + // directive in goroutine? a.OnChannelPendingOpen() }