liquidity: update default fee setting to flat percentage

pull/340/head
carla 3 years ago
parent 299a0a4ff9
commit d4b7f9a378
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91

@ -42,6 +42,10 @@ const (
// ensure that we will still be able to complete our swap in the case
// of a severe fee spike.
minerMultiplier = 100
// defaultFeePPM is the default percentage of swap amount that we
// allocate to fees, 2%.
defaultFeePPM = 20000
)
var (
@ -245,6 +249,12 @@ type FeePortion struct {
PartsPerMillion uint64
}
func defaultFeePortion() *FeePortion {
return &FeePortion{
PartsPerMillion: defaultFeePPM,
}
}
// NewFeePortion creates a fee limit based on a flat percentage of swap amount.
func NewFeePortion(ppm uint64) *FeePortion {
return &FeePortion{

@ -99,7 +99,7 @@ var (
PeerRules: make(map[route.Vertex]*ThresholdRule),
FailureBackOff: defaultFailureBackoff,
SweepConfTarget: loop.DefaultSweepConfTarget,
FeeLimit: defaultFeeCategoryLimit(),
FeeLimit: defaultFeePortion(),
}
// ErrZeroChannelID is returned if we get a rule for a 0 channel ID.

@ -50,15 +50,12 @@ var (
chanRule = NewThresholdRule(50, 0)
testQuote = &loop.LoopOutQuote{
SwapFee: btcutil.Amount(1),
PrepayAmount: btcutil.Amount(500),
MinerFee: btcutil.Amount(50),
SwapFee: btcutil.Amount(5),
PrepayAmount: btcutil.Amount(50),
MinerFee: btcutil.Amount(1),
}
prepayFee = ppmToSat(
testQuote.PrepayAmount, defaultPrepayRoutingFeePPM,
)
routingFee = ppmToSat(7500, defaultRoutingFeePPM)
prepayFee, routingFee = testPPMFees(defaultFeePPM, testQuote, 7500)
// chan1Rec is the suggested swap for channel 1 when we use chanRule.
chan1Rec = loop.OutRequest{
@ -66,7 +63,7 @@ var (
OutgoingChanSet: loopdb.ChannelSet{chanID1.ToUint64()},
MaxPrepayRoutingFee: prepayFee,
MaxSwapRoutingFee: routingFee,
MaxMinerFee: defaultMaximumMinerFee,
MaxMinerFee: scaleMinerFee(testQuote.MinerFee),
MaxSwapFee: testQuote.SwapFee,
MaxPrepayAmount: testQuote.PrepayAmount,
SweepConfTarget: loop.DefaultSweepConfTarget,
@ -79,7 +76,7 @@ var (
OutgoingChanSet: loopdb.ChannelSet{chanID2.ToUint64()},
MaxPrepayRoutingFee: prepayFee,
MaxSwapRoutingFee: routingFee,
MaxMinerFee: defaultMaximumMinerFee,
MaxMinerFee: scaleMinerFee(testQuote.MinerFee),
MaxPrepayAmount: testQuote.PrepayAmount,
MaxSwapFee: testQuote.SwapFee,
SweepConfTarget: loop.DefaultSweepConfTarget,
@ -164,6 +161,21 @@ func testPPMFees(ppm uint64, quote *loop.LoopOutQuote,
)
}
// applyFeeCategoryQuote returns a copy of the loop out request provided with
// fee categories updated to the quote and routing settings provided.
// nolint:unparam
func applyFeeCategoryQuote(req loop.OutRequest, minerFee btcutil.Amount,
prepayPPM, routingPPM uint64, quote loop.LoopOutQuote) loop.OutRequest {
req.MaxPrepayRoutingFee = ppmToSat(quote.PrepayAmount, prepayPPM)
req.MaxSwapRoutingFee = ppmToSat(req.Amount, routingPPM)
req.MaxSwapFee = quote.SwapFee
req.MaxPrepayAmount = quote.PrepayAmount
req.MaxMinerFee = minerFee
return req
}
// TestParameters tests getting and setting of parameters for our manager.
func TestParameters(t *testing.T) {
cfg, _ := newTestConfig()
@ -547,6 +559,12 @@ func TestRestrictedSuggestions(t *testing.T) {
// TestSweepFeeLimit tests getting of swap suggestions when our estimated sweep
// fee is above and below the configured limit.
func TestSweepFeeLimit(t *testing.T) {
quote := &loop.LoopOutQuote{
SwapFee: btcutil.Amount(1),
PrepayAmount: btcutil.Amount(500),
MinerFee: btcutil.Amount(50),
}
tests := []struct {
name string
feeRate chainfee.SatPerKWeight
@ -557,7 +575,11 @@ func TestSweepFeeLimit(t *testing.T) {
feeRate: defaultSweepFeeRateLimit,
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
chan1Rec,
applyFeeCategoryQuote(
chan1Rec, defaultMaximumMinerFee,
defaultPrepayRoutingFeePPM,
defaultRoutingFeePPM, *quote,
),
},
DisqualifiedChans: noneDisqualified,
DisqualifiedPeers: noPeersDisqualified,
@ -581,6 +603,13 @@ func TestSweepFeeLimit(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
cfg, lnd := newTestConfig()
cfg.LoopOutQuote = func(_ context.Context,
_ *loop.LoopOutQuoteRequest) (*loop.LoopOutQuote,
error) {
return quote, nil
}
// Set our test case's fee rate for our mock lnd.
lnd.SetFeeEstimate(
loop.DefaultSweepConfTarget, testCase.feeRate,
@ -591,6 +620,8 @@ func TestSweepFeeLimit(t *testing.T) {
}
params := defaultParameters
params.FeeLimit = defaultFeeCategoryLimit()
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
chanID1: chanRule,
}
@ -610,6 +641,9 @@ func TestSuggestSwaps(t *testing.T) {
channel1,
}
expectedAmt := btcutil.Amount(10000)
prepay, routing := testPPMFees(defaultFeePPM, testQuote, expectedAmt)
tests := []struct {
name string
channels []lndclient.ChannelInfo
@ -681,24 +715,18 @@ func TestSuggestSwaps(t *testing.T) {
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
{
Amount: 10000,
Amount: expectedAmt,
OutgoingChanSet: loopdb.ChannelSet{
chanID1.ToUint64(),
chanID2.ToUint64(),
},
MaxPrepayRoutingFee: ppmToSat(
testQuote.PrepayAmount,
defaultPrepayRoutingFeePPM,
),
MaxSwapRoutingFee: ppmToSat(
10000,
defaultRoutingFeePPM,
),
MaxMinerFee: defaultMaximumMinerFee,
MaxSwapFee: testQuote.SwapFee,
MaxPrepayAmount: testQuote.PrepayAmount,
SweepConfTarget: loop.DefaultSweepConfTarget,
Initiator: autoloopSwapInitiator,
MaxPrepayRoutingFee: prepay,
MaxSwapRoutingFee: routing,
MaxMinerFee: scaleMinerFee(testQuote.MinerFee),
MaxSwapFee: testQuote.SwapFee,
MaxPrepayAmount: testQuote.PrepayAmount,
SweepConfTarget: loop.DefaultSweepConfTarget,
Initiator: autoloopSwapInitiator,
},
},
DisqualifiedChans: noneDisqualified,
@ -736,6 +764,12 @@ func TestSuggestSwaps(t *testing.T) {
// TestFeeLimits tests limiting of swap suggestions by fees.
func TestFeeLimits(t *testing.T) {
quote := &loop.LoopOutQuote{
SwapFee: btcutil.Amount(1),
PrepayAmount: btcutil.Amount(500),
MinerFee: btcutil.Amount(50),
}
tests := []struct {
name string
quote *loop.LoopOutQuote
@ -743,10 +777,14 @@ func TestFeeLimits(t *testing.T) {
}{
{
name: "fees ok",
quote: testQuote,
quote: quote,
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
chan1Rec,
applyFeeCategoryQuote(
chan1Rec, defaultMaximumMinerFee,
defaultPrepayRoutingFeePPM,
defaultRoutingFeePPM, *quote,
),
},
DisqualifiedChans: noneDisqualified,
DisqualifiedPeers: noPeersDisqualified,
@ -813,7 +851,10 @@ func TestFeeLimits(t *testing.T) {
channel1,
}
// Set our params to use individual fee limits.
params := defaultParameters
params.FeeLimit = defaultFeeCategoryLimit()
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
chanID1: chanRule,
}
@ -838,6 +879,21 @@ func TestFeeLimits(t *testing.T) {
// amounts, we use our max miner fee to shift swap cost to values above/below
// our budget, fixing our other fees at 114 sat for simplicity.
func TestFeeBudget(t *testing.T) {
quote := &loop.LoopOutQuote{
SwapFee: btcutil.Amount(1),
PrepayAmount: btcutil.Amount(500),
MinerFee: btcutil.Amount(50),
}
chan1 := applyFeeCategoryQuote(
chan1Rec, 5000, defaultPrepayRoutingFeePPM,
defaultRoutingFeePPM, *quote,
)
chan2 := applyFeeCategoryQuote(
chan2Rec, 5000, defaultPrepayRoutingFeePPM,
defaultRoutingFeePPM, *quote,
)
tests := []struct {
name string
@ -862,7 +918,7 @@ func TestFeeBudget(t *testing.T) {
maxMinerFee: 5000,
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
chan1Rec, chan2Rec,
chan1, chan2,
},
DisqualifiedChans: noneDisqualified,
DisqualifiedPeers: noPeersDisqualified,
@ -876,7 +932,7 @@ func TestFeeBudget(t *testing.T) {
maxMinerFee: 5000,
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
chan1Rec,
chan1,
},
DisqualifiedChans: map[lnwire.ShortChannelID]Reason{
chanID2: ReasonBudgetInsufficient,
@ -895,7 +951,7 @@ func TestFeeBudget(t *testing.T) {
},
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
chan1Rec, chan2Rec,
chan1, chan2,
},
DisqualifiedChans: noneDisqualified,
DisqualifiedPeers: noPeersDisqualified,
@ -912,7 +968,7 @@ func TestFeeBudget(t *testing.T) {
},
suggestions: &Suggestions{
OutSwaps: []loop.OutRequest{
chan1Rec,
chan1,
},
DisqualifiedChans: map[lnwire.ShortChannelID]Reason{
chanID2: ReasonBudgetInsufficient,
@ -977,6 +1033,13 @@ func TestFeeBudget(t *testing.T) {
return swaps, nil
}
cfg.LoopOutQuote = func(_ context.Context,
_ *loop.LoopOutQuoteRequest) (*loop.LoopOutQuote,
error) {
return quote, nil
}
// Set two channels that need swaps.
lnd.Channels = []lndclient.ChannelInfo{
channel1,
@ -1141,18 +1204,17 @@ func TestSizeRestrictions(t *testing.T) {
Maximum: 10000,
}
outSwap = loop.OutRequest{
prepay, routing = testPPMFees(defaultFeePPM, testQuote, 7000)
outSwap = loop.OutRequest{
Amount: 7000,
OutgoingChanSet: loopdb.ChannelSet{chanID1.ToUint64()},
MaxPrepayRoutingFee: prepayFee,
MaxSwapRoutingFee: ppmToSat(
7000, defaultRoutingFeePPM,
),
MaxMinerFee: defaultMaximumMinerFee,
MaxSwapFee: testQuote.SwapFee,
MaxPrepayAmount: testQuote.PrepayAmount,
SweepConfTarget: loop.DefaultSweepConfTarget,
Initiator: autoloopSwapInitiator,
MaxPrepayRoutingFee: prepay,
MaxSwapRoutingFee: routing,
MaxMinerFee: scaleMinerFee(testQuote.MinerFee),
MaxSwapFee: testQuote.SwapFee,
MaxPrepayAmount: testQuote.PrepayAmount,
SweepConfTarget: loop.DefaultSweepConfTarget,
Initiator: autoloopSwapInitiator,
}
)

Loading…
Cancel
Save