autopilot: modify interfaces to specify *exactly* how many chans to open

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*.
This commit is contained in:
Olaoluwa Osuntokun
2018-02-08 20:06:57 -08:00
parent d1c12202ca
commit 9f52372cd2
5 changed files with 67 additions and 49 deletions

View File

@@ -58,14 +58,19 @@ var _ AttachmentHeuristic = (*ConstrainedPrefAttachment)(nil)
//
// NOTE: This is a part of the AttachmentHeuristic interface.
func (p *ConstrainedPrefAttachment) NeedMoreChans(channels []Channel,
funds btcutil.Amount) (btcutil.Amount, bool) {
funds btcutil.Amount) (btcutil.Amount, uint32, bool) {
// If we're already over our maximum allowed number of channels, then
// we'll instruct the controller not to create any more channels.
if len(channels) >= int(p.chanLimit) {
return 0, false
return 0, 0, false
}
// The number of additional channels that should be opened is the
// difference between the channel limit, and the number of channels we
// already have open.
numAdditionalChans := uint32(p.chanLimit) - uint32(len(channels))
// First, we'll tally up the total amount of funds that are currently
// present within the set of active channels.
var totalChanAllocation btcutil.Amount
@@ -86,14 +91,14 @@ func (p *ConstrainedPrefAttachment) NeedMoreChans(channels []Channel,
// of channels to attempt to open.
needMore := fundsFraction < p.threshold
if !needMore {
return 0, false
return 0, 0, false
}
// Now that we know we need more funds, we'll compute the amount of
// additional funds we should allocate towards channels.
targetAllocation := btcutil.Amount(float64(totalFunds) * p.threshold)
fundsAvailable := targetAllocation - totalChanAllocation
return fundsAvailable, true
return fundsAvailable, numAdditionalChans, true
}
// NodeID is a simple type that holds a EC public key serialized in compressed
@@ -137,7 +142,7 @@ func shuffleCandidates(candidates []Node) []Node {
//
// NOTE: This is a part of the AttachmentHeuristic interface.
func (p *ConstrainedPrefAttachment) Select(self *btcec.PublicKey, g ChannelGraph,
fundsAvailable btcutil.Amount,
fundsAvailable btcutil.Amount, numNewChans uint32,
skipNodes map[NodeID]struct{}) ([]AttachmentDirective, error) {
// TODO(roasbeef): rename?
@@ -151,8 +156,7 @@ func (p *ConstrainedPrefAttachment) Select(self *btcec.PublicKey, g ChannelGraph
// We'll continue our attachment loop until we've exhausted the current
// amount of available funds.
visited := make(map[NodeID]struct{})
chanLimit := p.chanLimit - uint16(len(skipNodes))
for i := uint16(0); i < chanLimit; i++ {
for i := uint32(0); i < numNewChans; i++ {
// selectionSlice will be used to randomly select a node
// according to a power law distribution. For each connected
// edge, we'll add an instance of the node to this slice. Thus,