Skip to content

Commit 9c5ac0f

Browse files
committed
liquidity: move parameters into a new file
This commit refactors the `liquidity` by moving `Parameters` related code into one file.
1 parent a4d343c commit 9c5ac0f

File tree

4 files changed

+334
-312
lines changed

4 files changed

+334
-312
lines changed

liquidity/liquidity.go

Lines changed: 0 additions & 258 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
"errors"
3838
"fmt"
3939
"sort"
40-
"strings"
4140
"sync"
4241
"time"
4342

@@ -102,19 +101,6 @@ var (
102101
// funding amount.
103102
defaultBudget = ppmToSat(funding.MaxBtcFundingAmount, defaultFeePPM)
104103

105-
// defaultParameters contains the default parameters that we start our
106-
// liquidity manger with.
107-
defaultParameters = Parameters{
108-
AutoFeeBudget: defaultBudget,
109-
MaxAutoInFlight: defaultMaxInFlight,
110-
ChannelRules: make(map[lnwire.ShortChannelID]*SwapRule),
111-
PeerRules: make(map[route.Vertex]*SwapRule),
112-
FailureBackOff: defaultFailureBackoff,
113-
SweepConfTarget: defaultConfTarget,
114-
HtlcConfTarget: defaultHtlcConfTarget,
115-
FeeLimit: defaultFeePortion(),
116-
}
117-
118104
// ErrZeroChannelID is returned if we get a rule for a 0 channel ID.
119105
ErrZeroChannelID = fmt.Errorf("zero channel ID not allowed")
120106

@@ -195,222 +181,6 @@ type Config struct {
195181
MinimumConfirmations int32
196182
}
197183

198-
// Parameters is a set of parameters provided by the user which guide
199-
// how we assess liquidity.
200-
type Parameters struct {
201-
// Autoloop enables automatic dispatch of swaps.
202-
Autoloop bool
203-
204-
// AutoFeeBudget is the total amount we allow to be spent on
205-
// automatically dispatched swaps. Once this budget has been used, we
206-
// will stop dispatching swaps until the budget is increased or the
207-
// start date is moved.
208-
AutoFeeBudget btcutil.Amount
209-
210-
// AutoFeeStartDate is the date from which we will include automatically
211-
// dispatched swaps in our current budget, inclusive.
212-
AutoFeeStartDate time.Time
213-
214-
// MaxAutoInFlight is the maximum number of in-flight automatically
215-
// dispatched swaps we allow.
216-
MaxAutoInFlight int
217-
218-
// FailureBackOff is the amount of time that we require passes after a
219-
// channel has been part of a failed loop out swap before we suggest
220-
// using it again.
221-
// TODO(carla): add exponential backoff
222-
FailureBackOff time.Duration
223-
224-
// SweepConfTarget is the number of blocks we aim to confirm our sweep
225-
// transaction in. This value affects the on chain fees we will pay.
226-
SweepConfTarget int32
227-
228-
// HtlcConfTarget is the confirmation target that we use for publishing
229-
// loop in swap htlcs on chain.
230-
HtlcConfTarget int32
231-
232-
// FeeLimit controls the fee limit we place on swaps.
233-
FeeLimit FeeLimit
234-
235-
// ClientRestrictions are the restrictions placed on swap size by the
236-
// client.
237-
ClientRestrictions Restrictions
238-
239-
// ChannelRules maps a short channel ID to a rule that describes how we
240-
// would like liquidity to be managed. These rules and PeerRules are
241-
// exclusively set to prevent overlap between peer and channel rules.
242-
ChannelRules map[lnwire.ShortChannelID]*SwapRule
243-
244-
// PeerRules maps a peer's pubkey to a rule that applies to all the
245-
// channels that we have with the peer collectively. These rules and
246-
// ChannelRules are exclusively set to prevent overlap between peer
247-
// and channel rules map to avoid ambiguity.
248-
PeerRules map[route.Vertex]*SwapRule
249-
}
250-
251-
// String returns the string representation of our parameters.
252-
func (p Parameters) String() string {
253-
ruleList := make([]string, 0, len(p.ChannelRules)+len(p.PeerRules))
254-
255-
for channel, rule := range p.ChannelRules {
256-
ruleList = append(
257-
ruleList, fmt.Sprintf("Channel: %v: %v", channel, rule),
258-
)
259-
}
260-
261-
for peer, rule := range p.PeerRules {
262-
ruleList = append(
263-
ruleList, fmt.Sprintf("Peer: %v: %v", peer, rule),
264-
)
265-
}
266-
267-
return fmt.Sprintf("rules: %v, failure backoff: %v, sweep "+
268-
"sweep conf target: %v, htlc conf target: %v,fees: %v, "+
269-
"auto budget: %v, budget start: %v, max auto in flight: %v, "+
270-
"minimum swap size=%v, maximum swap size=%v",
271-
strings.Join(ruleList, ","), p.FailureBackOff,
272-
p.SweepConfTarget, p.HtlcConfTarget, p.FeeLimit,
273-
p.AutoFeeBudget, p.AutoFeeStartDate, p.MaxAutoInFlight,
274-
p.ClientRestrictions.Minimum, p.ClientRestrictions.Maximum)
275-
}
276-
277-
// haveRules returns a boolean indicating whether we have any rules configured.
278-
func (p Parameters) haveRules() bool {
279-
if len(p.ChannelRules) != 0 {
280-
return true
281-
}
282-
283-
if len(p.PeerRules) != 0 {
284-
return true
285-
}
286-
287-
return false
288-
}
289-
290-
// validate checks whether a set of parameters is valid. Our set of currently
291-
// open channels are required to check that there is no overlap between the
292-
// rules set on a per-peer level, and those set for specific channels. We can't
293-
// allow both, because then we're trying to cater for two separate liquidity
294-
// goals on the same channel. Since we use short channel ID, we don't need to
295-
// worry about pending channels (users would need to work very hard to get the
296-
// short channel ID for a pending channel). Likewise, we don't care about closed
297-
// channels, since there is no action that may occur on them, and we want to
298-
// allow peer-level rules to be set once a channel which had a specific rule
299-
// has been closed. It takes the minimum confirmations we allow for sweep
300-
// confirmation target as a parameter.
301-
// TODO(carla): prune channels that have been closed from rules.
302-
func (p Parameters) validate(minConfs int32, openChans []lndclient.ChannelInfo,
303-
server *Restrictions) error {
304-
305-
// First, we check that the rules on a per peer and per channel do not
306-
// overlap, since this could lead to contractions.
307-
for _, channel := range openChans {
308-
// If we don't have a rule for the peer, there's no way we have
309-
// an overlap between this peer and the channel.
310-
_, ok := p.PeerRules[channel.PubKeyBytes]
311-
if !ok {
312-
continue
313-
}
314-
315-
shortID := lnwire.NewShortChanIDFromInt(channel.ChannelID)
316-
_, ok = p.ChannelRules[shortID]
317-
if ok {
318-
log.Debugf("Rules for peer: %v and its channel: %v "+
319-
"can't both be set", channel.PubKeyBytes, shortID)
320-
321-
return ErrExclusiveRules
322-
}
323-
}
324-
325-
for channel, rule := range p.ChannelRules {
326-
if channel.ToUint64() == 0 {
327-
return ErrZeroChannelID
328-
}
329-
330-
if rule.Type == swap.TypeIn {
331-
return errors.New("channel level rules not supported for " +
332-
"loop in swaps, only peer-level rules allowed")
333-
}
334-
335-
if err := rule.validate(); err != nil {
336-
return fmt.Errorf("channel: %v has invalid rule: %v",
337-
channel.ToUint64(), err)
338-
}
339-
}
340-
341-
for peer, rule := range p.PeerRules {
342-
if err := rule.validate(); err != nil {
343-
return fmt.Errorf("peer: %v has invalid rule: %v",
344-
peer, err)
345-
}
346-
}
347-
348-
// Check that our confirmation target is above our required minimum.
349-
if p.SweepConfTarget < minConfs {
350-
return fmt.Errorf("confirmation target must be at least: %v",
351-
minConfs)
352-
}
353-
354-
if p.HtlcConfTarget < 1 {
355-
return fmt.Errorf("htlc confirmation target must be > 0")
356-
}
357-
358-
if err := p.FeeLimit.validate(); err != nil {
359-
return err
360-
}
361-
362-
if p.AutoFeeBudget < 0 {
363-
return ErrNegativeBudget
364-
}
365-
366-
if p.MaxAutoInFlight <= 0 {
367-
return ErrZeroInFlight
368-
}
369-
370-
err := validateRestrictions(server, &p.ClientRestrictions)
371-
if err != nil {
372-
return err
373-
}
374-
375-
return nil
376-
}
377-
378-
// validateRestrictions checks that client restrictions fall within the server's
379-
// restrictions.
380-
func validateRestrictions(server, client *Restrictions) error {
381-
zeroMin := client.Minimum == 0
382-
zeroMax := client.Maximum == 0
383-
384-
if zeroMin && zeroMax {
385-
return nil
386-
}
387-
388-
// If we have a non-zero maximum, we need to ensure it is greater than
389-
// our minimum (which is fine if min is zero), and does not exceed the
390-
// server's maximum.
391-
if !zeroMax {
392-
if client.Minimum > client.Maximum {
393-
return ErrMinimumExceedsMaximumAmt
394-
}
395-
396-
if client.Maximum > server.Maximum {
397-
return ErrMaxExceedsServer
398-
}
399-
}
400-
401-
if zeroMin {
402-
return nil
403-
}
404-
405-
// If the client set a minimum, ensure it is at least equal to the
406-
// server's limit.
407-
if client.Minimum < server.Minimum {
408-
return ErrMinLessThanServer
409-
}
410-
411-
return nil
412-
}
413-
414184
// Manager contains a set of desired liquidity rules for our channel
415185
// balances.
416186
type Manager struct {
@@ -494,34 +264,6 @@ func (m *Manager) SetParameters(ctx context.Context, params Parameters) error {
494264
return nil
495265
}
496266

497-
// cloneParameters creates a deep clone of a parameters struct so that callers
498-
// cannot mutate our parameters. Although our parameters struct itself is not
499-
// a reference, we still need to clone the contents of maps.
500-
func cloneParameters(params Parameters) Parameters {
501-
paramCopy := params
502-
paramCopy.ChannelRules = make(
503-
map[lnwire.ShortChannelID]*SwapRule,
504-
len(params.ChannelRules),
505-
)
506-
507-
for channel, rule := range params.ChannelRules {
508-
ruleCopy := *rule
509-
paramCopy.ChannelRules[channel] = &ruleCopy
510-
}
511-
512-
paramCopy.PeerRules = make(
513-
map[route.Vertex]*SwapRule,
514-
len(params.PeerRules),
515-
)
516-
517-
for peer, rule := range params.PeerRules {
518-
ruleCopy := *rule
519-
paramCopy.PeerRules[peer] = &ruleCopy
520-
}
521-
522-
return paramCopy
523-
}
524-
525267
// autoloop gets a set of suggested swaps and dispatches them automatically if
526268
// we have automated looping enabled.
527269
func (m *Manager) autoloop(ctx context.Context) error {

liquidity/liquidity_test.go

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -246,60 +246,6 @@ func TestParameters(t *testing.T) {
246246
require.Equal(t, ErrZeroChannelID, err)
247247
}
248248

249-
// TestValidateRestrictions tests validating client restrictions against a set
250-
// of server restrictions.
251-
func TestValidateRestrictions(t *testing.T) {
252-
tests := []struct {
253-
name string
254-
client *Restrictions
255-
server *Restrictions
256-
err error
257-
}{
258-
{
259-
name: "client invalid",
260-
client: &Restrictions{
261-
Minimum: 100,
262-
Maximum: 1,
263-
},
264-
server: testRestrictions,
265-
err: ErrMinimumExceedsMaximumAmt,
266-
},
267-
{
268-
name: "maximum exceeds server",
269-
client: &Restrictions{
270-
Maximum: 2000,
271-
},
272-
server: &Restrictions{
273-
Minimum: 1000,
274-
Maximum: 1500,
275-
},
276-
err: ErrMaxExceedsServer,
277-
},
278-
{
279-
name: "minimum less than server",
280-
client: &Restrictions{
281-
Minimum: 500,
282-
},
283-
server: &Restrictions{
284-
Minimum: 1000,
285-
Maximum: 1500,
286-
},
287-
err: ErrMinLessThanServer,
288-
},
289-
}
290-
291-
for _, testCase := range tests {
292-
testCase := testCase
293-
294-
t.Run(testCase.name, func(t *testing.T) {
295-
err := validateRestrictions(
296-
testCase.server, testCase.client,
297-
)
298-
require.Equal(t, testCase.err, err)
299-
})
300-
}
301-
}
302-
303249
// TestRestrictedSuggestions tests getting of swap suggestions when we have
304250
// other in-flight swaps. We setup our manager with a set of channels and rules
305251
// that require a loop out swap, focusing on the filtering our of channels that

0 commit comments

Comments
 (0)