mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
liquidity: add type to rules
In preparation for adding loop in swaps, we relate liquidity rules to a specific type of swap that we want to dispatch. This allows us to use a single rule format for multiple swap types.
This commit is contained in:
parent
00c2d4e5f0
commit
25b8d20f75
5 changed files with 95 additions and 51 deletions
|
|
@ -27,7 +27,7 @@ func TestAutoLoopDisabled(t *testing.T) {
|
|||
}
|
||||
|
||||
params := defaultParameters
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ func TestAutoLoopEnabled(t *testing.T) {
|
|||
swapFeePPM, routeFeePPM, prepayFeePPM, maxMiner,
|
||||
prepayAmount, 20000,
|
||||
),
|
||||
ChannelRules: map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
ChannelRules: map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
chanID2: chanRule,
|
||||
},
|
||||
|
|
@ -312,10 +312,10 @@ func TestCompositeRules(t *testing.T) {
|
|||
MaxAutoInFlight: 2,
|
||||
FailureBackOff: time.Hour,
|
||||
SweepConfTarget: 10,
|
||||
ChannelRules: map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
ChannelRules: map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
},
|
||||
PeerRules: map[route.Vertex]*ThresholdRule{
|
||||
PeerRules: map[route.Vertex]*SwapRule{
|
||||
peer2: chanRule,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ var (
|
|||
defaultParameters = Parameters{
|
||||
AutoFeeBudget: defaultBudget,
|
||||
MaxAutoInFlight: defaultMaxInFlight,
|
||||
ChannelRules: make(map[lnwire.ShortChannelID]*ThresholdRule),
|
||||
PeerRules: make(map[route.Vertex]*ThresholdRule),
|
||||
ChannelRules: make(map[lnwire.ShortChannelID]*SwapRule),
|
||||
PeerRules: make(map[route.Vertex]*SwapRule),
|
||||
FailureBackOff: defaultFailureBackoff,
|
||||
SweepConfTarget: defaultConfTarget,
|
||||
FeeLimit: defaultFeePortion(),
|
||||
|
|
@ -216,13 +216,13 @@ type Parameters struct {
|
|||
// ChannelRules maps a short channel ID to a rule that describes how we
|
||||
// would like liquidity to be managed. These rules and PeerRules are
|
||||
// exclusively set to prevent overlap between peer and channel rules.
|
||||
ChannelRules map[lnwire.ShortChannelID]*ThresholdRule
|
||||
ChannelRules map[lnwire.ShortChannelID]*SwapRule
|
||||
|
||||
// PeerRules maps a peer's pubkey to a rule that applies to all the
|
||||
// channels that we have with the peer collectively. These rules and
|
||||
// ChannelRules are exclusively set to prevent overlap between peer
|
||||
// and channel rules map to avoid ambiguity.
|
||||
PeerRules map[route.Vertex]*ThresholdRule
|
||||
PeerRules map[route.Vertex]*SwapRule
|
||||
}
|
||||
|
||||
// String returns the string representation of our parameters.
|
||||
|
|
@ -473,7 +473,7 @@ func (m *Manager) SetParameters(ctx context.Context, params Parameters) error {
|
|||
func cloneParameters(params Parameters) Parameters {
|
||||
paramCopy := params
|
||||
paramCopy.ChannelRules = make(
|
||||
map[lnwire.ShortChannelID]*ThresholdRule,
|
||||
map[lnwire.ShortChannelID]*SwapRule,
|
||||
len(params.ChannelRules),
|
||||
)
|
||||
|
||||
|
|
@ -483,7 +483,7 @@ func cloneParameters(params Parameters) Parameters {
|
|||
}
|
||||
|
||||
paramCopy.PeerRules = make(
|
||||
map[route.Vertex]*ThresholdRule,
|
||||
map[route.Vertex]*SwapRule,
|
||||
len(params.PeerRules),
|
||||
)
|
||||
|
||||
|
|
@ -841,7 +841,7 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) (
|
|||
// suggestSwap checks whether we can currently perform a swap, and creates a
|
||||
// swap request for the rule provided.
|
||||
func (m *Manager) suggestSwap(ctx context.Context, traffic *swapTraffic,
|
||||
balance *balances, rule *ThresholdRule, restrictions *Restrictions,
|
||||
balance *balances, rule *SwapRule, restrictions *Restrictions,
|
||||
autoloop bool) (swapSuggestion, error) {
|
||||
|
||||
// First, check whether this peer/channel combination is already in use
|
||||
|
|
|
|||
|
|
@ -47,7 +47,10 @@ var (
|
|||
}
|
||||
|
||||
// chanRule is a rule that produces chan1Rec.
|
||||
chanRule = NewThresholdRule(50, 0)
|
||||
chanRule = &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(50, 0),
|
||||
Type: swap.TypeOut,
|
||||
}
|
||||
|
||||
testQuote = &loop.LoopOutQuote{
|
||||
SwapFee: btcutil.Amount(5),
|
||||
|
|
@ -188,7 +191,10 @@ func TestParameters(t *testing.T) {
|
|||
require.Equal(t, defaultParameters, startParams)
|
||||
|
||||
// Mutate the parameters returned by our get function.
|
||||
startParams.ChannelRules[chanID] = NewThresholdRule(1, 1)
|
||||
startParams.ChannelRules[chanID] = &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(1, 1),
|
||||
Type: swap.TypeOut,
|
||||
}
|
||||
|
||||
// Make sure that we have not mutated the liquidity manager's params
|
||||
// by making this change.
|
||||
|
|
@ -197,9 +203,13 @@ func TestParameters(t *testing.T) {
|
|||
|
||||
// Provide a valid set of parameters and validate assert that they are
|
||||
// set.
|
||||
originalRule := NewThresholdRule(10, 10)
|
||||
originalRule := &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(10, 10),
|
||||
Type: swap.TypeOut,
|
||||
}
|
||||
|
||||
expected := defaultParameters
|
||||
expected.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
expected.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID: originalRule,
|
||||
}
|
||||
|
||||
|
|
@ -208,15 +218,21 @@ func TestParameters(t *testing.T) {
|
|||
|
||||
// Check that changing the parameters we just set does not mutate
|
||||
// our liquidity manager's parameters.
|
||||
expected.ChannelRules[chanID] = NewThresholdRule(11, 11)
|
||||
expected.ChannelRules[chanID] = &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(11, 11),
|
||||
Type: swap.TypeOut,
|
||||
}
|
||||
|
||||
params = manager.GetParameters()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, originalRule, params.ChannelRules[chanID])
|
||||
|
||||
// Set invalid parameters and assert that we fail.
|
||||
expected.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
lnwire.NewShortChanIDFromInt(0): NewThresholdRule(1, 2),
|
||||
expected.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
lnwire.NewShortChanIDFromInt(0): {
|
||||
ThresholdRule: NewThresholdRule(1, 2),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
}
|
||||
err = manager.SetParameters(context.Background(), expected)
|
||||
require.Equal(t, ErrZeroChannelID, err)
|
||||
|
|
@ -310,7 +326,7 @@ func TestRestrictedSuggestions(t *testing.T) {
|
|||
),
|
||||
}
|
||||
|
||||
chanRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
chanRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
chanID2: chanRule,
|
||||
}
|
||||
|
|
@ -321,8 +337,8 @@ func TestRestrictedSuggestions(t *testing.T) {
|
|||
channels []lndclient.ChannelInfo
|
||||
loopOut []*loopdb.LoopOut
|
||||
loopIn []*loopdb.LoopIn
|
||||
chanRules map[lnwire.ShortChannelID]*ThresholdRule
|
||||
peerRules map[route.Vertex]*ThresholdRule
|
||||
chanRules map[lnwire.ShortChannelID]*SwapRule
|
||||
peerRules map[route.Vertex]*SwapRule
|
||||
expected *Suggestions
|
||||
}{
|
||||
{
|
||||
|
|
@ -511,8 +527,11 @@ func TestRestrictedSuggestions(t *testing.T) {
|
|||
Contract: chan1Out,
|
||||
},
|
||||
},
|
||||
peerRules: map[route.Vertex]*ThresholdRule{
|
||||
peer1: NewThresholdRule(0, 50),
|
||||
peerRules: map[route.Vertex]*SwapRule{
|
||||
peer1: {
|
||||
ThresholdRule: NewThresholdRule(0, 50),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
},
|
||||
expected: &Suggestions{
|
||||
DisqualifiedChans: noneDisqualified,
|
||||
|
|
@ -629,7 +648,7 @@ func TestSweepFeeLimit(t *testing.T) {
|
|||
ppmToSat(7500, defaultPrepayRoutingFeePPM) +
|
||||
ppmToSat(7500, defaultRoutingFeePPM)
|
||||
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
}
|
||||
|
||||
|
|
@ -654,21 +673,21 @@ func TestSuggestSwaps(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
channels []lndclient.ChannelInfo
|
||||
rules map[lnwire.ShortChannelID]*ThresholdRule
|
||||
peerRules map[route.Vertex]*ThresholdRule
|
||||
rules map[lnwire.ShortChannelID]*SwapRule
|
||||
peerRules map[route.Vertex]*SwapRule
|
||||
suggestions *Suggestions
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "no rules",
|
||||
channels: singleChannel,
|
||||
rules: map[lnwire.ShortChannelID]*ThresholdRule{},
|
||||
rules: map[lnwire.ShortChannelID]*SwapRule{},
|
||||
err: ErrNoRules,
|
||||
},
|
||||
{
|
||||
name: "loop out",
|
||||
channels: singleChannel,
|
||||
rules: map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
rules: map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
|
|
@ -682,8 +701,11 @@ func TestSuggestSwaps(t *testing.T) {
|
|||
{
|
||||
name: "no rule for channel",
|
||||
channels: singleChannel,
|
||||
rules: map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
chanID2: NewThresholdRule(10, 10),
|
||||
rules: map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID2: {
|
||||
ThresholdRule: NewThresholdRule(10, 10),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
DisqualifiedChans: noneDisqualified,
|
||||
|
|
@ -715,9 +737,15 @@ func TestSuggestSwaps(t *testing.T) {
|
|||
RemoteBalance: 3000,
|
||||
},
|
||||
},
|
||||
peerRules: map[route.Vertex]*ThresholdRule{
|
||||
peer1: NewThresholdRule(80, 0),
|
||||
peer2: NewThresholdRule(40, 50),
|
||||
peerRules: map[route.Vertex]*SwapRule{
|
||||
peer1: {
|
||||
ThresholdRule: NewThresholdRule(80, 0),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
peer2: {
|
||||
ThresholdRule: NewThresholdRule(40, 50),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
OutSwaps: []loop.OutRequest{
|
||||
|
|
@ -869,7 +897,7 @@ func TestFeeLimits(t *testing.T) {
|
|||
ppmToSat(7500, defaultPrepayRoutingFeePPM) +
|
||||
ppmToSat(7500, defaultRoutingFeePPM)
|
||||
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
}
|
||||
|
||||
|
|
@ -1061,7 +1089,7 @@ func TestFeeBudget(t *testing.T) {
|
|||
}
|
||||
|
||||
params := defaultParameters
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
chanID2: chanRule,
|
||||
}
|
||||
|
|
@ -1100,7 +1128,7 @@ func TestInFlightLimit(t *testing.T) {
|
|||
existingSwaps []*loopdb.LoopOut
|
||||
// peerRules will only be set (instead of test default values)
|
||||
// is it is non-nil.
|
||||
peerRules map[route.Vertex]*ThresholdRule
|
||||
peerRules map[route.Vertex]*SwapRule
|
||||
suggestions *Suggestions
|
||||
}{
|
||||
{
|
||||
|
|
@ -1189,9 +1217,15 @@ func TestInFlightLimit(t *testing.T) {
|
|||
// Create two peer-level rules, both in need of a swap,
|
||||
// but peer 1 needs a larger swap so will be
|
||||
// prioritized.
|
||||
peerRules: map[route.Vertex]*ThresholdRule{
|
||||
peer1: NewThresholdRule(50, 0),
|
||||
peer2: NewThresholdRule(40, 0),
|
||||
peerRules: map[route.Vertex]*SwapRule{
|
||||
peer1: {
|
||||
ThresholdRule: NewThresholdRule(50, 0),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
peer2: {
|
||||
ThresholdRule: NewThresholdRule(40, 0),
|
||||
Type: swap.TypeOut,
|
||||
},
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
OutSwaps: []loop.OutRequest{
|
||||
|
|
@ -1224,7 +1258,7 @@ func TestInFlightLimit(t *testing.T) {
|
|||
params.PeerRules = testCase.peerRules
|
||||
} else {
|
||||
params.ChannelRules =
|
||||
map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
chanID2: chanRule,
|
||||
}
|
||||
|
|
@ -1364,7 +1398,7 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
|
||||
params := defaultParameters
|
||||
params.ClientRestrictions = testCase.clientRestrictions
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
}
|
||||
|
||||
|
|
@ -1522,7 +1556,7 @@ func TestFeePercentage(t *testing.T) {
|
|||
|
||||
params := defaultParameters
|
||||
params.FeeLimit = NewFeePortion(testCase.feePPM)
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
}
|
||||
|
||||
|
|
@ -1572,7 +1606,7 @@ func testSuggestSwaps(t *testing.T, setup *testSuggestSwapsSetup,
|
|||
}
|
||||
|
||||
params := defaultParameters
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
|
||||
params.ChannelRules = map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: chanRule,
|
||||
chanID2: chanRule,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightninglabs/loop/swap"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -19,6 +20,12 @@ var (
|
|||
"percentages must be < 100")
|
||||
)
|
||||
|
||||
// SwapRule is a liquidity rule with a specific swap type.
|
||||
type SwapRule struct {
|
||||
*ThresholdRule
|
||||
swap.Type
|
||||
}
|
||||
|
||||
// ThresholdRule is a liquidity rule that implements minimum incoming and
|
||||
// outgoing liquidity threshold.
|
||||
type ThresholdRule struct {
|
||||
|
|
|
|||
|
|
@ -750,7 +750,7 @@ func (s *swapClientServer) GetLiquidityParams(_ context.Context,
|
|||
}
|
||||
|
||||
func newRPCRule(channelID uint64, peer []byte,
|
||||
rule *liquidity.ThresholdRule) *looprpc.LiquidityRule {
|
||||
rule *liquidity.SwapRule) *looprpc.LiquidityRule {
|
||||
|
||||
return &looprpc.LiquidityRule{
|
||||
ChannelId: channelID,
|
||||
|
|
@ -781,10 +781,10 @@ func (s *swapClientServer) SetLiquidityParams(ctx context.Context,
|
|||
AutoFeeBudget: btcutil.Amount(in.Parameters.AutoloopBudgetSat),
|
||||
MaxAutoInFlight: int(in.Parameters.AutoMaxInFlight),
|
||||
ChannelRules: make(
|
||||
map[lnwire.ShortChannelID]*liquidity.ThresholdRule,
|
||||
map[lnwire.ShortChannelID]*liquidity.SwapRule,
|
||||
),
|
||||
PeerRules: make(
|
||||
map[route.Vertex]*liquidity.ThresholdRule,
|
||||
map[route.Vertex]*liquidity.SwapRule,
|
||||
),
|
||||
ClientRestrictions: liquidity.Restrictions{
|
||||
Minimum: btcutil.Amount(in.Parameters.MinSwapAmount),
|
||||
|
|
@ -890,16 +890,19 @@ func rpcToFee(req *looprpc.LiquidityParameters) (liquidity.FeeLimit,
|
|||
}
|
||||
|
||||
// rpcToRule switches on rpc rule type to convert to our rule interface.
|
||||
func rpcToRule(rule *looprpc.LiquidityRule) (*liquidity.ThresholdRule, error) {
|
||||
func rpcToRule(rule *looprpc.LiquidityRule) (*liquidity.SwapRule, error) {
|
||||
switch rule.Type {
|
||||
case looprpc.LiquidityRuleType_UNKNOWN:
|
||||
return nil, fmt.Errorf("rule type field must be set")
|
||||
|
||||
case looprpc.LiquidityRuleType_THRESHOLD:
|
||||
return liquidity.NewThresholdRule(
|
||||
int(rule.IncomingThreshold),
|
||||
int(rule.OutgoingThreshold),
|
||||
), nil
|
||||
return &liquidity.SwapRule{
|
||||
ThresholdRule: liquidity.NewThresholdRule(
|
||||
int(rule.IncomingThreshold),
|
||||
int(rule.OutgoingThreshold),
|
||||
),
|
||||
Type: swap.TypeOut,
|
||||
}, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown rule: %T", rule)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue