Merge pull request #321 from carlaKC/319-customautoloopsizelimits

liquidity: add custom swap amounts to autoloop
pull/323/head
Carla Kirk-Cohen 3 years ago committed by GitHub
commit ca3e700cc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -248,6 +248,16 @@ var setParamsCommand = cli.Command{
"dispatched swaps that we allow to be in " +
"flight",
},
cli.Uint64Flag{
Name: "minamt",
Usage: "the minimum amount in satoshis that the " +
"autoloop client will dispatch per-swap",
},
cli.Uint64Flag{
Name: "maxamt",
Usage: "the maximum amount in satoshis that the " +
"autoloop client will dispatch per-swap",
},
},
Action: setParams,
}
@ -348,6 +358,16 @@ func setParams(ctx *cli.Context) error {
flagSet = true
}
if ctx.IsSet("minamt") {
params.MinSwapAmount = ctx.Uint64("minamt")
flagSet = true
}
if ctx.IsSet("maxamt") {
params.MaxSwapAmount = ctx.Uint64("maxamt")
flagSet = true
}
if !flagSet {
return fmt.Errorf("at least one flag required to set params")
}

@ -191,6 +191,33 @@ The default value for this parameter is 24hours, and it can be updated as follow
loop setparams --failurebackoff={backoff in seconds}
```
### Swap Size
By default, the autolooper will execute a swap when the amount that needs to be
rebalanced within a channel is equal to the swap server's minimum swap size.
This means that it will dispatch swaps more regularly, and ensure that channels
are not run down too far below their configured threshold. If you are willing
to allow your liquidity to drop further than the minimum swap amount below your
threshold, a custom minimum swap size can be set. If autolooper is configured
with a larger minimum swap size, it will allow channels to drop further below
their target threshold, but will perform fewer swaps, potentially saving on
fees.
```
loop setparams --minamt={amount in satoshis}
```
Swaps are also limited to the maximum swap amount advertised by the server. If
you would like to reduce the size of swap that autoloop created, this value can
also be configured.
```
loop setparams --maxamt={amount in satoshis}
```
The server's current terms are provided by the `loop terms` cli command. The
values set for minimum and maximum swap amount must be within the range that
the server supports.
## Manual Swap Interaction
The autolooper will not dispatch swaps over channels that are already included
in manually dispatched swaps - for loop out, this would mean the channel is

@ -28,7 +28,7 @@ func TestAutoLoopDisabled(t *testing.T) {
chanID1: chanRule,
}
c := newAutoloopTestCtx(t, params, channels)
c := newAutoloopTestCtx(t, params, channels, testRestrictions)
c.start()
// We expect a single quote to be required for our swap on channel 1.
@ -93,7 +93,7 @@ func TestAutoLoopEnabled(t *testing.T) {
},
}
c := newAutoloopTestCtx(t, params, channels)
c := newAutoloopTestCtx(t, params, channels, testRestrictions)
c.start()
// Calculate our maximum allowed fees and create quotes that fall within

@ -58,7 +58,8 @@ type autoloopTestCtx struct {
// newAutoloopTestCtx creates a test context with custom liquidity manager
// parameters and lnd channels.
func newAutoloopTestCtx(t *testing.T, parameters Parameters,
channels []lndclient.ChannelInfo) *autoloopTestCtx {
channels []lndclient.ChannelInfo,
server *Restrictions) *autoloopTestCtx {
// Create a mock lnd and set our expected fee rate for sweeps to our
// sweep fee rate limit value.
@ -121,11 +122,20 @@ func newAutoloopTestCtx(t *testing.T, parameters Parameters,
Clock: testCtx.testClock,
}
// SetParameters needs to make a call to our mocked restrictions call,
// which will block, so we push our test values in a goroutine.
done := make(chan struct{})
go func() {
testCtx.loopOutRestrictions <- server
close(done)
}()
// Create a manager with our test config and set our starting set of
// parameters.
testCtx.manager = NewManager(cfg)
assert.NoError(t, testCtx.manager.SetParameters(parameters))
err := testCtx.manager.SetParameters(context.Background(), parameters)
assert.NoError(t, err)
<-done
return testCtx
}

@ -162,6 +162,21 @@ var (
// ErrZeroInFlight is returned is a zero in flight swaps value is set.
ErrZeroInFlight = errors.New("max in flight swaps must be >=0")
// ErrMinimumExceedsMaximumAmt is returned when the minimum configured
// swap amount is more than the maximum.
ErrMinimumExceedsMaximumAmt = errors.New("minimum swap amount " +
"exceeds maximum")
// ErrMaxExceedsServer is returned if the maximum swap amount set is
// more than the server offers.
ErrMaxExceedsServer = errors.New("maximum swap amount is more than " +
"server maximum")
// ErrMinLessThanServer is returned if the minimum swap amount set is
// less than the server minimum.
ErrMinLessThanServer = errors.New("minimum swap amount is less than " +
"server minimum")
)
// Config contains the external functionality required to run the
@ -264,6 +279,10 @@ type Parameters struct {
// sweep during a fee spike.
MaximumMinerFee btcutil.Amount
// ClientRestrictions are the restrictions placed on swap size by the
// client.
ClientRestrictions Restrictions
// ChannelRules maps a short channel ID to a rule that describes how we
// would like liquidity to be managed.
ChannelRules map[lnwire.ShortChannelID]*ThresholdRule
@ -283,17 +302,19 @@ func (p Parameters) String() string {
"fee rate limit: %v, sweep conf target: %v, maximum prepay: "+
"%v, maximum miner fee: %v, maximum swap fee ppm: %v, maximum "+
"routing fee ppm: %v, maximum prepay routing fee ppm: %v, "+
"auto budget: %v, budget start: %v, max auto in flight: %v",
"auto budget: %v, budget start: %v, max auto in flight: %v, "+
"minimum swap size=%v, maximum swap size=%v",
strings.Join(channelRules, ","), p.FailureBackOff,
p.SweepFeeRateLimit, p.SweepConfTarget, p.MaximumPrepay,
p.MaximumMinerFee, p.MaximumSwapFeePPM,
p.MaximumRoutingFeePPM, p.MaximumPrepayRoutingFeePPM,
p.AutoFeeBudget, p.AutoFeeStartDate, p.MaxAutoInFlight)
p.AutoFeeBudget, p.AutoFeeStartDate, p.MaxAutoInFlight,
p.ClientRestrictions.Minimum, p.ClientRestrictions.Maximum)
}
// validate checks whether a set of parameters is valid. It takes the minimum
// confirmations we allow for sweep confirmation target as a parameter.
func (p Parameters) validate(minConfs int32) error {
func (p Parameters) validate(minConfs int32, server *Restrictions) error {
for channel, rule := range p.ChannelRules {
if channel.ToUint64() == 0 {
return ErrZeroChannelID
@ -347,6 +368,47 @@ func (p Parameters) validate(minConfs int32) error {
return ErrZeroInFlight
}
err := validateRestrictions(server, &p.ClientRestrictions)
if err != nil {
return err
}
return nil
}
// validateRestrictions checks that client restrictions fall within the server's
// restrictions.
func validateRestrictions(server, client *Restrictions) error {
zeroMin := client.Minimum == 0
zeroMax := client.Maximum == 0
if zeroMin && zeroMax {
return nil
}
// If we have a non-zero maximum, we need to ensure it is greater than
// our minimum (which is fine if min is zero), and does not exceed the
// server's maximum.
if !zeroMax {
if client.Minimum > client.Maximum {
return ErrMinimumExceedsMaximumAmt
}
if client.Maximum > server.Maximum {
return ErrMaxExceedsServer
}
}
if zeroMin {
return nil
}
// If the client set a minimum, ensure it is at least equal to the
// server's limit.
if client.Minimum < server.Minimum {
return ErrMinLessThanServer
}
return nil
}
@ -403,8 +465,14 @@ func (m *Manager) GetParameters() Parameters {
// SetParameters updates our current set of parameters if the new parameters
// provided are valid.
func (m *Manager) SetParameters(params Parameters) error {
if err := params.validate(m.cfg.MinimumConfirmations); err != nil {
func (m *Manager) SetParameters(ctx context.Context, params Parameters) error {
restrictions, err := m.cfg.LoopOutRestrictions(ctx)
if err != nil {
return err
}
err = params.validate(m.cfg.MinimumConfirmations, restrictions)
if err != nil {
return err
}
@ -517,8 +585,9 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoOut bool) (
return nil, nil
}
// Get the current server side restrictions.
outRestrictions, err := m.cfg.LoopOutRestrictions(ctx)
// Get the current server side restrictions, combined with the client
// set restrictions, if any.
outRestrictions, err := m.getLoopOutRestrictions(ctx)
if err != nil {
return nil, err
}
@ -674,6 +743,41 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoOut bool) (
return inBudget, nil
}
// getLoopOutRestrictions queries the server for its latest swap size
// restrictions, validates client restrictions (if present) against these
// values and merges the client's custom requirements with the server's limits
// to produce a single set of limitations for our swap.
func (m *Manager) getLoopOutRestrictions(ctx context.Context) (*Restrictions,
error) {
restrictions, err := m.cfg.LoopOutRestrictions(ctx)
if err != nil {
return nil, err
}
// It is possible that the server has updated its restrictions since
// we validated our client restrictions, so we validate again to ensure
// that our restrictions are within the server's bounds.
err = validateRestrictions(restrictions, &m.params.ClientRestrictions)
if err != nil {
return nil, err
}
// If our minimum is more than the server's minimum, we set it.
if m.params.ClientRestrictions.Minimum > restrictions.Minimum {
restrictions.Minimum = m.params.ClientRestrictions.Minimum
}
// If our maximum set and is less than the server's maximum, we set it.
if m.params.ClientRestrictions.Maximum != 0 &&
m.params.ClientRestrictions.Maximum < restrictions.Maximum {
restrictions.Maximum = m.params.ClientRestrictions.Maximum
}
return restrictions, nil
}
// makeLoopOutRequest creates a loop out request from a suggestion. Since we
// do not get any information about our off-chain routing fees when we request
// a quote, we just set our prepay and route maximum fees directly from the

@ -104,6 +104,8 @@ var (
},
OutgoingChanSet: loopdb.ChannelSet{999},
}
testRestrictions = NewRestrictions(1, 10000)
)
// newTestConfig creates a default test config.
@ -121,7 +123,7 @@ func newTestConfig() (*Config, *test.LndMockServices) {
LoopOutRestrictions: func(_ context.Context) (*Restrictions,
error) {
return NewRestrictions(1, 10000), nil
return testRestrictions, nil
},
Lnd: &lnd.LndServices,
Clock: clock.NewTestClock(testTime),
@ -167,7 +169,7 @@ func TestParameters(t *testing.T) {
chanID: originalRule,
}
err := manager.SetParameters(expected)
err := manager.SetParameters(context.Background(), expected)
require.NoError(t, err)
// Check that changing the parameters we just set does not mutate
@ -182,10 +184,64 @@ func TestParameters(t *testing.T) {
expected.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
lnwire.NewShortChanIDFromInt(0): NewThresholdRule(1, 2),
}
err = manager.SetParameters(expected)
err = manager.SetParameters(context.Background(), expected)
require.Equal(t, ErrZeroChannelID, err)
}
// TestValidateRestrictions tests validating client restrictions against a set
// of server restrictions.
func TestValidateRestrictions(t *testing.T) {
tests := []struct {
name string
client *Restrictions
server *Restrictions
err error
}{
{
name: "client invalid",
client: &Restrictions{
Minimum: 100,
Maximum: 1,
},
server: testRestrictions,
err: ErrMinimumExceedsMaximumAmt,
},
{
name: "maximum exceeds server",
client: &Restrictions{
Maximum: 2000,
},
server: &Restrictions{
Minimum: 1000,
Maximum: 1500,
},
err: ErrMaxExceedsServer,
},
{
name: "minimum less than server",
client: &Restrictions{
Minimum: 500,
},
server: &Restrictions{
Minimum: 1000,
Maximum: 1500,
},
err: ErrMinLessThanServer,
},
}
for _, testCase := range tests {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
err := validateRestrictions(
testCase.server, testCase.client,
)
require.Equal(t, testCase.err, err)
})
}
}
// TestRestrictedSuggestions tests getting of swap suggestions when we have
// other in-flight swaps. We setup our manager with a set of channels and rules
// that require a loop out swap, focusing on the filtering our of channels that
@ -376,7 +432,7 @@ func TestRestrictedSuggestions(t *testing.T) {
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
testCase.expected,
testCase.expected, nil,
)
})
}
@ -426,7 +482,7 @@ func TestSweepFeeLimit(t *testing.T) {
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
testCase.swaps,
testCase.swaps, nil,
)
})
}
@ -477,7 +533,7 @@ func TestSuggestSwaps(t *testing.T) {
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
testCase.swaps,
testCase.swaps, nil,
)
})
}
@ -547,7 +603,7 @@ func TestFeeLimits(t *testing.T) {
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
testCase.expected,
testCase.expected, nil,
)
})
}
@ -704,7 +760,7 @@ func TestFeeBudget(t *testing.T) {
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
testCase.expectedSwaps,
testCase.expectedSwaps, nil,
)
})
}
@ -797,7 +853,151 @@ func TestInFlightLimit(t *testing.T) {
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
testCase.expectedSwaps,
testCase.expectedSwaps, nil,
)
})
}
}
// TestSizeRestrictions tests the use of client-set size restrictions on swaps.
func TestSizeRestrictions(t *testing.T) {
var (
serverRestrictions = Restrictions{
Minimum: 6000,
Maximum: 10000,
}
swap = loop.OutRequest{
OutgoingChanSet: loopdb.ChannelSet{chanID1.ToUint64()},
MaxPrepayRoutingFee: prepayFee,
MaxMinerFee: defaultMaximumMinerFee,
MaxSwapFee: testQuote.SwapFee,
MaxPrepayAmount: testQuote.PrepayAmount,
SweepConfTarget: loop.DefaultSweepConfTarget,
Initiator: autoloopSwapInitiator,
}
)
tests := []struct {
name string
// clientRestrictions holds the restrictions that the client
// has configured.
clientRestrictions Restrictions
// server holds the server's mocked responses to our terms
// endpoint.
serverRestrictions []Restrictions
// expectedAmount is the amount that we expect for our swap.
expectedAmount btcutil.Amount
// expectedError is the error we expect.
expectedError error
}{
{
name: "minimum more than server, swap happens",
clientRestrictions: Restrictions{
Minimum: 7000,
},
serverRestrictions: []Restrictions{
serverRestrictions, serverRestrictions,
},
expectedAmount: 7500,
},
{
name: "minimum more than server, no swap",
clientRestrictions: Restrictions{
Minimum: 8000,
},
serverRestrictions: []Restrictions{
serverRestrictions, serverRestrictions,
},
expectedAmount: 0,
},
{
name: "maximum less than server, swap happens",
clientRestrictions: Restrictions{
Maximum: 7000,
},
serverRestrictions: []Restrictions{
serverRestrictions, serverRestrictions,
},
expectedAmount: 7000,
},
{
// Originally, our client params are ok. But then the
// server increases its minimum, making the client
// params stale.
name: "client params stale over time",
clientRestrictions: Restrictions{
Minimum: 6500,
Maximum: 9000,
},
serverRestrictions: []Restrictions{
serverRestrictions,
{
Minimum: 5000,
Maximum: 6000,
},
},
expectedAmount: 0,
expectedError: ErrMaxExceedsServer,
},
}
for _, testCase := range tests {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
cfg, lnd := newTestConfig()
lnd.Channels = []lndclient.ChannelInfo{
channel1,
}
params := defaultParameters
params.ClientRestrictions = testCase.clientRestrictions
params.ChannelRules = map[lnwire.ShortChannelID]*ThresholdRule{
chanID1: chanRule,
}
// callCount tracks the number of calls we make to
// our restrictions endpoint.
var callCount int
cfg.LoopOutRestrictions = func(_ context.Context) (
*Restrictions, error) {
restrictions := testCase.serverRestrictions[callCount]
callCount++
return &restrictions, nil
}
// If we expect a swap (non-zero amount), we add a
// swap to our set of expected swaps, and update amount
// and fee accordingly.
var expectedSwaps []loop.OutRequest
if testCase.expectedAmount != 0 {
swap.Amount = testCase.expectedAmount
swap.MaxSwapRoutingFee = ppmToSat(
testCase.expectedAmount,
defaultRoutingFeePPM,
)
expectedSwaps = append(expectedSwaps, swap)
}
testSuggestSwaps(
t, newSuggestSwapsSetup(cfg, lnd, params),
expectedSwaps, testCase.expectedError,
)
require.Equal(
t, callCount, len(testCase.serverRestrictions),
"too many restrictions provided by mock",
)
})
}
@ -827,7 +1027,7 @@ func newSuggestSwapsSetup(cfg *Config, lnd *test.LndMockServices,
// use the default parameters and setup two channels (channel1 + channel2) with
// chanRule set for each.
func testSuggestSwaps(t *testing.T, setup *testSuggestSwapsSetup,
expected []loop.OutRequest) {
expected []loop.OutRequest, expectedErr error) {
t.Parallel()
@ -857,10 +1057,10 @@ func testSuggestSwaps(t *testing.T, setup *testSuggestSwapsSetup,
// them to use the rules set by the test.
manager := NewManager(setup.cfg)
err := manager.SetParameters(setup.params)
err := manager.SetParameters(context.Background(), setup.params)
require.NoError(t, err)
actual, err := manager.SuggestSwaps(context.Background(), false)
require.NoError(t, err)
require.Equal(t, expectedErr, err)
require.Equal(t, expected, actual)
}

@ -587,6 +587,8 @@ func (s *swapClientServer) GetLiquidityParams(_ context.Context,
Rules: make(
[]*looprpc.LiquidityRule, 0, len(cfg.ChannelRules),
),
MinSwapAmount: uint64(cfg.ClientRestrictions.Minimum),
MaxSwapAmount: uint64(cfg.ClientRestrictions.Maximum),
}
// Zero golang time is different to a zero unix time, so we only set
@ -613,7 +615,7 @@ func (s *swapClientServer) GetLiquidityParams(_ context.Context,
// SetLiquidityParams attempts to set our current liquidity manager's
// parameters.
func (s *swapClientServer) SetLiquidityParams(_ context.Context,
func (s *swapClientServer) SetLiquidityParams(ctx context.Context,
in *looprpc.SetLiquidityParamsRequest) (*looprpc.SetLiquidityParamsResponse,
error) {
@ -638,6 +640,10 @@ func (s *swapClientServer) SetLiquidityParams(_ context.Context,
map[lnwire.ShortChannelID]*liquidity.ThresholdRule,
len(in.Parameters.Rules),
),
ClientRestrictions: liquidity.Restrictions{
Minimum: btcutil.Amount(in.Parameters.MinSwapAmount),
Maximum: btcutil.Amount(in.Parameters.MaxSwapAmount),
},
}
// Zero unix time is different to zero golang time.
@ -666,7 +672,7 @@ func (s *swapClientServer) SetLiquidityParams(_ context.Context,
}
}
if err := s.liquidityMgr.SetParameters(params); err != nil {
if err := s.liquidityMgr.SetParameters(ctx, params); err != nil {
return nil, err
}

@ -1626,7 +1626,17 @@ type LiquidityParameters struct {
//
//The maximum number of automatically dispatched swaps that we allow to be in
//flight at any point in time.
AutoMaxInFlight uint64 `protobuf:"varint,13,opt,name=auto_max_in_flight,json=autoMaxInFlight,proto3" json:"auto_max_in_flight,omitempty"`
AutoMaxInFlight uint64 `protobuf:"varint,13,opt,name=auto_max_in_flight,json=autoMaxInFlight,proto3" json:"auto_max_in_flight,omitempty"`
//
//The minimum amount, expressed in satoshis, that the autoloop client will
//dispatch a swap for. This value is subject to the server-side limits
//specified by the LoopOutTerms endpoint.
MinSwapAmount uint64 `protobuf:"varint,14,opt,name=min_swap_amount,json=minSwapAmount,proto3" json:"min_swap_amount,omitempty"`
//
//The maximum amount, expressed in satoshis, that the autoloop client will
//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"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -1748,6 +1758,20 @@ func (m *LiquidityParameters) GetAutoMaxInFlight() uint64 {
return 0
}
func (m *LiquidityParameters) GetMinSwapAmount() uint64 {
if m != nil {
return m.MinSwapAmount
}
return 0
}
func (m *LiquidityParameters) GetMaxSwapAmount() uint64 {
if m != nil {
return m.MaxSwapAmount
}
return 0
}
type LiquidityRule struct {
//
//The short channel ID of the channel that this rule should be applied to.
@ -2005,157 +2029,157 @@ func init() {
func init() { proto.RegisterFile("client.proto", fileDescriptor_014de31d7ac8c57c) }
var fileDescriptor_014de31d7ac8c57c = []byte{
// 2385 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcf, 0x6f, 0xe3, 0xc6,
0xf5, 0x5f, 0x49, 0x94, 0x25, 0x3d, 0x51, 0x12, 0x3d, 0xde, 0xb5, 0x65, 0xc5, 0x41, 0xbc, 0x4c,
0xf6, 0x1b, 0xc7, 0x49, 0xac, 0x6f, 0x9c, 0x4b, 0x1b, 0x24, 0x05, 0xb4, 0xb2, 0x1c, 0xcb, 0xb5,
0x25, 0x95, 0x92, 0x37, 0x48, 0x51, 0x80, 0x18, 0x4b, 0x63, 0x8b, 0x88, 0xf8, 0x63, 0xc9, 0xd1,
0xae, 0x8d, 0xa0, 0x2d, 0x50, 0xa0, 0xe7, 0x1e, 0xfa, 0x1f, 0xf4, 0xde, 0x5b, 0x6f, 0xed, 0x9f,
0xd0, 0x53, 0x7b, 0xec, 0xb5, 0x97, 0x1e, 0xfa, 0x27, 0x14, 0x28, 0xe6, 0x0d, 0x49, 0x91, 0xb2,
0xe4, 0xa2, 0x87, 0xde, 0xc4, 0xf7, 0x3e, 0xf3, 0xe6, 0xcd, 0xfb, 0xfd, 0x04, 0xea, 0x78, 0x66,
0x31, 0x87, 0x1f, 0x79, 0xbe, 0xcb, 0x5d, 0x52, 0x98, 0xb9, 0xae, 0xe7, 0x7b, 0xe3, 0xc6, 0xde,
0xad, 0xeb, 0xde, 0xce, 0x58, 0x93, 0x7a, 0x56, 0x93, 0x3a, 0x8e, 0xcb, 0x29, 0xb7, 0x5c, 0x27,
0x90, 0x30, 0xfd, 0xf7, 0x0a, 0x54, 0x2f, 0x5c, 0xd7, 0xeb, 0xcf, 0xb9, 0xc1, 0x5e, 0xcf, 0x59,
0xc0, 0x89, 0x06, 0x39, 0x6a, 0xf3, 0x7a, 0x66, 0x3f, 0x73, 0x90, 0x33, 0xc4, 0x4f, 0x42, 0x40,
0x99, 0xb0, 0x80, 0xd7, 0xb3, 0xfb, 0x99, 0x83, 0x92, 0x81, 0xbf, 0x49, 0x13, 0x9e, 0xda, 0xf4,
0xce, 0x0c, 0xde, 0x52, 0xcf, 0xf4, 0xdd, 0x39, 0xb7, 0x9c, 0x5b, 0xf3, 0x86, 0xb1, 0x7a, 0x0e,
0x8f, 0x6d, 0xda, 0xf4, 0x6e, 0xf8, 0x96, 0x7a, 0x86, 0xe4, 0x9c, 0x32, 0x46, 0x3e, 0x87, 0x6d,
0x71, 0xc0, 0xf3, 0x99, 0x47, 0xef, 0x53, 0x47, 0x14, 0x3c, 0xb2, 0x65, 0xd3, 0xbb, 0x01, 0x32,
0x13, 0x87, 0xf6, 0x41, 0x8d, 0x6f, 0x11, 0xd0, 0x3c, 0x42, 0x21, 0x94, 0x2e, 0x10, 0x1f, 0x40,
0x35, 0x21, 0x56, 0x28, 0xbe, 0x81, 0x18, 0x35, 0x16, 0xd7, 0xb2, 0x39, 0xd1, 0xa1, 0x22, 0x50,
0xb6, 0xe5, 0x30, 0x1f, 0x05, 0x15, 0x10, 0x54, 0xb6, 0xe9, 0xdd, 0xa5, 0xa0, 0x09, 0x49, 0x9f,
0x80, 0x26, 0x6c, 0x66, 0xba, 0x73, 0x6e, 0x8e, 0xa7, 0xd4, 0x71, 0xd8, 0xac, 0x5e, 0xdc, 0xcf,
0x1c, 0x28, 0x2f, 0xb3, 0xf5, 0x8c, 0x51, 0x9d, 0x49, 0x2b, 0xb5, 0x25, 0x87, 0x1c, 0xc2, 0xa6,
0x3b, 0xe7, 0xb7, 0xae, 0x78, 0x84, 0x40, 0x9b, 0x01, 0xe3, 0xf5, 0xf2, 0x7e, 0xee, 0x40, 0x31,
0x6a, 0x11, 0x43, 0x60, 0x87, 0x8c, 0x0b, 0x6c, 0xf0, 0x96, 0x31, 0xcf, 0x1c, 0xbb, 0xce, 0x8d,
0xc9, 0xa9, 0x7f, 0xcb, 0x78, 0xbd, 0xb4, 0x9f, 0x39, 0xc8, 0x1b, 0x35, 0x64, 0xb4, 0x5d, 0xe7,
0x66, 0x84, 0x64, 0xf2, 0x29, 0x90, 0x29, 0x9f, 0x8d, 0x11, 0x6a, 0xf9, 0xb6, 0x74, 0x56, 0xbd,
0x82, 0xe0, 0x4d, 0xc1, 0x69, 0x27, 0x19, 0xe4, 0x0b, 0xd8, 0x45, 0xe3, 0x78, 0xf3, 0xeb, 0x99,
0x35, 0x46, 0xa2, 0x39, 0x61, 0x74, 0x32, 0xb3, 0x1c, 0x56, 0x07, 0xa1, 0xbd, 0xb1, 0x23, 0x00,
0x83, 0x05, 0xff, 0x24, 0x64, 0x93, 0xa7, 0x90, 0x9f, 0xd1, 0x6b, 0x36, 0xab, 0xab, 0xe8, 0x57,
0xf9, 0x41, 0xf6, 0xa0, 0x64, 0x39, 0x16, 0xb7, 0x28, 0x77, 0xfd, 0x7a, 0x15, 0x39, 0x0b, 0x82,
0xfe, 0xeb, 0x2c, 0x54, 0x44, 0xbc, 0x74, 0x9d, 0xf5, 0xe1, 0xb2, 0xec, 0xb4, 0xec, 0x03, 0xa7,
0x3d, 0x70, 0x47, 0xee, 0xa1, 0x3b, 0x76, 0xa1, 0x38, 0xa3, 0x01, 0x37, 0xa7, 0xae, 0x87, 0x11,
0xa2, 0x1a, 0x05, 0xf1, 0x7d, 0xe6, 0x7a, 0xe4, 0x7d, 0xa8, 0xb0, 0x3b, 0xce, 0x7c, 0x87, 0xce,
0x4c, 0x61, 0x12, 0x0c, 0x8b, 0xa2, 0xa1, 0x46, 0xc4, 0x33, 0x3e, 0x1b, 0x93, 0x03, 0xd0, 0x62,
0x43, 0x46, 0x36, 0xdf, 0x40, 0x33, 0x56, 0x23, 0x33, 0x86, 0x26, 0x8f, 0xed, 0x50, 0x58, 0x6b,
0x87, 0xe2, 0xb2, 0x1d, 0xfe, 0x91, 0x01, 0x15, 0x03, 0x9c, 0x05, 0x9e, 0xeb, 0x04, 0x8c, 0x10,
0xc8, 0x5a, 0x13, 0xb4, 0x42, 0x09, 0xe3, 0x25, 0x6b, 0x4d, 0xc4, 0x13, 0xac, 0x89, 0x79, 0x7d,
0xcf, 0x59, 0x80, 0x2f, 0x54, 0x8d, 0x82, 0x35, 0x79, 0x29, 0x3e, 0xc9, 0x0b, 0x50, 0x51, 0x3b,
0x3a, 0x99, 0xf8, 0x2c, 0x08, 0x64, 0x6a, 0xe1, 0xc1, 0xb2, 0xa0, 0xb7, 0x24, 0x99, 0x1c, 0xc1,
0x56, 0x12, 0x66, 0x3a, 0xde, 0xf1, 0xdb, 0x60, 0x8a, 0xf6, 0x28, 0xc9, 0x70, 0x08, 0x91, 0x3d,
0x64, 0x90, 0x4f, 0xc2, 0xe8, 0x89, 0xf0, 0x12, 0x9e, 0x47, 0xb8, 0x96, 0x80, 0x0f, 0x10, 0xfd,
0x02, 0xaa, 0x01, 0xf3, 0xdf, 0x30, 0xdf, 0xb4, 0x59, 0x10, 0xd0, 0x5b, 0x86, 0x06, 0x2a, 0x19,
0x15, 0x49, 0xbd, 0x94, 0x44, 0x5d, 0x83, 0xea, 0xa5, 0xeb, 0x58, 0xdc, 0xf5, 0x43, 0x9f, 0xeb,
0x7f, 0x50, 0x00, 0xc4, 0xeb, 0x87, 0x9c, 0xf2, 0x79, 0xb0, 0xb2, 0x62, 0x08, 0x6b, 0x64, 0xd7,
0x5a, 0xa3, 0xbc, 0x6c, 0x0d, 0x85, 0xdf, 0x7b, 0x32, 0x0c, 0xaa, 0xc7, 0x9b, 0x47, 0x61, 0xed,
0x3a, 0x12, 0x77, 0x8c, 0xee, 0x3d, 0x66, 0x20, 0x9b, 0x1c, 0x40, 0x3e, 0xe0, 0x94, 0xcb, 0x8a,
0x51, 0x3d, 0x26, 0x29, 0x9c, 0xd0, 0x85, 0x19, 0x12, 0x40, 0xbe, 0x82, 0xea, 0x0d, 0xb5, 0x66,
0x73, 0x9f, 0x99, 0x3e, 0xa3, 0x81, 0xeb, 0x60, 0x24, 0x57, 0x8f, 0xb7, 0xe3, 0x23, 0xa7, 0x92,
0x6d, 0x20, 0xd7, 0xa8, 0xdc, 0x24, 0x3f, 0xc9, 0x87, 0x50, 0x0b, 0x5d, 0x2d, 0xf2, 0x89, 0x5b,
0x76, 0x54, 0x79, 0xaa, 0x0b, 0xf2, 0xc8, 0xb2, 0x85, 0x46, 0x1a, 0x06, 0xe9, 0xdc, 0x9b, 0x50,
0xce, 0x24, 0x52, 0xd6, 0x9f, 0xaa, 0xa0, 0x5f, 0x21, 0x19, 0x91, 0xcb, 0x0e, 0x2f, 0xac, 0x76,
0xf8, 0x6a, 0x07, 0xaa, 0x6b, 0x1c, 0xb8, 0x26, 0x3c, 0x2a, 0xeb, 0xc2, 0xe3, 0x3d, 0x28, 0x8f,
0xdd, 0x80, 0x9b, 0xd2, 0xbf, 0x18, 0xd5, 0x39, 0x03, 0x04, 0x69, 0x88, 0x14, 0xf2, 0x1c, 0x54,
0x04, 0xb8, 0xce, 0x78, 0x4a, 0x2d, 0x07, 0x8b, 0x54, 0xce, 0xc0, 0x43, 0x7d, 0x49, 0x12, 0xc9,
0x27, 0x21, 0x37, 0x37, 0x12, 0x03, 0xb2, 0xde, 0x22, 0x26, 0xa4, 0x2d, 0x52, 0xaa, 0x96, 0x48,
0x29, 0x9d, 0x80, 0x76, 0x61, 0x05, 0x5c, 0x78, 0x2b, 0x88, 0x42, 0xe9, 0x47, 0xb0, 0x99, 0xa0,
0x85, 0xc9, 0xf4, 0x11, 0xe4, 0x45, 0xf5, 0x08, 0xea, 0x99, 0xfd, 0xdc, 0x41, 0xf9, 0x78, 0xeb,
0x81, 0xa3, 0xe7, 0x81, 0x21, 0x11, 0xfa, 0x73, 0xa8, 0x09, 0x62, 0xd7, 0xb9, 0x71, 0xa3, 0x8a,
0x54, 0x8d, 0x53, 0x51, 0x15, 0x81, 0xa7, 0x57, 0x41, 0x1d, 0x31, 0xdf, 0x8e, 0xaf, 0xfc, 0x25,
0xd4, 0xba, 0x4e, 0x48, 0x09, 0x2f, 0xfc, 0x3f, 0xa8, 0xd9, 0x96, 0x23, 0x4b, 0x16, 0xb5, 0xdd,
0xb9, 0xc3, 0x43, 0x87, 0x57, 0x6c, 0xcb, 0x11, 0xf2, 0x5b, 0x48, 0x44, 0x5c, 0x54, 0xda, 0x42,
0xdc, 0x46, 0x88, 0x93, 0xd5, 0x4d, 0xe2, 0xce, 0x95, 0x62, 0x46, 0xcb, 0x9e, 0x2b, 0xc5, 0xac,
0x96, 0x3b, 0x57, 0x8a, 0x39, 0x4d, 0x39, 0x57, 0x8a, 0x8a, 0x96, 0x3f, 0x57, 0x8a, 0x05, 0xad,
0xa8, 0xff, 0x39, 0x03, 0x5a, 0x7f, 0xce, 0xff, 0xa7, 0x2a, 0x60, 0x63, 0xb4, 0x1c, 0x73, 0x3c,
0xe3, 0x6f, 0xcc, 0x09, 0x9b, 0x71, 0x8a, 0xee, 0xce, 0x1b, 0xaa, 0x6d, 0x39, 0xed, 0x19, 0x7f,
0x73, 0x22, 0x68, 0x51, 0xfb, 0x4c, 0xa0, 0x4a, 0x21, 0x8a, 0xde, 0xc5, 0xa8, 0xff, 0xf0, 0x9c,
0xdf, 0x65, 0x40, 0xfd, 0xc9, 0xdc, 0xe5, 0x6c, 0x7d, 0x4b, 0xc0, 0xc0, 0x5b, 0xd4, 0xe1, 0x2c,
0xde, 0x01, 0xe3, 0x45, 0x0d, 0x7e, 0x50, 0xd2, 0x73, 0x2b, 0x4a, 0xfa, 0xa3, 0xcd, 0x4e, 0x79,
0xb4, 0xd9, 0xe9, 0xbf, 0xc9, 0x08, 0xaf, 0x87, 0x6a, 0x86, 0x26, 0xdf, 0x07, 0x35, 0x6a, 0x52,
0x66, 0x40, 0x23, 0x85, 0x21, 0x90, 0x5d, 0x6a, 0x48, 0x71, 0xca, 0xc1, 0x04, 0xc3, 0x1b, 0x83,
0x69, 0x8c, 0x0c, 0xa7, 0x1c, 0xc1, 0x1b, 0x48, 0x56, 0x78, 0xe0, 0x5d, 0x80, 0x84, 0x2d, 0xf3,
0xf8, 0xce, 0xd2, 0x38, 0x61, 0x48, 0x69, 0x42, 0x45, 0xcb, 0xeb, 0x7f, 0x91, 0x51, 0xf0, 0xdf,
0xaa, 0xf4, 0x01, 0x54, 0x17, 0xc3, 0x0e, 0x62, 0x64, 0x7f, 0x55, 0xbd, 0x68, 0xda, 0x11, 0xa8,
0x8f, 0xc3, 0x3a, 0x22, 0xe7, 0x8e, 0xb4, 0xda, 0x35, 0xc1, 0x19, 0x0a, 0x46, 0x28, 0x12, 0xe7,
0x13, 0x61, 0x57, 0x7a, 0x6f, 0x33, 0x87, 0x9b, 0x38, 0xec, 0xc9, 0x9e, 0x5b, 0x43, 0x7b, 0x4a,
0xfa, 0x89, 0xf0, 0xed, 0xe3, 0x0f, 0xd4, 0x6b, 0x50, 0x19, 0xb9, 0xdf, 0x31, 0x27, 0x4e, 0xb6,
0x2f, 0xa1, 0x1a, 0x11, 0xc2, 0x27, 0x1e, 0xc2, 0x06, 0x47, 0x4a, 0x98, 0xdd, 0x8b, 0x32, 0x7e,
0x11, 0x50, 0x8e, 0x60, 0x23, 0x44, 0xe8, 0x7f, 0xcc, 0x42, 0x29, 0xa6, 0x8a, 0x20, 0xb9, 0xa6,
0x01, 0x33, 0x6d, 0x3a, 0xa6, 0xbe, 0xeb, 0x3a, 0x61, 0x8e, 0xab, 0x82, 0x78, 0x19, 0xd2, 0x44,
0x09, 0x8b, 0xde, 0x31, 0xa5, 0xc1, 0x14, 0xad, 0xa3, 0x1a, 0xe5, 0x90, 0x76, 0x46, 0x83, 0x29,
0xf9, 0x08, 0xb4, 0x08, 0xe2, 0xf9, 0xcc, 0xb2, 0x45, 0xe7, 0x93, 0xfd, 0xb9, 0x16, 0xd2, 0x07,
0x21, 0x59, 0x14, 0x78, 0x99, 0x64, 0xa6, 0x47, 0xad, 0x89, 0x69, 0x0b, 0x2b, 0xca, 0x79, 0xb5,
0x2a, 0xe9, 0x03, 0x6a, 0x4d, 0x2e, 0x03, 0xca, 0xc9, 0x67, 0xf0, 0x2c, 0x31, 0xd4, 0x26, 0xe0,
0x32, 0x8b, 0x89, 0x1f, 0x4f, 0xb5, 0xf1, 0x91, 0xe7, 0xa0, 0x8a, 0x8e, 0x61, 0x8e, 0x7d, 0x46,
0x39, 0x9b, 0x84, 0x79, 0x5c, 0x16, 0xb4, 0xb6, 0x24, 0x91, 0x3a, 0x14, 0xd8, 0x9d, 0x67, 0xf9,
0x6c, 0x82, 0x1d, 0xa3, 0x68, 0x44, 0x9f, 0xe2, 0x70, 0xc0, 0x5d, 0x9f, 0xde, 0x32, 0xd3, 0xa1,
0x36, 0x0b, 0x47, 0x94, 0x72, 0x48, 0xeb, 0x51, 0x9b, 0xe9, 0xef, 0xc0, 0xee, 0xd7, 0x8c, 0x5f,
0x58, 0xaf, 0xe7, 0xd6, 0xc4, 0xe2, 0xf7, 0x03, 0xea, 0xd3, 0x45, 0x15, 0xfc, 0x97, 0x02, 0x5b,
0x69, 0x16, 0xe3, 0xcc, 0x17, 0x1d, 0x28, 0xef, 0xcf, 0x67, 0x2c, 0xf2, 0xce, 0xa2, 0x63, 0xc6,
0x60, 0x63, 0x3e, 0x63, 0x86, 0x04, 0x91, 0xaf, 0x60, 0x6f, 0x11, 0x62, 0xbe, 0xe8, 0x81, 0x01,
0xe5, 0xa6, 0xc7, 0x7c, 0xf3, 0x8d, 0xe8, 0xf4, 0x68, 0x7d, 0xcc, 0x4a, 0x19, 0x6d, 0x06, 0xe5,
0x22, 0xe2, 0x06, 0xcc, 0x7f, 0x25, 0xd8, 0xe4, 0x43, 0xd0, 0x92, 0xa3, 0xa2, 0xe9, 0x79, 0x36,
0x7a, 0x42, 0x89, 0xab, 0x99, 0xb0, 0x97, 0x67, 0x93, 0x4f, 0x41, 0xec, 0x07, 0x66, 0xca, 0xc2,
0x9e, 0x1d, 0x26, 0xbd, 0x90, 0xb1, 0x58, 0x1a, 0x04, 0xfc, 0x0b, 0x68, 0xac, 0x5e, 0x36, 0xf0,
0x54, 0x1e, 0x4f, 0x6d, 0xaf, 0x58, 0x38, 0xc4, 0xd9, 0xf4, 0x46, 0x21, 0x3c, 0xb8, 0x81, 0xf8,
0xc5, 0x46, 0x21, 0x72, 0xe6, 0x23, 0xd8, 0x4c, 0x8d, 0xb0, 0x08, 0x2c, 0x20, 0xb0, 0x9a, 0x18,
0x63, 0xe3, 0xf4, 0x5a, 0x1e, 0xff, 0x8b, 0xab, 0xc7, 0xff, 0x23, 0xd8, 0x8a, 0x06, 0x97, 0x6b,
0x3a, 0xfe, 0xce, 0xbd, 0xb9, 0x31, 0x03, 0x36, 0xc6, 0xa2, 0xac, 0x18, 0x9b, 0x21, 0xeb, 0xa5,
0xe4, 0x0c, 0xd9, 0x58, 0x4c, 0xd2, 0x74, 0xce, 0x5d, 0x33, 0xda, 0x5c, 0xb0, 0x1b, 0x17, 0x8d,
0xb2, 0x20, 0x86, 0x7b, 0x9d, 0xb0, 0x1d, 0x62, 0xc4, 0x62, 0x73, 0x3d, 0x9f, 0xdc, 0x32, 0x59,
0x36, 0xca, 0xd2, 0x76, 0x82, 0xd5, 0x9f, 0xf3, 0x97, 0xc8, 0x10, 0xea, 0xfe, 0x00, 0x76, 0x1f,
0xc0, 0x39, 0xf5, 0x39, 0x2a, 0xa2, 0xe2, 0xa1, 0x67, 0xe9, 0x43, 0x82, 0x2b, 0x94, 0xf9, 0x18,
0x08, 0x9e, 0x14, 0x86, 0xb1, 0x1c, 0xf3, 0x66, 0x66, 0xdd, 0x4e, 0x39, 0x4e, 0x23, 0x8a, 0x51,
0x13, 0x9c, 0x4b, 0x7a, 0xd7, 0x75, 0x4e, 0x91, 0xac, 0xff, 0x29, 0x03, 0x95, 0x54, 0x48, 0x61,
0x69, 0x91, 0xdb, 0x95, 0x19, 0xf6, 0x6f, 0xc5, 0x28, 0x85, 0x94, 0xee, 0x84, 0x1c, 0x85, 0x43,
0x62, 0x16, 0x27, 0xb9, 0xc6, 0xea, 0xb8, 0x4c, 0x4c, 0x8b, 0x9f, 0x02, 0xb1, 0x9c, 0xb1, 0x6b,
0x0b, 0xcf, 0xf3, 0xa9, 0xcf, 0x82, 0xa9, 0x3b, 0x9b, 0x60, 0x74, 0x55, 0x8c, 0xcd, 0x88, 0x33,
0x8a, 0x18, 0x02, 0x1e, 0x2f, 0x74, 0x0b, 0xb8, 0x22, 0xe1, 0x11, 0x27, 0x86, 0xeb, 0xdf, 0xc2,
0xee, 0x70, 0x5d, 0x6e, 0x91, 0x2f, 0x01, 0xbc, 0x38, 0xa3, 0xf0, 0x25, 0xe5, 0xe3, 0xbd, 0x87,
0x0a, 0x2f, 0xb2, 0xce, 0x48, 0xe0, 0xf5, 0x3d, 0x68, 0xac, 0x12, 0x2d, 0xcb, 0xa7, 0xfe, 0x0c,
0xb6, 0x86, 0xf3, 0xdb, 0x5b, 0xb6, 0x34, 0x47, 0x9d, 0xc3, 0xd3, 0x34, 0x39, 0xac, 0xb6, 0xc7,
0x50, 0x8c, 0x63, 0x43, 0x66, 0xf4, 0xce, 0x42, 0x91, 0xd4, 0xe2, 0x6f, 0x14, 0xc2, 0x15, 0xf7,
0xf0, 0x05, 0x14, 0xa3, 0xc9, 0x9b, 0xa8, 0x50, 0xbc, 0xe8, 0xf7, 0x07, 0x66, 0xff, 0x6a, 0xa4,
0x3d, 0x21, 0x65, 0x28, 0xe0, 0x57, 0xb7, 0xa7, 0x65, 0x0e, 0x03, 0x28, 0xc5, 0x83, 0x37, 0xa9,
0x40, 0xa9, 0xdb, 0xeb, 0x8e, 0xba, 0xad, 0x51, 0xe7, 0x44, 0x7b, 0x42, 0x9e, 0xc1, 0xe6, 0xc0,
0xe8, 0x74, 0x2f, 0x5b, 0x5f, 0x77, 0x4c, 0xa3, 0xf3, 0xaa, 0xd3, 0xba, 0xe8, 0x9c, 0x68, 0x19,
0x42, 0xa0, 0x7a, 0x36, 0xba, 0x68, 0x9b, 0x83, 0xab, 0x97, 0x17, 0xdd, 0xe1, 0x59, 0xe7, 0x44,
0xcb, 0x0a, 0x99, 0xc3, 0xab, 0x76, 0xbb, 0x33, 0x1c, 0x6a, 0x39, 0x02, 0xb0, 0x71, 0xda, 0xea,
0x0a, 0xb0, 0x42, 0xb6, 0xa0, 0xd6, 0xed, 0xbd, 0xea, 0x77, 0xdb, 0x1d, 0x73, 0xd8, 0x19, 0x8d,
0x04, 0x31, 0x7f, 0xf8, 0xcf, 0x0c, 0x54, 0x52, 0xb3, 0x3b, 0xd9, 0x81, 0x2d, 0x71, 0xe4, 0xca,
0x10, 0x37, 0xb5, 0x86, 0xfd, 0x9e, 0xd9, 0xeb, 0xf7, 0x3a, 0xda, 0x13, 0xf2, 0x0e, 0xec, 0x2c,
0x31, 0xfa, 0xa7, 0xa7, 0xed, 0xb3, 0x96, 0x50, 0x9e, 0x34, 0x60, 0x7b, 0x89, 0x39, 0xea, 0x5e,
0x76, 0xc4, 0x2b, 0xb3, 0x64, 0x1f, 0xf6, 0x96, 0x78, 0xc3, 0x6f, 0x3a, 0x9d, 0x41, 0x8c, 0xc8,
0x91, 0x17, 0xf0, 0x7c, 0x09, 0xd1, 0xed, 0x0d, 0xaf, 0x4e, 0x4f, 0xbb, 0xed, 0x6e, 0xa7, 0x37,
0x32, 0x5f, 0xb5, 0x2e, 0xae, 0x3a, 0x9a, 0x42, 0xf6, 0xa0, 0xbe, 0x7c, 0x49, 0xe7, 0x72, 0xd0,
0x37, 0x5a, 0xc6, 0xb7, 0x5a, 0x9e, 0xbc, 0x0f, 0xef, 0x3d, 0x10, 0xd2, 0xee, 0x1b, 0x46, 0xa7,
0x3d, 0x32, 0x5b, 0x97, 0xfd, 0xab, 0xde, 0x48, 0xdb, 0x38, 0x6c, 0x8a, 0xf9, 0x78, 0x29, 0xc0,
0x85, 0xc9, 0xae, 0x7a, 0x3f, 0xee, 0xf5, 0xbf, 0xe9, 0x69, 0x4f, 0x84, 0xe5, 0x47, 0x67, 0x46,
0x67, 0x78, 0xd6, 0xbf, 0x38, 0xd1, 0x32, 0xc7, 0x7f, 0x2b, 0xc9, 0xdd, 0xac, 0x8d, 0xff, 0x06,
0x11, 0x03, 0x0a, 0x51, 0x1d, 0x58, 0xe7, 0xf8, 0xc6, 0xb3, 0xd4, 0x7c, 0x1d, 0x47, 0xda, 0xce,
0xaf, 0xfe, 0xfa, 0xf7, 0xdf, 0x66, 0x37, 0x75, 0xb5, 0xf9, 0xe6, 0xb3, 0xa6, 0x40, 0x34, 0xdd,
0x39, 0xff, 0x22, 0x73, 0x48, 0xfa, 0xb0, 0x21, 0xff, 0x03, 0x20, 0xdb, 0x29, 0x91, 0xf1, 0x9f,
0x02, 0xeb, 0x24, 0x6e, 0xa3, 0x44, 0x4d, 0x2f, 0xc7, 0x12, 0x2d, 0x47, 0x08, 0xfc, 0x21, 0x14,
0xc2, 0x0d, 0x33, 0xa1, 0x64, 0x7a, 0xe7, 0x6c, 0xac, 0x5a, 0x02, 0xfe, 0x3f, 0x43, 0x7e, 0x0a,
0xa5, 0x78, 0x7f, 0x20, 0xbb, 0x89, 0x1c, 0x4b, 0xe7, 0x47, 0xa3, 0xb1, 0x8a, 0x95, 0x56, 0x8b,
0x54, 0x63, 0xb5, 0x70, 0xb7, 0x20, 0x57, 0x32, 0x0f, 0xc4, 0x6e, 0x41, 0xea, 0xa9, 0xeb, 0x13,
0xeb, 0xc6, 0x4a, 0xc5, 0xf4, 0x06, 0x8a, 0x7c, 0x4a, 0x48, 0x4a, 0x64, 0xf3, 0x7b, 0x6b, 0xf2,
0x73, 0xf2, 0x33, 0x50, 0x43, 0x07, 0xe0, 0x06, 0x40, 0x16, 0xc6, 0x4a, 0xae, 0x29, 0x8d, 0xc5,
0x63, 0x96, 0x77, 0x85, 0x15, 0xd2, 0xdd, 0x39, 0x6f, 0x72, 0x94, 0x76, 0x1d, 0x4b, 0xc7, 0xc9,
0x32, 0x21, 0x3d, 0x39, 0xa3, 0xa7, 0xa5, 0xa7, 0x66, 0x50, 0x7d, 0x1f, 0xa5, 0x37, 0x48, 0x3d,
0x25, 0xfd, 0xb5, 0xc0, 0x34, 0xbf, 0xa7, 0x36, 0x17, 0x2f, 0xa8, 0x8a, 0xc1, 0x02, 0x5d, 0xfe,
0xe8, 0x1b, 0x16, 0x56, 0x5b, 0xda, 0xb8, 0xf4, 0x5d, 0xbc, 0x64, 0x8b, 0x6c, 0x26, 0x42, 0x21,
0x7e, 0xc1, 0x42, 0xfa, 0xa3, 0x6f, 0x48, 0x4a, 0x4f, 0x3f, 0xe1, 0x3d, 0x94, 0xbe, 0x4b, 0x76,
0x92, 0xd2, 0x93, 0x2f, 0xf8, 0x16, 0x2a, 0xe2, 0x8e, 0x68, 0xb4, 0x0c, 0x12, 0x91, 0x9c, 0x9a,
0x5f, 0x1b, 0x3b, 0x0f, 0xe8, 0xe9, 0xec, 0x20, 0x35, 0xbc, 0x22, 0xa0, 0xbc, 0x29, 0x67, 0x56,
0xc2, 0x81, 0x3c, 0x9c, 0xba, 0x88, 0x1e, 0xcb, 0x59, 0x3b, 0x92, 0x35, 0x1e, 0x6d, 0x11, 0xfa,
0x1e, 0x5e, 0xb8, 0x4d, 0x9e, 0xe2, 0x85, 0x11, 0xa0, 0xe9, 0x49, 0xf9, 0xbf, 0x00, 0x32, 0x7c,
0xec, 0xd6, 0xb5, 0xcd, 0xaa, 0xf1, 0xfe, 0xa3, 0x98, 0xb4, 0x41, 0xf5, 0x95, 0x97, 0x8b, 0x14,
0x66, 0xa0, 0x26, 0xfb, 0x0f, 0x59, 0xbc, 0x65, 0x45, 0xb7, 0x6a, 0xbc, 0xbb, 0x86, 0x1b, 0xde,
0x56, 0xc7, 0xdb, 0x08, 0xd1, 0xc4, 0x6d, 0x62, 0x70, 0x68, 0x06, 0x12, 0x76, 0xbd, 0x81, 0x7f,
0x5b, 0x7f, 0xfe, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x45, 0xeb, 0x2a, 0xdc, 0xed, 0x16, 0x00,
0x00,
// 2396 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0x4b, 0x6f, 0x23, 0xc7,
0x11, 0x5e, 0xbe, 0x44, 0xb2, 0xf8, 0x1a, 0xb5, 0x76, 0x57, 0x14, 0x2d, 0xc3, 0xda, 0xb1, 0x37,
0x96, 0x65, 0x7b, 0x19, 0xcb, 0x97, 0xc4, 0xb0, 0x03, 0x68, 0x29, 0xca, 0xe2, 0x46, 0x22, 0x99,
0x21, 0xb5, 0x86, 0x83, 0x00, 0x83, 0x16, 0xd9, 0x92, 0x06, 0xe6, 0x3c, 0x3c, 0xd3, 0xdc, 0xd5,
0xc2, 0x48, 0x02, 0x04, 0xc8, 0x39, 0x87, 0xfc, 0x83, 0xdc, 0x73, 0xcb, 0x2d, 0xf9, 0x09, 0xc9,
0x25, 0x39, 0xe6, 0x9a, 0x4b, 0x0e, 0xf9, 0x0f, 0x41, 0x55, 0xcf, 0x0c, 0x67, 0x28, 0x52, 0x46,
0x0e, 0xb9, 0x71, 0xaa, 0xbe, 0xae, 0xae, 0xae, 0x77, 0x11, 0xaa, 0x93, 0x99, 0x25, 0x1c, 0xf9,
0xcc, 0xf3, 0x5d, 0xe9, 0xb2, 0xe2, 0xcc, 0x75, 0x3d, 0xdf, 0x9b, 0xb4, 0x76, 0xaf, 0x5d, 0xf7,
0x7a, 0x26, 0xda, 0xdc, 0xb3, 0xda, 0xdc, 0x71, 0x5c, 0xc9, 0xa5, 0xe5, 0x3a, 0x81, 0x82, 0xe9,
0x7f, 0xcc, 0x43, 0xfd, 0xcc, 0x75, 0xbd, 0xc1, 0x5c, 0x1a, 0xe2, 0xdb, 0xb9, 0x08, 0x24, 0xd3,
0x20, 0xc7, 0x6d, 0xd9, 0xcc, 0xec, 0x65, 0xf6, 0x73, 0x06, 0xfe, 0x64, 0x0c, 0xf2, 0x53, 0x11,
0xc8, 0x66, 0x76, 0x2f, 0xb3, 0x5f, 0x36, 0xe8, 0x37, 0x6b, 0xc3, 0x43, 0x9b, 0xdf, 0x9a, 0xc1,
0x6b, 0xee, 0x99, 0xbe, 0x3b, 0x97, 0x96, 0x73, 0x6d, 0x5e, 0x09, 0xd1, 0xcc, 0xd1, 0xb1, 0x4d,
0x9b, 0xdf, 0x8e, 0x5e, 0x73, 0xcf, 0x50, 0x9c, 0x13, 0x21, 0xd8, 0xa7, 0xf0, 0x18, 0x0f, 0x78,
0xbe, 0xf0, 0xf8, 0x9b, 0xd4, 0x91, 0x3c, 0x1d, 0xd9, 0xb2, 0xf9, 0xed, 0x90, 0x98, 0x89, 0x43,
0x7b, 0x50, 0x8d, 0x6f, 0x41, 0x68, 0x81, 0xa0, 0x10, 0x4a, 0x47, 0xc4, 0x7b, 0x50, 0x4f, 0x88,
0x45, 0xc5, 0x37, 0x08, 0x53, 0x8d, 0xc5, 0x1d, 0xd9, 0x92, 0xe9, 0x50, 0x43, 0x94, 0x6d, 0x39,
0xc2, 0x27, 0x41, 0x45, 0x02, 0x55, 0x6c, 0x7e, 0x7b, 0x8e, 0x34, 0x94, 0xf4, 0x11, 0x68, 0x68,
0x33, 0xd3, 0x9d, 0x4b, 0x73, 0x72, 0xc3, 0x1d, 0x47, 0xcc, 0x9a, 0xa5, 0xbd, 0xcc, 0x7e, 0xfe,
0x79, 0xb6, 0x99, 0x31, 0xea, 0x33, 0x65, 0xa5, 0x8e, 0xe2, 0xb0, 0x03, 0xd8, 0x74, 0xe7, 0xf2,
0xda, 0xc5, 0x47, 0x20, 0xda, 0x0c, 0x84, 0x6c, 0x56, 0xf6, 0x72, 0xfb, 0x79, 0xa3, 0x11, 0x31,
0x10, 0x3b, 0x12, 0x12, 0xb1, 0xc1, 0x6b, 0x21, 0x3c, 0x73, 0xe2, 0x3a, 0x57, 0xa6, 0xe4, 0xfe,
0xb5, 0x90, 0xcd, 0xf2, 0x5e, 0x66, 0xbf, 0x60, 0x34, 0x88, 0xd1, 0x71, 0x9d, 0xab, 0x31, 0x91,
0xd9, 0xc7, 0xc0, 0x6e, 0xe4, 0x6c, 0x42, 0x50, 0xcb, 0xb7, 0x95, 0xb3, 0x9a, 0x35, 0x02, 0x6f,
0x22, 0xa7, 0x93, 0x64, 0xb0, 0xcf, 0x60, 0x87, 0x8c, 0xe3, 0xcd, 0x2f, 0x67, 0xd6, 0x84, 0x88,
0xe6, 0x54, 0xf0, 0xe9, 0xcc, 0x72, 0x44, 0x13, 0x50, 0x7b, 0x63, 0x1b, 0x01, 0xc3, 0x05, 0xff,
0x38, 0x64, 0xb3, 0x87, 0x50, 0x98, 0xf1, 0x4b, 0x31, 0x6b, 0x56, 0xc9, 0xaf, 0xea, 0x83, 0xed,
0x42, 0xd9, 0x72, 0x2c, 0x69, 0x71, 0xe9, 0xfa, 0xcd, 0x3a, 0x71, 0x16, 0x04, 0xfd, 0xb7, 0x59,
0xa8, 0x61, 0xbc, 0xf4, 0x9c, 0xf5, 0xe1, 0xb2, 0xec, 0xb4, 0xec, 0x1d, 0xa7, 0xdd, 0x71, 0x47,
0xee, 0xae, 0x3b, 0x76, 0xa0, 0x34, 0xe3, 0x81, 0x34, 0x6f, 0x5c, 0x8f, 0x22, 0xa4, 0x6a, 0x14,
0xf1, 0xfb, 0xd4, 0xf5, 0xd8, 0xbb, 0x50, 0x13, 0xb7, 0x52, 0xf8, 0x0e, 0x9f, 0x99, 0x68, 0x12,
0x0a, 0x8b, 0x92, 0x51, 0x8d, 0x88, 0xa7, 0x72, 0x36, 0x61, 0xfb, 0xa0, 0xc5, 0x86, 0x8c, 0x6c,
0xbe, 0x41, 0x66, 0xac, 0x47, 0x66, 0x0c, 0x4d, 0x1e, 0xdb, 0xa1, 0xb8, 0xd6, 0x0e, 0xa5, 0x65,
0x3b, 0xfc, 0x3b, 0x03, 0x55, 0x0a, 0x70, 0x11, 0x78, 0xae, 0x13, 0x08, 0xc6, 0x20, 0x6b, 0x4d,
0xc9, 0x0a, 0x65, 0x8a, 0x97, 0xac, 0x35, 0xc5, 0x27, 0x58, 0x53, 0xf3, 0xf2, 0x8d, 0x14, 0x01,
0xbd, 0xb0, 0x6a, 0x14, 0xad, 0xe9, 0x73, 0xfc, 0x64, 0x4f, 0xa1, 0x4a, 0xda, 0xf1, 0xe9, 0xd4,
0x17, 0x41, 0xa0, 0x52, 0x8b, 0x0e, 0x56, 0x90, 0x7e, 0xa4, 0xc8, 0xec, 0x19, 0x6c, 0x25, 0x61,
0xa6, 0xe3, 0x1d, 0xbe, 0x0e, 0x6e, 0xc8, 0x1e, 0x65, 0x15, 0x0e, 0x21, 0xb2, 0x4f, 0x0c, 0xf6,
0x51, 0x18, 0x3d, 0x11, 0x5e, 0xc1, 0x0b, 0x04, 0xd7, 0x12, 0xf0, 0x21, 0xa1, 0x9f, 0x42, 0x3d,
0x10, 0xfe, 0x2b, 0xe1, 0x9b, 0xb6, 0x08, 0x02, 0x7e, 0x2d, 0xc8, 0x40, 0x65, 0xa3, 0xa6, 0xa8,
0xe7, 0x8a, 0xa8, 0x6b, 0x50, 0x3f, 0x77, 0x1d, 0x4b, 0xba, 0x7e, 0xe8, 0x73, 0xfd, 0x4f, 0x79,
0x00, 0x7c, 0xfd, 0x48, 0x72, 0x39, 0x0f, 0x56, 0x56, 0x0c, 0xb4, 0x46, 0x76, 0xad, 0x35, 0x2a,
0xcb, 0xd6, 0xc8, 0xcb, 0x37, 0x9e, 0x0a, 0x83, 0xfa, 0xe1, 0xe6, 0xb3, 0xb0, 0x76, 0x3d, 0xc3,
0x3b, 0xc6, 0x6f, 0x3c, 0x61, 0x10, 0x9b, 0xed, 0x43, 0x21, 0x90, 0x5c, 0xaa, 0x8a, 0x51, 0x3f,
0x64, 0x29, 0x1c, 0xea, 0x22, 0x0c, 0x05, 0x60, 0x5f, 0x40, 0xfd, 0x8a, 0x5b, 0xb3, 0xb9, 0x2f,
0x4c, 0x5f, 0xf0, 0xc0, 0x75, 0x28, 0x92, 0xeb, 0x87, 0x8f, 0xe3, 0x23, 0x27, 0x8a, 0x6d, 0x10,
0xd7, 0xa8, 0x5d, 0x25, 0x3f, 0xd9, 0xfb, 0xd0, 0x08, 0x5d, 0x8d, 0xf9, 0x24, 0x2d, 0x3b, 0xaa,
0x3c, 0xf5, 0x05, 0x79, 0x6c, 0xd9, 0xa8, 0x91, 0x46, 0x41, 0x3a, 0xf7, 0xa6, 0x5c, 0x0a, 0x85,
0x54, 0xf5, 0xa7, 0x8e, 0xf4, 0x0b, 0x22, 0x13, 0x72, 0xd9, 0xe1, 0xc5, 0xd5, 0x0e, 0x5f, 0xed,
0xc0, 0xea, 0x1a, 0x07, 0xae, 0x09, 0x8f, 0xda, 0xba, 0xf0, 0x78, 0x07, 0x2a, 0x13, 0x37, 0x90,
0xa6, 0xf2, 0x2f, 0x45, 0x75, 0xce, 0x00, 0x24, 0x8d, 0x88, 0xc2, 0x9e, 0x40, 0x95, 0x00, 0xae,
0x33, 0xb9, 0xe1, 0x96, 0x43, 0x45, 0x2a, 0x67, 0xd0, 0xa1, 0x81, 0x22, 0x61, 0xf2, 0x29, 0xc8,
0xd5, 0x95, 0xc2, 0x80, 0xaa, 0xb7, 0x84, 0x09, 0x69, 0x8b, 0x94, 0x6a, 0x24, 0x52, 0x4a, 0x67,
0xa0, 0x9d, 0x59, 0x81, 0x44, 0x6f, 0x05, 0x51, 0x28, 0xfd, 0x04, 0x36, 0x13, 0xb4, 0x30, 0x99,
0x3e, 0x80, 0x02, 0x56, 0x8f, 0xa0, 0x99, 0xd9, 0xcb, 0xed, 0x57, 0x0e, 0xb7, 0xee, 0x38, 0x7a,
0x1e, 0x18, 0x0a, 0xa1, 0x3f, 0x81, 0x06, 0x12, 0x7b, 0xce, 0x95, 0x1b, 0x55, 0xa4, 0x7a, 0x9c,
0x8a, 0x55, 0x0c, 0x3c, 0xbd, 0x0e, 0xd5, 0xb1, 0xf0, 0xed, 0xf8, 0xca, 0x5f, 0x43, 0xa3, 0xe7,
0x84, 0x94, 0xf0, 0xc2, 0x1f, 0x40, 0xc3, 0xb6, 0x1c, 0x55, 0xb2, 0xb8, 0xed, 0xce, 0x1d, 0x19,
0x3a, 0xbc, 0x66, 0x5b, 0x0e, 0xca, 0x3f, 0x22, 0x22, 0xe1, 0xa2, 0xd2, 0x16, 0xe2, 0x36, 0x42,
0x9c, 0xaa, 0x6e, 0x0a, 0xf7, 0x22, 0x5f, 0xca, 0x68, 0xd9, 0x17, 0xf9, 0x52, 0x56, 0xcb, 0xbd,
0xc8, 0x97, 0x72, 0x5a, 0xfe, 0x45, 0xbe, 0x94, 0xd7, 0x0a, 0x2f, 0xf2, 0xa5, 0xa2, 0x56, 0xd2,
0xff, 0x9a, 0x01, 0x6d, 0x30, 0x97, 0xff, 0x57, 0x15, 0xa8, 0x31, 0x5a, 0x8e, 0x39, 0x99, 0xc9,
0x57, 0xe6, 0x54, 0xcc, 0x24, 0x27, 0x77, 0x17, 0x8c, 0xaa, 0x6d, 0x39, 0x9d, 0x99, 0x7c, 0x75,
0x8c, 0xb4, 0xa8, 0x7d, 0x26, 0x50, 0xe5, 0x10, 0xc5, 0x6f, 0x63, 0xd4, 0xf7, 0x3c, 0xe7, 0x0f,
0x19, 0xa8, 0xfe, 0x6c, 0xee, 0x4a, 0xb1, 0xbe, 0x25, 0x50, 0xe0, 0x2d, 0xea, 0x70, 0x96, 0xee,
0x80, 0xc9, 0xa2, 0x06, 0xdf, 0x29, 0xe9, 0xb9, 0x15, 0x25, 0xfd, 0xde, 0x66, 0x97, 0xbf, 0xb7,
0xd9, 0xe9, 0xbf, 0xcb, 0xa0, 0xd7, 0x43, 0x35, 0x43, 0x93, 0xef, 0x41, 0x35, 0x6a, 0x52, 0x66,
0xc0, 0x23, 0x85, 0x21, 0x50, 0x5d, 0x6a, 0xc4, 0x69, 0xca, 0xa1, 0x04, 0xa3, 0x1b, 0x83, 0x9b,
0x18, 0x19, 0x4e, 0x39, 0xc8, 0x1b, 0x2a, 0x56, 0x78, 0xe0, 0x6d, 0x80, 0x84, 0x2d, 0x0b, 0xf4,
0xce, 0xf2, 0x24, 0x61, 0x48, 0x65, 0xc2, 0xbc, 0x56, 0xd0, 0xff, 0xae, 0xa2, 0xe0, 0x7f, 0x55,
0xe9, 0x3d, 0xa8, 0x2f, 0x86, 0x1d, 0xc2, 0xa8, 0xfe, 0x5a, 0xf5, 0xa2, 0x69, 0x07, 0x51, 0x1f,
0x86, 0x75, 0x44, 0xcd, 0x1d, 0x69, 0xb5, 0x1b, 0xc8, 0x19, 0x21, 0x23, 0x14, 0x49, 0xf3, 0x09,
0xda, 0x95, 0xbf, 0xb1, 0x85, 0x23, 0x4d, 0x1a, 0xf6, 0x54, 0xcf, 0x6d, 0x90, 0x3d, 0x15, 0xfd,
0x18, 0x7d, 0x7b, 0xff, 0x03, 0xf5, 0x06, 0xd4, 0xc6, 0xee, 0x37, 0xc2, 0x89, 0x93, 0xed, 0x73,
0xa8, 0x47, 0x84, 0xf0, 0x89, 0x07, 0xb0, 0x21, 0x89, 0x12, 0x66, 0xf7, 0xa2, 0x8c, 0x9f, 0x05,
0x5c, 0x12, 0xd8, 0x08, 0x11, 0xfa, 0x9f, 0xb3, 0x50, 0x8e, 0xa9, 0x18, 0x24, 0x97, 0x3c, 0x10,
0xa6, 0xcd, 0x27, 0xdc, 0x77, 0x5d, 0x27, 0xcc, 0xf1, 0x2a, 0x12, 0xcf, 0x43, 0x1a, 0x96, 0xb0,
0xe8, 0x1d, 0x37, 0x3c, 0xb8, 0x21, 0xeb, 0x54, 0x8d, 0x4a, 0x48, 0x3b, 0xe5, 0xc1, 0x0d, 0xfb,
0x00, 0xb4, 0x08, 0xe2, 0xf9, 0xc2, 0xb2, 0xb1, 0xf3, 0xa9, 0xfe, 0xdc, 0x08, 0xe9, 0xc3, 0x90,
0x8c, 0x05, 0x5e, 0x25, 0x99, 0xe9, 0x71, 0x6b, 0x6a, 0xda, 0x68, 0x45, 0x35, 0xaf, 0xd6, 0x15,
0x7d, 0xc8, 0xad, 0xe9, 0x79, 0xc0, 0x25, 0xfb, 0x04, 0x1e, 0x25, 0x86, 0xda, 0x04, 0x5c, 0x65,
0x31, 0xf3, 0xe3, 0xa9, 0x36, 0x3e, 0xf2, 0x04, 0xaa, 0xd8, 0x31, 0xcc, 0x89, 0x2f, 0xb8, 0x14,
0xd3, 0x30, 0x8f, 0x2b, 0x48, 0xeb, 0x28, 0x12, 0x6b, 0x42, 0x51, 0xdc, 0x7a, 0x96, 0x2f, 0xa6,
0xd4, 0x31, 0x4a, 0x46, 0xf4, 0x89, 0x87, 0x03, 0xe9, 0xfa, 0xfc, 0x5a, 0x98, 0x0e, 0xb7, 0x45,
0x38, 0xa2, 0x54, 0x42, 0x5a, 0x9f, 0xdb, 0x42, 0x7f, 0x0b, 0x76, 0xbe, 0x14, 0xf2, 0xcc, 0xfa,
0x76, 0x6e, 0x4d, 0x2d, 0xf9, 0x66, 0xc8, 0x7d, 0xbe, 0xa8, 0x82, 0x7f, 0x2b, 0xc0, 0x56, 0x9a,
0x25, 0xa4, 0xf0, 0xb1, 0x03, 0x15, 0xfc, 0xf9, 0x4c, 0x44, 0xde, 0x59, 0x74, 0xcc, 0x18, 0x6c,
0xcc, 0x67, 0xc2, 0x50, 0x20, 0xf6, 0x05, 0xec, 0x2e, 0x42, 0xcc, 0xc7, 0x1e, 0x18, 0x70, 0x69,
0x7a, 0xc2, 0x37, 0x5f, 0x61, 0xa7, 0x27, 0xeb, 0x53, 0x56, 0xaa, 0x68, 0x33, 0xb8, 0xc4, 0x88,
0x1b, 0x0a, 0xff, 0x25, 0xb2, 0xd9, 0xfb, 0xa0, 0x25, 0x47, 0x45, 0xd3, 0xf3, 0x6c, 0xf2, 0x44,
0x3e, 0xae, 0x66, 0x68, 0x2f, 0xcf, 0x66, 0x1f, 0x03, 0xee, 0x07, 0x66, 0xca, 0xc2, 0x9e, 0x1d,
0x26, 0x3d, 0xca, 0x58, 0x2c, 0x0d, 0x08, 0xff, 0x0c, 0x5a, 0xab, 0x97, 0x0d, 0x3a, 0x55, 0xa0,
0x53, 0x8f, 0x57, 0x2c, 0x1c, 0x78, 0x36, 0xbd, 0x51, 0xa0, 0x07, 0x37, 0x08, 0xbf, 0xd8, 0x28,
0x30, 0x67, 0x3e, 0x80, 0xcd, 0xd4, 0x08, 0x4b, 0xc0, 0x22, 0x01, 0xeb, 0x89, 0x31, 0x36, 0x4e,
0xaf, 0xe5, 0xf1, 0xbf, 0xb4, 0x7a, 0xfc, 0x7f, 0x06, 0x5b, 0xd1, 0xe0, 0x72, 0xc9, 0x27, 0xdf,
0xb8, 0x57, 0x57, 0x66, 0x20, 0x26, 0x54, 0x94, 0xf3, 0xc6, 0x66, 0xc8, 0x7a, 0xae, 0x38, 0x23,
0x31, 0xc1, 0x49, 0x9a, 0xcf, 0xa5, 0x6b, 0x46, 0x9b, 0x0b, 0x75, 0xe3, 0x92, 0x51, 0x41, 0x62,
0xb8, 0xd7, 0xa1, 0xed, 0x08, 0x83, 0x8b, 0xcd, 0xe5, 0x7c, 0x7a, 0x2d, 0x54, 0xd9, 0xa8, 0x28,
0xdb, 0x21, 0x6b, 0x30, 0x97, 0xcf, 0x89, 0x81, 0xea, 0xfe, 0x08, 0x76, 0xee, 0xc0, 0x25, 0xf7,
0x25, 0x29, 0x52, 0xa5, 0x43, 0x8f, 0xd2, 0x87, 0x90, 0x8b, 0xca, 0x7c, 0x08, 0x8c, 0x4e, 0xa2,
0x61, 0x2c, 0xc7, 0xbc, 0x9a, 0x59, 0xd7, 0x37, 0x92, 0xa6, 0x91, 0xbc, 0xd1, 0x40, 0xce, 0x39,
0xbf, 0xed, 0x39, 0x27, 0x44, 0x5e, 0xd5, 0xef, 0xea, 0xa1, 0xe7, 0xbf, 0xaf, 0xdf, 0x35, 0x52,
0x11, 0xa2, 0x70, 0xfa, 0x5f, 0x32, 0x50, 0x4b, 0x85, 0x28, 0x95, 0x2a, 0xb5, 0xad, 0x99, 0xe1,
0x3c, 0x90, 0x37, 0xca, 0x21, 0xa5, 0x37, 0x65, 0xcf, 0xc2, 0xa1, 0x33, 0x4b, 0x93, 0x61, 0x6b,
0x75, 0x9c, 0x27, 0xa6, 0xcf, 0x8f, 0x81, 0x59, 0xce, 0xc4, 0xb5, 0x31, 0x92, 0xe4, 0x8d, 0x2f,
0x82, 0x1b, 0x77, 0x36, 0xa5, 0x68, 0xad, 0x19, 0x9b, 0x11, 0x67, 0x1c, 0x31, 0x10, 0x1e, 0x2f,
0x88, 0x0b, 0x78, 0x5e, 0xc1, 0x23, 0x4e, 0x0c, 0xd7, 0xbf, 0x86, 0x9d, 0xd1, 0xba, 0x5c, 0x65,
0x9f, 0x03, 0x78, 0x71, 0x86, 0xd2, 0x4b, 0x2a, 0x87, 0xbb, 0x77, 0x15, 0x5e, 0x64, 0xb1, 0x91,
0xc0, 0xeb, 0xbb, 0xd0, 0x5a, 0x25, 0x5a, 0x95, 0x63, 0xfd, 0x11, 0x6c, 0x8d, 0xe6, 0xd7, 0xd7,
0x62, 0x69, 0x2e, 0x7b, 0x01, 0x0f, 0xd3, 0xe4, 0xb0, 0x7a, 0x1f, 0x42, 0x29, 0x8e, 0x35, 0x55,
0x21, 0xb6, 0x17, 0x8a, 0xa4, 0xfe, 0x48, 0x30, 0x8a, 0xe1, 0xca, 0x7c, 0xf0, 0x14, 0x4a, 0xd1,
0x24, 0xcf, 0xaa, 0x50, 0x3a, 0x1b, 0x0c, 0x86, 0xe6, 0xe0, 0x62, 0xac, 0x3d, 0x60, 0x15, 0x28,
0xd2, 0x57, 0xaf, 0xaf, 0x65, 0x0e, 0x02, 0x28, 0xc7, 0x83, 0x3c, 0xab, 0x41, 0xb9, 0xd7, 0xef,
0x8d, 0x7b, 0x47, 0xe3, 0xee, 0xb1, 0xf6, 0x80, 0x3d, 0x82, 0xcd, 0xa1, 0xd1, 0xed, 0x9d, 0x1f,
0x7d, 0xd9, 0x35, 0x8d, 0xee, 0xcb, 0xee, 0xd1, 0x59, 0xf7, 0x58, 0xcb, 0x30, 0x06, 0xf5, 0xd3,
0xf1, 0x59, 0xc7, 0x1c, 0x5e, 0x3c, 0x3f, 0xeb, 0x8d, 0x4e, 0xbb, 0xc7, 0x5a, 0x16, 0x65, 0x8e,
0x2e, 0x3a, 0x9d, 0xee, 0x68, 0xa4, 0xe5, 0x18, 0xc0, 0xc6, 0xc9, 0x51, 0x0f, 0xc1, 0x79, 0xb6,
0x05, 0x8d, 0x5e, 0xff, 0xe5, 0xa0, 0xd7, 0xe9, 0x9a, 0xa3, 0xee, 0x78, 0x8c, 0xc4, 0xc2, 0xc1,
0x7f, 0x32, 0x50, 0x4b, 0xed, 0x02, 0x6c, 0x1b, 0xb6, 0xf0, 0xc8, 0x85, 0x81, 0x37, 0x1d, 0x8d,
0x06, 0x7d, 0xb3, 0x3f, 0xe8, 0x77, 0xb5, 0x07, 0xec, 0x2d, 0xd8, 0x5e, 0x62, 0x0c, 0x4e, 0x4e,
0x3a, 0xa7, 0x47, 0xa8, 0x3c, 0x6b, 0xc1, 0xe3, 0x25, 0xe6, 0xb8, 0x77, 0xde, 0xc5, 0x57, 0x66,
0xd9, 0x1e, 0xec, 0x2e, 0xf1, 0x46, 0x5f, 0x75, 0xbb, 0xc3, 0x18, 0x91, 0x63, 0x4f, 0xe1, 0xc9,
0x12, 0xa2, 0xd7, 0x1f, 0x5d, 0x9c, 0x9c, 0xf4, 0x3a, 0xbd, 0x6e, 0x7f, 0x6c, 0xbe, 0x3c, 0x3a,
0xbb, 0xe8, 0x6a, 0x79, 0xb6, 0x0b, 0xcd, 0xe5, 0x4b, 0xba, 0xe7, 0xc3, 0x81, 0x71, 0x64, 0x7c,
0xad, 0x15, 0xd8, 0xbb, 0xf0, 0xce, 0x1d, 0x21, 0x9d, 0x81, 0x61, 0x74, 0x3b, 0x63, 0xf3, 0xe8,
0x7c, 0x70, 0xd1, 0x1f, 0x6b, 0x1b, 0x07, 0x6d, 0x9c, 0xb7, 0x97, 0x02, 0x1c, 0x4d, 0x76, 0xd1,
0xff, 0x69, 0x7f, 0xf0, 0x55, 0x5f, 0x7b, 0x80, 0x96, 0x1f, 0x9f, 0x1a, 0xdd, 0xd1, 0xe9, 0xe0,
0xec, 0x58, 0xcb, 0x1c, 0xfe, 0xb3, 0xac, 0x76, 0xbd, 0x0e, 0xfd, 0xbb, 0xc4, 0x0c, 0x28, 0x46,
0x75, 0x65, 0x9d, 0xe3, 0x5b, 0x8f, 0x52, 0xf3, 0x7a, 0x1c, 0x69, 0xdb, 0xbf, 0xf9, 0xc7, 0xbf,
0x7e, 0x9f, 0xdd, 0xd4, 0xab, 0xed, 0x57, 0x9f, 0xb4, 0x11, 0xd1, 0x76, 0xe7, 0xf2, 0xb3, 0xcc,
0x01, 0x1b, 0xc0, 0x86, 0xfa, 0x4f, 0x81, 0x3d, 0x4e, 0x89, 0x8c, 0xff, 0x64, 0x58, 0x27, 0xf1,
0x31, 0x49, 0xd4, 0xf4, 0x4a, 0x2c, 0xd1, 0x72, 0x50, 0xe0, 0x8f, 0xa1, 0x18, 0x6e, 0xac, 0x09,
0x25, 0xd3, 0x3b, 0x6c, 0x6b, 0xd5, 0x52, 0xf1, 0xc3, 0x0c, 0xfb, 0x39, 0x94, 0xe3, 0x7d, 0x84,
0xed, 0x24, 0x72, 0x2c, 0x9d, 0x1f, 0xad, 0xd6, 0x2a, 0x56, 0x5a, 0x2d, 0x56, 0x8f, 0xd5, 0xa2,
0x5d, 0x85, 0x5d, 0xa8, 0x3c, 0xc0, 0x5d, 0x85, 0x35, 0x53, 0xd7, 0x27, 0xd6, 0x97, 0x95, 0x8a,
0xe9, 0x2d, 0x12, 0xf9, 0x90, 0xb1, 0x94, 0xc8, 0xf6, 0x77, 0xd6, 0xf4, 0x97, 0xec, 0x17, 0x50,
0x0d, 0x1d, 0x40, 0x1b, 0x05, 0x5b, 0x18, 0x2b, 0xb9, 0xf6, 0xb4, 0x16, 0x8f, 0x59, 0xde, 0x3d,
0x56, 0x48, 0x77, 0xe7, 0xb2, 0x2d, 0x49, 0xda, 0x65, 0x2c, 0x9d, 0x26, 0xd5, 0x84, 0xf4, 0xe4,
0xcc, 0x9f, 0x96, 0x9e, 0x9a, 0x69, 0xf5, 0x3d, 0x92, 0xde, 0x62, 0xcd, 0x94, 0xf4, 0x6f, 0x11,
0xd3, 0xfe, 0x8e, 0xdb, 0x12, 0x5f, 0x50, 0xc7, 0x41, 0x85, 0x5c, 0x7e, 0xef, 0x1b, 0x16, 0x56,
0x5b, 0xda, 0xe0, 0xf4, 0x1d, 0xba, 0x64, 0x8b, 0x6d, 0x26, 0x42, 0x21, 0x7e, 0xc1, 0x42, 0xfa,
0xbd, 0x6f, 0x48, 0x4a, 0x4f, 0x3f, 0xe1, 0x1d, 0x92, 0xbe, 0xc3, 0xb6, 0x93, 0xd2, 0x93, 0x2f,
0xf8, 0x1a, 0x6a, 0x78, 0x47, 0x34, 0xaa, 0x06, 0x89, 0x48, 0x4e, 0xcd, 0xc3, 0xad, 0xed, 0x3b,
0xf4, 0x74, 0x76, 0xb0, 0x06, 0x5d, 0x11, 0x70, 0xd9, 0x56, 0x33, 0x30, 0x93, 0xc0, 0xee, 0x4e,
0x71, 0x4c, 0x8f, 0xe5, 0xac, 0x1d, 0xf1, 0x5a, 0xf7, 0xb6, 0x08, 0x7d, 0x97, 0x2e, 0x7c, 0xcc,
0x1e, 0xd2, 0x85, 0x11, 0xa0, 0xed, 0x29, 0xf9, 0xbf, 0x02, 0x36, 0xba, 0xef, 0xd6, 0xb5, 0xcd,
0xaa, 0xf5, 0xee, 0xbd, 0x98, 0xb4, 0x41, 0xf5, 0x95, 0x97, 0x63, 0x0a, 0x0b, 0xa8, 0x26, 0xfb,
0x0f, 0x5b, 0xbc, 0x65, 0x45, 0xb7, 0x6a, 0xbd, 0xbd, 0x86, 0x1b, 0xde, 0xd6, 0xa4, 0xdb, 0x18,
0xd3, 0xf0, 0x36, 0x1c, 0x44, 0xda, 0x81, 0x82, 0x5d, 0x6e, 0xd0, 0xdf, 0xe0, 0x9f, 0xfe, 0x37,
0x00, 0x00, 0xff, 0xff, 0x79, 0xf0, 0xb4, 0xfa, 0x3d, 0x17, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

@ -808,6 +808,20 @@ message LiquidityParameters {
flight at any point in time.
*/
uint64 auto_max_in_flight = 13;
/*
The minimum amount, expressed in satoshis, that the autoloop client will
dispatch a swap for. This value is subject to the server-side limits
specified by the LoopOutTerms endpoint.
*/
uint64 min_swap_amount = 14;
/*
The maximum amount, expressed in satoshis, that the autoloop client will
dispatch a swap for. This value is subject to the server-side limits
specified by the LoopOutTerms endpoint.
*/
uint64 max_swap_amount = 15;
}
enum LiquidityRuleType {

@ -513,6 +513,16 @@
"type": "string",
"format": "uint64",
"description": "The maximum number of automatically dispatched swaps that we allow to be in\nflight at any point in time."
},
"min_swap_amount": {
"type": "string",
"format": "uint64",
"description": "The minimum 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."
},
"max_swap_amount": {
"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."
}
}
},

@ -14,7 +14,19 @@ This file tracks release notes for the loop client.
## Next release
#### NewFeatures
#### New Features
##### Autoloop Swap Size
* Autoloop can now be configured with custom swap size limits. Previously,
autoloop would use the minimum/maximum swap amount set by the server (exposed
by the `loop terms` command) to decide on swap size.
* Setting a custom minimum swap amount is particularly useful for clients that
would like to perform fewer, larger swaps to save on fees. The trade-off when
setting a large minimum amount is that autoloop will wait until your channel is
at least the minimum amount below its incoming threshold amount before executing
a swap, which may result in channels staying under the threshold for longer.
* These values can be set using the following command: `loop setparams --minamt={minimum in sats} --maxamt={maximum in sats}`.
* The values set must fall within the limits set by the loop server.
#### Breaking Changes

Loading…
Cancel
Save