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.
pull/433/head
carla 2 years ago
parent 00c2d4e5f0
commit 25b8d20f75
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91

@ -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…
Cancel
Save