autopilot: define AgentConstraints
To decouple the autopilot heuristic from the constraints, we start by abstracting them behind an interface to make them easier to mock. We also rename them HeuristicConstraints->AgentConstraints to make it clear that they are now constraints the agent must adhere to.
This commit is contained in:
7 files changed
+271
-168
No files matched your search
@@ -0,0 +1,151 @@
|
||||
package autopilot
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// AgentConstraints is an interface the agent will query to determine what
|
||||
// limits it will need to stay inside when opening channels.
|
||||
type AgentConstraints interface {
|
||||
// ChannelBudget should, given the passed parameters, return whether
|
||||
// more channels can be be opened while still staying withing the set
|
||||
// constraints. If the constraints allow us to open more channels, then
|
||||
// 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) (
|
||||
btcutil.Amount, uint32)
|
||||
|
||||
// MaxPendingOpens returns the maximum number of pending channel
|
||||
// establishment goroutines that can be lingering. We cap this value in
|
||||
// order to control the level of parallelism caused by the autopilot
|
||||
// agent.
|
||||
MaxPendingOpens() uint16
|
||||
|
||||
// MinChanSize returns the smallest channel that the autopilot agent
|
||||
// should create.
|
||||
MinChanSize() btcutil.Amount
|
||||
|
||||
// MaxChanSize returns largest channel that the autopilot agent should
|
||||
// create.
|
||||
MaxChanSize() btcutil.Amount
|
||||
}
|
||||
|
||||
// agenConstraints is an implementation of the AgentConstraints interface that
|
||||
// indicate the constraints the autopilot agent must adhere to when opening
|
||||
// channels.
|
||||
type agentConstraints struct {
|
||||
// minChanSize is the smallest channel that the autopilot agent should
|
||||
// create.
|
||||
minChanSize btcutil.Amount
|
||||
|
||||
// maxChanSize the largest channel that the autopilot agent should
|
||||
// create.
|
||||
maxChanSize btcutil.Amount
|
||||
|
||||
// chanLimit the maximum number of channels that should be created.
|
||||
chanLimit uint16
|
||||
|
||||
// allocation the percentage of total funds that should be committed to
|
||||
// automatic channel establishment.
|
||||
allocation float64
|
||||
|
||||
// maxPendingOpens is the maximum number of pending channel
|
||||
// establishment goroutines that can be lingering. We cap this value in
|
||||
// order to control the level of parallelism caused by the autopilot
|
||||
// agent.
|
||||
maxPendingOpens uint16
|
||||
}
|
||||
|
||||
// A compile time assertion to ensure agentConstraints satisfies the
|
||||
// AgentConstraints interface.
|
||||
var _ AgentConstraints = (*agentConstraints)(nil)
|
||||
|
||||
// NewConstraints returns a new AgentConstraints with the given limits.
|
||||
func NewConstraints(minChanSize, maxChanSize btcutil.Amount, chanLimit,
|
||||
maxPendingOpens uint16, allocation float64) AgentConstraints {
|
||||
|
||||
return &agentConstraints{
|
||||
minChanSize: minChanSize,
|
||||
maxChanSize: maxChanSize,
|
||||
chanLimit: chanLimit,
|
||||
allocation: allocation,
|
||||
maxPendingOpens: maxPendingOpens,
|
||||
}
|
||||
}
|
||||
|
||||
// ChannelBudget should, given the passed parameters, return whether more
|
||||
// channels can be be opened while still staying withing the set constraints.
|
||||
// If the constraints allow us to open more channels, then 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.
|
||||
//
|
||||
// Note: part of the AgentConstraints interface.
|
||||
func (h *agentConstraints) ChannelBudget(channels []Channel,
|
||||
funds btcutil.Amount) (btcutil.Amount, uint32) {
|
||||
|
||||
// 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(h.chanLimit) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// 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(h.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
|
||||
for _, channel := range channels {
|
||||
totalChanAllocation += channel.Capacity
|
||||
}
|
||||
|
||||
// With this value known, we'll now compute the total amount of fund
|
||||
// allocated across regular utxo's and channel utxo's.
|
||||
totalFunds := funds + totalChanAllocation
|
||||
|
||||
// Once the total amount has been computed, we then calculate the
|
||||
// fraction of funds currently allocated to channels.
|
||||
fundsFraction := float64(totalChanAllocation) / float64(totalFunds)
|
||||
|
||||
// If this fraction is below our threshold, then we'll return true, to
|
||||
// indicate the controller should call Select to obtain a candidate set
|
||||
// of channels to attempt to open.
|
||||
needMore := fundsFraction < h.allocation
|
||||
if !needMore {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// 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) * h.allocation)
|
||||
fundsAvailable := targetAllocation - totalChanAllocation
|
||||
return fundsAvailable, numAdditionalChans
|
||||
}
|
||||
|
||||
// MaxPendingOpens returns the maximum number of pending channel establishment
|
||||
// goroutines that can be lingering. We cap this value in order to control the
|
||||
// level of parallelism caused by the autopilot agent.
|
||||
//
|
||||
// Note: part of the AgentConstraints interface.
|
||||
func (h *agentConstraints) MaxPendingOpens() uint16 {
|
||||
return h.maxPendingOpens
|
||||
}
|
||||
|
||||
// MinChanSize returns the smallest channel that the autopilot agent should
|
||||
// create.
|
||||
//
|
||||
// Note: part of the AgentConstraints interface.
|
||||
func (h *agentConstraints) MinChanSize() btcutil.Amount {
|
||||
return h.minChanSize
|
||||
}
|
||||
|
||||
// MaxChanSize returns largest channel that the autopilot agent should create.
|
||||
//
|
||||
// Note: part of the AgentConstraints interface.
|
||||
func (h *agentConstraints) MaxChanSize() btcutil.Amount {
|
||||
return h.maxChanSize
|
||||
}
|
||||
Reference in new issue
Block a user