multi: add new config option BudgetConfig and NoDeadlineConfTarget
This commit adds a new group config `BudgetConfig` to allow users specifying their own preference when sweeping outputs. And a new config option `NoDeadlineConfTarget` is added in case the user wants to use a different "lazy" conf target.
This commit is contained in:
9 files changed
+298
-20
No files matched your search
@@ -199,6 +199,9 @@ type ChainArbitratorConfig struct {
|
||||
|
||||
// HtlcNotifier is an interface that htlc events are sent to.
|
||||
HtlcNotifier HtlcNotifier
|
||||
|
||||
// Budget is the configured budget for the arbitrator.
|
||||
Budget BudgetConfig
|
||||
}
|
||||
|
||||
// ChainArbitrator is a sub-system that oversees the on-chain resolution of all
|
||||
@@ -497,7 +500,8 @@ func (c *ChainArbitrator) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Info("ChainArbitrator starting")
|
||||
log.Infof("ChainArbitrator starting with config: budget=[%v]",
|
||||
&c.cfg.Budget)
|
||||
|
||||
// First, we'll fetch all the channels that are still open, in order to
|
||||
// collect them within our set of active contracts.
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package contractcourt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// MinBudgetValue is the minimal budget that we allow when configuring
|
||||
// the budget used in sweeping outputs. The actual budget can be lower
|
||||
// if the user decides to NOT set this value.
|
||||
//
|
||||
// NOTE: This value is chosen so the linear fee function can increase
|
||||
// at least 1 sat/kw per block.
|
||||
MinBudgetValue btcutil.Amount = 1008
|
||||
|
||||
// MinBudgetRatio is the minimal ratio that we allow when configuring
|
||||
// the budget ratio used in sweeping outputs.
|
||||
MinBudgetRatio = 0.001
|
||||
|
||||
// DefaultBudgetRatio defines a default budget ratio to be used when
|
||||
// sweeping inputs. This is a large value, which is fine as the final
|
||||
// fee rate is capped at the max fee rate configured.
|
||||
DefaultBudgetRatio = 0.5
|
||||
)
|
||||
|
||||
// BudgetConfig is a struct that holds the configuration when offering outputs
|
||||
// to the sweeper.
|
||||
//
|
||||
//nolint:lll
|
||||
type BudgetConfig struct {
|
||||
ToLocal btcutil.Amount `long:"tolocal" description:"The amount in satoshis to allocate as the budget to pay fees when sweeping the to_local output. If set, the budget calculated using the ratio (if set) will be capped at this value."`
|
||||
ToLocalRatio float64 `long:"tolocalratio" description:"The ratio of the value in to_local output to allocate as the budget to pay fees when sweeping it."`
|
||||
|
||||
AnchorCPFP btcutil.Amount `long:"anchorcpfp" description:"The amount in satoshis to allocate as the budget to pay fees when CPFPing a force close tx using the anchor output. If set, the budget calculated using the ratio (if set) will be capped at this value."`
|
||||
AnchorCPFPRatio float64 `long:"anchorcpfpratio" description:"The ratio of a special value to allocate as the budget to pay fees when CPFPing a force close tx using the anchor output. The special value is the sum of all time-sensitive HTLCs on this commitment subtracted by their budgets."`
|
||||
|
||||
DeadlineHTLC btcutil.Amount `long:"deadlinehtlc" description:"The amount in satoshis to allocate as the budget to pay fees when sweeping a time-sensitive (first-level) HTLC. If set, the budget calculated using the ratio (if set) will be capped at this value."`
|
||||
DeadlineHTLCRatio float64 `long:"deadlinehtlcratio" description:"The ratio of the value in a time-sensitive (first-level) HTLC to allocate as the budget to pay fees when sweeping it."`
|
||||
|
||||
NoDeadlineHTLC btcutil.Amount `long:"nodeadlinehtlc" description:"The amount in satoshis to allocate as the budget to pay fees when sweeping a non-time-sensitive (second-level) HTLC. If set, the budget calculated using the ratio (if set) will be capped at this value."`
|
||||
NoDeadlineHTLCRatio float64 `long:"nodeadlinehtlcratio" description:"The ratio of the value in a non-time-sensitive (second-level) HTLC to allocate as the budget to pay fees when sweeping it."`
|
||||
}
|
||||
|
||||
// Validate checks the budget configuration for any invalid values.
|
||||
func (b *BudgetConfig) Validate() error {
|
||||
// Exit early if no budget config is set.
|
||||
if b == nil {
|
||||
return fmt.Errorf("no budget config set")
|
||||
}
|
||||
|
||||
// Sanity check all fields.
|
||||
if b.ToLocal != 0 && b.ToLocal < MinBudgetValue {
|
||||
return fmt.Errorf("tolocal must be at least %v",
|
||||
MinBudgetValue)
|
||||
}
|
||||
if b.ToLocalRatio != 0 && b.ToLocalRatio < MinBudgetRatio {
|
||||
return fmt.Errorf("tolocalratio must be at least %v",
|
||||
MinBudgetRatio)
|
||||
}
|
||||
|
||||
if b.AnchorCPFP != 0 && b.AnchorCPFP < MinBudgetValue {
|
||||
return fmt.Errorf("anchorcpfp must be at least %v",
|
||||
MinBudgetValue)
|
||||
}
|
||||
if b.AnchorCPFPRatio != 0 && b.AnchorCPFPRatio < MinBudgetRatio {
|
||||
return fmt.Errorf("anchorcpfpratio must be at least %v",
|
||||
MinBudgetRatio)
|
||||
}
|
||||
|
||||
if b.DeadlineHTLC != 0 && b.DeadlineHTLC < MinBudgetValue {
|
||||
return fmt.Errorf("deadlinehtlc must be at least %v",
|
||||
MinBudgetValue)
|
||||
}
|
||||
if b.DeadlineHTLCRatio != 0 && b.DeadlineHTLCRatio < MinBudgetRatio {
|
||||
return fmt.Errorf("deadlinehtlcratio must be at least %v",
|
||||
MinBudgetRatio)
|
||||
}
|
||||
|
||||
if b.NoDeadlineHTLC != 0 && b.NoDeadlineHTLC < MinBudgetValue {
|
||||
return fmt.Errorf("nodeadlinehtlc must be at least %v",
|
||||
MinBudgetValue)
|
||||
}
|
||||
if b.NoDeadlineHTLCRatio != 0 &&
|
||||
b.NoDeadlineHTLCRatio < MinBudgetRatio {
|
||||
|
||||
return fmt.Errorf("nodeadlinehtlcratio must be at least %v",
|
||||
MinBudgetRatio)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a human-readable description of the budget configuration.
|
||||
func (b *BudgetConfig) String() string {
|
||||
return fmt.Sprintf("tolocal=%v tolocalratio=%v anchorcpfp=%v "+
|
||||
"anchorcpfpratio=%v deadlinehtlc=%v deadlinehtlcratio=%v "+
|
||||
"nodeadlinehtlc=%v nodeadlinehtlcratio=%v",
|
||||
b.ToLocal, b.ToLocalRatio, b.AnchorCPFP, b.AnchorCPFPRatio,
|
||||
b.DeadlineHTLC, b.DeadlineHTLCRatio, b.NoDeadlineHTLC,
|
||||
b.NoDeadlineHTLCRatio)
|
||||
}
|
||||
|
||||
// DefaultSweeperConfig returns the default configuration for the sweeper.
|
||||
func DefaultBudgetConfig() *BudgetConfig {
|
||||
return &BudgetConfig{
|
||||
ToLocalRatio: DefaultBudgetRatio,
|
||||
AnchorCPFPRatio: DefaultBudgetRatio,
|
||||
DeadlineHTLCRatio: DefaultBudgetRatio,
|
||||
NoDeadlineHTLCRatio: DefaultBudgetRatio,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package contractcourt
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestBudgetConfigValidate checks that the budget config validation works as
|
||||
// expected.
|
||||
func TestBudgetConfigValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
cfg *BudgetConfig
|
||||
expectedErrStr string
|
||||
}{
|
||||
{
|
||||
name: "valid config",
|
||||
cfg: DefaultBudgetConfig(),
|
||||
},
|
||||
{
|
||||
name: "nil config",
|
||||
cfg: nil,
|
||||
expectedErrStr: "no budget config set",
|
||||
},
|
||||
{
|
||||
name: "invalid tolocal",
|
||||
cfg: &BudgetConfig{ToLocal: -1},
|
||||
expectedErrStr: "tolocal",
|
||||
},
|
||||
{
|
||||
name: "invalid tolocalratio",
|
||||
cfg: &BudgetConfig{ToLocalRatio: -1},
|
||||
expectedErrStr: "tolocalratio",
|
||||
},
|
||||
{
|
||||
name: "invalid anchorcpfp",
|
||||
cfg: &BudgetConfig{AnchorCPFP: -1},
|
||||
expectedErrStr: "anchorcpfp",
|
||||
},
|
||||
{
|
||||
name: "invalid anchorcpfpratio",
|
||||
cfg: &BudgetConfig{AnchorCPFPRatio: -1},
|
||||
expectedErrStr: "anchorcpfpratio",
|
||||
},
|
||||
{
|
||||
name: "invalid deadlinehtlc",
|
||||
cfg: &BudgetConfig{DeadlineHTLC: -1},
|
||||
expectedErrStr: "deadlinehtlc",
|
||||
},
|
||||
{
|
||||
name: "invalid deadlinehtlcratio",
|
||||
cfg: &BudgetConfig{DeadlineHTLCRatio: -1},
|
||||
expectedErrStr: "deadlinehtlcratio",
|
||||
},
|
||||
|
||||
{
|
||||
name: "invalid nodeadlinehtlc",
|
||||
cfg: &BudgetConfig{NoDeadlineHTLC: -1},
|
||||
expectedErrStr: "nodeadlinehtlc",
|
||||
},
|
||||
{
|
||||
name: "invalid nodeadlinehtlcratio",
|
||||
cfg: &BudgetConfig{NoDeadlineHTLCRatio: -1},
|
||||
expectedErrStr: "nodeadlinehtlcratio",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := tc.cfg.Validate()
|
||||
|
||||
if tc.expectedErrStr == "" {
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
require.ErrorContains(t, err, tc.expectedErrStr)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user