Skip to content

Commit 8217ee3

Browse files
committed
liquidity+loopd: refactor SetParameters to take a rpc request
This commit refactors the method `manager.SetParameters` to take a `SetLiquidityParamsRequest`. As we'll see in the following commit, this will enable us saving the params to disk more easily.
1 parent 9c5ac0f commit 8217ee3

File tree

5 files changed

+177
-150
lines changed

5 files changed

+177
-150
lines changed

liquidity/autoloop_testcontext_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func newAutoloopTestCtx(t *testing.T, parameters Parameters,
179179
// Create a manager with our test config and set our starting set of
180180
// parameters.
181181
testCtx.manager = NewManager(cfg)
182-
err := testCtx.manager.SetParameters(context.Background(), parameters)
182+
err := testCtx.manager.setParameters(context.Background(), parameters)
183183
assert.NoError(t, err)
184184
<-done
185185
return testCtx

liquidity/liquidity.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ import (
5252
"github.com/lightningnetwork/lnd/lnwire"
5353
"github.com/lightningnetwork/lnd/routing/route"
5454
"github.com/lightningnetwork/lnd/ticker"
55+
56+
clientrpc "github.com/lightninglabs/loop/looprpc"
5557
)
5658

5759
const (
@@ -239,9 +241,24 @@ func (m *Manager) GetParameters() Parameters {
239241
return cloneParameters(m.params)
240242
}
241243

244+
// SetParameters takes an RPC request and calls the internal method to set
245+
// parameters for the manager.
246+
func (m *Manager) SetParameters(ctx context.Context,
247+
req *clientrpc.LiquidityParameters) error {
248+
249+
params, err := rpcToParameters(req)
250+
if err != nil {
251+
return err
252+
}
253+
254+
return m.setParameters(ctx, *params)
255+
}
256+
242257
// SetParameters updates our current set of parameters if the new parameters
243258
// provided are valid.
244-
func (m *Manager) SetParameters(ctx context.Context, params Parameters) error {
259+
func (m *Manager) setParameters(ctx context.Context,
260+
params Parameters) error {
261+
245262
restrictions, err := m.cfg.Restrictions(ctx, swap.TypeOut)
246263
if err != nil {
247264
return err
@@ -252,7 +269,9 @@ func (m *Manager) SetParameters(ctx context.Context, params Parameters) error {
252269
return err
253270
}
254271

255-
err = params.validate(m.cfg.MinimumConfirmations, channels, restrictions)
272+
err = params.validate(
273+
m.cfg.MinimumConfirmations, channels, restrictions,
274+
)
256275
if err != nil {
257276
return err
258277
}

liquidity/liquidity_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func TestParameters(t *testing.T) {
221221
chanID: originalRule,
222222
}
223223

224-
err := manager.SetParameters(context.Background(), expected)
224+
err := manager.setParameters(context.Background(), expected)
225225
require.NoError(t, err)
226226

227227
// Check that changing the parameters we just set does not mutate
@@ -242,7 +242,7 @@ func TestParameters(t *testing.T) {
242242
Type: swap.TypeOut,
243243
},
244244
}
245-
err = manager.SetParameters(context.Background(), expected)
245+
err = manager.setParameters(context.Background(), expected)
246246
require.Equal(t, ErrZeroChannelID, err)
247247
}
248248

@@ -1778,7 +1778,7 @@ func testSuggestSwaps(t *testing.T, setup *testSuggestSwapsSetup,
17781778
// them to use the rules set by the test.
17791779
manager := NewManager(setup.cfg)
17801780

1781-
err := manager.SetParameters(context.Background(), setup.params)
1781+
err := manager.setParameters(context.Background(), setup.params)
17821782
require.NoError(t, err)
17831783

17841784
actual, err := manager.SuggestSwaps(context.Background(), false)
@@ -1960,7 +1960,7 @@ func TestCurrentTraffic(t *testing.T) {
19601960

19611961
params := m.GetParameters()
19621962
params.FailureBackOff = backoff
1963-
require.NoError(t, m.SetParameters(context.Background(), params))
1963+
require.NoError(t, m.setParameters(context.Background(), params))
19641964

19651965
actual := m.currentSwapTraffic(testCase.loopOut, testCase.loopIn)
19661966
require.Equal(t, testCase.expected, actual)

liquidity/parameters.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ import (
99
"github.com/btcsuite/btcd/btcutil"
1010
"github.com/lightninglabs/lndclient"
1111
"github.com/lightninglabs/loop/swap"
12+
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
1213
"github.com/lightningnetwork/lnd/lnwire"
1314
"github.com/lightningnetwork/lnd/routing/route"
15+
16+
clientrpc "github.com/lightninglabs/loop/looprpc"
1417
)
1518

1619
var (
@@ -271,3 +274,150 @@ func cloneParameters(params Parameters) Parameters {
271274

272275
return paramCopy
273276
}
277+
278+
// rpcToFee converts the values provided over rpc to a fee limit interface,
279+
// failing if an inconsistent set of fields are set.
280+
func rpcToFee(req *clientrpc.LiquidityParameters) (FeeLimit, error) {
281+
// Check which fee limit type we have values set for. If any fields
282+
// relevant to our individual categories are set, we count that type
283+
// as set.
284+
isFeePPM := req.FeePpm != 0
285+
isCategories := req.MaxSwapFeePpm != 0 || req.MaxRoutingFeePpm != 0 ||
286+
req.MaxPrepayRoutingFeePpm != 0 || req.MaxMinerFeeSat != 0 ||
287+
req.MaxPrepaySat != 0 || req.SweepFeeRateSatPerVbyte != 0
288+
289+
switch {
290+
case isFeePPM && isCategories:
291+
return nil, errors.New("set either fee ppm, or individual " +
292+
"fee categories")
293+
case isFeePPM:
294+
return NewFeePortion(req.FeePpm), nil
295+
296+
case isCategories:
297+
satPerKVbyte := chainfee.SatPerKVByte(
298+
req.SweepFeeRateSatPerVbyte * 1000,
299+
)
300+
301+
return NewFeeCategoryLimit(
302+
req.MaxSwapFeePpm,
303+
req.MaxRoutingFeePpm,
304+
req.MaxPrepayRoutingFeePpm,
305+
btcutil.Amount(req.MaxMinerFeeSat),
306+
btcutil.Amount(req.MaxPrepaySat),
307+
satPerKVbyte.FeePerKWeight(),
308+
), nil
309+
310+
default:
311+
return nil, errors.New("no fee categories set")
312+
}
313+
}
314+
315+
// rpcToRule switches on rpc rule type to convert to our rule interface.
316+
func rpcToRule(rule *clientrpc.LiquidityRule) (*SwapRule, error) {
317+
swapType := swap.TypeOut
318+
if rule.SwapType == clientrpc.SwapType_LOOP_IN {
319+
swapType = swap.TypeIn
320+
}
321+
322+
switch rule.Type {
323+
case clientrpc.LiquidityRuleType_UNKNOWN:
324+
return nil, fmt.Errorf("rule type field must be set")
325+
326+
case clientrpc.LiquidityRuleType_THRESHOLD:
327+
return &SwapRule{
328+
ThresholdRule: NewThresholdRule(
329+
int(rule.IncomingThreshold),
330+
int(rule.OutgoingThreshold),
331+
),
332+
Type: swapType,
333+
}, nil
334+
335+
default:
336+
return nil, fmt.Errorf("unknown rule: %T", rule)
337+
}
338+
}
339+
340+
// rpcToParameters takes a `LiquidityParameters` and creates a `Parameters`
341+
// from it.
342+
func rpcToParameters(req *clientrpc.LiquidityParameters) (*Parameters,
343+
error) {
344+
345+
feeLimit, err := rpcToFee(req)
346+
if err != nil {
347+
return nil, err
348+
}
349+
350+
params := &Parameters{
351+
FeeLimit: feeLimit,
352+
SweepConfTarget: req.SweepConfTarget,
353+
FailureBackOff: time.Duration(req.FailureBackoffSec) *
354+
time.Second,
355+
Autoloop: req.Autoloop,
356+
AutoFeeBudget: btcutil.Amount(req.AutoloopBudgetSat),
357+
MaxAutoInFlight: int(req.AutoMaxInFlight),
358+
ChannelRules: make(
359+
map[lnwire.ShortChannelID]*SwapRule,
360+
),
361+
PeerRules: make(
362+
map[route.Vertex]*SwapRule,
363+
),
364+
ClientRestrictions: Restrictions{
365+
Minimum: btcutil.Amount(req.MinSwapAmount),
366+
Maximum: btcutil.Amount(req.MaxSwapAmount),
367+
},
368+
HtlcConfTarget: req.HtlcConfTarget,
369+
}
370+
371+
// Zero unix time is different to zero golang time.
372+
if req.AutoloopBudgetStartSec != 0 {
373+
params.AutoFeeStartDate = time.Unix(
374+
int64(req.AutoloopBudgetStartSec), 0,
375+
)
376+
}
377+
378+
for _, rule := range req.Rules {
379+
peerRule := rule.Pubkey != nil
380+
chanRule := rule.ChannelId != 0
381+
382+
liquidityRule, err := rpcToRule(rule)
383+
if err != nil {
384+
return nil, err
385+
}
386+
387+
switch {
388+
case peerRule && chanRule:
389+
return nil, fmt.Errorf("cannot set channel: %v and "+
390+
"peer: %v fields in rule", rule.ChannelId,
391+
rule.Pubkey)
392+
393+
case peerRule:
394+
pubkey, err := route.NewVertexFromBytes(rule.Pubkey)
395+
if err != nil {
396+
return nil, err
397+
}
398+
399+
if _, ok := params.PeerRules[pubkey]; ok {
400+
return nil, fmt.Errorf("multiple rules set "+
401+
"for peer: %v", pubkey)
402+
}
403+
404+
params.PeerRules[pubkey] = liquidityRule
405+
406+
case chanRule:
407+
shortID := lnwire.NewShortChanIDFromInt(rule.ChannelId)
408+
409+
if _, ok := params.ChannelRules[shortID]; ok {
410+
return nil, fmt.Errorf("multiple rules set "+
411+
"for channel: %v", shortID)
412+
}
413+
414+
params.ChannelRules[shortID] = liquidityRule
415+
416+
default:
417+
return nil, errors.New("please set channel id or " +
418+
"pubkey for rule")
419+
}
420+
}
421+
422+
return params, nil
423+
}

0 commit comments

Comments
 (0)