From bfa1cf17b94628fb52ea308b19202047d6632848 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 2 Feb 2022 14:24:52 +0100 Subject: [PATCH] lnwallet: introduce default routing fee calculation --- lnwallet/parameters.go | 29 +++++++++++++++++++++++++++ lnwallet/parameters_test.go | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/lnwallet/parameters.go b/lnwallet/parameters.go index ccd5583d0..9e4b67422 100644 --- a/lnwallet/parameters.go +++ b/lnwallet/parameters.go @@ -5,8 +5,37 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnwire" ) +const ( + // RoutingFee100PercentUpTo is the cut-off amount we allow 100% fees to + // be charged up to. + RoutingFee100PercentUpTo lnwire.MilliSatoshi = 50_000 + + // DefaultRoutingFeePercentage is the default off-chain routing fee we + // allow to be charged for a payment over the RoutingFee100PercentUpTo + // size. + DefaultRoutingFeePercentage lnwire.MilliSatoshi = 5 +) + +// DefaultRoutingFeeLimitForAmount returns the default off-chain routing fee +// limit lnd uses if the user does not specify a limit manually. The fee is +// amount dependent because of the base routing fee that is set on many +// channels. For example the default base fee is 1 satoshi. So sending a payment +// of one satoshi will cost 1 satoshi in fees over most channels, which comes to +// a fee of 100%. That's why for very small amounts we allow 100% fee. +func DefaultRoutingFeeLimitForAmount(a lnwire.MilliSatoshi) lnwire.MilliSatoshi { + // Allow 100% fees up to a certain amount to accommodate for base fees. + if a <= RoutingFee100PercentUpTo { + return a + } + + // Everything larger than the cut-off amount will get a default fee + // percentage. + return a * DefaultRoutingFeePercentage / 100 +} + // DustLimitForSize retrieves the dust limit for a given pkscript size. Given // the size, it automatically determines whether the script is a witness script // or not. It calls btcd's GetDustThreshold method under the hood. It must be diff --git a/lnwallet/parameters_test.go b/lnwallet/parameters_test.go index 021cb7bc6..cde35c05e 100644 --- a/lnwallet/parameters_test.go +++ b/lnwallet/parameters_test.go @@ -1,13 +1,52 @@ package lnwallet import ( + "fmt" "testing" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnwire" "github.com/stretchr/testify/require" ) +// TestDefaultRoutingFeeLimitForAmount tests that we use the correct default +// routing fee depending on the amount. +func TestDefaultRoutingFeeLimitForAmount(t *testing.T) { + t.Parallel() + + tests := []struct { + amount lnwire.MilliSatoshi + expectedLimit lnwire.MilliSatoshi + }{ + { + amount: 1, + expectedLimit: 1, + }, + { + amount: 50_000, + expectedLimit: 50_000, + }, + { + amount: 50_001, + expectedLimit: 2_500, + }, + { + amount: 5_000_000_000, + expectedLimit: 250_000_000, + }, + } + + for _, test := range tests { + test := test + + t.Run(fmt.Sprintf("%d sats", test.amount), func(t *testing.T) { + feeLimit := DefaultRoutingFeeLimitForAmount(test.amount) + require.Equal(t, test.expectedLimit, feeLimit) + }) + } +} + // TestDustLimitForSize tests that we receive the expected dust limits for // various script types from btcd's GetDustThreshold function. func TestDustLimitForSize(t *testing.T) {