mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
Merge pull request #419 from carlaKC/autoloop-4-loopin
liquidity: add loopin to autoloop
This commit is contained in:
commit
be6eae3bda
18 changed files with 1340 additions and 277 deletions
|
|
@ -48,6 +48,14 @@ var setLiquidityRuleCommand = cli.Command{
|
|||
Description: "Update or remove the liquidity rule for a channel/peer.",
|
||||
ArgsUsage: "{shortchanid | peerpubkey}",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "type",
|
||||
Usage: "the type of swap to perform, set to 'out' " +
|
||||
"for acquiring inbound liquidity or 'in' for " +
|
||||
"acquiring outbound liquidity.",
|
||||
Value: "out",
|
||||
},
|
||||
|
||||
cli.IntFlag{
|
||||
Name: "incoming_threshold",
|
||||
Usage: "the minimum percentage of incoming liquidity " +
|
||||
|
|
@ -168,7 +176,18 @@ func setRule(ctx *cli.Context) error {
|
|||
newRule := &looprpc.LiquidityRule{
|
||||
ChannelId: chanID,
|
||||
Type: looprpc.LiquidityRuleType_THRESHOLD,
|
||||
SwapType: looprpc.SwapType_LOOP_OUT,
|
||||
}
|
||||
if ctx.IsSet("type") {
|
||||
switch ctx.String("type") {
|
||||
case "in":
|
||||
newRule.SwapType = looprpc.SwapType_LOOP_IN
|
||||
|
||||
case "out":
|
||||
newRule.SwapType = looprpc.SwapType_LOOP_OUT
|
||||
|
||||
default:
|
||||
return errors.New("please set type to in or out")
|
||||
}
|
||||
}
|
||||
|
||||
if pubkeyRule {
|
||||
|
|
@ -292,6 +311,11 @@ var setParamsCommand = cli.Command{
|
|||
Usage: "the maximum amount in satoshis that the " +
|
||||
"autoloop client will dispatch per-swap",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "htlc_conf",
|
||||
Usage: "the confirmation target for loop in on-chain " +
|
||||
"htlcs",
|
||||
},
|
||||
},
|
||||
Action: setParams,
|
||||
}
|
||||
|
|
@ -422,6 +446,11 @@ func setParams(ctx *cli.Context) error {
|
|||
flagSet = true
|
||||
}
|
||||
|
||||
if ctx.IsSet("htlc_conf") {
|
||||
params.HtlcConfTarget = int32(ctx.Int("htlc_conf"))
|
||||
flagSet = true
|
||||
}
|
||||
|
||||
if !flagSet {
|
||||
return fmt.Errorf("at least one flag required to set params")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,16 @@ following command:
|
|||
loop setparams --autoloop=true
|
||||
```
|
||||
|
||||
At present, autoloop can be configured to either acquire incoming liquidity
|
||||
using loop out, or acquire outgoing liquidity using loop in. It cannot support
|
||||
automated swaps in both directions. To set the type of swaps you would like
|
||||
to automatically dispatch, use:
|
||||
```
|
||||
loop setparams --type={in|out}
|
||||
```
|
||||
|
||||
Autoloop will perform loop out swaps *by default*.
|
||||
|
||||
Swaps that are dispatched by the autolooper can be identified in the output of
|
||||
`ListSwaps` by their label field, which will contain: `[reserved]: autoloop-out`.
|
||||
|
||||
|
|
@ -286,7 +296,9 @@ following reasons will be displayed:
|
|||
* Fee insufficient: if the fees that a swap will cost are more than the
|
||||
percentage of total swap amount that we allow, this reason will be displayed.
|
||||
See [fees](#fees) to update this value.
|
||||
|
||||
* Loop in unreachable: if the client node is unreachable by the server
|
||||
off-chain, this reason will be displayed. Try improving the connectivity of
|
||||
your node so that it is reachable by the loop server.
|
||||
|
||||
Further details for all of these reasons can be found in loopd's debug level
|
||||
logs.
|
||||
|
|
|
|||
|
|
@ -50,13 +50,22 @@ func TestAutoLoopDisabled(t *testing.T) {
|
|||
// loop in/out swaps. We expect a swap for our channel to be suggested,
|
||||
// but do not expect any swaps to be executed, since autoloop is
|
||||
// disabled by default.
|
||||
c.autoloop(1, chan1Rec.Amount+1, nil, quotes, nil)
|
||||
step := &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: chan1Rec.Amount + 1,
|
||||
quotesOut: quotes,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
// Trigger another autoloop, this time setting our server restrictions
|
||||
// to have a minimum swap amount greater than the amount that we need
|
||||
// to swap. In this case we don't even expect to get a quote, because
|
||||
// our suggested swap is beneath the minimum swap size.
|
||||
c.autoloop(chan1Rec.Amount+1, chan1Rec.Amount+2, nil, nil, nil)
|
||||
step = &autoloopStep{
|
||||
minAmt: chan1Rec.Amount + 1,
|
||||
maxAmt: chan1Rec.Amount + 2,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
c.stop()
|
||||
}
|
||||
|
|
@ -99,6 +108,7 @@ func TestAutoLoopEnabled(t *testing.T) {
|
|||
chanID1: chanRule,
|
||||
chanID2: chanRule,
|
||||
},
|
||||
HtlcConfTarget: defaultHtlcConfTarget,
|
||||
}
|
||||
)
|
||||
c := newAutoloopTestCtx(t, params, channels, testRestrictions)
|
||||
|
|
@ -191,7 +201,13 @@ func TestAutoLoopEnabled(t *testing.T) {
|
|||
|
||||
// Tick our autolooper with no existing swaps, we expect a loop out
|
||||
// swap to be dispatched for each channel.
|
||||
c.autoloop(1, amt+1, nil, quotes, loopOuts)
|
||||
step := &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: amt + 1,
|
||||
quotesOut: quotes,
|
||||
expectedOut: loopOuts,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
// Tick again with both of our swaps in progress. We haven't shifted our
|
||||
// channel balances at all, so swaps should still be suggested, but we
|
||||
|
|
@ -201,7 +217,12 @@ func TestAutoLoopEnabled(t *testing.T) {
|
|||
existingSwapFromRequest(chan2Swap, testTime, nil),
|
||||
}
|
||||
|
||||
c.autoloop(1, amt+1, existing, nil, nil)
|
||||
step = &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: amt + 1,
|
||||
existingOut: existing,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
// Now, we update our channel 2 swap to have failed due to off chain
|
||||
// failure and our first swap to have succeeded.
|
||||
|
|
@ -254,7 +275,14 @@ func TestAutoLoopEnabled(t *testing.T) {
|
|||
// We tick again, this time we expect another swap on channel 1 (which
|
||||
// still has balances which reflect that we need to swap), but nothing
|
||||
// for channel 2, since it has had a failure.
|
||||
c.autoloop(1, amt+1, existing, quotes, loopOuts)
|
||||
step = &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: amt + 1,
|
||||
existingOut: existing,
|
||||
quotesOut: quotes,
|
||||
expectedOut: loopOuts,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
// Now, we progress our time so that we have sufficiently backed off
|
||||
// for channel 2, and could perform another swap.
|
||||
|
|
@ -268,7 +296,13 @@ func TestAutoLoopEnabled(t *testing.T) {
|
|||
existingSwapFromRequest(chan2Swap, testTime, failedOffChain),
|
||||
}
|
||||
|
||||
c.autoloop(1, amt+1, existing, quotes, nil)
|
||||
step = &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: amt + 1,
|
||||
existingOut: existing,
|
||||
quotesOut: quotes,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
c.stop()
|
||||
}
|
||||
|
|
@ -318,6 +352,7 @@ func TestCompositeRules(t *testing.T) {
|
|||
PeerRules: map[route.Vertex]*SwapRule{
|
||||
peer2: chanRule,
|
||||
},
|
||||
HtlcConfTarget: defaultHtlcConfTarget,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -425,11 +460,360 @@ func TestCompositeRules(t *testing.T) {
|
|||
// swap to be dispatched for each of our rules. We set our server side
|
||||
// maximum to be greater than the swap amount for our peer swap (which
|
||||
// is the larger of the two swaps).
|
||||
c.autoloop(1, peerAmount+1, nil, quotes, loopOuts)
|
||||
step := &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: peerAmount + 1,
|
||||
quotesOut: quotes,
|
||||
expectedOut: loopOuts,
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
c.stop()
|
||||
}
|
||||
|
||||
// TestAutoLoopInEnabled tests dispatch of autoloop in swaps.
|
||||
func TestAutoLoopInEnabled(t *testing.T) {
|
||||
defer test.Guard(t)()
|
||||
|
||||
var (
|
||||
chan1 = lndclient.ChannelInfo{
|
||||
ChannelID: chanID1.ToUint64(),
|
||||
PubKeyBytes: peer1,
|
||||
Capacity: 100000,
|
||||
RemoteBalance: 100000,
|
||||
LocalBalance: 0,
|
||||
}
|
||||
|
||||
chan2 = lndclient.ChannelInfo{
|
||||
ChannelID: chanID2.ToUint64(),
|
||||
PubKeyBytes: peer2,
|
||||
Capacity: 200000,
|
||||
RemoteBalance: 200000,
|
||||
LocalBalance: 0,
|
||||
}
|
||||
|
||||
channels = []lndclient.ChannelInfo{
|
||||
chan1, chan2,
|
||||
}
|
||||
|
||||
// Create a rule which will loop in, with no inbound liquidity
|
||||
// reserve.
|
||||
rule = &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(0, 60),
|
||||
Type: swap.TypeIn,
|
||||
}
|
||||
|
||||
// Under these rules, we'll have the following recommended
|
||||
// swaps:
|
||||
peer1ExpectedAmt btcutil.Amount = 80000
|
||||
peer2ExpectedAmt btcutil.Amount = 160000
|
||||
|
||||
// Set our per-swap budget to 5% of swap amount.
|
||||
swapFeePPM uint64 = 50000
|
||||
|
||||
htlcConfTarget int32 = 10
|
||||
|
||||
// Calculate the maximum amount we'll pay for each swap and
|
||||
// set our budget to be able to accommodate both.
|
||||
peer1MaxFee = ppmToSat(peer1ExpectedAmt, swapFeePPM)
|
||||
peer2MaxFee = ppmToSat(peer2ExpectedAmt, swapFeePPM)
|
||||
|
||||
params = Parameters{
|
||||
Autoloop: true,
|
||||
AutoFeeBudget: peer1MaxFee + peer2MaxFee + 1,
|
||||
AutoFeeStartDate: testTime,
|
||||
MaxAutoInFlight: 2,
|
||||
FailureBackOff: time.Hour,
|
||||
FeeLimit: NewFeePortion(swapFeePPM),
|
||||
ChannelRules: make(map[lnwire.ShortChannelID]*SwapRule),
|
||||
PeerRules: map[route.Vertex]*SwapRule{
|
||||
peer1: rule,
|
||||
peer2: rule,
|
||||
},
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
SweepConfTarget: loop.DefaultSweepConfTarget,
|
||||
}
|
||||
)
|
||||
c := newAutoloopTestCtx(t, params, channels, testRestrictions)
|
||||
c.start()
|
||||
|
||||
// Calculate our maximum allowed fees and create quotes that fall within
|
||||
// our budget.
|
||||
var (
|
||||
quote1 = &loop.LoopInQuote{
|
||||
SwapFee: peer1MaxFee / 4,
|
||||
MinerFee: peer1MaxFee / 8,
|
||||
}
|
||||
|
||||
quote2Unaffordable = &loop.LoopInQuote{
|
||||
SwapFee: peer2MaxFee * 2,
|
||||
MinerFee: peer2MaxFee * 2,
|
||||
}
|
||||
|
||||
quoteRequest1 = &loop.LoopInQuoteRequest{
|
||||
Amount: peer1ExpectedAmt,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer1,
|
||||
}
|
||||
|
||||
quoteRequest2 = &loop.LoopInQuoteRequest{
|
||||
Amount: peer2ExpectedAmt,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer2,
|
||||
}
|
||||
|
||||
peer1Swap = &loop.LoopInRequest{
|
||||
Amount: peer1ExpectedAmt,
|
||||
MaxSwapFee: quote1.SwapFee,
|
||||
MaxMinerFee: quote1.MinerFee,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer1,
|
||||
ExternalHtlc: false,
|
||||
Label: labels.AutoloopLabel(swap.TypeIn),
|
||||
Initiator: autoloopSwapInitiator,
|
||||
}
|
||||
)
|
||||
|
||||
// Tick our autolooper with no existing swaps. Both of our peers
|
||||
// require swaps, but one of our peer's quotes is too expensive.
|
||||
step := &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: peer2ExpectedAmt + 1,
|
||||
quotesIn: []quoteInRequestResp{
|
||||
{
|
||||
request: quoteRequest1,
|
||||
quote: quote1,
|
||||
},
|
||||
{
|
||||
request: quoteRequest2,
|
||||
quote: quote2Unaffordable,
|
||||
},
|
||||
},
|
||||
expectedIn: []loopInRequestResp{
|
||||
{
|
||||
request: peer1Swap,
|
||||
response: &loop.LoopInSwapInfo{
|
||||
SwapHash: lntypes.Hash{1},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
// Now, we tick again with our first swap in progress. This time, we
|
||||
// provide a quote for our second swap which is more affordable, so we
|
||||
// expect it to be dispatched.
|
||||
|
||||
var (
|
||||
quote2Affordable = &loop.LoopInQuote{
|
||||
SwapFee: peer2MaxFee / 8,
|
||||
MinerFee: peer2MaxFee / 2,
|
||||
}
|
||||
|
||||
peer2Swap = &loop.LoopInRequest{
|
||||
Amount: peer2ExpectedAmt,
|
||||
MaxSwapFee: quote2Affordable.SwapFee,
|
||||
MaxMinerFee: quote2Affordable.MinerFee,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer2,
|
||||
ExternalHtlc: false,
|
||||
Label: labels.AutoloopLabel(swap.TypeIn),
|
||||
Initiator: autoloopSwapInitiator,
|
||||
}
|
||||
|
||||
existing = []*loopdb.LoopIn{
|
||||
existingInFromRequest(peer1Swap, testTime, nil),
|
||||
}
|
||||
)
|
||||
|
||||
step = &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: peer2ExpectedAmt + 1,
|
||||
quotesIn: []quoteInRequestResp{
|
||||
{
|
||||
request: quoteRequest2,
|
||||
quote: quote2Affordable,
|
||||
},
|
||||
},
|
||||
existingIn: existing,
|
||||
expectedIn: []loopInRequestResp{
|
||||
{
|
||||
request: peer2Swap,
|
||||
response: &loop.LoopInSwapInfo{
|
||||
SwapHash: lntypes.Hash{2},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.autoloop(step)
|
||||
|
||||
c.stop()
|
||||
}
|
||||
|
||||
// TestAutoloopBothTypes tests dispatching of a loop out and loop in swap at the
|
||||
// same time.
|
||||
func TestAutoloopBothTypes(t *testing.T) {
|
||||
defer test.Guard(t)()
|
||||
|
||||
var (
|
||||
chan1 = lndclient.ChannelInfo{
|
||||
ChannelID: chanID1.ToUint64(),
|
||||
PubKeyBytes: peer1,
|
||||
Capacity: 1000000,
|
||||
LocalBalance: 1000000,
|
||||
}
|
||||
chan2 = lndclient.ChannelInfo{
|
||||
ChannelID: chanID2.ToUint64(),
|
||||
PubKeyBytes: peer2,
|
||||
Capacity: 200000,
|
||||
RemoteBalance: 200000,
|
||||
LocalBalance: 0,
|
||||
}
|
||||
|
||||
channels = []lndclient.ChannelInfo{
|
||||
chan1, chan2,
|
||||
}
|
||||
|
||||
// Create a rule which will loop out, with no outbound liquidity
|
||||
// reserve.
|
||||
outRule = &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(40, 0),
|
||||
Type: swap.TypeOut,
|
||||
}
|
||||
|
||||
// Create a rule which will loop in, with no inbound liquidity
|
||||
// reserve.
|
||||
inRule = &SwapRule{
|
||||
ThresholdRule: NewThresholdRule(0, 60),
|
||||
Type: swap.TypeIn,
|
||||
}
|
||||
|
||||
// Under this rule, we expect a loop in swap.
|
||||
loopOutAmt btcutil.Amount = 700000
|
||||
loopInAmount btcutil.Amount = 160000
|
||||
|
||||
// Set our per-swap budget to 5% of swap amount.
|
||||
swapFeePPM uint64 = 50000
|
||||
|
||||
htlcConfTarget int32 = 10
|
||||
|
||||
// Calculate the maximum amount we'll pay for our loop in.
|
||||
loopOutMaxFee = ppmToSat(loopOutAmt, swapFeePPM)
|
||||
loopInMaxFee = ppmToSat(loopInAmount, swapFeePPM)
|
||||
|
||||
params = Parameters{
|
||||
Autoloop: true,
|
||||
AutoFeeBudget: loopOutMaxFee + loopInMaxFee + 1,
|
||||
AutoFeeStartDate: testTime,
|
||||
MaxAutoInFlight: 2,
|
||||
FailureBackOff: time.Hour,
|
||||
FeeLimit: NewFeePortion(swapFeePPM),
|
||||
ChannelRules: map[lnwire.ShortChannelID]*SwapRule{
|
||||
chanID1: outRule,
|
||||
},
|
||||
PeerRules: map[route.Vertex]*SwapRule{
|
||||
peer2: inRule,
|
||||
},
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
SweepConfTarget: loop.DefaultSweepConfTarget,
|
||||
}
|
||||
)
|
||||
c := newAutoloopTestCtx(t, params, channels, testRestrictions)
|
||||
c.start()
|
||||
|
||||
// Calculate our maximum allowed fees and create quotes that fall within
|
||||
// our budget.
|
||||
var (
|
||||
loopOutQuote = &loop.LoopOutQuote{
|
||||
SwapFee: loopOutMaxFee / 4,
|
||||
PrepayAmount: loopOutMaxFee / 4,
|
||||
}
|
||||
|
||||
loopOutQuoteReq = &loop.LoopOutQuoteRequest{
|
||||
Amount: loopOutAmt,
|
||||
SweepConfTarget: params.SweepConfTarget,
|
||||
SwapPublicationDeadline: testTime,
|
||||
}
|
||||
|
||||
prepayMaxFee, routeMaxFee,
|
||||
minerFee = params.FeeLimit.loopOutFees(
|
||||
loopOutAmt, loopOutQuote,
|
||||
)
|
||||
|
||||
loopOutSwap = &loop.OutRequest{
|
||||
Amount: loopOutAmt,
|
||||
MaxSwapRoutingFee: routeMaxFee,
|
||||
MaxPrepayRoutingFee: prepayMaxFee,
|
||||
MaxSwapFee: loopOutQuote.SwapFee,
|
||||
MaxPrepayAmount: loopOutQuote.PrepayAmount,
|
||||
MaxMinerFee: minerFee,
|
||||
SweepConfTarget: params.SweepConfTarget,
|
||||
OutgoingChanSet: loopdb.ChannelSet{
|
||||
chanID1.ToUint64(),
|
||||
},
|
||||
Label: labels.AutoloopLabel(swap.TypeOut),
|
||||
Initiator: autoloopSwapInitiator,
|
||||
}
|
||||
|
||||
loopinQuote = &loop.LoopInQuote{
|
||||
SwapFee: loopInMaxFee / 4,
|
||||
MinerFee: loopInMaxFee / 8,
|
||||
}
|
||||
|
||||
loopInQuoteReq = &loop.LoopInQuoteRequest{
|
||||
Amount: loopInAmount,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer2,
|
||||
}
|
||||
|
||||
loopInSwap = &loop.LoopInRequest{
|
||||
Amount: loopInAmount,
|
||||
MaxSwapFee: loopinQuote.SwapFee,
|
||||
MaxMinerFee: loopinQuote.MinerFee,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer2,
|
||||
ExternalHtlc: false,
|
||||
Label: labels.AutoloopLabel(swap.TypeIn),
|
||||
Initiator: autoloopSwapInitiator,
|
||||
}
|
||||
)
|
||||
|
||||
step := &autoloopStep{
|
||||
minAmt: 1,
|
||||
maxAmt: loopOutAmt + 1,
|
||||
quotesOut: []quoteRequestResp{
|
||||
{
|
||||
request: loopOutQuoteReq,
|
||||
quote: loopOutQuote,
|
||||
},
|
||||
},
|
||||
quotesIn: []quoteInRequestResp{
|
||||
{
|
||||
request: loopInQuoteReq,
|
||||
quote: loopinQuote,
|
||||
},
|
||||
},
|
||||
expectedOut: []loopOutRequestResp{
|
||||
{
|
||||
request: loopOutSwap,
|
||||
response: &loop.LoopOutSwapInfo{
|
||||
SwapHash: lntypes.Hash{1},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedIn: []loopInRequestResp{
|
||||
{
|
||||
request: loopInSwap,
|
||||
response: &loop.LoopInSwapInfo{
|
||||
SwapHash: lntypes.Hash{2},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.autoloop(step)
|
||||
c.stop()
|
||||
}
|
||||
|
||||
// existingSwapFromRequest is a helper function which returns the db
|
||||
// representation of a loop out request with the event set provided.
|
||||
func existingSwapFromRequest(request *loop.OutRequest, initTime time.Time,
|
||||
|
|
@ -455,3 +839,24 @@ func existingSwapFromRequest(request *loop.OutRequest, initTime time.Time,
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func existingInFromRequest(in *loop.LoopInRequest, initTime time.Time,
|
||||
events []*loopdb.LoopEvent) *loopdb.LoopIn {
|
||||
|
||||
return &loopdb.LoopIn{
|
||||
Loop: loopdb.Loop{
|
||||
Events: events,
|
||||
},
|
||||
Contract: &loopdb.LoopInContract{
|
||||
SwapContract: loopdb.SwapContract{
|
||||
MaxSwapFee: in.MaxSwapFee,
|
||||
MaxMinerFee: in.MaxMinerFee,
|
||||
InitiationTime: initTime,
|
||||
Label: in.Label,
|
||||
},
|
||||
HtlcConfTarget: in.HtlcConfTarget,
|
||||
LastHop: in.LastHop,
|
||||
ExternalHtlc: in.ExternalHtlc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,21 @@ type autoloopTestCtx struct {
|
|||
// quotes is a channel that we get loop out quote requests on.
|
||||
quotes chan *loop.LoopOutQuote
|
||||
|
||||
// quoteRequestIn is a channel that requests for loop in quotes are
|
||||
// pushed into.
|
||||
quoteRequestIn chan *loop.LoopInQuoteRequest
|
||||
|
||||
// quotesIn is a channel that we get loop in quote responses on.
|
||||
quotesIn chan *loop.LoopInQuote
|
||||
|
||||
// loopOutRestrictions is a channel that we get the server's
|
||||
// restrictions on.
|
||||
loopOutRestrictions chan *Restrictions
|
||||
|
||||
// loopInRestrictions is a channel that we get the server's
|
||||
// loop in restrictions on.
|
||||
loopInRestrictions chan *Restrictions
|
||||
|
||||
// loopOuts is a channel that we get existing loop out swaps on.
|
||||
loopOuts chan []*loopdb.LoopOut
|
||||
|
||||
|
|
@ -47,6 +58,13 @@ type autoloopTestCtx struct {
|
|||
// loopOut is a channel that we return loop out responses on.
|
||||
loopOut chan *loop.LoopOutSwapInfo
|
||||
|
||||
// inRequest is a channel that requests to dispatch loop in swaps are
|
||||
// pushed into.
|
||||
inRequest chan *loop.LoopInRequest
|
||||
|
||||
// loopIn is a channel that we return loop in responses on.
|
||||
loopIn chan *loop.LoopInSwapInfo
|
||||
|
||||
// errChan is a channel that we send run errors into.
|
||||
errChan chan error
|
||||
|
||||
|
|
@ -80,14 +98,18 @@ func newAutoloopTestCtx(t *testing.T, parameters Parameters,
|
|||
|
||||
quoteRequest: make(chan *loop.LoopOutQuoteRequest),
|
||||
quotes: make(chan *loop.LoopOutQuote),
|
||||
quoteRequestIn: make(chan *loop.LoopInQuoteRequest),
|
||||
quotesIn: make(chan *loop.LoopInQuote),
|
||||
loopOutRestrictions: make(chan *Restrictions),
|
||||
loopInRestrictions: make(chan *Restrictions),
|
||||
loopOuts: make(chan []*loopdb.LoopOut),
|
||||
loopIns: make(chan []*loopdb.LoopIn),
|
||||
restrictions: make(chan *Restrictions),
|
||||
outRequest: make(chan *loop.OutRequest),
|
||||
loopOut: make(chan *loop.LoopOutSwapInfo),
|
||||
|
||||
errChan: make(chan error, 1),
|
||||
inRequest: make(chan *loop.LoopInRequest),
|
||||
loopIn: make(chan *loop.LoopInSwapInfo),
|
||||
errChan: make(chan error, 1),
|
||||
}
|
||||
|
||||
// Set lnd's channels to equal the set of channels we want for our
|
||||
|
|
@ -96,10 +118,14 @@ func newAutoloopTestCtx(t *testing.T, parameters Parameters,
|
|||
|
||||
cfg := &Config{
|
||||
AutoloopTicker: ticker.NewForce(DefaultAutoloopTicker),
|
||||
Restrictions: func(context.Context, swap.Type) (*Restrictions,
|
||||
Restrictions: func(_ context.Context, swapType swap.Type) (*Restrictions,
|
||||
error) {
|
||||
|
||||
return <-testCtx.loopOutRestrictions, nil
|
||||
if swapType == swap.TypeOut {
|
||||
return <-testCtx.loopOutRestrictions, nil
|
||||
}
|
||||
|
||||
return <-testCtx.loopInRestrictions, nil
|
||||
},
|
||||
ListLoopOut: func() ([]*loopdb.LoopOut, error) {
|
||||
return <-testCtx.loopOuts, nil
|
||||
|
|
@ -123,6 +149,20 @@ func newAutoloopTestCtx(t *testing.T, parameters Parameters,
|
|||
|
||||
return <-testCtx.loopOut, nil
|
||||
},
|
||||
LoopInQuote: func(_ context.Context,
|
||||
req *loop.LoopInQuoteRequest) (*loop.LoopInQuote, error) {
|
||||
|
||||
testCtx.quoteRequestIn <- req
|
||||
|
||||
return <-testCtx.quotesIn, nil
|
||||
},
|
||||
LoopIn: func(_ context.Context,
|
||||
req *loop.LoopInRequest) (*loop.LoopInSwapInfo, error) {
|
||||
|
||||
testCtx.inRequest <- req
|
||||
|
||||
return <-testCtx.loopIn, nil
|
||||
},
|
||||
MinimumConfirmations: loop.DefaultSweepConfTarget,
|
||||
Lnd: &testCtx.lnd.LndServices,
|
||||
Clock: testCtx.testClock,
|
||||
|
|
@ -177,31 +217,70 @@ type loopOutRequestResp struct {
|
|||
response *loop.LoopOutSwapInfo
|
||||
}
|
||||
|
||||
// quoteInRequestResp pairs an expected loop in quote request with the response
|
||||
// we would like to provide the manager with.
|
||||
type quoteInRequestResp struct {
|
||||
request *loop.LoopInQuoteRequest
|
||||
quote *loop.LoopInQuote
|
||||
}
|
||||
|
||||
// loopInRequestResp pairs and expected loop in request with the response we
|
||||
// would like the mocked server to respond with.
|
||||
type loopInRequestResp struct {
|
||||
request *loop.LoopInRequest
|
||||
response *loop.LoopInSwapInfo
|
||||
}
|
||||
|
||||
// autoloopStep contains all of the information to required to step
|
||||
// through an autoloop tick.
|
||||
type autoloopStep struct {
|
||||
minAmt btcutil.Amount
|
||||
maxAmt btcutil.Amount
|
||||
existingOut []*loopdb.LoopOut
|
||||
existingIn []*loopdb.LoopIn
|
||||
quotesOut []quoteRequestResp
|
||||
quotesIn []quoteInRequestResp
|
||||
expectedOut []loopOutRequestResp
|
||||
expectedIn []loopInRequestResp
|
||||
}
|
||||
|
||||
// autoloop walks our test context through the process of triggering our
|
||||
// autoloop functionality, providing mocked values as required. The set of
|
||||
// quotes provided indicates that we expect swap suggestions to be made (since
|
||||
// we will query for a quote for each suggested swap). The set of expected
|
||||
// swaps indicates whether we expect any of these swap suggestions to actually
|
||||
// be dispatched by the autolooper.
|
||||
func (c *autoloopTestCtx) autoloop(minAmt, maxAmt btcutil.Amount,
|
||||
existingOut []*loopdb.LoopOut, quotes []quoteRequestResp,
|
||||
expectedSwaps []loopOutRequestResp) {
|
||||
|
||||
func (c *autoloopTestCtx) autoloop(step *autoloopStep) {
|
||||
// Tick our autoloop ticker to force assessing whether we want to loop.
|
||||
c.manager.cfg.AutoloopTicker.Force <- testTime
|
||||
|
||||
// Send a mocked response from the server with the swap size limits.
|
||||
c.loopOutRestrictions <- NewRestrictions(minAmt, maxAmt)
|
||||
c.loopOutRestrictions <- NewRestrictions(step.minAmt, step.maxAmt)
|
||||
c.loopInRestrictions <- NewRestrictions(step.minAmt, step.maxAmt)
|
||||
|
||||
// Provide the liquidity manager with our desired existing set of swaps.
|
||||
c.loopOuts <- existingOut
|
||||
c.loopIns <- nil
|
||||
c.loopOuts <- step.existingOut
|
||||
c.loopIns <- step.existingIn
|
||||
|
||||
// Assert that we query the server for a quote for each of our
|
||||
// recommended swaps. Note that this differs from our set of expected
|
||||
// swaps because we may get quotes for suggested swaps but then just
|
||||
// log them.
|
||||
for _, expected := range quotes {
|
||||
for _, expected := range step.quotesIn {
|
||||
request := <-c.quoteRequestIn
|
||||
assert.Equal(
|
||||
c.t, expected.request.Amount, request.Amount,
|
||||
)
|
||||
|
||||
assert.Equal(
|
||||
c.t, expected.request.HtlcConfTarget,
|
||||
request.HtlcConfTarget,
|
||||
)
|
||||
|
||||
c.quotesIn <- expected.quote
|
||||
}
|
||||
|
||||
for _, expected := range step.quotesOut {
|
||||
request := <-c.quoteRequest
|
||||
assert.Equal(
|
||||
c.t, expected.request.Amount, request.Amount,
|
||||
|
|
@ -214,7 +293,7 @@ func (c *autoloopTestCtx) autoloop(minAmt, maxAmt btcutil.Amount,
|
|||
}
|
||||
|
||||
// Assert that we dispatch the expected set of swaps.
|
||||
for _, expected := range expectedSwaps {
|
||||
for _, expected := range step.expectedOut {
|
||||
actual := <-c.outRequest
|
||||
|
||||
// Set our destination address to nil so that we do not need to
|
||||
|
|
@ -224,4 +303,12 @@ func (c *autoloopTestCtx) autoloop(minAmt, maxAmt btcutil.Amount,
|
|||
assert.Equal(c.t, expected.request, actual)
|
||||
c.loopOut <- expected.response
|
||||
}
|
||||
|
||||
for _, expected := range step.expectedIn {
|
||||
actual := <-c.inRequest
|
||||
|
||||
assert.Equal(c.t, expected.request, actual)
|
||||
|
||||
c.loopIn <- expected.response
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
// defaultHtlcConfTarget is the default confirmation target we use for
|
||||
// loop in swap htlcs, set to the same default at the client.
|
||||
defaultHtlcConfTarget = loop.DefaultHtlcConfTarget
|
||||
|
||||
// defaultBudget is the default autoloop budget we set. This budget will
|
||||
// only be used for automatically dispatched swaps if autoloop is
|
||||
// explicitly enabled, so we are happy to set a non-zero value here. The
|
||||
|
|
@ -107,6 +111,7 @@ var (
|
|||
PeerRules: make(map[route.Vertex]*SwapRule),
|
||||
FailureBackOff: defaultFailureBackoff,
|
||||
SweepConfTarget: defaultConfTarget,
|
||||
HtlcConfTarget: defaultHtlcConfTarget,
|
||||
FeeLimit: defaultFeePortion(),
|
||||
}
|
||||
|
||||
|
|
@ -170,10 +175,18 @@ type Config struct {
|
|||
LoopOutQuote func(ctx context.Context,
|
||||
request *loop.LoopOutQuoteRequest) (*loop.LoopOutQuote, error)
|
||||
|
||||
// LoopInQuote provides a quote for a loop in swap.
|
||||
LoopInQuote func(ctx context.Context,
|
||||
request *loop.LoopInQuoteRequest) (*loop.LoopInQuote, error)
|
||||
|
||||
// LoopOut dispatches a loop out.
|
||||
LoopOut func(ctx context.Context, request *loop.OutRequest) (
|
||||
*loop.LoopOutSwapInfo, error)
|
||||
|
||||
// LoopIn dispatches a loop in swap.
|
||||
LoopIn func(ctx context.Context,
|
||||
request *loop.LoopInRequest) (*loop.LoopInSwapInfo, error)
|
||||
|
||||
// Clock allows easy mocking of time in unit tests.
|
||||
Clock clock.Clock
|
||||
|
||||
|
|
@ -212,6 +225,10 @@ type Parameters struct {
|
|||
// transaction in. This value affects the on chain fees we will pay.
|
||||
SweepConfTarget int32
|
||||
|
||||
// HtlcConfTarget is the confirmation target that we use for publishing
|
||||
// loop in swap htlcs on chain.
|
||||
HtlcConfTarget int32
|
||||
|
||||
// FeeLimit controls the fee limit we place on swaps.
|
||||
FeeLimit FeeLimit
|
||||
|
||||
|
|
@ -249,10 +266,11 @@ func (p Parameters) String() string {
|
|||
}
|
||||
|
||||
return fmt.Sprintf("rules: %v, failure backoff: %v, sweep "+
|
||||
"sweep conf target: %v, fees: %v, auto budget: %v, budget "+
|
||||
"start: %v, max auto in flight: %v, minimum swap size=%v, "+
|
||||
"maximum swap size=%v", strings.Join(ruleList, ","),
|
||||
p.FailureBackOff, p.SweepConfTarget, p.FeeLimit,
|
||||
"sweep conf target: %v, htlc conf target: %v,fees: %v, "+
|
||||
"auto budget: %v, budget start: %v, max auto in flight: %v, "+
|
||||
"minimum swap size=%v, maximum swap size=%v",
|
||||
strings.Join(ruleList, ","), p.FailureBackOff,
|
||||
p.SweepConfTarget, p.HtlcConfTarget, p.FeeLimit,
|
||||
p.AutoFeeBudget, p.AutoFeeStartDate, p.MaxAutoInFlight,
|
||||
p.ClientRestrictions.Minimum, p.ClientRestrictions.Maximum)
|
||||
}
|
||||
|
|
@ -310,6 +328,11 @@ func (p Parameters) validate(minConfs int32, openChans []lndclient.ChannelInfo,
|
|||
return ErrZeroChannelID
|
||||
}
|
||||
|
||||
if rule.Type == swap.TypeIn {
|
||||
return errors.New("channel level rules not supported for " +
|
||||
"loop in swaps, only peer-level rules allowed")
|
||||
}
|
||||
|
||||
if err := rule.validate(); err != nil {
|
||||
return fmt.Errorf("channel: %v has invalid rule: %v",
|
||||
channel.ToUint64(), err)
|
||||
|
|
@ -329,6 +352,10 @@ func (p Parameters) validate(minConfs int32, openChans []lndclient.ChannelInfo,
|
|||
minConfs)
|
||||
}
|
||||
|
||||
if p.HtlcConfTarget < 1 {
|
||||
return fmt.Errorf("htlc confirmation target must be > 0")
|
||||
}
|
||||
|
||||
if err := p.FeeLimit.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -508,7 +535,7 @@ func (m *Manager) autoloop(ctx context.Context) error {
|
|||
// If we don't actually have dispatch of swaps enabled, log
|
||||
// suggestions.
|
||||
if !m.params.Autoloop {
|
||||
log.Debugf("recommended autoloop: %v sats over "+
|
||||
log.Debugf("recommended autoloop out: %v sats over "+
|
||||
"%v", swap.Amount, swap.OutgoingChanSet)
|
||||
|
||||
continue
|
||||
|
|
@ -526,6 +553,27 @@ func (m *Manager) autoloop(ctx context.Context) error {
|
|||
loopOut.HtlcAddressP2WSH)
|
||||
}
|
||||
|
||||
for _, in := range suggestion.InSwaps {
|
||||
// If we don't actually have dispatch of swaps enabled, log
|
||||
// suggestions.
|
||||
if !m.params.Autoloop {
|
||||
log.Debugf("recommended autoloop in: %v sats over "+
|
||||
"%v", in.Amount, in.LastHop)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
in := in
|
||||
loopIn, err := m.cfg.LoopIn(ctx, &in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("loop in automatically dispatched: hash: %v, "+
|
||||
"address: %v", loopIn.SwapHash,
|
||||
loopIn.HtlcAddressNP2WSH)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -546,6 +594,9 @@ type Suggestions struct {
|
|||
// OutSwaps is the set of loop out swaps that we suggest executing.
|
||||
OutSwaps []loop.OutRequest
|
||||
|
||||
// InSwaps is the set of loop in swaps that we suggest executing.
|
||||
InSwaps []loop.LoopInRequest
|
||||
|
||||
// DisqualifiedChans maps the set of channels that we do not recommend
|
||||
// swaps on to the reason that we did not recommend a swap.
|
||||
DisqualifiedChans map[lnwire.ShortChannelID]Reason
|
||||
|
|
@ -563,13 +614,17 @@ func newSuggestions() *Suggestions {
|
|||
}
|
||||
|
||||
func (s *Suggestions) addSwap(swap swapSuggestion) error {
|
||||
out, ok := swap.(*loopOutSwapSuggestion)
|
||||
if !ok {
|
||||
switch t := swap.(type) {
|
||||
case *loopOutSwapSuggestion:
|
||||
s.OutSwaps = append(s.OutSwaps, t.OutRequest)
|
||||
|
||||
case *loopInSwapSuggestion:
|
||||
s.InSwaps = append(s.InSwaps, t.LoopInRequest)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unexpected swap type: %T", swap)
|
||||
}
|
||||
|
||||
s.OutSwaps = append(s.OutSwaps, out.OutRequest)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -624,6 +679,11 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) (
|
|||
return nil, err
|
||||
}
|
||||
|
||||
inRestrictions, err := m.getSwapRestrictions(ctx, swap.TypeIn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List our current set of swaps so that we can determine which channels
|
||||
// are already being utilized by swaps. Note that these calls may race
|
||||
// with manual initiation of swaps.
|
||||
|
|
@ -708,7 +768,7 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) (
|
|||
|
||||
suggestion, err := m.suggestSwap(
|
||||
ctx, traffic, balances, rule, outRestrictions,
|
||||
autoloop,
|
||||
inRestrictions, autoloop,
|
||||
)
|
||||
var reasonErr *reasonError
|
||||
if errors.As(err, &reasonErr) {
|
||||
|
|
@ -734,7 +794,7 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) (
|
|||
|
||||
suggestion, err := m.suggestSwap(
|
||||
ctx, traffic, balance, rule, outRestrictions,
|
||||
autoloop,
|
||||
inRestrictions, autoloop,
|
||||
)
|
||||
|
||||
var reasonErr *reasonError
|
||||
|
|
@ -830,18 +890,24 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) (
|
|||
// swap request for the rule provided.
|
||||
func (m *Manager) suggestSwap(ctx context.Context, traffic *swapTraffic,
|
||||
balance *balances, rule *SwapRule, outRestrictions *Restrictions,
|
||||
autoloop bool) (swapSuggestion, error) {
|
||||
inRestrictions *Restrictions, autoloop bool) (swapSuggestion, error) {
|
||||
|
||||
var (
|
||||
builder swapBuilder
|
||||
restrictions *Restrictions
|
||||
)
|
||||
|
||||
// Get an appropriate builder and set of restrictions based on our swap
|
||||
// type.
|
||||
switch rule.Type {
|
||||
case swap.TypeOut:
|
||||
builder = newLoopOutBuilder(m.cfg)
|
||||
restrictions = outRestrictions
|
||||
|
||||
case swap.TypeIn:
|
||||
builder = newLoopInBuilder(m.cfg)
|
||||
restrictions = inRestrictions
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported swap type: %v", rule.Type)
|
||||
}
|
||||
|
|
@ -863,7 +929,7 @@ func (m *Manager) suggestSwap(ctx context.Context, traffic *swapTraffic,
|
|||
|
||||
// Next, get the amount that we need to swap for this entity, skipping
|
||||
// over it if no change in liquidity is required.
|
||||
amount := rule.swapAmount(balance, restrictions)
|
||||
amount := rule.swapAmount(balance, restrictions, rule.Type)
|
||||
if amount == 0 {
|
||||
return nil, newReasonError(ReasonLiquidityOk)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -1292,6 +1293,19 @@ func TestInFlightLimit(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type mockServer struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Restrictions mocks a call to the server to get swap size restrictions.
|
||||
func (m *mockServer) Restrictions(ctx context.Context, swapType swap.Type) (
|
||||
*Restrictions, error) {
|
||||
|
||||
args := m.Called(ctx, swapType)
|
||||
|
||||
return args.Get(0).(*Restrictions), args.Error(1)
|
||||
}
|
||||
|
||||
// TestSizeRestrictions tests the use of client-set size restrictions on swaps.
|
||||
func TestSizeRestrictions(t *testing.T) {
|
||||
var (
|
||||
|
|
@ -1321,9 +1335,7 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
// has configured.
|
||||
clientRestrictions Restrictions
|
||||
|
||||
// server holds the server's mocked responses to our terms
|
||||
// endpoint.
|
||||
serverRestrictions []Restrictions
|
||||
prepareMock func(m *mockServer)
|
||||
|
||||
// suggestions is the set of suggestions we expect.
|
||||
suggestions *Suggestions
|
||||
|
|
@ -1336,9 +1348,6 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
clientRestrictions: Restrictions{
|
||||
Minimum: 7000,
|
||||
},
|
||||
serverRestrictions: []Restrictions{
|
||||
serverRestrictions, serverRestrictions,
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
OutSwaps: []loop.OutRequest{
|
||||
chan1Rec,
|
||||
|
|
@ -1352,9 +1361,6 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
clientRestrictions: Restrictions{
|
||||
Minimum: 8000,
|
||||
},
|
||||
serverRestrictions: []Restrictions{
|
||||
serverRestrictions, serverRestrictions,
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
DisqualifiedChans: map[lnwire.ShortChannelID]Reason{
|
||||
chanID1: ReasonLiquidityOk,
|
||||
|
|
@ -1367,9 +1373,6 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
clientRestrictions: Restrictions{
|
||||
Maximum: 7000,
|
||||
},
|
||||
serverRestrictions: []Restrictions{
|
||||
serverRestrictions, serverRestrictions,
|
||||
},
|
||||
suggestions: &Suggestions{
|
||||
OutSwaps: []loop.OutRequest{
|
||||
outSwap,
|
||||
|
|
@ -1387,12 +1390,26 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
Minimum: 6500,
|
||||
Maximum: 9000,
|
||||
},
|
||||
serverRestrictions: []Restrictions{
|
||||
serverRestrictions,
|
||||
{
|
||||
Minimum: 5000,
|
||||
Maximum: 6000,
|
||||
},
|
||||
prepareMock: func(m *mockServer) {
|
||||
restrictions := serverRestrictions
|
||||
|
||||
m.On(
|
||||
"Restrictions", mock.Anything,
|
||||
swap.TypeOut,
|
||||
).Return(
|
||||
&restrictions, nil,
|
||||
).Once()
|
||||
|
||||
m.On(
|
||||
"Restrictions", mock.Anything,
|
||||
swap.TypeOut,
|
||||
).Return(
|
||||
&Restrictions{
|
||||
Minimum: 5000,
|
||||
Maximum: 6000,
|
||||
}, nil,
|
||||
).Once()
|
||||
|
||||
},
|
||||
suggestions: nil,
|
||||
expectedError: ErrMaxExceedsServer,
|
||||
|
|
@ -1415,27 +1432,32 @@ func TestSizeRestrictions(t *testing.T) {
|
|||
chanID1: chanRule,
|
||||
}
|
||||
|
||||
// callCount tracks the number of calls we make to
|
||||
// our restrictions endpoint.
|
||||
var callCount int
|
||||
// Use a mock that has our expected calls for the test
|
||||
// case set to provide server restrictions.
|
||||
mockServer := &mockServer{}
|
||||
|
||||
cfg.Restrictions = func(_ context.Context, _ swap.Type) (
|
||||
*Restrictions, error) {
|
||||
// If the test wants us to prime the mock, use its
|
||||
// function, otherwise just return our default
|
||||
// restrictions.
|
||||
if testCase.prepareMock != nil {
|
||||
testCase.prepareMock(mockServer)
|
||||
} else {
|
||||
restrictions := serverRestrictions
|
||||
|
||||
restrictions := testCase.serverRestrictions[callCount]
|
||||
callCount++
|
||||
|
||||
return &restrictions, nil
|
||||
mockServer.On(
|
||||
"Restrictions", mock.Anything,
|
||||
mock.Anything,
|
||||
).Return(&restrictions, nil)
|
||||
}
|
||||
|
||||
cfg.Restrictions = mockServer.Restrictions
|
||||
|
||||
testSuggestSwaps(
|
||||
t, newSuggestSwapsSetup(cfg, lnd, params),
|
||||
testCase.suggestions, testCase.expectedError,
|
||||
)
|
||||
|
||||
require.Equal(
|
||||
t, callCount, len(testCase.serverRestrictions),
|
||||
"too many restrictions provided by mock",
|
||||
)
|
||||
mockServer.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
126
liquidity/loopin_builder.go
Normal file
126
liquidity/loopin_builder.go
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
package liquidity
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightninglabs/loop"
|
||||
"github.com/lightninglabs/loop/labels"
|
||||
"github.com/lightninglabs/loop/swap"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Compile-time assertion that loopInBuilder satisfies the swapBuilder
|
||||
// interface.
|
||||
var _ swapBuilder = (*loopInBuilder)(nil)
|
||||
|
||||
func newLoopInBuilder(cfg *Config) *loopInBuilder {
|
||||
return &loopInBuilder{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
type loopInBuilder struct {
|
||||
// cfg contains all the external functionality we require to create
|
||||
// swaps.
|
||||
cfg *Config
|
||||
}
|
||||
|
||||
// swapType returns the swap type that the builder is responsible for creating.
|
||||
func (b *loopInBuilder) swapType() swap.Type {
|
||||
return swap.TypeIn
|
||||
}
|
||||
|
||||
// maySwap checks whether we can currently execute a swap, examining the
|
||||
// current on-chain fee conditions against relevant to our swap type against
|
||||
// our fee restrictions.
|
||||
//
|
||||
// For loop in, we cannot check any upfront costs because we do not know how
|
||||
// many inputs will be used for our on-chain htlc before it is made, so we can't
|
||||
// make nay estimations.
|
||||
func (b *loopInBuilder) maySwap(_ context.Context, _ Parameters) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// inUse examines our current swap traffic to determine whether we should
|
||||
// suggest the builder's type of swap for the peer and channels suggested.
|
||||
func (b *loopInBuilder) inUse(traffic *swapTraffic, peer route.Vertex,
|
||||
channels []lnwire.ShortChannelID) error {
|
||||
|
||||
for _, chanID := range channels {
|
||||
if traffic.ongoingLoopOut[chanID] {
|
||||
log.Debugf("Channel: %v not eligible for suggestions, "+
|
||||
"ongoing loop out utilizing channel", chanID)
|
||||
|
||||
return newReasonError(ReasonLoopOut)
|
||||
}
|
||||
}
|
||||
|
||||
if traffic.ongoingLoopIn[peer] {
|
||||
log.Debugf("Peer: %x not eligible for suggestions ongoing "+
|
||||
"loop in utilizing peer", peer)
|
||||
|
||||
return newReasonError(ReasonLoopIn)
|
||||
}
|
||||
|
||||
lastFail, recentFail := traffic.failedLoopIn[peer]
|
||||
if recentFail {
|
||||
log.Debugf("Peer: %v not eligible for suggestions, "+
|
||||
"was part of a failed swap at: %v", peer,
|
||||
lastFail)
|
||||
|
||||
return newReasonError(ReasonFailureBackoff)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildSwap creates a swap for the target peer/channels provided. The autoloop
|
||||
// boolean indicates whether this swap will actually be executed.
|
||||
//
|
||||
// For loop in, we do not add the autoloop label for dry runs.
|
||||
func (b *loopInBuilder) buildSwap(ctx context.Context, pubkey route.Vertex,
|
||||
_ []lnwire.ShortChannelID, amount btcutil.Amount,
|
||||
autoloop bool, params Parameters) (swapSuggestion, error) {
|
||||
|
||||
quote, err := b.cfg.LoopInQuote(ctx, &loop.LoopInQuoteRequest{
|
||||
Amount: amount,
|
||||
LastHop: &pubkey,
|
||||
HtlcConfTarget: params.HtlcConfTarget,
|
||||
})
|
||||
if err != nil {
|
||||
// If the server fails our quote, we're not reachable right
|
||||
// now, so we want to catch this error and fail with a
|
||||
// structured error so that we know why we can't swap.
|
||||
status, ok := status.FromError(err)
|
||||
if ok && status.Code() == codes.FailedPrecondition {
|
||||
return nil, newReasonError(ReasonLoopInUnreachable)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := params.FeeLimit.loopInLimits(amount, quote); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request := loop.LoopInRequest{
|
||||
Amount: amount,
|
||||
MaxSwapFee: quote.SwapFee,
|
||||
MaxMinerFee: quote.MinerFee,
|
||||
HtlcConfTarget: params.HtlcConfTarget,
|
||||
LastHop: &pubkey,
|
||||
Initiator: autoloopSwapInitiator,
|
||||
}
|
||||
|
||||
if autoloop {
|
||||
request.Label = labels.AutoloopLabel(swap.TypeIn)
|
||||
}
|
||||
|
||||
return &loopInSwapSuggestion{
|
||||
LoopInRequest: request,
|
||||
}, nil
|
||||
}
|
||||
193
liquidity/loopin_builder_test.go
Normal file
193
liquidity/loopin_builder_test.go
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
package liquidity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightninglabs/loop"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// TestLoopinInUse tests that the loop in swap builder prevents dispatching
|
||||
// swaps for peers when there is already a swap running for that peer.
|
||||
func TestLoopinInUse(t *testing.T) {
|
||||
var (
|
||||
peer1 = route.Vertex{1}
|
||||
chan1 = lnwire.NewShortChanIDFromInt(1)
|
||||
|
||||
peer2 = route.Vertex{2}
|
||||
chan2 = lnwire.NewShortChanIDFromInt(2)
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ongoingLoopOut *lnwire.ShortChannelID
|
||||
ongoingLoopIn *route.Vertex
|
||||
failedLoopIn *route.Vertex
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "swap allowed",
|
||||
ongoingLoopIn: &peer2,
|
||||
ongoingLoopOut: &chan2,
|
||||
failedLoopIn: &peer2,
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "conflicts with loop out",
|
||||
ongoingLoopOut: &chan1,
|
||||
expectedErr: newReasonError(ReasonLoopOut),
|
||||
},
|
||||
{
|
||||
name: "conflicts with loop in",
|
||||
ongoingLoopIn: &peer1,
|
||||
expectedErr: newReasonError(ReasonLoopIn),
|
||||
},
|
||||
{
|
||||
name: "previous failed loopin",
|
||||
failedLoopIn: &peer1,
|
||||
expectedErr: newReasonError(ReasonFailureBackoff),
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range tests {
|
||||
traffic := newSwapTraffic()
|
||||
|
||||
if testCase.ongoingLoopOut != nil {
|
||||
traffic.ongoingLoopOut[*testCase.ongoingLoopOut] = true
|
||||
}
|
||||
|
||||
if testCase.ongoingLoopIn != nil {
|
||||
traffic.ongoingLoopIn[*testCase.ongoingLoopIn] = true
|
||||
}
|
||||
|
||||
if testCase.failedLoopIn != nil {
|
||||
traffic.failedLoopIn[*testCase.failedLoopIn] = testTime
|
||||
}
|
||||
|
||||
builder := newLoopInBuilder(nil)
|
||||
err := builder.inUse(traffic, peer1, []lnwire.ShortChannelID{
|
||||
chan1,
|
||||
})
|
||||
|
||||
require.Equal(t, testCase.expectedErr, err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoopinBuildSwap tests construction of loop in swaps for autoloop,
|
||||
// including the case where the client cannot get a quote because it is not
|
||||
// reachable from the server.
|
||||
func TestLoopinBuildSwap(t *testing.T) {
|
||||
var (
|
||||
peer1 = route.Vertex{1}
|
||||
chan1 = lnwire.NewShortChanIDFromInt(1)
|
||||
|
||||
htlcConfTarget int32 = 6
|
||||
swapAmt btcutil.Amount = 100000
|
||||
|
||||
quote = &loop.LoopInQuote{
|
||||
SwapFee: 1,
|
||||
MinerFee: 2,
|
||||
}
|
||||
|
||||
expectedSwap = &loopInSwapSuggestion{
|
||||
loop.LoopInRequest{
|
||||
Amount: swapAmt,
|
||||
MaxSwapFee: quote.SwapFee,
|
||||
MaxMinerFee: quote.MinerFee,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
LastHop: &peer1,
|
||||
Initiator: autoloopSwapInitiator,
|
||||
},
|
||||
}
|
||||
|
||||
quoteRequest = &loop.LoopInQuoteRequest{
|
||||
Amount: swapAmt,
|
||||
LastHop: &peer1,
|
||||
HtlcConfTarget: htlcConfTarget,
|
||||
}
|
||||
|
||||
errPrecondition = status.Error(codes.FailedPrecondition, "failed")
|
||||
errOtherCode = status.Error(codes.DeadlineExceeded, "timeout")
|
||||
errNoCode = errors.New("failure")
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
prepareMock func(*mockCfg)
|
||||
expectedSwap swapSuggestion
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "quote successful",
|
||||
prepareMock: func(m *mockCfg) {
|
||||
m.On(
|
||||
"LoopInQuote", mock.Anything,
|
||||
quoteRequest,
|
||||
).Return(quote, nil)
|
||||
},
|
||||
expectedSwap: expectedSwap,
|
||||
},
|
||||
{
|
||||
name: "client unreachable",
|
||||
prepareMock: func(m *mockCfg) {
|
||||
m.On(
|
||||
"LoopInQuote", mock.Anything,
|
||||
quoteRequest,
|
||||
).Return(quote, errPrecondition)
|
||||
},
|
||||
expectedSwap: nil,
|
||||
expectedErr: newReasonError(ReasonLoopInUnreachable),
|
||||
},
|
||||
{
|
||||
name: "other error code",
|
||||
prepareMock: func(m *mockCfg) {
|
||||
m.On(
|
||||
"LoopInQuote", mock.Anything,
|
||||
quoteRequest,
|
||||
).Return(quote, errOtherCode)
|
||||
},
|
||||
expectedSwap: nil,
|
||||
expectedErr: errOtherCode,
|
||||
},
|
||||
{
|
||||
name: "no error code",
|
||||
prepareMock: func(m *mockCfg) {
|
||||
m.On(
|
||||
"LoopInQuote", mock.Anything,
|
||||
quoteRequest,
|
||||
).Return(quote, errNoCode)
|
||||
},
|
||||
expectedSwap: nil,
|
||||
expectedErr: errNoCode,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range tests {
|
||||
mock, cfg := newMockConfig()
|
||||
params := defaultParameters
|
||||
params.HtlcConfTarget = htlcConfTarget
|
||||
params.AutoFeeBudget = 100000
|
||||
|
||||
testCase.prepareMock(mock)
|
||||
|
||||
builder := newLoopInBuilder(cfg)
|
||||
swap, err := builder.buildSwap(
|
||||
context.Background(), peer1, []lnwire.ShortChannelID{
|
||||
chan1,
|
||||
}, swapAmt, false, params,
|
||||
)
|
||||
assert.Equal(t, testCase.expectedSwap, swap)
|
||||
assert.Equal(t, testCase.expectedErr, err)
|
||||
|
||||
mock.AssertExpectations(t)
|
||||
}
|
||||
}
|
||||
33
liquidity/mock.go
Normal file
33
liquidity/mock.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package liquidity
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightninglabs/loop"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// newMockConfig returns a liquidity config with mocked calls. Note that
|
||||
// functions that are not implemented by the mock will panic if called.
|
||||
func newMockConfig() (*mockCfg, *Config) {
|
||||
mockCfg := &mockCfg{}
|
||||
|
||||
// Create a liquidity config which calls our mock.
|
||||
config := &Config{
|
||||
LoopInQuote: mockCfg.LoopInQuote,
|
||||
}
|
||||
|
||||
return mockCfg, config
|
||||
}
|
||||
|
||||
type mockCfg struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// LoopInQuote mocks a call to get a loop in quote from the server.
|
||||
func (m *mockCfg) LoopInQuote(ctx context.Context,
|
||||
request *loop.LoopInQuoteRequest) (*loop.LoopInQuote, error) {
|
||||
|
||||
args := m.Called(ctx, request)
|
||||
return args.Get(0).(*loop.LoopInQuote), args.Error(1)
|
||||
}
|
||||
|
|
@ -65,6 +65,10 @@ const (
|
|||
// ReasonFeePPMInsufficient indicates that the fees a swap would require
|
||||
// are greater than the portion of swap amount allocated to fees.
|
||||
ReasonFeePPMInsufficient
|
||||
|
||||
// ReasonLoopInUnreachable indicates that the server does not have a
|
||||
// path to the client, so cannot perform a loop in swap at this time.
|
||||
ReasonLoopInUnreachable
|
||||
)
|
||||
|
||||
// String returns a string representation of a reason.
|
||||
|
|
@ -112,6 +116,9 @@ func (r Reason) String() string {
|
|||
case ReasonFeePPMInsufficient:
|
||||
return "fee portion insufficient"
|
||||
|
||||
case ReasonLoopInUnreachable:
|
||||
return "loop in unreachable"
|
||||
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func (r *ThresholdRule) validate() error {
|
|||
// swapAmount suggests a swap based on the liquidity thresholds configured,
|
||||
// returning zero if no swap is recommended.
|
||||
func (r *ThresholdRule) swapAmount(channel *balances,
|
||||
restrictions *Restrictions) btcutil.Amount {
|
||||
restrictions *Restrictions, swapType swap.Type) btcutil.Amount {
|
||||
|
||||
var (
|
||||
// For loop out swaps, we want to adjust our incoming liquidity
|
||||
|
|
@ -95,6 +95,14 @@ func (r *ThresholdRule) swapAmount(channel *balances,
|
|||
reservePercentage = uint64(r.MinimumOutgoing)
|
||||
)
|
||||
|
||||
// For loop in swaps, we reverse our target and reserve values.
|
||||
if swapType == swap.TypeIn {
|
||||
targetBalance = channel.outgoing
|
||||
targetPercentage = uint64(r.MinimumOutgoing)
|
||||
reserveBalance = channel.incoming
|
||||
reservePercentage = uint64(r.MinimumIncoming)
|
||||
}
|
||||
|
||||
// Examine our total balance and required ratios to decide whether we
|
||||
// need to swap.
|
||||
amount := calculateSwapAmount(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightninglabs/loop/swap"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -249,6 +250,7 @@ func TestSuggestSwap(t *testing.T) {
|
|||
t.Run(test.name, func(t *testing.T) {
|
||||
swap := test.rule.swapAmount(
|
||||
test.channel, test.outRestrictions,
|
||||
swap.TypeOut,
|
||||
)
|
||||
require.Equal(t, test.swap, swap)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -719,8 +719,9 @@ func (s *swapClientServer) GetLiquidityParams(_ context.Context,
|
|||
Rules: make(
|
||||
[]*clientrpc.LiquidityRule, 0, totalRules,
|
||||
),
|
||||
MinSwapAmount: uint64(cfg.ClientRestrictions.Minimum),
|
||||
MaxSwapAmount: uint64(cfg.ClientRestrictions.Maximum),
|
||||
MinSwapAmount: uint64(cfg.ClientRestrictions.Minimum),
|
||||
MaxSwapAmount: uint64(cfg.ClientRestrictions.Maximum),
|
||||
HtlcConfTarget: cfg.HtlcConfTarget,
|
||||
}
|
||||
|
||||
switch f := cfg.FeeLimit.(type) {
|
||||
|
|
@ -812,6 +813,7 @@ func (s *swapClientServer) SetLiquidityParams(ctx context.Context,
|
|||
Minimum: btcutil.Amount(in.Parameters.MinSwapAmount),
|
||||
Maximum: btcutil.Amount(in.Parameters.MaxSwapAmount),
|
||||
},
|
||||
HtlcConfTarget: in.Parameters.HtlcConfTarget,
|
||||
}
|
||||
|
||||
// Zero unix time is different to zero golang time.
|
||||
|
|
@ -953,13 +955,17 @@ func (s *swapClientServer) SuggestSwaps(ctx context.Context,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
loopOut []*clientrpc.LoopOutRequest
|
||||
disqualified []*clientrpc.Disqualified
|
||||
)
|
||||
resp := &clientrpc.SuggestSwapsResponse{
|
||||
LoopOut: make(
|
||||
[]*clientrpc.LoopOutRequest, len(suggestions.OutSwaps),
|
||||
),
|
||||
LoopIn: make(
|
||||
[]*clientrpc.LoopInRequest, len(suggestions.InSwaps),
|
||||
),
|
||||
}
|
||||
|
||||
for _, swap := range suggestions.OutSwaps {
|
||||
loopOut = append(loopOut, &clientrpc.LoopOutRequest{
|
||||
for i, swap := range suggestions.OutSwaps {
|
||||
resp.LoopOut[i] = &clientrpc.LoopOutRequest{
|
||||
Amt: int64(swap.Amount),
|
||||
OutgoingChanSet: swap.OutgoingChanSet,
|
||||
MaxSwapFee: int64(swap.MaxSwapFee),
|
||||
|
|
@ -968,7 +974,22 @@ func (s *swapClientServer) SuggestSwaps(ctx context.Context,
|
|||
MaxSwapRoutingFee: int64(swap.MaxSwapRoutingFee),
|
||||
MaxPrepayRoutingFee: int64(swap.MaxPrepayRoutingFee),
|
||||
SweepConfTarget: swap.SweepConfTarget,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for i, swap := range suggestions.InSwaps {
|
||||
loopIn := &clientrpc.LoopInRequest{
|
||||
Amt: int64(swap.Amount),
|
||||
MaxSwapFee: int64(swap.MaxSwapFee),
|
||||
MaxMinerFee: int64(swap.MaxMinerFee),
|
||||
HtlcConfTarget: swap.HtlcConfTarget,
|
||||
}
|
||||
|
||||
if swap.LastHop != nil {
|
||||
loopIn.LastHop = swap.LastHop[:]
|
||||
}
|
||||
|
||||
resp.LoopIn[i] = loopIn
|
||||
}
|
||||
|
||||
for id, reason := range suggestions.DisqualifiedChans {
|
||||
|
|
@ -982,7 +1003,7 @@ func (s *swapClientServer) SuggestSwaps(ctx context.Context,
|
|||
ChannelId: id.ToUint64(),
|
||||
}
|
||||
|
||||
disqualified = append(disqualified, exclChan)
|
||||
resp.Disqualified = append(resp.Disqualified, exclChan)
|
||||
}
|
||||
|
||||
for pubkey, reason := range suggestions.DisqualifiedPeers {
|
||||
|
|
@ -996,13 +1017,10 @@ func (s *swapClientServer) SuggestSwaps(ctx context.Context,
|
|||
Pubkey: pubkey[:],
|
||||
}
|
||||
|
||||
disqualified = append(disqualified, exclChan)
|
||||
resp.Disqualified = append(resp.Disqualified, exclChan)
|
||||
}
|
||||
|
||||
return &clientrpc.SuggestSwapsResponse{
|
||||
LoopOut: loopOut,
|
||||
Disqualified: disqualified,
|
||||
}, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ func getLiquidityManager(client *loop.Client) *liquidity.Manager {
|
|||
mngrCfg := &liquidity.Config{
|
||||
AutoloopTicker: ticker.NewForce(liquidity.DefaultAutoloopTicker),
|
||||
LoopOut: client.LoopOut,
|
||||
LoopIn: client.LoopIn,
|
||||
Restrictions: func(ctx context.Context,
|
||||
swapType swap.Type) (*liquidity.Restrictions, error) {
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ func getLiquidityManager(client *loop.Client) *liquidity.Manager {
|
|||
Lnd: client.LndServices,
|
||||
Clock: clock.NewDefaultClock(),
|
||||
LoopOutQuote: client.LoopOutQuote,
|
||||
LoopInQuote: client.LoopInQuote,
|
||||
ListLoopOut: client.Store.FetchLoopOutSwaps,
|
||||
ListLoopIn: client.Store.FetchLoopInSwaps,
|
||||
MinimumConfirmations: minConfTarget,
|
||||
|
|
|
|||
|
|
@ -2179,6 +2179,9 @@ type LiquidityParameters struct {
|
|||
//dispatch a swap for. This value is subject to the server-side limits
|
||||
//specified by the LoopOutTerms endpoint.
|
||||
MaxSwapAmount uint64 `protobuf:"varint,15,opt,name=max_swap_amount,json=maxSwapAmount,proto3" json:"max_swap_amount,omitempty"`
|
||||
//
|
||||
//The confirmation target for loop in on-chain htlcs.
|
||||
HtlcConfTarget int32 `protobuf:"varint,17,opt,name=htlc_conf_target,json=htlcConfTarget,proto3" json:"htlc_conf_target,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LiquidityParameters) Reset() {
|
||||
|
|
@ -2325,6 +2328,13 @@ func (x *LiquidityParameters) GetMaxSwapAmount() uint64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (x *LiquidityParameters) GetHtlcConfTarget() int32 {
|
||||
if x != nil {
|
||||
return x.HtlcConfTarget
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type LiquidityRule struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
|
@ -2636,6 +2646,9 @@ type SuggestSwapsResponse struct {
|
|||
//The set of recommended loop outs.
|
||||
LoopOut []*LoopOutRequest `protobuf:"bytes,1,rep,name=loop_out,json=loopOut,proto3" json:"loop_out,omitempty"`
|
||||
//
|
||||
//The set of recommended loop in swaps
|
||||
LoopIn []*LoopInRequest `protobuf:"bytes,3,rep,name=loop_in,json=loopIn,proto3" json:"loop_in,omitempty"`
|
||||
//
|
||||
//Disqualified contains the set of channels that swaps are not recommended
|
||||
//for.
|
||||
Disqualified []*Disqualified `protobuf:"bytes,2,rep,name=disqualified,proto3" json:"disqualified,omitempty"`
|
||||
|
|
@ -2680,6 +2693,13 @@ func (x *SuggestSwapsResponse) GetLoopOut() []*LoopOutRequest {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *SuggestSwapsResponse) GetLoopIn() []*LoopInRequest {
|
||||
if x != nil {
|
||||
return x.LoopIn
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SuggestSwapsResponse) GetDisqualified() []*Disqualified {
|
||||
if x != nil {
|
||||
return x.Disqualified
|
||||
|
|
@ -2910,7 +2930,7 @@ var file_client_proto_rawDesc = []byte{
|
|||
0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x47, 0x65,
|
||||
0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe0, 0x05, 0x0a, 0x13, 0x4c, 0x69, 0x71, 0x75,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8a, 0x06, 0x0a, 0x13, 0x4c, 0x69, 0x71, 0x75,
|
||||
0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12,
|
||||
0x2c, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69,
|
||||
|
|
@ -2956,166 +2976,172 @@ var file_client_proto_rawDesc = []byte{
|
|||
0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x41, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x61,
|
||||
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x61, 0x78,
|
||||
0x53, 0x77, 0x61, 0x70, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x84, 0x02, 0x0a, 0x0d, 0x4c,
|
||||
0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x09, 0x73,
|
||||
0x77, 0x61, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x54, 0x79, 0x70,
|
||||
0x65, 0x52, 0x08, 0x73, 0x77, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70,
|
||||
0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62,
|
||||
0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75,
|
||||
0x69, 0x64, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
|
||||
0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f,
|
||||
0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x11, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f,
|
||||
0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x74,
|
||||
0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11,
|
||||
0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c,
|
||||
0x64, 0x22, 0x59, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74,
|
||||
0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c,
|
||||
0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71,
|
||||
0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
|
||||
0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x1c, 0x0a, 0x1a,
|
||||
0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61,
|
||||
0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x75,
|
||||
0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x22, 0x72, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65,
|
||||
0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73,
|
||||
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72,
|
||||
0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x85, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73,
|
||||
0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32,
|
||||
0x0a, 0x08, 0x6c, 0x6f, 0x6f, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x4f,
|
||||
0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x6c, 0x6f, 0x6f, 0x70, 0x4f,
|
||||
0x75, 0x74, 0x12, 0x39, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69,
|
||||
0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x52,
|
||||
0x0c, 0x64, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2a, 0x25, 0x0a,
|
||||
0x08, 0x53, 0x77, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x4f,
|
||||
0x50, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x4f, 0x4f, 0x50, 0x5f,
|
||||
0x49, 0x4e, 0x10, 0x01, 0x2a, 0x73, 0x0a, 0x09, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74,
|
||||
0x65, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00,
|
||||
0x12, 0x15, 0x0a, 0x11, 0x50, 0x52, 0x45, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x56,
|
||||
0x45, 0x41, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x54, 0x4c, 0x43, 0x5f,
|
||||
0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53,
|
||||
0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c,
|
||||
0x45, 0x44, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f,
|
||||
0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xed, 0x01, 0x0a, 0x0d, 0x46, 0x61,
|
||||
0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x46,
|
||||
0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f,
|
||||
0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f,
|
||||
0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4f, 0x46, 0x46, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10,
|
||||
0x01, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41,
|
||||
0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x20, 0x0a,
|
||||
0x1c, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f,
|
||||
0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x12,
|
||||
0x25, 0x0a, 0x21, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x56,
|
||||
0x41, 0x4c, 0x55, 0x45, 0x10, 0x04, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52,
|
||||
0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41,
|
||||
0x52, 0x59, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f,
|
||||
0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54,
|
||||
0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x06, 0x2a, 0x2f, 0x0a, 0x11, 0x4c, 0x69, 0x71,
|
||||
0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b,
|
||||
0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54,
|
||||
0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x01, 0x2a, 0xa6, 0x03, 0x0a, 0x0a, 0x41,
|
||||
0x75, 0x74, 0x6f, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54,
|
||||
0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
|
||||
0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x54, 0x41,
|
||||
0x52, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52,
|
||||
0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x46, 0x45, 0x45, 0x53,
|
||||
0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x45, 0x4c, 0x41, 0x50, 0x53, 0x45, 0x44,
|
||||
0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x49, 0x4e, 0x5f, 0x46, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x10, 0x04, 0x12, 0x18, 0x0a,
|
||||
0x14, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x41,
|
||||
0x50, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f,
|
||||
0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x46, 0x45, 0x45,
|
||||
0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x59, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x55,
|
||||
0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52,
|
||||
0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x4f, 0x46, 0x46, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x41,
|
||||
0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, 0x5f,
|
||||
0x4f, 0x55, 0x54, 0x10, 0x09, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45,
|
||||
0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x49, 0x4e, 0x10, 0x0a, 0x12, 0x1c,
|
||||
0x0a, 0x18, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x49,
|
||||
0x51, 0x55, 0x49, 0x44, 0x49, 0x54, 0x59, 0x5f, 0x4f, 0x4b, 0x10, 0x0b, 0x12, 0x23, 0x0a, 0x1f,
|
||||
0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47,
|
||||
0x45, 0x54, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10,
|
||||
0x0c, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e,
|
||||
0x5f, 0x46, 0x45, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e,
|
||||
0x54, 0x10, 0x0d, 0x32, 0xc2, 0x07, 0x0a, 0x0a, 0x53, 0x77, 0x61, 0x70, 0x43, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x17, 0x2e,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a,
|
||||
0x06, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x12, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
|
||||
0x72, 0x12, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x6e, 0x69,
|
||||
0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f, 0x6f,
|
||||
0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x30,
|
||||
0x01, 0x12, 0x42, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x12, 0x19,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61,
|
||||
0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x12, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f,
|
||||
0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x12, 0x40, 0x0a, 0x0c, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x54, 0x65, 0x72, 0x6d, 0x73,
|
||||
0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x4f, 0x75, 0x74, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f,
|
||||
0x74, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x6f,
|
||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49,
|
||||
0x6e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f,
|
||||
0x6f, 0x70, 0x49, 0x6e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x51, 0x75, 0x6f,
|
||||
0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x50, 0x72,
|
||||
0x6f, 0x62, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72,
|
||||
0x6f, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6f, 0x6f,
|
||||
0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x73, 0x61, 0x74, 0x54, 0x6f, 0x6b,
|
||||
0x65, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f,
|
||||
0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6f,
|
||||
0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69,
|
||||
0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x2e, 0x6c, 0x6f, 0x6f,
|
||||
0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74,
|
||||
0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69,
|
||||
0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5d, 0x0a, 0x12,
|
||||
0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61,
|
||||
0x6d, 0x73, 0x12, 0x22, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74,
|
||||
0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72,
|
||||
0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53,
|
||||
0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6f,
|
||||
0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61,
|
||||
0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67,
|
||||
0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70,
|
||||
0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x53, 0x77, 0x61, 0x70, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x74,
|
||||
0x6c, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x11,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x68, 0x74, 0x6c, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x54, 0x61,
|
||||
0x72, 0x67, 0x65, 0x74, 0x22, 0x84, 0x02, 0x0a, 0x0d, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69,
|
||||
0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
||||
0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e,
|
||||
0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x09, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x74, 0x79,
|
||||
0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x73, 0x77, 0x61,
|
||||
0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6f,
|
||||
0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x52,
|
||||
0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a,
|
||||
0x12, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68,
|
||||
0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6f, 0x6d,
|
||||
0x69, 0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x12,
|
||||
0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f,
|
||||
0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69,
|
||||
0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0x59, 0x0a, 0x19, 0x53,
|
||||
0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61,
|
||||
0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6c,
|
||||
0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79,
|
||||
0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61,
|
||||
0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x1c, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71,
|
||||
0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53,
|
||||
0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x72, 0x0a, 0x0c, 0x44,
|
||||
0x69, 0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63,
|
||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75,
|
||||
0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x2b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x75, 0x74,
|
||||
0x6f, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22,
|
||||
0xb6, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x5f, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6c, 0x6f, 0x6f,
|
||||
0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x52, 0x07, 0x6c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x2f, 0x0a, 0x07,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x5f, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x06, 0x6c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x12, 0x39, 0x0a,
|
||||
0x0c, 0x64, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x02, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69,
|
||||
0x73, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x71,
|
||||
0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2a, 0x25, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x70,
|
||||
0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x4f, 0x55, 0x54,
|
||||
0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x49, 0x4e, 0x10, 0x01, 0x2a,
|
||||
0x73, 0x0a, 0x09, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x0a, 0x09,
|
||||
0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x50,
|
||||
0x52, 0x45, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x56, 0x45, 0x41, 0x4c, 0x45, 0x44,
|
||||
0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49,
|
||||
0x53, 0x48, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53,
|
||||
0x53, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12,
|
||||
0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x4c,
|
||||
0x45, 0x44, 0x10, 0x05, 0x2a, 0xed, 0x01, 0x0a, 0x0d, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65,
|
||||
0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52,
|
||||
0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12,
|
||||
0x1b, 0x0a, 0x17, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x4f, 0x46, 0x46, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16,
|
||||
0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x54,
|
||||
0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x46, 0x41, 0x49, 0x4c,
|
||||
0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x45, 0x45, 0x50,
|
||||
0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x46, 0x41,
|
||||
0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53,
|
||||
0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10,
|
||||
0x04, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41,
|
||||
0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x10, 0x05, 0x12,
|
||||
0x23, 0x0a, 0x1f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x41, 0x4d, 0x4f, 0x55,
|
||||
0x4e, 0x54, 0x10, 0x06, 0x2a, 0x2f, 0x0a, 0x11, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74,
|
||||
0x79, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b,
|
||||
0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48,
|
||||
0x4f, 0x4c, 0x44, 0x10, 0x01, 0x2a, 0xa6, 0x03, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x6f, 0x52, 0x65,
|
||||
0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41,
|
||||
0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x22, 0x0a,
|
||||
0x1e, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44,
|
||||
0x47, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10,
|
||||
0x01, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e,
|
||||
0x5f, 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x46, 0x45, 0x45, 0x53, 0x10, 0x02, 0x12, 0x1e, 0x0a,
|
||||
0x1a, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44,
|
||||
0x47, 0x45, 0x54, 0x5f, 0x45, 0x4c, 0x41, 0x50, 0x53, 0x45, 0x44, 0x10, 0x03, 0x12, 0x19, 0x0a,
|
||||
0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x5f,
|
||||
0x46, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x55, 0x54, 0x4f,
|
||||
0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x46, 0x45, 0x45,
|
||||
0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f,
|
||||
0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x06, 0x12, 0x16, 0x0a,
|
||||
0x12, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45,
|
||||
0x50, 0x41, 0x59, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45,
|
||||
0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x42, 0x41, 0x43,
|
||||
0x4b, 0x4f, 0x46, 0x46, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52,
|
||||
0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x09,
|
||||
0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f,
|
||||
0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x49, 0x4e, 0x10, 0x0a, 0x12, 0x1c, 0x0a, 0x18, 0x41, 0x55, 0x54,
|
||||
0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x49, 0x51, 0x55, 0x49, 0x44, 0x49,
|
||||
0x54, 0x59, 0x5f, 0x4f, 0x4b, 0x10, 0x0b, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x55, 0x54, 0x4f, 0x5f,
|
||||
0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x49, 0x4e,
|
||||
0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x0c, 0x12, 0x20, 0x0a, 0x1c,
|
||||
0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x45, 0x45, 0x5f,
|
||||
0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x0d, 0x32, 0xc2,
|
||||
0x07, 0x0a, 0x0a, 0x53, 0x77, 0x61, 0x70, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a,
|
||||
0x07, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x4c, 0x6f, 0x6f, 0x70,
|
||||
0x49, 0x6e, 0x12, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f,
|
||||
0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6c, 0x6f, 0x6f,
|
||||
0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x39, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x6c,
|
||||
0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x09,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x39, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x2e, 0x6c,
|
||||
0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x40, 0x0a, 0x0c, 0x4c,
|
||||
0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x15, 0x2e, 0x6c, 0x6f,
|
||||
0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74,
|
||||
0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a,
|
||||
0x0c, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x12, 0x15, 0x2e,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f,
|
||||
0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d,
|
||||
0x73, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x51,
|
||||
0x75, 0x6f, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51,
|
||||
0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f,
|
||||
0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x15,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a,
|
||||
0x0d, 0x47, 0x65, 0x74, 0x4c, 0x73, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x16,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x56, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50,
|
||||
0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61,
|
||||
0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70,
|
||||
0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72,
|
||||
0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x4c, 0x69,
|
||||
0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x2e,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69,
|
||||
0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c,
|
||||
0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73,
|
||||
0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53,
|
||||
0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f,
|
||||
0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -3182,40 +3208,41 @@ var file_client_proto_depIdxs = []int32{
|
|||
25, // 11: looprpc.SetLiquidityParamsRequest.parameters:type_name -> looprpc.LiquidityParameters
|
||||
4, // 12: looprpc.Disqualified.reason:type_name -> looprpc.AutoReason
|
||||
5, // 13: looprpc.SuggestSwapsResponse.loop_out:type_name -> looprpc.LoopOutRequest
|
||||
30, // 14: looprpc.SuggestSwapsResponse.disqualified:type_name -> looprpc.Disqualified
|
||||
5, // 15: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest
|
||||
6, // 16: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest
|
||||
8, // 17: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest
|
||||
10, // 18: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest
|
||||
12, // 19: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest
|
||||
13, // 20: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest
|
||||
16, // 21: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest
|
||||
13, // 22: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest
|
||||
16, // 23: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest
|
||||
19, // 24: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest
|
||||
21, // 25: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest
|
||||
24, // 26: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest
|
||||
27, // 27: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest
|
||||
29, // 28: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest
|
||||
7, // 29: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse
|
||||
7, // 30: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse
|
||||
9, // 31: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus
|
||||
11, // 32: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse
|
||||
9, // 33: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus
|
||||
15, // 34: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse
|
||||
18, // 35: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse
|
||||
14, // 36: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse
|
||||
17, // 37: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse
|
||||
20, // 38: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse
|
||||
22, // 39: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse
|
||||
25, // 40: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters
|
||||
28, // 41: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse
|
||||
31, // 42: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse
|
||||
29, // [29:43] is the sub-list for method output_type
|
||||
15, // [15:29] is the sub-list for method input_type
|
||||
15, // [15:15] is the sub-list for extension type_name
|
||||
15, // [15:15] is the sub-list for extension extendee
|
||||
0, // [0:15] is the sub-list for field type_name
|
||||
6, // 14: looprpc.SuggestSwapsResponse.loop_in:type_name -> looprpc.LoopInRequest
|
||||
30, // 15: looprpc.SuggestSwapsResponse.disqualified:type_name -> looprpc.Disqualified
|
||||
5, // 16: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest
|
||||
6, // 17: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest
|
||||
8, // 18: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest
|
||||
10, // 19: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest
|
||||
12, // 20: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest
|
||||
13, // 21: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest
|
||||
16, // 22: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest
|
||||
13, // 23: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest
|
||||
16, // 24: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest
|
||||
19, // 25: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest
|
||||
21, // 26: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest
|
||||
24, // 27: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest
|
||||
27, // 28: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest
|
||||
29, // 29: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest
|
||||
7, // 30: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse
|
||||
7, // 31: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse
|
||||
9, // 32: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus
|
||||
11, // 33: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse
|
||||
9, // 34: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus
|
||||
15, // 35: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse
|
||||
18, // 36: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse
|
||||
14, // 37: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse
|
||||
17, // 38: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse
|
||||
20, // 39: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse
|
||||
22, // 40: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse
|
||||
25, // 41: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters
|
||||
28, // 42: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse
|
||||
31, // 43: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse
|
||||
30, // [30:44] is the sub-list for method output_type
|
||||
16, // [16:30] is the sub-list for method input_type
|
||||
16, // [16:16] is the sub-list for extension type_name
|
||||
16, // [16:16] is the sub-list for extension extendee
|
||||
0, // [0:16] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_client_proto_init() }
|
||||
|
|
|
|||
|
|
@ -848,6 +848,11 @@ message LiquidityParameters {
|
|||
specified by the LoopOutTerms endpoint.
|
||||
*/
|
||||
uint64 max_swap_amount = 15;
|
||||
|
||||
/*
|
||||
The confirmation target for loop in on-chain htlcs.
|
||||
*/
|
||||
int32 htlc_conf_target = 17;
|
||||
}
|
||||
|
||||
enum LiquidityRuleType {
|
||||
|
|
@ -1012,6 +1017,11 @@ message SuggestSwapsResponse {
|
|||
*/
|
||||
repeated LoopOutRequest loop_out = 1;
|
||||
|
||||
/*
|
||||
The set of recommended loop in swaps
|
||||
*/
|
||||
repeated LoopInRequest loop_in = 3;
|
||||
|
||||
/*
|
||||
Disqualified contains the set of channels that swaps are not recommended
|
||||
for.
|
||||
|
|
|
|||
|
|
@ -675,6 +675,11 @@
|
|||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "The maximum amount, expressed in satoshis, that the autoloop client will\ndispatch a swap for. This value is subject to the server-side limits\nspecified by the LoopOutTerms endpoint."
|
||||
},
|
||||
"htlc_conf_target": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "The confirmation target for loop in on-chain htlcs."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -999,6 +1004,13 @@
|
|||
},
|
||||
"description": "The set of recommended loop outs."
|
||||
},
|
||||
"loop_in": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/looprpcLoopInRequest"
|
||||
},
|
||||
"title": "The set of recommended loop in swaps"
|
||||
},
|
||||
"disqualified": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ This file tracks release notes for the loop client.
|
|||
## Next release
|
||||
|
||||
#### New Features
|
||||
* Loop in functionality has been added to AutoLoop. This feature can be enabled
|
||||
to acquire outgoing capacity on your node automatically, using
|
||||
`loop setrule --type=in`. At present, autoloop can only be set to loop out
|
||||
*or* loop in, and cannot manage liquidity in both directions.
|
||||
|
||||
#### Breaking Changes
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue