From edad1a8c0dd224a6f64d02fc68c091888ed2e0d9 Mon Sep 17 00:00:00 2001 From: Daniel McNally Date: Mon, 25 May 2020 04:35:03 -0400 Subject: [PATCH] feat(rpc/connext): deposit & openchannel calls This refactors the `Deposit` and `OpenChannel` methods in `SwapClient` to make them generic and applicable to Connext. It implements this functionality for Connext, namely retrieiving an address for sending funds on-chain to the Connext wallet and depositing those funds into Connext channels. It also refactors the `CloseChannel` call similarly, however the Connext REST client does not currently implement a `/withdraw` endpoint for taking funds out of Connext channels. This adds dummy code to construct a withdraw payload and make a request. Withdrawing coins from the on-chain Connext wallet is not currently supported by the Connext client and so the `Withdraw` rpc call remains specific to lnd. Closes #1472. Closes #1473. --- docs/api.md | 2 + lib/cli/commands/closechannel.ts | 25 +- lib/cli/commands/openchannel.ts | 3 +- lib/connextclient/ConnextClient.ts | 36 +- lib/lndclient/LndClient.ts | 38 +- lib/proto/xudrpc_pb.d.ts | 8 + lib/proto/xudrpc_pb.js | 56 +- lib/raidenclient/RaidenClient.ts | 15 +- lib/service/Service.ts | 44 +- lib/swaps/SwapClient.ts | 24 +- lib/swaps/SwapClientManager.ts | 85 ++- lib/swaps/types.ts | 29 ++ proto/xudrpc.proto | 6 + test/jest/LndClient.spec.ts | 10 +- test/jest/Service.spec.ts | 25 +- test/jest/SwapClientManager.spec.ts | 30 +- .../SwapClientManager.spec.ts.snap | 2 - test/simulation/xudrpc/xudrpc.pb.go | 485 +++++++++--------- 18 files changed, 551 insertions(+), 372 deletions(-) diff --git a/docs/api.md b/docs/api.md index 03a2082cf..4dbd93344 100644 --- a/docs/api.md +++ b/docs/api.md @@ -231,6 +231,8 @@ | node_identifier | [string](#string) | | The node pub key or alias of the peer with which to close any channels with. | | currency | [string](#string) | | The ticker symbol of the currency of the channel to close. | | force | [bool](#bool) | | Whether to force close the channel in case the peer is offline or unresponsive. | +| destination | [string](#string) | | The on-chain address to send funds extracted from the channel. If unspecified, the funds return to the default wallet for the client closing the channel. | +| amount | [uint64](#uint64) | | For Connext only - the amount to extract from the channel. If 0 or unspecified, the entire off-chain balance for the specified currency will be extracted. | diff --git a/lib/cli/commands/closechannel.ts b/lib/cli/commands/closechannel.ts index b1a281176..64c8b3913 100644 --- a/lib/cli/commands/closechannel.ts +++ b/lib/cli/commands/closechannel.ts @@ -2,26 +2,35 @@ import { Arguments, Argv } from 'yargs'; import { CloseChannelRequest } from '../../proto/xudrpc_pb'; import { callback, loadXudClient } from '../command'; -export const command = 'closechannel [--force]'; +export const command = 'closechannel [node_identifier ] [--force]'; export const describe = 'close any payment channels with a peer'; export const builder = (argv: Argv) => argv - .positional('node_identifier', { - description: 'the node key or alias of the connected peer to close the channel with', - type: 'string', - }) .positional('currency', { description: 'the ticker symbol for the currency', type: 'string', }) + .option('node_identifier', { + description: 'the node key or alias of the connected peer to close the channel with', + type: 'string', + }) .option('force', { type: 'boolean', description: 'whether to force close if the peer is offline', }) - .example('$0 closechannel 028599d05b18c0c3f8028915a17d603416f7276c822b6b2d20e71a3502bd0f9e0b BTC', 'close BTC channels by node key') - .example('$0 closechannel CheeseMonkey BTC', 'close BTC channels by alias') - .example('$0 closechannel CheeseMonkey BTC --force', 'force close BTC channels by alias'); + .option('destination', { + type: 'string', + description: 'the on-chain address to send funds extracted from the channel', + }) + .option('amount', { + type: 'number', + description: 'for Connext only - the amount to extract from the channel', + }) + .example('$0 closechannel BTC 028599d05b18c0c3f8028915a17d603416f7276c822b6b2d20e71a3502bd0f9e0b', 'close BTC channels by node key') + .example('$0 closechannel BTC CheeseMonkey', 'close BTC channels by alias') + .example('$0 closechannel BTC CheeseMonkey --force', 'force close BTC channels by alias') + .example('$0 closechannel ETH --amount 0.1', '[UNIMPLEMENTED] remove 0.1 ETH from a Connext channel'); export const handler = async (argv: Arguments) => { const request = new CloseChannelRequest(); diff --git a/lib/cli/commands/openchannel.ts b/lib/cli/commands/openchannel.ts index 7de405300..9f934a8b0 100644 --- a/lib/cli/commands/openchannel.ts +++ b/lib/cli/commands/openchannel.ts @@ -27,7 +27,8 @@ export const builder = (argv: Argv) => argv }) .example('$0 openchannel BTC 0.1 028599d05b18c0c3f8028915a17d603416f7276c822b6b2d20e71a3502bd0f9e0b', 'open an 0.1 BTC channel by node key') .example('$0 openchannel BTC 0.1 CheeseMonkey', 'open an 0.1 BTC channel by alias') - .example('$0 openchannel BTC 0.1 CheeseMonkey 0.05', 'open an 0.1 BTC channel by alias and push 0.05 to remote side'); + .example('$0 openchannel BTC 0.1 CheeseMonkey 0.05', 'open an 0.1 BTC channel by alias and push 0.05 to remote side') + .example('$0 openchannel ETH 0.5', 'deposit 0.5 into an ETH Connext channel without specifying a remote node'); export const handler = async (argv: Arguments) => { const request = new OpenChannelRequest(); diff --git a/lib/connextclient/ConnextClient.ts b/lib/connextclient/ConnextClient.ts index 4bb4df484..380a0d285 100644 --- a/lib/connextclient/ConnextClient.ts +++ b/lib/connextclient/ConnextClient.ts @@ -12,7 +12,7 @@ import SwapClient, { TradingLimits, SwapClientInfo, } from '../swaps/SwapClient'; -import { SwapDeal } from '../swaps/types'; +import { SwapDeal, CloseChannelParams, OpenChannelParams } from '../swaps/types'; import { UnitConverter } from '../utils/UnitConverter'; import errors, { errorCodes } from './errors'; import { @@ -544,13 +544,15 @@ class ConnextClient extends SwapClient { }; } - /** - * Deposits funds to a node - */ - public deposit = async ( - { currency, units }: - { currency: string, units: number }, - ) => { + public deposit = async () => { + const clientConfig = await this.getClientConfig(); + return clientConfig.signerAddress; + } + + public openChannel = async ({ currency, units }: OpenChannelParams) => { + if (!currency) { + throw errors.CURRENCY_MISSING; + } const assetId = this.getTokenAddress(currency); await this.sendRequest('/deposit', 'POST', { assetId, @@ -558,14 +560,16 @@ class ConnextClient extends SwapClient { }); } - public async openChannel() {} - - /** - * Closes a payment client. - * @param multisigAddress the address of the client to close - */ - public closeChannel = async (): Promise => { - // not relevant for connext + public closeChannel = async ({ units, currency, destination }: CloseChannelParams): Promise => { + if (!currency) { + throw errors.CURRENCY_MISSING; + } + // TODO: connext-api-client withdraw endpoint not currently implemented + await this.sendRequest('/withdraw', 'POST', { + recipient: destination, + amount: BigInt(units).toString(), + assetId: this.tokenAddresses.get(currency), + }); } /** diff --git a/lib/lndclient/LndClient.ts b/lib/lndclient/LndClient.ts index 93ef44753..928dddc5c 100644 --- a/lib/lndclient/LndClient.ts +++ b/lib/lndclient/LndClient.ts @@ -10,7 +10,7 @@ import { LightningClient, WalletUnlockerClient } from '../proto/lndrpc_grpc_pb'; import * as lndrpc from '../proto/lndrpc_pb'; import swapErrors from '../swaps/errors'; import SwapClient, { ChannelBalance, ClientStatus, PaymentState, SwapClientInfo, TradingLimits } from '../swaps/SwapClient'; -import { SwapDeal } from '../swaps/types'; +import { SwapDeal, CloseChannelParams, OpenChannelParams } from '../swaps/types'; import { base64ToHex, hexToUint8Array } from '../utils/utils'; import errors from './errors'; import { Chain, ChannelCount, ClientMethods, LndClientConfig, LndInfo } from './types'; @@ -519,6 +519,11 @@ class LndClient extends SwapClient { return this.unaryCall('closedChannels', new lndrpc.ClosedChannelsRequest()); } + public deposit = async () => { + const depositAddress = await this.newAddress(); + return depositAddress; + } + public withdraw = async ({ amount, destination, all = false, fee }: { amount: number, destination: string, @@ -653,7 +658,7 @@ class LndClient extends SwapClient { /** * Gets a new address for the internal lnd wallet. */ - public newAddress = async (addressType = lndrpc.AddressType.WITNESS_PUBKEY_HASH) => { + private newAddress = async (addressType = lndrpc.AddressType.WITNESS_PUBKEY_HASH) => { const request = new lndrpc.NewAddressRequest(); request.setType(addressType); const newAddressResponse = await this.unaryCall('newAddress', request); @@ -739,14 +744,17 @@ class LndClient extends SwapClient { * Opens a channel given peerPubKey and amount. */ public openChannel = async ( - { peerIdentifier: peerPubKey, units, uris, pushUnits = 0 }: - { peerIdentifier: string, units: number, uris?: string[], pushUnits?: number }, + { remoteIdentifier, units, uris, pushUnits = 0 }: OpenChannelParams, ): Promise => { + if (!remoteIdentifier) { + // TODO: better handling for for unrecognized peers & force closing channels + throw new Error('peer not connected to swap client'); + } if (uris) { await this.connectPeerAddresses(uris); } - await this.openChannelSync(peerPubKey, units, pushUnits); + await this.openChannelSync(remoteIdentifier, units, pushUnits); } /** @@ -1025,13 +1033,29 @@ class LndClient extends SwapClient { } /** - * Attempts to close an open channel. + * Closes any payment channels with a specified node. */ - public closeChannel = (fundingTxId: string, outputIndex: number, force: boolean): Promise => { + public closeChannel = async ({ remoteIdentifier, force = false }: CloseChannelParams) => { + const channels = (await this.listChannels()).getChannelsList(); + const closePromises: Promise[] = []; + channels.forEach((channel) => { + if (channel.getRemotePubkey() === remoteIdentifier) { + const [fundingTxId, outputIndex] = channel.getChannelPoint().split(':'); + const closePromise = this.closeChannelSync(fundingTxId, Number(outputIndex), force); + closePromises.push(closePromise); + } + }); + await Promise.all(closePromises); + } + + /** A synchronous helper method for the closeChannel call */ + public closeChannelSync = (fundingTxId: string, outputIndex: number, force: boolean): Promise => { return new Promise((resolve, reject) => { if (!this.lightning) { throw(errors.UNAVAILABLE(this.currency, this.status)); } + + // TODO: set delivery_address parameter after upgrading to 0.10+ lnd API proto definition const request = new lndrpc.CloseChannelRequest(); const channelPoint = new lndrpc.ChannelPoint(); channelPoint.setFundingTxidStr(fundingTxId); diff --git a/lib/proto/xudrpc_pb.d.ts b/lib/proto/xudrpc_pb.d.ts index 044d7c2cb..3dadd8335 100644 --- a/lib/proto/xudrpc_pb.d.ts +++ b/lib/proto/xudrpc_pb.d.ts @@ -212,6 +212,12 @@ export class CloseChannelRequest extends jspb.Message { getForce(): boolean; setForce(value: boolean): void; + getDestination(): string; + setDestination(value: string): void; + + getAmount(): number; + setAmount(value: number): void; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): CloseChannelRequest.AsObject; @@ -228,6 +234,8 @@ export namespace CloseChannelRequest { nodeIdentifier: string, currency: string, force: boolean, + destination: string, + amount: number, } } diff --git a/lib/proto/xudrpc_pb.js b/lib/proto/xudrpc_pb.js index 74bae1dd0..87a0129a6 100644 --- a/lib/proto/xudrpc_pb.js +++ b/lib/proto/xudrpc_pb.js @@ -1469,7 +1469,9 @@ proto.xudrpc.CloseChannelRequest.toObject = function(includeInstance, msg) { var f, obj = { nodeIdentifier: jspb.Message.getFieldWithDefault(msg, 1, ""), currency: jspb.Message.getFieldWithDefault(msg, 2, ""), - force: jspb.Message.getFieldWithDefault(msg, 3, false) + force: jspb.Message.getFieldWithDefault(msg, 3, false), + destination: jspb.Message.getFieldWithDefault(msg, 4, ""), + amount: jspb.Message.getFieldWithDefault(msg, 5, 0) }; if (includeInstance) { @@ -1518,6 +1520,14 @@ proto.xudrpc.CloseChannelRequest.deserializeBinaryFromReader = function(msg, rea var value = /** @type {boolean} */ (reader.readBool()); msg.setForce(value); break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setDestination(value); + break; + case 5: + var value = /** @type {number} */ (reader.readUint64()); + msg.setAmount(value); + break; default: reader.skipField(); break; @@ -1568,6 +1578,20 @@ proto.xudrpc.CloseChannelRequest.serializeBinaryToWriter = function(message, wri f ); } + f = message.getDestination(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } + f = message.getAmount(); + if (f !== 0) { + writer.writeUint64( + 5, + f + ); + } }; @@ -1618,6 +1642,36 @@ proto.xudrpc.CloseChannelRequest.prototype.setForce = function(value) { }; +/** + * optional string destination = 4; + * @return {string} + */ +proto.xudrpc.CloseChannelRequest.prototype.getDestination = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** @param {string} value */ +proto.xudrpc.CloseChannelRequest.prototype.setDestination = function(value) { + jspb.Message.setProto3StringField(this, 4, value); +}; + + +/** + * optional uint64 amount = 5; + * @return {number} + */ +proto.xudrpc.CloseChannelRequest.prototype.getAmount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +}; + + +/** @param {number} value */ +proto.xudrpc.CloseChannelRequest.prototype.setAmount = function(value) { + jspb.Message.setProto3IntField(this, 5, value); +}; + + /** * Generated by JsPbCodeGenerator. diff --git a/lib/raidenclient/RaidenClient.ts b/lib/raidenclient/RaidenClient.ts index e076ba986..8b8da3bb9 100644 --- a/lib/raidenclient/RaidenClient.ts +++ b/lib/raidenclient/RaidenClient.ts @@ -526,7 +526,7 @@ class RaidenClient extends SwapClient { * Creates a payment channel. */ public openChannel = async ( - { peerIdentifier: peerAddress, units, currency }: + { peerIdentifier, units, currency }: { peerIdentifier: string, units: number, currency: string }, ): Promise => { const tokenAddress = this.tokenAddresses.get(currency); @@ -534,7 +534,7 @@ class RaidenClient extends SwapClient { throw(errors.TOKEN_ADDRESS_NOT_FOUND); } await this.openChannelRequest({ - partner_address: peerAddress, + partner_address: peerIdentifier, token_address: tokenAddress, total_deposit: units, settle_timeout: 20660, @@ -557,11 +557,15 @@ class RaidenClient extends SwapClient { * Closes a payment channel. * @param channel_address the address of the channel to close */ - public closeChannel = async (channel_address: string): Promise => { + public closeChannelRequest = async (channel_address: string): Promise => { const endpoint = `channels/${channel_address}`; await this.sendRequest(endpoint, 'PATCH', { state: 'settled' }); } + public closeChannel = async () => { + // unimplemented + } + /** * Sends a token payment through the Raiden network. * @param target_address recipient of the payment @@ -601,6 +605,11 @@ class RaidenClient extends SwapClient { return body.our_address; } + public deposit = async () => { + const depositAddress = await this.getAddress(); + return depositAddress; + } + /** Raiden client specific cleanup. */ protected disconnect = () => { this.setStatus(ClientStatus.Disconnected); diff --git a/lib/service/Service.ts b/lib/service/Service.ts index a506e5f11..f52e1c125 100644 --- a/lib/service/Service.ts +++ b/lib/service/Service.ts @@ -222,18 +222,29 @@ class Service { * Closes any payment channels for a specified node and currency. */ public closeChannel = async ( - args: { nodeIdentifier: string, currency: string, force: boolean }, + args: { nodeIdentifier: string, currency: string, force: boolean, destination: string, amount: number }, ) => { - const { nodeIdentifier, currency, force } = args; + const { nodeIdentifier, currency, force, destination, amount } = args; argChecks.HAS_NODE_IDENTIFIER({ nodeIdentifier }); argChecks.VALID_CURRENCY({ currency }); - const nodePubKey = isNodePubKey(args.nodeIdentifier) ? args.nodeIdentifier : this.pool.resolveAlias(args.nodeIdentifier); - const peer = this.pool.getPeer(nodePubKey); + let remoteIdentifier: string | undefined; + if (nodeIdentifier) { + const nodePubKey = isNodePubKey(nodeIdentifier) ? nodeIdentifier : this.pool.resolveAlias(nodeIdentifier); + const swapClientType = this.swapClientManager.getType(currency); + if (swapClientType === undefined) { + throw swapsErrors.SWAP_CLIENT_NOT_FOUND(currency); + } + const peer = this.pool.getPeer(nodePubKey); + remoteIdentifier = peer.getIdentifier(swapClientType, currency); + } + await this.swapClientManager.closeChannel({ - peer, currency, force, + destination, + amount, + remoteIdentifier, }); } @@ -246,14 +257,27 @@ class Service { const { nodeIdentifier, amount, currency, pushAmount } = args; argChecks.POSITIVE_AMOUNT({ amount }); argChecks.VALID_CURRENCY({ currency }); + + let remoteIdentifier: string | undefined; + let uris: string[] | undefined; + try { - let peer; - if (args.nodeIdentifier) { - const nodePubKey = isNodePubKey(args.nodeIdentifier) ? args.nodeIdentifier : this.pool.resolveAlias(args.nodeIdentifier); - peer = this.pool.getPeer(nodePubKey); + if (nodeIdentifier) { + const nodePubKey = isNodePubKey(nodeIdentifier) ? nodeIdentifier : this.pool.resolveAlias(nodeIdentifier); + const swapClientType = this.swapClientManager.getType(currency); + if (swapClientType === undefined) { + throw swapsErrors.SWAP_CLIENT_NOT_FOUND(currency); + } + const peer = this.pool.getPeer(nodePubKey); + remoteIdentifier = peer.getIdentifier(swapClientType, currency); + if (swapClientType === SwapClientType.Lnd) { + uris = peer.getLndUris(currency); + } } + await this.swapClientManager.openChannel({ - peer, + remoteIdentifier, + uris, amount, currency, pushAmount, diff --git a/lib/swaps/SwapClient.ts b/lib/swaps/SwapClient.ts index 8bb832290..514dcae57 100644 --- a/lib/swaps/SwapClient.ts +++ b/lib/swaps/SwapClient.ts @@ -1,6 +1,6 @@ import Logger from '../Logger'; import { EventEmitter } from 'events'; -import { SwapDeal, Route } from './types'; +import { SwapDeal, Route, CloseChannelParams, OpenChannelParams } from './types'; import { SwapClientType } from '../constants/enums'; import { setTimeoutPromise } from '../utils/utils'; @@ -315,20 +315,22 @@ abstract class SwapClient extends EventEmitter { public abstract async getHeight(): Promise; /** - * Opens a payment channel given peerIdentifier, amount - * optional currency and optional lndUris. + * Opens a payment channel. */ public abstract async openChannel( - { peerIdentifier, units, currency, uris, pushUnits }: - { - peerIdentifier: string, - units: number, - currency?: string, - uris?: string[], - pushUnits?: number, - }, + { remoteIdentifier, units, currency, uris, pushUnits }: OpenChannelParams, ): Promise; + /** + * Closes a payment channel. + */ + public abstract async closeChannel( + { remoteIdentifier, units, currency, destination, force }: CloseChannelParams, + ): Promise; + + /** Gets a deposit address. */ + public abstract async deposit(): Promise; + public isConnected(): boolean { return this.status === ClientStatus.ConnectionVerified; } diff --git a/lib/swaps/SwapClientManager.ts b/lib/swaps/SwapClientManager.ts index 7829894c6..67a009116 100644 --- a/lib/swaps/SwapClientManager.ts +++ b/lib/swaps/SwapClientManager.ts @@ -1,6 +1,7 @@ import { EventEmitter } from 'events'; import { promises as fs } from 'fs'; import Config from '../Config'; +import ConnextClient from '../connextclient/ConnextClient'; import { SwapClientType } from '../constants/enums'; import { Models } from '../db/DB'; import lndErrors from '../lndclient/errors'; @@ -10,7 +11,6 @@ import { Loggers } from '../Logger'; import { Currency } from '../orderbook/types'; import Peer from '../p2p/Peer'; import RaidenClient from '../raidenclient/RaidenClient'; -import ConnextClient from '../connextclient/ConnextClient'; import { keystore } from '../utils/seedutil'; import { UnitConverter } from '../utils/UnitConverter'; import errors from './errors'; @@ -312,6 +312,10 @@ class SwapClientManager extends EventEmitter { return this.swapClients.get(currency); } + /** Gets the type of swap client for a given currency. */ + public getType = (currency: string) => { + return this.swapClients.get(currency)?.type; + } /** * Returns whether the swap client for a specified currency is connected. * @returns `true` if a swap client exists and is connected, otherwise `false` @@ -440,13 +444,9 @@ class SwapClientManager extends EventEmitter { if (!swapClient) { throw errors.SWAP_CLIENT_NOT_FOUND(currency); } - if (isLndClient(swapClient)) { - const address = await swapClient.newAddress(); - return address; - } else { - // TODO: generic deposit logic - throw new Error('currency currently not supported for fetching deposit addresses'); - } + + const address = await swapClient.deposit(); + return address; } public withdraw = async ({ currency, amount, destination, all, fee }: { @@ -470,49 +470,44 @@ class SwapClientManager extends EventEmitter { } /** - * Closes any payment channels with a peer for a given currency. - * @param peer a peer to open the payment channel with. + * Closes a payment channel. + * @param remoteIdentifier the identifier for the remote side of the channel. * @param currency a currency for the payment channel. - * @param amount the size of the payment channel local balance + * @param amount the amount to extract from the channel. If 0 or unspecified, + * the entire off-chain balance for the specified currency will be extracted. * @returns Nothing upon success, throws otherwise. */ public closeChannel = async ( - { peer, currency, force }: - { peer: Peer, currency: string, force: boolean }, + { remoteIdentifier, currency, force, destination, amount }: + { remoteIdentifier?: string, currency: string, force: boolean, destination?: string, amount?: number }, ): Promise => { const swapClient = this.get(currency); if (!swapClient) { throw errors.SWAP_CLIENT_NOT_FOUND(currency); } - const peerIdentifier = peer.getIdentifier(swapClient.type, currency); - if (!peerIdentifier) { - throw new Error('peer not connected to swap client'); - } - // TODO: temporarily we only support closing lnd channels, make this logic generic - if (isLndClient(swapClient)) { - const lndChannels = (await swapClient.listChannels()).getChannelsList(); - const closePromises: Promise[] = []; - lndChannels.forEach((channel) => { - if (channel.getRemotePubkey() === peerIdentifier) { - const [fundingTxId, outputIndex] = channel.getChannelPoint().split(':'); - const closePromise = swapClient.closeChannel(fundingTxId, Number(outputIndex), force); - closePromises.push(closePromise); - } - }); - await Promise.all(closePromises); - } + const units = amount ? this.unitConverter.amountToUnits({ + amount, + currency, + }) : undefined; + await swapClient.closeChannel({ + remoteIdentifier, + currency, + force, + destination, + units, + }); } /** * Opens a payment channel. - * @param peer a peer to open the payment channel with. + * @param remoteIdentifier the identifier for the remote side of the channel. * @param currency a currency for the payment channel. * @param amount the size of the payment channel local balance * @returns Nothing upon success, throws otherwise. */ public openChannel = async ( - { peer, amount, currency, pushAmount = 0 }: - { peer?: Peer, amount: number, currency: string, pushAmount?: number }, + { remoteIdentifier, amount, currency, pushAmount = 0, uris }: + { remoteIdentifier?: string, amount: number, currency: string, pushAmount?: number, uris?: string[] }, ): Promise => { const swapClient = this.get(currency); if (!swapClient) { @@ -527,23 +522,13 @@ class SwapClientManager extends EventEmitter { amount: pushAmount, }); - if (!peer) { - if (isConnextClient(swapClient)) { - await swapClient.deposit({ currency, units }); - return; - } else { - throw new Error('peerPubKey or alias must be specified'); - } - } - const peerIdentifier = peer.getIdentifier(swapClient.type, currency); - if (!peerIdentifier) { - throw new Error('peer not connected to swap client'); - } - let uris: string[] | undefined; - if (isLndClient(swapClient)) { - uris = peer.getLndUris(currency); - } - await swapClient.openChannel({ peerIdentifier, currency, units, uris, pushUnits }); + await swapClient.openChannel({ + remoteIdentifier, + currency, + units, + uris, + pushUnits, + }); } /** diff --git a/lib/swaps/types.ts b/lib/swaps/types.ts index 937c6246c..97828c1cd 100644 --- a/lib/swaps/types.ts +++ b/lib/swaps/types.ts @@ -107,3 +107,32 @@ export type ResolveRequest = { expiration: number, chain_height: number, }; + +export type CloseChannelParams = { + /** The remote node with which to close channels.. */ + remoteIdentifier?: string, + /** + * The amount to extract from the channel, if applicable. If 0 or unspecified, + * the entire off-chain balance for the specified currency will be extracted. + */ + units?: number, + currency?: string, + /** + * The on-chain address to send funds extracted from the channel. If unspecified + * the funds return to the default wallet for the client closing the channel. + */ + destination?: string, + force?: boolean, +}; + +export type OpenChannelParams = { + /** The remote node with which to open the channel. */ + remoteIdentifier?: string, + /** The size of the channel. */ + units: number, + currency?: string, + /** Uris with which to connect to the remote node. */ + uris?: string[], + /** The balance to assign to the remote node. */ + pushUnits?: number, +}; diff --git a/proto/xudrpc.proto b/proto/xudrpc.proto index 51e96e417..64217595a 100644 --- a/proto/xudrpc.proto +++ b/proto/xudrpc.proto @@ -376,6 +376,12 @@ message CloseChannelRequest { string currency = 2 [json_name = "currency"]; // Whether to force close the channel in case the peer is offline or unresponsive. bool force = 3 [json_name = "force"]; + // The on-chain address to send funds extracted from the channel. If unspecified, + // the funds return to the default wallet for the client closing the channel. + string destination = 4 [json_name = "destination"]; + // For Connext only - the amount to extract from the channel. If 0 or unspecified, + // the entire off-chain balance for the specified currency will be extracted. + uint64 amount = 5 [json_name = "amount"]; } message CloseChannelResponse {} diff --git a/test/jest/LndClient.spec.ts b/test/jest/LndClient.spec.ts index e41db518d..085cd828c 100644 --- a/test/jest/LndClient.spec.ts +++ b/test/jest/LndClient.spec.ts @@ -76,7 +76,7 @@ describe('LndClient', () => { }); await lnd.openChannel({ units, - peerIdentifier: peerPubKey, + remoteIdentifier: peerPubKey, uris: lndListeningUris, }); expect(lnd['connectPeer']).toHaveBeenCalledTimes(2); @@ -96,7 +96,7 @@ describe('LndClient', () => { .mockImplementation(alreadyConnected); await lnd.openChannel({ units, - peerIdentifier: peerPubKey, + remoteIdentifier: peerPubKey, uris: lndListeningUris, }); expect(lnd['connectPeer']).toHaveBeenCalledTimes(1); @@ -118,7 +118,7 @@ describe('LndClient', () => { await lnd.openChannel({ units, pushUnits, - peerIdentifier: peerPubKey, + remoteIdentifier: peerPubKey, uris: lndListeningUris, }); expect(lnd['connectPeer']).toHaveBeenCalledTimes(1); @@ -138,7 +138,7 @@ describe('LndClient', () => { }); await lnd.openChannel({ units, - peerIdentifier: peerPubKey, + remoteIdentifier: peerPubKey, uris: lndListeningUris, }); expect(lnd['connectPeer']).toHaveBeenCalledTimes(1); @@ -157,7 +157,7 @@ describe('LndClient', () => { try { await lnd.openChannel({ units, - peerIdentifier: peerPubKey, + remoteIdentifier: peerPubKey, uris: lndListeningUris, }); } catch (e) { diff --git a/test/jest/Service.spec.ts b/test/jest/Service.spec.ts index a6264978f..149a2399e 100644 --- a/test/jest/Service.spec.ts +++ b/test/jest/Service.spec.ts @@ -1,4 +1,4 @@ -import { Owner } from '../../lib/constants/enums'; +import { Owner, SwapClientType } from '../../lib/constants/enums'; import Orderbook from '../../lib/orderbook/OrderBook'; import Peer from '../../lib/p2p/Peer'; import Pool from '../../lib/p2p/Pool'; @@ -12,15 +12,32 @@ jest.mock('../../lib/orderbook/OrderBook'); const mockedOrderbook = >Orderbook; jest.mock('../../lib/swaps/Swaps'); const mockedSwaps = >Swaps; -jest.mock('../../lib/swaps/SwapClientManager'); +jest.mock('../../lib/swaps/SwapClientManager', () => { + return jest.fn().mockImplementation(() => { + return { + getType: () => SwapClientType.Lnd, + }; + }); +}); const mockedSwapClientManager = >SwapClientManager; jest.mock('../../lib/swaps/SwapClient'); const mockedSwapClient = >SwapClient; jest.mock('../../lib/p2p/Pool'); const mockedPool = >Pool; jest.mock('../../lib/p2p/Peer'); +jest.mock('../../lib/p2p/Peer', () => { + return jest.fn().mockImplementation(() => { + return { + getLndPubKey: () => lndPubKey, + getIdentifier: () => lndPubKey, + getLndUris: jest.fn(), + }; + }); +}); const mockedPeer = >Peer; +const lndPubKey = 'lndpubkey'; + const getArgs = () => { return { nodeIdentifier: '02f8895eb03c37b2665415be4d83b20228acc0abc55ebf6728565141c66cfc164a', @@ -52,7 +69,7 @@ describe('Service', () => { }); describe('openChannel', () => { - test('gets peer from pool for swapClientManager', async () => { + test('gets peer identifier from pool for swapClientManager', async () => { service = new Service(components); const args = getArgs(); await service.openChannel(args); @@ -60,7 +77,7 @@ describe('Service', () => { .toHaveBeenCalledWith(args.nodeIdentifier); expect(components.swapClientManager.openChannel) .toHaveBeenCalledWith({ - peer, + remoteIdentifier: lndPubKey, amount: args.amount, currency: args.currency, }); diff --git a/test/jest/SwapClientManager.spec.ts b/test/jest/SwapClientManager.spec.ts index 4e5f0f158..d5aef989a 100644 --- a/test/jest/SwapClientManager.spec.ts +++ b/test/jest/SwapClientManager.spec.ts @@ -2,7 +2,6 @@ import Config from '../../lib/Config'; import { SwapClientType } from '../../lib/constants/enums'; import DB from '../../lib/db/DB'; import Logger from '../../lib/Logger'; -import Peer from '../../lib/p2p/Peer'; import SwapClientManager from '../../lib/swaps/SwapClientManager'; import { UnitConverter } from '../../lib/utils/UnitConverter'; @@ -82,8 +81,6 @@ const loggers = { swaps: logger, http: logger, }; -jest.mock('../../lib/p2p/Peer'); -const mockedPeer = >Peer; describe('Swaps.SwapClientManager', () => { let config: Config; @@ -209,13 +206,10 @@ describe('Swaps.SwapClientManager', () => { }); describe('openChannel', () => { - let peer: Peer; - let peerLndPubKey: string; + let remoteIdentifier: string; beforeEach(() => { - peer = new mockedPeer(); - peerLndPubKey = '02afaef2634e5c7ca8d682b828a62bd040929b1e4b5030b21e2a0a891cf545b2e1'; - peer.getIdentifier = jest.fn().mockReturnValue(peerLndPubKey); + remoteIdentifier = '02afaef2634e5c7ca8d682b828a62bd040929b1e4b5030b21e2a0a891cf545b2e1'; }); test('it fails without swap client', async () => { @@ -226,21 +220,19 @@ describe('Swaps.SwapClientManager', () => { swapClientManager.get = jest.fn().mockReturnValue(undefined); await swapClientManager.init(db.models); try { - await swapClientManager.openChannel({ peer, currency, amount }); + await swapClientManager.openChannel({ remoteIdentifier, currency, amount }); } catch (e) { expect(e).toMatchSnapshot(); } }); test('it fails without peerSwapClientPubKey', async () => { - expect.assertions(1); const currency = 'BTC'; const amount = 16000000; swapClientManager = new SwapClientManager(config, loggers, unitConverter); - peer.getIdentifier = jest.fn().mockReturnValue(undefined); await swapClientManager.init(db.models); try { - await swapClientManager.openChannel({ peer, currency, amount }); + await swapClientManager.openChannel({ remoteIdentifier, currency, amount }); } catch (e) { expect(e).toMatchSnapshot(); } @@ -255,17 +247,15 @@ describe('Swaps.SwapClientManager', () => { '123.456.789.321:9735', '192.168.63.155:9777', ]; - peer.getLndUris = jest.fn().mockReturnValue(lndListeningUris); await swapClientManager.init(db.models); - await swapClientManager.openChannel({ peer, currency, amount }); + await swapClientManager.openChannel({ remoteIdentifier, currency, amount, uris: lndListeningUris }); expect(getClientSpy).toHaveBeenCalledWith(currency); - expect(peer.getIdentifier).toHaveBeenCalledWith(SwapClientType.Lnd, currency); expect(mockLndOpenChannel).toHaveBeenCalledTimes(1); expect(mockLndOpenChannel).toHaveBeenCalledWith( expect.objectContaining({ + remoteIdentifier, units: amount, uris: lndListeningUris, - peerIdentifier: peerLndPubKey, }), ); }); @@ -276,21 +266,17 @@ describe('Swaps.SwapClientManager', () => { const amount = 5000000; const expectedUnits = 50000000000000000; const peerRaidenAddress = '0x10D8CCAD85C7dc123090B43aA1f98C00a303BFC5'; - peer.getIdentifier = jest.fn().mockReturnValue(peerRaidenAddress); swapClientManager = new SwapClientManager(config, loggers, unitConverter); const getClientSpy = jest.spyOn(swapClientManager, 'get'); - peer.getLndUris = jest.fn(); await swapClientManager.init(db.models); - await swapClientManager.openChannel({ peer, currency, amount }); + await swapClientManager.openChannel({ currency, amount, remoteIdentifier: peerRaidenAddress }); expect(getClientSpy).toHaveBeenCalledWith(currency); - expect(peer.getIdentifier).toHaveBeenCalledWith(SwapClientType.Raiden, currency); - expect(peer.getLndUris).toHaveBeenCalledTimes(0); expect(mockRaidenOpenChannel).toHaveBeenCalledTimes(1); expect(mockRaidenOpenChannel).toHaveBeenCalledWith( expect.objectContaining({ currency, units: expectedUnits, - peerIdentifier: peerRaidenAddress, + remoteIdentifier: peerRaidenAddress, // uris: undefined, pushUnits: 0, }), diff --git a/test/jest/__snapshots__/SwapClientManager.spec.ts.snap b/test/jest/__snapshots__/SwapClientManager.spec.ts.snap index 65c59b7cf..4ec2a09a6 100644 --- a/test/jest/__snapshots__/SwapClientManager.spec.ts.snap +++ b/test/jest/__snapshots__/SwapClientManager.spec.ts.snap @@ -1,7 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Swaps.SwapClientManager openChannel it fails without peerSwapClientPubKey 1`] = `[Error: peer not connected to swap client]`; - exports[`Swaps.SwapClientManager openChannel it fails without swap client 1`] = ` Object { "code": "7.1", diff --git a/test/simulation/xudrpc/xudrpc.pb.go b/test/simulation/xudrpc/xudrpc.pb.go index bd9c5132d..0f941210d 100644 --- a/test/simulation/xudrpc/xudrpc.pb.go +++ b/test/simulation/xudrpc/xudrpc.pb.go @@ -515,7 +515,13 @@ type CloseChannelRequest struct { // The ticker symbol of the currency of the channel to close. Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"` // Whether to force close the channel in case the peer is offline or unresponsive. - Force bool `protobuf:"varint,3,opt,name=force,proto3" json:"force,omitempty"` + Force bool `protobuf:"varint,3,opt,name=force,proto3" json:"force,omitempty"` + // The on-chain address to send funds extracted from the channel. If unspecified, + // the funds return to the default wallet for the client closing the channel. + Destination string `protobuf:"bytes,4,opt,name=destination,proto3" json:"destination,omitempty"` + // For Connext only - the amount to extract from the channel. If 0 or unspecified, + // the entire off-chain balance for the specified currency will be extracted. + Amount uint64 `protobuf:"varint,5,opt,name=amount,proto3" json:"amount,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -567,6 +573,20 @@ func (m *CloseChannelRequest) GetForce() bool { return false } +func (m *CloseChannelRequest) GetDestination() string { + if m != nil { + return m.Destination + } + return "" +} + +func (m *CloseChannelRequest) GetAmount() uint64 { + if m != nil { + return m.Amount + } + return 0 +} + type CloseChannelResponse struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -4256,237 +4276,238 @@ func init() { func init() { proto.RegisterFile("xudrpc.proto", fileDescriptor_6960a02cc0a63cf6) } var fileDescriptor_6960a02cc0a63cf6 = []byte{ - // 3675 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x3a, 0x4d, 0x8f, 0xdc, 0xc6, - 0xb1, 0xcb, 0xf9, 0xd8, 0x99, 0xad, 0xf9, 0xdc, 0xde, 0x0f, 0x8d, 0x46, 0xb2, 0x2c, 0xf3, 0xd9, - 0x7a, 0xb2, 0x2c, 0xad, 0xf4, 0xd6, 0xcf, 0xcf, 0x96, 0xfc, 0x6c, 0x58, 0xbb, 0xda, 0x67, 0xc9, - 0x5e, 0x7d, 0x80, 0x2b, 0xd9, 0x7a, 0x41, 0x62, 0x82, 0x43, 0xb6, 0xb4, 0x8c, 0x38, 0xcd, 0x11, - 0x3f, 0xf6, 0x23, 0xa7, 0xc0, 0x06, 0x72, 0x48, 0x8e, 0xce, 0xd1, 0x40, 0x72, 0xca, 0x25, 0xb9, - 0x07, 0xc8, 0x29, 0xe7, 0x5c, 0x03, 0x04, 0x39, 0x04, 0x08, 0x02, 0xe4, 0x17, 0xe4, 0x17, 0x04, - 0xfd, 0x45, 0x76, 0x93, 0x9c, 0xb5, 0x64, 0x24, 0x37, 0x76, 0x75, 0x75, 0x55, 0x57, 0x75, 0x75, - 0x55, 0x75, 0x15, 0xa1, 0x7b, 0x94, 0x7a, 0xd1, 0xcc, 0xdd, 0x98, 0x45, 0x61, 0x12, 0xa2, 0x45, - 0x3e, 0x1a, 0x2f, 0x3b, 0x84, 0x84, 0x89, 0x93, 0xf8, 0x21, 0x89, 0xf9, 0x94, 0xb9, 0x06, 0x2b, - 0x37, 0x3d, 0x6f, 0x3b, 0x8d, 0x22, 0x4c, 0xdc, 0x63, 0x0b, 0xc7, 0xb3, 0x90, 0xc4, 0xd8, 0xfc, - 0x02, 0xfa, 0x37, 0x3d, 0xef, 0x81, 0xe3, 0x47, 0x16, 0x7e, 0x9e, 0xe2, 0x38, 0x41, 0xaf, 0x43, - 0x6f, 0xe2, 0xc4, 0xd8, 0x76, 0x05, 0xea, 0xc8, 0x38, 0x6f, 0x5c, 0x5c, 0xb2, 0x74, 0x20, 0xba, - 0x00, 0xfd, 0xe7, 0x69, 0x98, 0x28, 0x68, 0x35, 0x86, 0x56, 0x80, 0x9a, 0xcb, 0x30, 0xc8, 0xe8, - 0x0b, 0x96, 0xbf, 0xad, 0x41, 0x6b, 0xcb, 0x09, 0x1c, 0xe2, 0x62, 0xca, 0x2c, 0x09, 0x13, 0x27, - 0xb0, 0x27, 0x1c, 0xc0, 0x98, 0x35, 0x2c, 0x1d, 0x88, 0x2e, 0xc2, 0xc0, 0xdd, 0x77, 0x08, 0xc1, - 0x39, 0x5e, 0x8d, 0xe1, 0x15, 0xc1, 0xe8, 0x3d, 0x38, 0x35, 0xc3, 0xc4, 0xf3, 0xc9, 0x53, 0xbb, - 0xb8, 0xa2, 0xce, 0x56, 0xcc, 0x9b, 0x46, 0x37, 0x60, 0xe4, 0x13, 0xc7, 0x4d, 0xfc, 0x03, 0x5c, - 0x5a, 0xda, 0x60, 0x4b, 0xe7, 0xce, 0x53, 0x65, 0x1c, 0x3a, 0x41, 0x80, 0x93, 0x6c, 0x45, 0x93, - 0xad, 0x28, 0x40, 0xd1, 0x87, 0x30, 0x4e, 0x89, 0x1b, 0x92, 0x27, 0x7e, 0x34, 0xc5, 0x9e, 0x5d, - 0x58, 0xb3, 0xc8, 0xd6, 0x9c, 0x80, 0x61, 0xfe, 0x0f, 0xc0, 0x96, 0x43, 0xe4, 0x41, 0x5d, 0x84, - 0x01, 0x09, 0x3d, 0x6c, 0xfb, 0x1e, 0x26, 0x89, 0xff, 0xc4, 0xc7, 0x91, 0x38, 0xaa, 0x22, 0xd8, - 0xec, 0x41, 0x87, 0xad, 0x13, 0x07, 0xf0, 0x2e, 0x34, 0xb7, 0xf7, 0x1d, 0x9f, 0xa0, 0x55, 0x68, - 0xba, 0xf4, 0x43, 0xac, 0xe3, 0x03, 0x34, 0x82, 0x16, 0xc1, 0xc9, 0x61, 0x18, 0x3d, 0x13, 0x67, - 0x2a, 0x87, 0xe6, 0x0c, 0xda, 0xdb, 0x5c, 0xf4, 0x18, 0xad, 0xc3, 0x22, 0xd7, 0x06, 0x5b, 0xdc, - 0xb3, 0xc4, 0x08, 0x8d, 0xa1, 0x2d, 0xf5, 0xc4, 0x96, 0xf7, 0xac, 0x6c, 0x4c, 0x29, 0x0b, 0xf5, - 0xb3, 0xd3, 0xe8, 0x59, 0x72, 0x48, 0xa9, 0xb9, 0x41, 0x18, 0x63, 0x8f, 0xe9, 0xba, 0x67, 0x89, - 0x91, 0xf9, 0x1c, 0x56, 0xb6, 0xe9, 0x97, 0x60, 0xfb, 0xd2, 0xa2, 0xd3, 0xed, 0x14, 0x2c, 0x34, - 0x1b, 0x53, 0xf1, 0x9f, 0x84, 0x91, 0x30, 0x8d, 0xb6, 0xc5, 0x07, 0xe6, 0x3a, 0xac, 0xea, 0x2c, - 0x85, 0xd6, 0x2e, 0x43, 0x7f, 0x3b, 0x24, 0x04, 0xbb, 0x89, 0xdc, 0xc5, 0x18, 0xda, 0x8c, 0x5d, - 0x1a, 0xf9, 0x82, 0x7d, 0x36, 0xa6, 0x76, 0x9f, 0x61, 0x0b, 0x02, 0x57, 0x61, 0x79, 0x3b, 0xc2, - 0x4e, 0x82, 0xef, 0x85, 0x1e, 0x56, 0x68, 0xcc, 0x9c, 0x38, 0x3e, 0x0c, 0x23, 0x4f, 0xd2, 0x90, - 0x63, 0xf3, 0x6b, 0x03, 0x90, 0xba, 0x82, 0xd3, 0x41, 0xff, 0x01, 0xbd, 0x18, 0x63, 0xcf, 0x9e, - 0x12, 0x3c, 0x0d, 0x89, 0xef, 0x8e, 0x8c, 0xf3, 0xf5, 0x8b, 0x4b, 0x56, 0x97, 0x02, 0xef, 0x0a, - 0x18, 0x7a, 0x13, 0x86, 0x3e, 0xf1, 0x13, 0xdf, 0x09, 0xfc, 0x1f, 0x61, 0xcf, 0x0e, 0x88, 0x17, - 0x8f, 0x6a, 0x0c, 0x6f, 0xa0, 0xc0, 0x77, 0x89, 0x17, 0xa3, 0x2b, 0x80, 0x54, 0xd4, 0xc8, 0xa1, - 0xea, 0x13, 0x3a, 0x59, 0x56, 0x66, 0x2c, 0x36, 0x61, 0xfe, 0xc9, 0x80, 0xb6, 0x74, 0x23, 0x9a, - 0x7a, 0x8d, 0x82, 0x7a, 0x3f, 0x80, 0x4e, 0x7c, 0xe8, 0xcc, 0x6c, 0x37, 0xf0, 0x31, 0x49, 0x98, - 0xf6, 0xfb, 0x9b, 0x67, 0x36, 0x84, 0xc3, 0x92, 0x24, 0x36, 0xf6, 0x0e, 0x9d, 0xd9, 0x36, 0x43, - 0xb1, 0x54, 0x7c, 0xee, 0x1a, 0x9e, 0x61, 0x62, 0x3b, 0x9e, 0x17, 0xe1, 0x38, 0x66, 0x3b, 0x5a, - 0xb2, 0x74, 0x20, 0xbd, 0x7a, 0x1e, 0x76, 0xfd, 0xa9, 0x13, 0xd8, 0xb3, 0xc0, 0x71, 0x71, 0x2c, - 0x0c, 0xa8, 0x00, 0x35, 0x5f, 0x03, 0xc8, 0x19, 0xa1, 0x16, 0xd4, 0x77, 0xef, 0xdd, 0x1a, 0x2e, - 0x20, 0x80, 0x45, 0xeb, 0xe6, 0x9d, 0x5b, 0x3b, 0xf7, 0x86, 0x06, 0x3d, 0xe0, 0x5b, 0x78, 0x16, - 0xc6, 0xbe, 0x7a, 0xc0, 0xf3, 0xa4, 0x33, 0xdf, 0x82, 0x41, 0x86, 0x2d, 0x0e, 0x66, 0x04, 0x2d, - 0xb9, 0x57, 0x8e, 0x2d, 0x87, 0xe6, 0x47, 0xb0, 0x7a, 0xcb, 0x8f, 0xdd, 0xf0, 0x00, 0x47, 0xf4, - 0x28, 0xe3, 0x97, 0xbf, 0xc2, 0xef, 0xc0, 0x5a, 0x81, 0x82, 0x60, 0x7a, 0x16, 0x96, 0x48, 0x3a, - 0xb5, 0x29, 0x7e, 0x2c, 0xae, 0x62, 0x0e, 0x30, 0x7f, 0x6a, 0x00, 0xda, 0x39, 0xc2, 0x6e, 0x9a, - 0x60, 0x2a, 0xbe, 0x22, 0x58, 0x18, 0x79, 0x38, 0xb2, 0xfd, 0xcc, 0xea, 0xe4, 0x98, 0x5d, 0x52, - 0xc7, 0x67, 0x53, 0xe2, 0xfa, 0x8b, 0x21, 0x32, 0xa1, 0x3b, 0xc3, 0x38, 0xb2, 0x67, 0xe9, 0xc4, - 0x7e, 0x86, 0x8f, 0xc5, 0x81, 0x68, 0x30, 0x4a, 0xf9, 0x79, 0xea, 0x90, 0xc4, 0x4f, 0x8e, 0x85, - 0xdb, 0xcc, 0xc6, 0xf4, 0x02, 0x7c, 0x8c, 0x13, 0xe1, 0xfa, 0x5f, 0x44, 0xc7, 0xbf, 0x32, 0x00, - 0xa9, 0x2b, 0x84, 0xc8, 0x5b, 0xd0, 0x16, 0x1e, 0x31, 0x66, 0xb6, 0xdf, 0xd9, 0xbc, 0x28, 0xad, - 0xaa, 0x8c, 0xbd, 0x21, 0xc6, 0xf1, 0x0e, 0x49, 0xa2, 0x63, 0x6b, 0x91, 0xc9, 0x19, 0x8f, 0x77, - 0xa1, 0xa7, 0x4d, 0xa0, 0x21, 0xd4, 0xa9, 0x4c, 0x7c, 0x0b, 0xf4, 0x13, 0xbd, 0x01, 0xcd, 0x03, - 0x27, 0x48, 0xb9, 0x1b, 0xeb, 0x6c, 0x0e, 0x24, 0x0f, 0xc9, 0x80, 0xcf, 0xde, 0xa8, 0xbd, 0x67, - 0x98, 0x43, 0xe8, 0x7f, 0x8c, 0x93, 0x3b, 0xe4, 0x49, 0x28, 0xc4, 0x32, 0x7f, 0xd2, 0x80, 0x41, - 0x06, 0xca, 0xed, 0xe3, 0x00, 0x47, 0xb1, 0x1f, 0x4a, 0x87, 0x2b, 0x87, 0x54, 0xb3, 0xec, 0xc0, - 0xa5, 0x66, 0xb9, 0xe2, 0x35, 0x18, 0x42, 0xd0, 0x48, 0x23, 0x9f, 0x5e, 0x03, 0x7a, 0x8b, 0xd9, - 0xb7, 0x3c, 0x7c, 0x7a, 0x02, 0xd2, 0xf0, 0x73, 0x40, 0x36, 0xeb, 0xf8, 0x51, 0xcc, 0x22, 0x92, - 0x9c, 0xa5, 0x00, 0xf4, 0x16, 0x08, 0x5d, 0xb0, 0xc0, 0xd3, 0xd9, 0x5c, 0x91, 0xf2, 0xdd, 0x67, - 0xd0, 0xed, 0x30, 0x25, 0x89, 0x54, 0x17, 0xda, 0x84, 0x7a, 0x40, 0xbc, 0x51, 0x8b, 0x69, 0xfb, - 0xbc, 0xa2, 0x6d, 0x55, 0xc0, 0x8d, 0x5d, 0xe2, 0x71, 0x2d, 0x53, 0x64, 0x74, 0x09, 0x16, 0x85, - 0x2f, 0x69, 0x33, 0x06, 0x48, 0x2e, 0xe3, 0x8e, 0x84, 0xad, 0x14, 0x18, 0xd4, 0x15, 0x3b, 0x81, - 0xef, 0xc4, 0xa3, 0x25, 0x1e, 0x89, 0xd8, 0x40, 0x8d, 0x44, 0xa0, 0x45, 0x22, 0x74, 0x0d, 0x56, - 0x64, 0x20, 0x67, 0x3e, 0x63, 0xdf, 0x89, 0xf7, 0x71, 0x3c, 0xea, 0x30, 0xdd, 0x54, 0x4d, 0xa1, - 0x2b, 0xd0, 0x72, 0xa9, 0x43, 0x3e, 0x4a, 0x46, 0x5d, 0x5d, 0xde, 0x6d, 0x0e, 0x66, 0xfb, 0x91, - 0x38, 0xe3, 0x8f, 0xa1, 0x2d, 0xa5, 0x79, 0x09, 0xd3, 0xd8, 0x25, 0x1e, 0x23, 0xa3, 0x98, 0xc6, - 0x87, 0xcc, 0x84, 0xe9, 0x9d, 0x55, 0xcc, 0xe3, 0x25, 0x2e, 0xbe, 0x05, 0x2b, 0xda, 0xfa, 0x2c, - 0x08, 0x0c, 0x22, 0x3c, 0x4b, 0x79, 0x8e, 0xb7, 0xe7, 0x86, 0x11, 0x8f, 0xc3, 0xcb, 0x16, 0xe4, - 0x60, 0x1a, 0x55, 0x27, 0x34, 0x88, 0xf1, 0x9b, 0xdc, 0xb6, 0xc4, 0xc8, 0x3c, 0x05, 0x6b, 0xbb, - 0x7e, 0x9c, 0x08, 0x17, 0xec, 0x67, 0xfe, 0xc8, 0xfc, 0x04, 0xd6, 0x8b, 0x13, 0x82, 0xdf, 0x35, - 0x00, 0x37, 0x83, 0x8a, 0x5b, 0x37, 0x2c, 0xfa, 0x72, 0x4b, 0xc1, 0x31, 0xff, 0x60, 0xc0, 0x32, - 0x25, 0xc6, 0xcd, 0x49, 0x0a, 0xae, 0x78, 0x17, 0x43, 0xf7, 0x2e, 0xef, 0x40, 0x33, 0x3c, 0x24, - 0x38, 0x12, 0x81, 0xe2, 0xd5, 0x4c, 0xa7, 0x45, 0x1a, 0x1b, 0xf7, 0x29, 0x9a, 0xc5, 0xb1, 0xa9, - 0xe5, 0x04, 0xfe, 0xd4, 0x4f, 0x44, 0x46, 0xc1, 0x07, 0x54, 0xbf, 0x3e, 0x71, 0x83, 0xd4, 0xc3, - 0x36, 0x33, 0x25, 0x11, 0x17, 0xda, 0x56, 0x11, 0x6c, 0xbe, 0x0e, 0x4d, 0x46, 0x0f, 0xb5, 0xa1, - 0xb1, 0x75, 0xff, 0xe1, 0xed, 0xe1, 0x02, 0x8d, 0x0e, 0xf7, 0x3f, 0xbf, 0x37, 0x34, 0x28, 0xe8, - 0xc1, 0xce, 0x8e, 0x35, 0xac, 0x99, 0xbf, 0x30, 0x00, 0xa9, 0x1b, 0x11, 0x5a, 0xf9, 0x30, 0xbb, - 0x43, 0x5c, 0x23, 0x17, 0xaa, 0x36, 0x2d, 0x2e, 0x07, 0x1f, 0xea, 0x5e, 0xe8, 0x0e, 0x74, 0x14, - 0x70, 0x85, 0xa1, 0xbd, 0xae, 0x1b, 0x5a, 0x5f, 0xbf, 0xa3, 0xaa, 0x9d, 0x21, 0x18, 0x52, 0xa6, - 0x34, 0xd3, 0xce, 0x8e, 0xf3, 0x4d, 0x7e, 0x02, 0x02, 0x26, 0xf6, 0xbc, 0x0a, 0x4d, 0xee, 0x11, - 0x78, 0xda, 0xc0, 0x07, 0xd9, 0x72, 0x9c, 0xeb, 0xd9, 0x7c, 0x57, 0x2c, 0xc7, 0xaa, 0xc8, 0x26, - 0x34, 0xb9, 0xbb, 0xe1, 0x12, 0x77, 0xe5, 0x8e, 0x28, 0x96, 0xc5, 0xa7, 0x24, 0xdf, 0x87, 0x91, - 0xa3, 0xc4, 0xba, 0xec, 0xa0, 0x0c, 0xe5, 0xa0, 0xcc, 0xf7, 0xb9, 0x5e, 0x25, 0xaa, 0x60, 0xf2, - 0x06, 0x2c, 0x26, 0x0c, 0x22, 0xb8, 0xf4, 0x24, 0x17, 0x86, 0x67, 0x89, 0x49, 0xf3, 0x2f, 0x06, - 0xb4, 0xc4, 0x95, 0xa3, 0xb6, 0x1e, 0x27, 0x4e, 0x92, 0xca, 0xd8, 0x2b, 0x46, 0xe8, 0x32, 0xb4, - 0x45, 0xba, 0x1e, 0x0b, 0x25, 0xe6, 0x66, 0x2b, 0xe0, 0x56, 0x86, 0x41, 0x19, 0xb3, 0x24, 0x98, - 0xbb, 0x59, 0x85, 0x31, 0x4b, 0x98, 0x2d, 0x31, 0x89, 0xce, 0x43, 0x67, 0x12, 0x84, 0xee, 0xb3, - 0x7d, 0xec, 0x3f, 0xdd, 0x4f, 0x84, 0xe7, 0x55, 0x41, 0x99, 0xb7, 0x6e, 0x2a, 0xde, 0x5a, 0xf1, - 0xff, 0x8b, 0xba, 0xff, 0xcf, 0xdc, 0x5f, 0x4b, 0x71, 0x7f, 0xe6, 0x27, 0xd0, 0x67, 0xf7, 0x3e, - 0xcf, 0x66, 0x8b, 0x71, 0xc2, 0xa8, 0x88, 0x13, 0x19, 0xad, 0x9a, 0x4a, 0xeb, 0xe7, 0x06, 0xa0, - 0xfb, 0x33, 0x4c, 0xfe, 0x2d, 0x89, 0x34, 0x7d, 0x0b, 0x4c, 0x69, 0xbc, 0x10, 0x8f, 0x2c, 0x31, - 0xa2, 0x6a, 0x9a, 0xa5, 0xf1, 0xbe, 0x2d, 0x26, 0x79, 0x3e, 0xa0, 0x82, 0xe8, 0xab, 0x54, 0xdb, - 0x95, 0x48, 0x95, 0x7f, 0x5f, 0x83, 0x26, 0x33, 0x71, 0x66, 0xad, 0x91, 0x2f, 0x1e, 0x86, 0x86, - 0xc5, 0x07, 0x5a, 0x96, 0x51, 0xd3, 0xb3, 0x0c, 0xd5, 0xc3, 0xd4, 0x75, 0x0f, 0xd3, 0x87, 0x9a, - 0xcf, 0x1f, 0x18, 0x4b, 0x56, 0xcd, 0xf7, 0xd0, 0x47, 0x65, 0xe1, 0x9b, 0xcc, 0x42, 0xd6, 0xe5, - 0xa9, 0xeb, 0xea, 0xaf, 0x54, 0x4a, 0x10, 0xba, 0x4e, 0x40, 0x99, 0xf1, 0x23, 0xcd, 0xc6, 0xe8, - 0x1c, 0x80, 0xcb, 0x92, 0x77, 0xcf, 0x76, 0x12, 0x76, 0xb0, 0x0d, 0x4b, 0x81, 0xa0, 0x37, 0xa0, - 0x11, 0xfb, 0x1e, 0x66, 0xc1, 0xb1, 0xbf, 0xb9, 0xac, 0xdd, 0xec, 0x3d, 0xdf, 0xc3, 0x16, 0x9b, - 0xa6, 0x47, 0xee, 0xc7, 0x76, 0x78, 0x48, 0x6c, 0xe6, 0x33, 0x58, 0x80, 0x6c, 0x5b, 0x1a, 0x8c, - 0x1a, 0xdb, 0x7e, 0x18, 0x78, 0x2c, 0x48, 0x36, 0x2c, 0xf6, 0x6d, 0xfe, 0xd2, 0x80, 0x2e, 0xa3, - 0x65, 0xe1, 0x69, 0x78, 0xe0, 0x04, 0x9a, 0xce, 0x8c, 0xf9, 0x3a, 0x2b, 0xe4, 0x7c, 0x6a, 0xa6, - 0x58, 0x2f, 0x64, 0x8a, 0xaa, 0xf4, 0x8d, 0x82, 0xf4, 0xc5, 0x6d, 0x37, 0xcb, 0xdb, 0x36, 0xf7, - 0x61, 0x91, 0xfb, 0x31, 0x74, 0x05, 0x60, 0x92, 0x1e, 0xdb, 0x9a, 0x2f, 0xed, 0x69, 0x1a, 0xb1, - 0x14, 0x04, 0x74, 0x15, 0x3a, 0x31, 0x0e, 0x02, 0x89, 0x5f, 0xab, 0xc2, 0x57, 0x31, 0xcc, 0xb7, - 0xa5, 0x9f, 0x65, 0x59, 0x0d, 0xd5, 0x17, 0x75, 0x54, 0xc2, 0x13, 0xb1, 0x6f, 0xea, 0x7b, 0xc3, - 0x43, 0x22, 0x9e, 0xac, 0xf4, 0xd3, 0xfc, 0xd2, 0x10, 0xab, 0x1e, 0xcd, 0x3c, 0x27, 0xa1, 0x4e, - 0xa9, 0xc9, 0x65, 0x31, 0x98, 0x91, 0xe8, 0xfc, 0x6e, 0x2f, 0x58, 0x7c, 0x16, 0xfd, 0x2f, 0xf4, - 0xb8, 0x86, 0x22, 0xae, 0x78, 0xe1, 0x75, 0x56, 0xf5, 0xed, 0xf1, 0xb9, 0xdb, 0x0b, 0x96, 0x8e, - 0xbc, 0xd5, 0x87, 0x2e, 0x07, 0xa4, 0x8c, 0xa9, 0xf9, 0x55, 0x1d, 0x1a, 0xd4, 0xb5, 0xce, 0x7f, - 0x5c, 0xbc, 0x50, 0xf2, 0xf8, 0x11, 0x74, 0x03, 0xe2, 0xc9, 0xa1, 0xf4, 0x6e, 0x67, 0x55, 0xe7, - 0x4d, 0x93, 0x97, 0x07, 0xe9, 0xe4, 0x53, 0x7c, 0x2c, 0x82, 0x94, 0xb6, 0x82, 0xf2, 0xf7, 0xc9, - 0x24, 0x4c, 0x89, 0x27, 0x22, 0xa9, 0x1c, 0xe6, 0x01, 0xa5, 0xa9, 0x04, 0x14, 0x7a, 0xf7, 0x8f, - 0x52, 0xcf, 0xd6, 0x1d, 0x9e, 0x0a, 0x42, 0x97, 0x61, 0x39, 0xc6, 0x6e, 0x48, 0xbc, 0xd8, 0x76, - 0xf9, 0x53, 0x19, 0x7b, 0xec, 0x9e, 0xf4, 0xac, 0xf2, 0x04, 0x7d, 0xe8, 0xf1, 0x5c, 0x31, 0x7b, - 0x0f, 0xb6, 0x79, 0xc1, 0x49, 0x87, 0x56, 0x67, 0x92, 0xe3, 0x0f, 0x60, 0x50, 0x10, 0xaf, 0x22, - 0xd8, 0xae, 0xaa, 0xc1, 0x76, 0x49, 0x0d, 0xae, 0x3f, 0xae, 0xc1, 0xf2, 0x03, 0xfa, 0x90, 0x14, - 0x87, 0x97, 0x45, 0xb4, 0x7f, 0x99, 0x6f, 0x52, 0xef, 0x59, 0xa3, 0x70, 0xcf, 0xa4, 0xa7, 0x68, - 0x9e, 0xec, 0x29, 0x2e, 0xc1, 0x30, 0xc2, 0xec, 0xb9, 0x6b, 0x67, 0xa4, 0xb8, 0xda, 0x4b, 0x70, - 0x9a, 0x3f, 0xfb, 0xd3, 0x29, 0xf6, 0x7c, 0x27, 0xa1, 0x50, 0xdb, 0xa5, 0x2f, 0x9a, 0x80, 0x69, - 0xbf, 0x6d, 0x55, 0x4d, 0x51, 0x15, 0x20, 0x55, 0x05, 0x22, 0x52, 0x5f, 0x87, 0xa1, 0x4f, 0x12, - 0x1c, 0x11, 0x27, 0xb0, 0xa7, 0x4e, 0xe2, 0xee, 0xe3, 0x39, 0xf7, 0xb7, 0x84, 0x86, 0xde, 0x87, - 0x3e, 0x4b, 0xd0, 0xe3, 0xd4, 0x75, 0x71, 0x4c, 0x53, 0x34, 0x7e, 0x91, 0xb3, 0xc4, 0x9c, 0xbe, - 0x58, 0xf7, 0xf8, 0xa4, 0x55, 0x40, 0x45, 0xef, 0xd2, 0xfc, 0x77, 0xea, 0xf8, 0x84, 0xe6, 0xf9, - 0xfc, 0x5a, 0xd6, 0x2b, 0xae, 0xa5, 0x55, 0xc4, 0x42, 0xd7, 0xa1, 0xc7, 0x48, 0x3d, 0x71, 0xfc, - 0x20, 0x8d, 0x58, 0x5e, 0x58, 0x62, 0xfa, 0x7f, 0x7c, 0xce, 0xd2, 0x31, 0xcd, 0x7f, 0x18, 0x30, - 0xc8, 0x55, 0xb0, 0x73, 0x80, 0x09, 0xf5, 0xe2, 0x4d, 0x26, 0xcf, 0x5c, 0xa7, 0xc0, 0x66, 0xd1, - 0x75, 0xe8, 0xaa, 0x02, 0x08, 0x9f, 0x50, 0x25, 0xe9, 0xed, 0x05, 0x4b, 0x43, 0x45, 0xd7, 0x5f, - 0x4c, 0xd2, 0xdb, 0x0b, 0x55, 0xb2, 0x76, 0x55, 0x09, 0x98, 0x61, 0x55, 0x8b, 0x9a, 0x71, 0x15, - 0xa8, 0x5b, 0x2d, 0x68, 0x62, 0x2a, 0xa0, 0xf9, 0x8d, 0x01, 0x90, 0x3f, 0xd8, 0xe6, 0xa6, 0x59, - 0x8a, 0x7b, 0xaa, 0xe9, 0xee, 0x49, 0x4d, 0xc0, 0xea, 0xdf, 0x9a, 0x80, 0x29, 0x39, 0x52, 0xa3, - 0x94, 0x23, 0xf1, 0x62, 0x65, 0x53, 0x29, 0x56, 0x9a, 0x21, 0x74, 0x94, 0xf7, 0xdb, 0x77, 0xd8, - 0xde, 0xcb, 0x32, 0x7c, 0x1b, 0xd6, 0x98, 0xf3, 0xc6, 0x79, 0x29, 0xfd, 0xdb, 0x0b, 0x19, 0x23, - 0x58, 0x2f, 0x2e, 0x12, 0x99, 0xce, 0x2e, 0x20, 0x3e, 0xa3, 0x79, 0x96, 0x93, 0xea, 0x33, 0x27, - 0xf8, 0x17, 0xf3, 0x1d, 0x58, 0xd1, 0xa8, 0x89, 0x4b, 0x7a, 0x0e, 0x86, 0x12, 0xc5, 0x0e, 0x89, - 0xcd, 0x72, 0x05, 0x43, 0xc9, 0x15, 0xae, 0xc0, 0x32, 0x5f, 0xa6, 0xf6, 0x01, 0xe6, 0xbe, 0xd4, - 0xcc, 0x55, 0xb9, 0x67, 0xad, 0xac, 0xff, 0xd7, 0x1a, 0x05, 0xc7, 0x49, 0x18, 0x69, 0x05, 0xce, - 0x17, 0xaa, 0x56, 0xaa, 0x55, 0xd0, 0x9a, 0x5e, 0x05, 0x45, 0x9f, 0x42, 0x87, 0x06, 0xa2, 0x89, - 0xe3, 0x3e, 0x4b, 0x67, 0x32, 0x72, 0x5d, 0xca, 0x6a, 0x09, 0x25, 0x8e, 0x34, 0x8e, 0x6d, 0x71, - 0x64, 0x1e, 0xc7, 0x20, 0xc8, 0x00, 0xe8, 0x3f, 0x61, 0x20, 0xe2, 0x85, 0xe7, 0x24, 0xce, 0xc4, - 0x89, 0xf9, 0xa5, 0xe8, 0xca, 0x30, 0x72, 0x4b, 0x40, 0xd1, 0x35, 0x58, 0x2d, 0x20, 0xda, 0x33, - 0x27, 0xd9, 0x17, 0xb6, 0x80, 0x74, 0xec, 0x07, 0x4e, 0xb2, 0x8f, 0x5e, 0x63, 0xbd, 0x98, 0x9c, - 0xee, 0x22, 0xa3, 0x4b, 0x23, 0x9e, 0x44, 0x13, 0x51, 0x48, 0xdd, 0xdc, 0xb7, 0x45, 0xa1, 0xae, - 0x1a, 0x85, 0x5c, 0x7a, 0xba, 0x8a, 0xb8, 0x79, 0x3d, 0x38, 0xe2, 0x60, 0x51, 0xe7, 0x15, 0x1a, - 0x96, 0x40, 0x56, 0xe4, 0xa5, 0x82, 0x4b, 0x24, 0x51, 0x95, 0xe1, 0x35, 0x81, 0xbe, 0x04, 0x8b, - 0xf2, 0xee, 0x32, 0x0c, 0xf6, 0xf6, 0xd3, 0xc4, 0x0b, 0x0f, 0x65, 0xa3, 0x81, 0xbe, 0x0d, 0x73, - 0x90, 0x38, 0xed, 0xff, 0x86, 0xf5, 0xbd, 0x74, 0x12, 0xbb, 0x91, 0x3f, 0xc1, 0xfa, 0x0b, 0x7f, - 0x0c, 0x6d, 0x7c, 0xe4, 0xc7, 0x89, 0x4f, 0x9e, 0x32, 0xb1, 0xda, 0x56, 0x36, 0x36, 0x3f, 0x80, - 0xb5, 0x6c, 0x15, 0xf5, 0x3e, 0xb1, 0xd2, 0x74, 0x92, 0x0f, 0xf3, 0xc4, 0x79, 0x26, 0x72, 0xac, - 0xb6, 0xa5, 0x03, 0xcd, 0x5f, 0x1b, 0xd0, 0x51, 0x9c, 0xd6, 0x77, 0x2c, 0x63, 0xaa, 0x17, 0xa8, - 0x5e, 0x08, 0xd0, 0xc5, 0x12, 0x67, 0xa3, 0xa2, 0xc4, 0x79, 0x01, 0xfa, 0xc2, 0x4b, 0xda, 0x11, - 0x76, 0xe2, 0x50, 0x3a, 0x88, 0x02, 0xd4, 0xfc, 0x73, 0x9d, 0xef, 0x56, 0x38, 0x76, 0x74, 0xba, - 0xb4, 0xdb, 0x16, 0x1b, 0xdf, 0xd1, 0x33, 0xe9, 0x5a, 0x21, 0x93, 0x3e, 0x31, 0x67, 0x98, 0x57, - 0x6b, 0xa5, 0x8e, 0x30, 0x62, 0xa5, 0x2f, 0xb1, 0x39, 0x31, 0xa2, 0x0f, 0x3e, 0xfe, 0xf4, 0xb2, - 0x23, 0xec, 0x62, 0xff, 0x00, 0x7b, 0x2c, 0x8f, 0x6a, 0x58, 0x45, 0x30, 0x4d, 0xe0, 0x04, 0x28, - 0xc6, 0x24, 0x61, 0xe9, 0x54, 0xc3, 0x52, 0x41, 0x25, 0x65, 0x41, 0x85, 0xb2, 0x2e, 0x43, 0x23, - 0x0a, 0x03, 0x3c, 0xea, 0xb0, 0xdc, 0x65, 0x54, 0x11, 0xf0, 0x36, 0xac, 0x30, 0xc0, 0x16, 0xc3, - 0xa2, 0x29, 0xa1, 0xf4, 0x99, 0xf9, 0xfe, 0xba, 0x8c, 0x6c, 0x79, 0x82, 0x1a, 0x4d, 0x06, 0x64, - 0x7b, 0xec, 0xf1, 0x0e, 0x81, 0x06, 0xa4, 0xef, 0xb0, 0xc8, 0x9e, 0x45, 0xd8, 0x9f, 0x3a, 0x4f, - 0xf1, 0xa8, 0xcf, 0x50, 0x14, 0x48, 0x9e, 0xc5, 0x0d, 0x94, 0x2c, 0xce, 0x3c, 0x0b, 0x0d, 0xba, - 0x2f, 0xb4, 0x04, 0xcd, 0x87, 0x37, 0x3f, 0xdd, 0xb1, 0x86, 0x0b, 0xf4, 0xf3, 0x2e, 0xfb, 0x34, - 0xcc, 0x6d, 0xe8, 0x3d, 0x8c, 0x1c, 0xcf, 0x27, 0x4f, 0x77, 0xfd, 0xa9, 0x9f, 0xd0, 0xb3, 0x6d, - 0xdd, 0x75, 0x8e, 0xf6, 0x70, 0x10, 0xc8, 0xb7, 0xd5, 0xd4, 0x39, 0xb2, 0xe9, 0x13, 0x04, 0x9d, - 0x82, 0xc5, 0xbb, 0xce, 0xd1, 0x56, 0x2a, 0xbd, 0x75, 0x8b, 0xce, 0x4c, 0xd2, 0x63, 0xf3, 0x77, - 0x06, 0x34, 0x59, 0x3d, 0x83, 0xbe, 0x67, 0xa6, 0xd4, 0xc0, 0xed, 0xf9, 0xef, 0x0b, 0x4b, 0xc5, - 0x40, 0x9b, 0xd0, 0x49, 0x94, 0x05, 0xb5, 0xaa, 0x05, 0x7d, 0x05, 0x83, 0x5a, 0x4b, 0x6e, 0x11, - 0x75, 0xcd, 0x22, 0x4e, 0xb2, 0x22, 0xc5, 0xf6, 0x9a, 0x7a, 0x0c, 0xd8, 0x84, 0x55, 0x4d, 0x03, - 0x2f, 0x12, 0x05, 0x7f, 0x63, 0xc0, 0x5a, 0x61, 0x91, 0x70, 0x61, 0x37, 0x61, 0x91, 0x95, 0x83, - 0x64, 0xee, 0xf8, 0xa6, 0x5a, 0xef, 0x29, 0xa1, 0x6f, 0xf0, 0xa1, 0x28, 0xa5, 0xf1, 0x85, 0xe3, - 0x07, 0xd0, 0x51, 0xc0, 0x15, 0x7e, 0xf5, 0x2d, 0xbd, 0x94, 0xb6, 0x56, 0xcd, 0x42, 0x71, 0xb7, - 0x9f, 0x41, 0xf7, 0x11, 0x99, 0x7c, 0x87, 0x7e, 0x2b, 0x3a, 0x0b, 0x4b, 0x11, 0x16, 0x4f, 0x17, - 0xe1, 0x66, 0x73, 0x80, 0x39, 0x80, 0x9e, 0xa0, 0x9b, 0x37, 0x06, 0x1f, 0x91, 0x20, 0x74, 0x9f, - 0xbd, 0x68, 0x63, 0xf0, 0x2b, 0x03, 0x90, 0xba, 0x22, 0x0f, 0x04, 0x29, 0x83, 0x16, 0x02, 0x81, - 0x04, 0xca, 0x40, 0x90, 0x21, 0xe9, 0x81, 0x40, 0x82, 0x79, 0x20, 0x40, 0xaf, 0x42, 0x47, 0xa5, - 0xc5, 0xdb, 0x0e, 0x90, 0x53, 0x32, 0x7f, 0x66, 0xc0, 0xe0, 0x73, 0x3f, 0xd9, 0xf7, 0x22, 0xe7, - 0xf0, 0x05, 0x8e, 0x9f, 0x3a, 0x14, 0x0f, 0xd3, 0x38, 0xc0, 0x8a, 0xd3, 0xc2, 0xcf, 0xa9, 0xa0, - 0xb9, 0x75, 0xa4, 0x21, 0xd4, 0x9d, 0x20, 0x10, 0xef, 0x4e, 0xfa, 0x49, 0x21, 0x4f, 0x30, 0x16, - 0x4d, 0x0d, 0xfa, 0x69, 0xde, 0x80, 0x61, 0xbe, 0x19, 0xa1, 0x90, 0x0b, 0xd0, 0x4f, 0x22, 0x87, - 0xc4, 0x8e, 0x4b, 0xc9, 0xe7, 0x7e, 0xb7, 0x00, 0xbd, 0x74, 0x0e, 0x96, 0xb2, 0xc7, 0x14, 0x6a, - 0x41, 0x7d, 0xeb, 0xd1, 0xff, 0x0f, 0x17, 0x50, 0x1b, 0x1a, 0x7b, 0x3b, 0xbb, 0xbb, 0x43, 0x63, - 0xf3, 0x6f, 0x06, 0xb4, 0x1e, 0xa7, 0xde, 0x1d, 0xe2, 0x27, 0x68, 0x07, 0x20, 0xef, 0xc9, 0xa2, - 0xd3, 0x59, 0x2a, 0x5b, 0xec, 0xec, 0x8e, 0xc7, 0x55, 0x53, 0xe2, 0xc4, 0x17, 0xd0, 0x6d, 0xe8, - 0x28, 0xb1, 0x1c, 0x8d, 0xe7, 0xe7, 0x33, 0xe3, 0x33, 0x95, 0x73, 0x19, 0xa5, 0x1d, 0x80, 0xdc, - 0x16, 0xf2, 0x0d, 0x95, 0x2c, 0x2a, 0xdf, 0x50, 0xd9, 0x74, 0xcc, 0x85, 0xcd, 0x6f, 0xd6, 0xa0, - 0xfe, 0x38, 0xf5, 0xd0, 0x63, 0xe8, 0x28, 0xff, 0x89, 0xa0, 0x52, 0x8d, 0x3f, 0xdf, 0x4e, 0xd5, - 0xef, 0x24, 0xe3, 0x2f, 0xff, 0xf8, 0xf7, 0xaf, 0x6b, 0xab, 0xe6, 0xe0, 0xea, 0xc1, 0x7f, 0x5d, - 0x75, 0x3c, 0x4f, 0x1e, 0xfe, 0x0d, 0xe3, 0x12, 0xb2, 0xa0, 0x25, 0x7e, 0x05, 0x41, 0xeb, 0x0a, - 0x0d, 0x25, 0xe7, 0x1c, 0x9f, 0x2a, 0xc1, 0x05, 0xdd, 0x75, 0x46, 0x77, 0x68, 0x76, 0x04, 0x5d, - 0xea, 0x86, 0x28, 0xcd, 0x2d, 0xa8, 0x6f, 0x39, 0x04, 0xa1, 0xbc, 0x37, 0x27, 0xaf, 0xeb, 0x78, - 0x45, 0x83, 0x09, 0x3a, 0x88, 0xd1, 0xe9, 0x9a, 0x2d, 0x4a, 0x67, 0xe2, 0x10, 0x4a, 0xc3, 0x85, - 0xae, 0xda, 0xf0, 0x47, 0x79, 0x8b, 0xba, 0xfc, 0xe7, 0xc1, 0xf8, 0x6c, 0xf5, 0xa4, 0x20, 0x3f, - 0x62, 0xe4, 0x91, 0x39, 0xa4, 0xe4, 0xd9, 0x2f, 0x0c, 0xe2, 0x61, 0x43, 0x85, 0x17, 0xff, 0x03, - 0xe4, 0xc2, 0xeb, 0xbf, 0x13, 0xe4, 0xc2, 0x17, 0x7f, 0x1c, 0xd0, 0x84, 0x17, 0x5e, 0x44, 0x28, - 0x54, 0xb4, 0xa0, 0x73, 0x9a, 0x7a, 0x07, 0x3b, 0xa7, 0x59, 0xe8, 0x55, 0xeb, 0x34, 0x3d, 0x3e, - 0x49, 0x69, 0xfe, 0x10, 0x7a, 0x5a, 0x9f, 0x19, 0x65, 0x02, 0x57, 0x35, 0xb0, 0xc7, 0xaf, 0xcc, - 0x99, 0x15, 0x5c, 0xce, 0x32, 0x2e, 0xeb, 0xe6, 0x32, 0xe3, 0x22, 0x50, 0x58, 0x67, 0x9a, 0xf2, - 0x7a, 0x0c, 0x90, 0xf7, 0x6b, 0x73, 0xcb, 0x2d, 0xf5, 0x88, 0x73, 0xcb, 0x2d, 0xb7, 0x77, 0xcd, - 0x15, 0xc6, 0xa2, 0x87, 0x3a, 0xfc, 0x44, 0x39, 0xad, 0x5d, 0x68, 0x89, 0xde, 0x64, 0xae, 0x19, - 0xbd, 0x41, 0x9b, 0x6b, 0xa6, 0xd0, 0xc4, 0x34, 0x87, 0x8c, 0x20, 0xa0, 0x36, 0x25, 0xe8, 0x53, - 0x12, 0xdf, 0x87, 0x8e, 0xd2, 0x82, 0x43, 0xea, 0x6e, 0x0a, 0x7d, 0xbd, 0xfc, 0x72, 0x54, 0xf4, - 0xec, 0xcc, 0x55, 0x46, 0xb9, 0x8f, 0xba, 0x94, 0x32, 0xd5, 0x02, 0xa3, 0xfe, 0x39, 0x40, 0xde, - 0x2d, 0xca, 0xb5, 0x50, 0x6a, 0x7b, 0xe5, 0x5a, 0x28, 0x37, 0x97, 0xa4, 0x5d, 0x23, 0xa0, 0xa4, - 0x45, 0x95, 0xf4, 0x29, 0xf4, 0xf5, 0x66, 0x1e, 0x7a, 0x45, 0xa5, 0x50, 0xea, 0xfe, 0x8d, 0xcf, - 0xcd, 0x9b, 0xd6, 0x6d, 0x06, 0xf5, 0x99, 0x1d, 0xe6, 0x64, 0xf7, 0x60, 0x29, 0x6b, 0x33, 0xa1, - 0x91, 0x4a, 0x44, 0xed, 0x46, 0x8d, 0x4f, 0x57, 0xcc, 0x08, 0xca, 0xcb, 0x8c, 0x72, 0x07, 0x2d, - 0x51, 0xca, 0xbc, 0x7e, 0x28, 0x89, 0xb2, 0x4e, 0xb6, 0x4e, 0x54, 0xe9, 0x51, 0x15, 0x88, 0xaa, - 0x9d, 0xaa, 0x02, 0x51, 0x46, 0xe7, 0x0b, 0xae, 0x6b, 0xde, 0x6d, 0xd2, 0x75, 0xad, 0x35, 0xab, - 0x74, 0x5d, 0xeb, 0xcd, 0x29, 0xf3, 0x34, 0xa3, 0xbb, 0x62, 0x32, 0x35, 0x04, 0x7e, 0x9c, 0xf0, - 0x6e, 0x14, 0xb5, 0x68, 0x1b, 0x3a, 0x4a, 0x3b, 0x23, 0xb7, 0x94, 0x72, 0xe7, 0x25, 0xb7, 0x94, - 0xaa, 0xfe, 0xc7, 0x29, 0xc6, 0x62, 0x99, 0xbb, 0xd1, 0x70, 0x86, 0x89, 0x74, 0x23, 0x3f, 0x00, - 0xc8, 0x2b, 0x50, 0xb9, 0x00, 0xa5, 0xda, 0x64, 0x6e, 0xde, 0x85, 0x82, 0x95, 0xbe, 0x7b, 0x56, - 0x15, 0x64, 0xe6, 0x72, 0xc3, 0xb8, 0x74, 0xcd, 0x40, 0x4f, 0xa0, 0x9f, 0xe3, 0xef, 0x1d, 0x13, - 0xf7, 0x24, 0x16, 0xe3, 0xaa, 0x29, 0x21, 0xc0, 0x2b, 0x8c, 0xcb, 0x29, 0x13, 0xe9, 0x5c, 0xe2, - 0x63, 0xe2, 0x52, 0x3d, 0x7d, 0x0f, 0x3a, 0xca, 0x5f, 0x29, 0xb9, 0x9e, 0xca, 0xbf, 0xaa, 0x8c, - 0xab, 0x6a, 0x64, 0x7a, 0x98, 0xc1, 0x7c, 0x51, 0x7c, 0xe8, 0xcc, 0x28, 0x6d, 0x02, 0x7d, 0xbd, - 0xd6, 0x92, 0x9b, 0x7d, 0x65, 0xe1, 0x26, 0x37, 0xfb, 0x39, 0x25, 0x1a, 0x4d, 0x16, 0x56, 0xa7, - 0xc7, 0x6a, 0x58, 0x9b, 0xd0, 0x48, 0x9e, 0xd5, 0x5c, 0xd4, 0x48, 0x5e, 0x2c, 0xeb, 0xa8, 0x91, - 0xbc, 0x54, 0xa4, 0xd1, 0x65, 0xe2, 0x6c, 0xe4, 0xc9, 0x50, 0xbb, 0xcd, 0x2b, 0x2e, 0xf9, 0x99, - 0x94, 0x8a, 0x36, 0xe3, 0x71, 0xd5, 0x54, 0x95, 0xdd, 0x72, 0x06, 0x32, 0x8c, 0x7e, 0x06, 0x6d, - 0xf9, 0xc2, 0x47, 0x99, 0xe5, 0x14, 0xca, 0x00, 0xe3, 0x51, 0x79, 0xa2, 0x60, 0xae, 0xcc, 0xb1, - 0xc5, 0x62, 0x96, 0xd2, 0xc5, 0x30, 0x28, 0x54, 0x09, 0x50, 0xa6, 0xed, 0xea, 0xf2, 0xc1, 0x58, - 0xff, 0x0d, 0x85, 0xb7, 0x5e, 0xcc, 0x33, 0x8c, 0xc1, 0x1a, 0x5a, 0x61, 0x0c, 0xe4, 0x42, 0x6e, - 0x52, 0xd7, 0x0c, 0x34, 0x81, 0xbe, 0x5e, 0x56, 0xc8, 0x8f, 0xbc, 0xb2, 0xdc, 0x70, 0xa2, 0x51, - 0x21, 0xa4, 0x31, 0xa1, 0x66, 0x45, 0x79, 0xcc, 0x0a, 0xa5, 0x0b, 0x51, 0x83, 0x78, 0x39, 0x56, - 0x62, 0x91, 0xf9, 0x1a, 0x63, 0x75, 0x06, 0x9d, 0x2e, 0xb1, 0x92, 0xc5, 0xe6, 0x6b, 0x06, 0x7a, - 0x5a, 0x7c, 0x64, 0x9e, 0x9d, 0xf3, 0x2a, 0x2a, 0x84, 0xe2, 0xca, 0x37, 0x93, 0x3c, 0x7d, 0xc4, - 0x42, 0x71, 0xc2, 0x51, 0xf8, 0xd3, 0x09, 0x7d, 0x02, 0x4d, 0xf6, 0x20, 0x41, 0xab, 0x79, 0x86, - 0x98, 0xbf, 0x7b, 0xc6, 0x6b, 0x05, 0xa8, 0x1e, 0xcd, 0x4c, 0xe6, 0x5e, 0x53, 0x22, 0x92, 0xa9, - 0xcf, 0xa0, 0x2d, 0xd3, 0xf0, 0xdc, 0x92, 0x0a, 0xaf, 0x84, 0xdc, 0x92, 0x8a, 0x19, 0xbb, 0x6e, - 0x49, 0x87, 0x62, 0xf6, 0x86, 0x71, 0x69, 0xb2, 0xc8, 0xfe, 0x62, 0x7e, 0xfb, 0x9f, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x9d, 0xa6, 0x7e, 0x1c, 0xf0, 0x2c, 0x00, 0x00, + // 3688 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x3a, 0x4b, 0x8f, 0xdc, 0x46, + 0x73, 0xcb, 0x79, 0xec, 0xcc, 0xd6, 0x3c, 0xb7, 0xf7, 0xa1, 0xd1, 0x48, 0xd6, 0x27, 0x33, 0xb6, + 0x22, 0xcb, 0xd2, 0x4a, 0x59, 0xc7, 0xb1, 0x25, 0xc7, 0x86, 0xb5, 0xab, 0x8d, 0x25, 0x7b, 0xf5, + 0x00, 0x57, 0xb2, 0x95, 0x20, 0x31, 0xc1, 0x21, 0x5b, 0x5a, 0x46, 0x9c, 0xe6, 0x98, 0x8f, 0x7d, + 0xe4, 0x14, 0xd8, 0x40, 0x0e, 0xc9, 0xd1, 0x39, 0x1a, 0x48, 0x4e, 0xb9, 0x38, 0xf7, 0x00, 0x39, + 0xe5, 0x9c, 0x6b, 0x80, 0x20, 0x87, 0x00, 0x41, 0x80, 0xfc, 0x82, 0xfc, 0x82, 0xa0, 0x5f, 0xec, + 0x6e, 0x0e, 0x67, 0x2d, 0x19, 0xf9, 0x6e, 0xec, 0xea, 0xea, 0xaa, 0xae, 0xea, 0xea, 0xaa, 0xea, + 0x2a, 0x42, 0xf7, 0x24, 0x0f, 0x92, 0x99, 0xbf, 0x35, 0x4b, 0xe2, 0x2c, 0x46, 0xcb, 0x7c, 0x34, + 0x5e, 0xf5, 0x08, 0x89, 0x33, 0x2f, 0x0b, 0x63, 0x92, 0xf2, 0x29, 0x7b, 0x03, 0xd6, 0xee, 0x06, + 0xc1, 0x6e, 0x9e, 0x24, 0x98, 0xf8, 0xa7, 0x0e, 0x4e, 0x67, 0x31, 0x49, 0xb1, 0xfd, 0x2d, 0xf4, + 0xef, 0x06, 0xc1, 0x13, 0x2f, 0x4c, 0x1c, 0xfc, 0x5d, 0x8e, 0xd3, 0x0c, 0xbd, 0x03, 0xbd, 0x89, + 0x97, 0x62, 0xd7, 0x17, 0xa8, 0x23, 0xeb, 0xb2, 0x75, 0x75, 0xc5, 0x31, 0x81, 0xe8, 0x0a, 0xf4, + 0xbf, 0xcb, 0xe3, 0x4c, 0x43, 0xab, 0x31, 0xb4, 0x12, 0xd4, 0x5e, 0x85, 0x41, 0x41, 0x5f, 0xb0, + 0xfc, 0xa7, 0x1a, 0xb4, 0x76, 0xbc, 0xc8, 0x23, 0x3e, 0xa6, 0xcc, 0xb2, 0x38, 0xf3, 0x22, 0x77, + 0xc2, 0x01, 0x8c, 0x59, 0xc3, 0x31, 0x81, 0xe8, 0x2a, 0x0c, 0xfc, 0x43, 0x8f, 0x10, 0xac, 0xf0, + 0x6a, 0x0c, 0xaf, 0x0c, 0x46, 0x1f, 0xc3, 0xb9, 0x19, 0x26, 0x41, 0x48, 0x5e, 0xba, 0xe5, 0x15, + 0x75, 0xb6, 0x62, 0xd1, 0x34, 0xba, 0x03, 0xa3, 0x90, 0x78, 0x7e, 0x16, 0x1e, 0xe1, 0xb9, 0xa5, + 0x0d, 0xb6, 0x74, 0xe1, 0x3c, 0x55, 0xc6, 0xb1, 0x17, 0x45, 0x38, 0x2b, 0x56, 0x34, 0xd9, 0x8a, + 0x12, 0x14, 0x7d, 0x06, 0xe3, 0x9c, 0xf8, 0x31, 0x79, 0x11, 0x26, 0x53, 0x1c, 0xb8, 0xa5, 0x35, + 0xcb, 0x6c, 0xcd, 0x19, 0x18, 0xf6, 0x1f, 0x00, 0xec, 0x78, 0x44, 0x1e, 0xd4, 0x55, 0x18, 0x90, + 0x38, 0xc0, 0x6e, 0x18, 0x60, 0x92, 0x85, 0x2f, 0x42, 0x9c, 0x88, 0xa3, 0x2a, 0x83, 0xed, 0x1e, + 0x74, 0xd8, 0x3a, 0x71, 0x00, 0x1f, 0x41, 0x73, 0xf7, 0xd0, 0x0b, 0x09, 0x5a, 0x87, 0xa6, 0x4f, + 0x3f, 0xc4, 0x3a, 0x3e, 0x40, 0x23, 0x68, 0x11, 0x9c, 0x1d, 0xc7, 0xc9, 0x2b, 0x71, 0xa6, 0x72, + 0x68, 0xcf, 0xa0, 0xbd, 0xcb, 0x45, 0x4f, 0xd1, 0x26, 0x2c, 0x73, 0x6d, 0xb0, 0xc5, 0x3d, 0x47, + 0x8c, 0xd0, 0x18, 0xda, 0x52, 0x4f, 0x6c, 0x79, 0xcf, 0x29, 0xc6, 0x94, 0xb2, 0x50, 0x3f, 0x3b, + 0x8d, 0x9e, 0x23, 0x87, 0x94, 0x9a, 0x1f, 0xc5, 0x29, 0x0e, 0x98, 0xae, 0x7b, 0x8e, 0x18, 0xd9, + 0x3f, 0x5b, 0xb0, 0xb6, 0x4b, 0x3f, 0x05, 0xdf, 0x37, 0x96, 0x9d, 0xee, 0xa7, 0x64, 0xa2, 0xc5, + 0x98, 0xca, 0xff, 0x22, 0x4e, 0x84, 0x6d, 0xb4, 0x1d, 0x3e, 0x40, 0x97, 0xa1, 0x13, 0xe0, 0x34, + 0x0b, 0x09, 0xbb, 0x3f, 0x6c, 0x43, 0x2b, 0x8e, 0x0e, 0x62, 0xb2, 0x4f, 0xe3, 0x9c, 0x64, 0xe2, + 0x9c, 0xc5, 0xc8, 0xde, 0x84, 0x75, 0x73, 0xb3, 0x42, 0xe1, 0xd7, 0xa1, 0xbf, 0x1b, 0x13, 0x82, + 0xfd, 0x4c, 0xee, 0x7f, 0x0c, 0x6d, 0xb6, 0xd1, 0x3c, 0x09, 0xc5, 0xc6, 0x8b, 0x31, 0xbd, 0x32, + 0x05, 0xb6, 0x20, 0x70, 0x13, 0x56, 0x77, 0x13, 0xec, 0x65, 0xf8, 0x51, 0x1c, 0x60, 0x8d, 0xc6, + 0xcc, 0x4b, 0xd3, 0xe3, 0x38, 0x09, 0x24, 0x0d, 0x39, 0xb6, 0x7f, 0xb4, 0x00, 0xe9, 0x2b, 0x38, + 0x1d, 0xf4, 0x3b, 0xd0, 0x4b, 0x31, 0x0e, 0xdc, 0x29, 0xc1, 0xd3, 0x98, 0x84, 0xfe, 0xc8, 0xba, + 0x5c, 0xbf, 0xba, 0xe2, 0x74, 0x29, 0xf0, 0xa1, 0x80, 0xa1, 0xf7, 0x60, 0x18, 0x92, 0x30, 0x0b, + 0xbd, 0x28, 0xfc, 0x0b, 0x1c, 0xb8, 0x11, 0x09, 0xd2, 0x51, 0x8d, 0xe1, 0x0d, 0x34, 0xf8, 0x3e, + 0x09, 0x52, 0x74, 0x03, 0x90, 0x8e, 0x9a, 0x78, 0x54, 0xf1, 0x42, 0x9b, 0xab, 0xda, 0x8c, 0xc3, + 0x26, 0xec, 0x7f, 0xb7, 0xa0, 0x2d, 0x3d, 0x90, 0x71, 0x30, 0x56, 0xe9, 0x60, 0x3e, 0x85, 0x4e, + 0x7a, 0xec, 0xcd, 0x5c, 0x3f, 0x0a, 0x31, 0xc9, 0xd8, 0xb9, 0xf5, 0xb7, 0x2f, 0x6c, 0x09, 0x5f, + 0x27, 0x49, 0x6c, 0x1d, 0x1c, 0x7b, 0xb3, 0x5d, 0x86, 0xe2, 0xe8, 0xf8, 0xdc, 0xab, 0xbc, 0xc2, + 0xc4, 0xf5, 0x82, 0x20, 0xc1, 0x69, 0xca, 0x76, 0xb4, 0xe2, 0x98, 0x40, 0x7a, 0x6b, 0x03, 0xec, + 0x87, 0x53, 0x2f, 0x72, 0x67, 0x91, 0xe7, 0xe3, 0x54, 0xd8, 0x5e, 0x09, 0x6a, 0xbf, 0x0d, 0xa0, + 0x18, 0xa1, 0x16, 0xd4, 0xf7, 0x1f, 0xdd, 0x1b, 0x2e, 0x21, 0x80, 0x65, 0xe7, 0xee, 0x83, 0x7b, + 0x7b, 0x8f, 0x86, 0x16, 0x3d, 0xe0, 0x7b, 0x78, 0x16, 0xa7, 0xa1, 0x7e, 0xc0, 0x8b, 0xa4, 0xb3, + 0xdf, 0x87, 0x41, 0x81, 0x2d, 0x0e, 0x66, 0x04, 0x2d, 0xb9, 0x57, 0x8e, 0x2d, 0x87, 0xf6, 0xe7, + 0xb0, 0x7e, 0x2f, 0x4c, 0xfd, 0xf8, 0x08, 0x27, 0xf4, 0x28, 0xd3, 0x37, 0xbf, 0xfd, 0x1f, 0xc2, + 0x46, 0x89, 0x82, 0x60, 0x7a, 0x11, 0x56, 0x48, 0x3e, 0x75, 0x29, 0x7e, 0x2a, 0x6e, 0xb1, 0x02, + 0xd8, 0x7f, 0x6d, 0x01, 0xda, 0x3b, 0xc1, 0x7e, 0x9e, 0x61, 0x2a, 0xbe, 0x26, 0x58, 0x9c, 0x04, + 0x38, 0x71, 0xc3, 0xc2, 0xea, 0xe4, 0x98, 0xdd, 0x6f, 0x2f, 0x64, 0x53, 0xc2, 0x73, 0x88, 0x21, + 0xb2, 0xa1, 0x3b, 0xc3, 0x38, 0x71, 0x67, 0xf9, 0xc4, 0x7d, 0x85, 0x4f, 0xc5, 0x81, 0x18, 0x30, + 0x4a, 0xf9, 0xbb, 0xdc, 0x23, 0x59, 0x98, 0x9d, 0x0a, 0x8f, 0x5b, 0x8c, 0xe9, 0x05, 0xf8, 0x02, + 0x67, 0x22, 0x6a, 0xbc, 0x8e, 0x8e, 0xff, 0xc1, 0x02, 0xa4, 0xaf, 0x10, 0x22, 0xef, 0x40, 0x5b, + 0x38, 0xd3, 0x94, 0xd9, 0x7e, 0x67, 0xfb, 0xaa, 0xb4, 0xaa, 0x79, 0xec, 0x2d, 0x31, 0x4e, 0xf7, + 0x48, 0x96, 0x9c, 0x3a, 0xcb, 0x4c, 0xce, 0x74, 0xbc, 0x0f, 0x3d, 0x63, 0x02, 0x0d, 0xa1, 0x4e, + 0x65, 0xe2, 0x5b, 0xa0, 0x9f, 0xe8, 0x5d, 0x68, 0x1e, 0x79, 0x51, 0xce, 0x3d, 0x60, 0x67, 0x7b, + 0x20, 0x79, 0x48, 0x06, 0x7c, 0xf6, 0x4e, 0xed, 0x63, 0xcb, 0x1e, 0x42, 0xff, 0x0b, 0x9c, 0x3d, + 0x20, 0x2f, 0x62, 0x21, 0x96, 0xfd, 0x57, 0x0d, 0x18, 0x14, 0x20, 0x65, 0x1f, 0x47, 0x38, 0x49, + 0xa9, 0x3f, 0x12, 0xf6, 0x21, 0x86, 0x54, 0xb3, 0xec, 0xc0, 0xa5, 0x66, 0xb9, 0xe2, 0x0d, 0x18, + 0x42, 0xd0, 0xc8, 0x93, 0x90, 0x5e, 0x03, 0x7a, 0x8b, 0xd9, 0xb7, 0x3c, 0x7c, 0x7a, 0x02, 0xd2, + 0xf0, 0x15, 0xa0, 0x98, 0xf5, 0xc2, 0x24, 0x65, 0x4e, 0x4e, 0xce, 0x52, 0x00, 0x7a, 0x1f, 0x84, + 0x2e, 0x58, 0xcc, 0xea, 0x6c, 0xaf, 0x49, 0xf9, 0x1e, 0x33, 0xe8, 0x2e, 0x75, 0x86, 0x52, 0x5d, + 0x68, 0x1b, 0xea, 0x11, 0x09, 0x46, 0x2d, 0xa6, 0xed, 0xcb, 0x9a, 0xb6, 0x75, 0x01, 0xb7, 0xf6, + 0x49, 0xc0, 0xb5, 0x4c, 0x91, 0xd1, 0x35, 0x58, 0x16, 0xbe, 0xa4, 0xcd, 0x18, 0x20, 0xb9, 0x8c, + 0x3b, 0x12, 0xb6, 0x52, 0x60, 0x50, 0x27, 0xee, 0x45, 0xa1, 0x97, 0x8e, 0x56, 0x78, 0x10, 0x63, + 0x03, 0x3d, 0x88, 0x81, 0x11, 0xc4, 0xd0, 0x2d, 0x58, 0x93, 0x39, 0x00, 0xf3, 0x19, 0x87, 0x5e, + 0x7a, 0x88, 0xd3, 0x51, 0x87, 0xe9, 0xa6, 0x6a, 0x0a, 0xdd, 0x80, 0x96, 0x4f, 0x1d, 0xf2, 0x49, + 0x36, 0xea, 0x9a, 0xf2, 0xee, 0x72, 0x30, 0xdb, 0x8f, 0xc4, 0x19, 0x7f, 0x01, 0x6d, 0x29, 0xcd, + 0x1b, 0x98, 0xc6, 0x3e, 0x09, 0x18, 0x19, 0xcd, 0x34, 0x3e, 0x63, 0x26, 0x4c, 0xef, 0xac, 0x66, + 0x1e, 0x6f, 0x70, 0xf1, 0x1d, 0x58, 0x33, 0xd6, 0x17, 0x41, 0x60, 0x90, 0xe0, 0x59, 0xce, 0xd3, + 0xc3, 0x03, 0x3f, 0x4e, 0x78, 0x08, 0x5f, 0x75, 0x40, 0x81, 0x69, 0x88, 0x9b, 0xd0, 0x20, 0xc6, + 0x6f, 0x72, 0xdb, 0x11, 0x23, 0xfb, 0x1c, 0x6c, 0xec, 0x87, 0x69, 0x26, 0x5c, 0x70, 0x58, 0xf8, + 0x23, 0xfb, 0x4b, 0xd8, 0x2c, 0x4f, 0x08, 0x7e, 0xb7, 0x00, 0xfc, 0x02, 0x2a, 0x6e, 0xdd, 0xb0, + 0xec, 0xcb, 0x1d, 0x0d, 0xc7, 0xfe, 0x57, 0x0b, 0x56, 0x29, 0x31, 0x6e, 0x4e, 0x52, 0x70, 0xcd, + 0xbb, 0x58, 0xa6, 0x77, 0xf9, 0x10, 0x9a, 0xf1, 0x31, 0xc1, 0x89, 0x08, 0x14, 0xbf, 0x29, 0x74, + 0x5a, 0xa6, 0xb1, 0xf5, 0x98, 0xa2, 0x39, 0x1c, 0x9b, 0x5a, 0x4e, 0x14, 0x4e, 0xc3, 0x4c, 0x24, + 0x23, 0x7c, 0x40, 0xf5, 0x1b, 0x12, 0x3f, 0xca, 0x03, 0xec, 0x32, 0x53, 0x12, 0x71, 0xa1, 0xed, + 0x94, 0xc1, 0xf6, 0x3b, 0xd0, 0x64, 0xf4, 0x50, 0x1b, 0x1a, 0x3b, 0x8f, 0x9f, 0xde, 0x1f, 0x2e, + 0xd1, 0xe8, 0xf0, 0xf8, 0x9b, 0x47, 0x43, 0x8b, 0x82, 0x9e, 0xec, 0xed, 0x39, 0xc3, 0x9a, 0xfd, + 0x77, 0x16, 0x20, 0x7d, 0x23, 0x42, 0x2b, 0x9f, 0x15, 0x77, 0x88, 0x6b, 0xe4, 0x4a, 0xd5, 0xa6, + 0xc5, 0xe5, 0xe0, 0x43, 0xd3, 0x0b, 0x3d, 0x80, 0x8e, 0x06, 0xae, 0x30, 0xb4, 0x77, 0x4c, 0x43, + 0xeb, 0x9b, 0x77, 0x54, 0xb7, 0x33, 0x04, 0x43, 0xca, 0x94, 0x26, 0xe9, 0xc5, 0x71, 0xbe, 0xc7, + 0x4f, 0x40, 0xc0, 0xc4, 0x9e, 0xd7, 0xa1, 0xc9, 0x3d, 0x02, 0x4f, 0x1b, 0xf8, 0xa0, 0x58, 0x8e, + 0x95, 0x9e, 0xed, 0x8f, 0xc4, 0x72, 0xac, 0x8b, 0x6c, 0x43, 0x93, 0xbb, 0x1b, 0x2e, 0x71, 0x57, + 0xee, 0x88, 0x62, 0x39, 0x7c, 0x4a, 0xf2, 0x7d, 0x9a, 0x78, 0x5a, 0xac, 0x2b, 0x0e, 0xca, 0xd2, + 0x0e, 0xca, 0xfe, 0x84, 0xeb, 0x55, 0xa2, 0x0a, 0x26, 0xef, 0xc2, 0x72, 0xc6, 0x20, 0x82, 0x4b, + 0x4f, 0x72, 0x61, 0x78, 0x8e, 0x98, 0xb4, 0xff, 0xd3, 0x82, 0x96, 0xb8, 0x72, 0xd4, 0xd6, 0xd3, + 0xcc, 0xcb, 0x72, 0x19, 0x7b, 0xc5, 0x08, 0x5d, 0x87, 0xb6, 0xc8, 0xf4, 0x53, 0xa1, 0x44, 0x65, + 0xb6, 0x02, 0xee, 0x14, 0x18, 0x94, 0x31, 0xcb, 0x9f, 0xb9, 0x9b, 0xd5, 0x18, 0xb3, 0x5c, 0xdb, + 0x11, 0x93, 0x34, 0xbb, 0x9c, 0x44, 0xb1, 0xff, 0xea, 0x10, 0x87, 0x2f, 0x0f, 0x33, 0xe1, 0x79, + 0x75, 0x50, 0xe1, 0xad, 0x9b, 0x9a, 0xb7, 0xd6, 0xfc, 0xff, 0xb2, 0xe9, 0xff, 0x0b, 0xf7, 0xd7, + 0xd2, 0xdc, 0x9f, 0xfd, 0x25, 0xf4, 0xd9, 0xbd, 0x57, 0x79, 0x70, 0x39, 0x4e, 0x58, 0x15, 0x71, + 0xa2, 0xa0, 0x55, 0xd3, 0x69, 0xfd, 0xad, 0x05, 0xe8, 0xf1, 0x0c, 0x93, 0xdf, 0x4a, 0x0a, 0xae, + 0x52, 0xe9, 0xba, 0x9e, 0x4a, 0x53, 0x35, 0xcd, 0xf2, 0xf4, 0xd0, 0x15, 0x93, 0x3c, 0x1f, 0xd0, + 0x41, 0xf4, 0x41, 0x6b, 0xec, 0x4a, 0xa4, 0xca, 0xff, 0x52, 0x83, 0x26, 0x33, 0x71, 0x66, 0xad, + 0x49, 0x28, 0xde, 0x94, 0x96, 0xc3, 0x07, 0x46, 0x96, 0x51, 0x33, 0xb3, 0x0c, 0xdd, 0xc3, 0xd4, + 0x4d, 0x0f, 0xd3, 0x87, 0x5a, 0x18, 0x88, 0xa7, 0x40, 0x2d, 0x0c, 0xd0, 0xe7, 0xf3, 0xc2, 0x37, + 0x99, 0x85, 0x6c, 0xca, 0x53, 0x37, 0xd5, 0x5f, 0xa9, 0x94, 0x28, 0xf6, 0xbd, 0x88, 0x32, 0xe3, + 0x47, 0x5a, 0x8c, 0xd1, 0x25, 0x00, 0x9f, 0x25, 0xef, 0x81, 0xeb, 0x65, 0xec, 0x60, 0x1b, 0x8e, + 0x06, 0x41, 0xef, 0x42, 0x23, 0x0d, 0x03, 0xcc, 0x82, 0x63, 0x7f, 0x7b, 0xd5, 0xb8, 0xd9, 0x07, + 0x61, 0x80, 0x1d, 0x36, 0x4d, 0x8f, 0x3c, 0x4c, 0xdd, 0xf8, 0x98, 0xb8, 0xcc, 0x67, 0xb0, 0x00, + 0xd9, 0x76, 0x0c, 0x18, 0x35, 0xb6, 0xc3, 0x38, 0x0a, 0x58, 0x90, 0x6c, 0x38, 0xec, 0xdb, 0xfe, + 0x7b, 0x0b, 0xba, 0x8c, 0x96, 0x83, 0xa7, 0xf1, 0x91, 0x17, 0x19, 0x3a, 0xb3, 0x16, 0xeb, 0xac, + 0x94, 0xf3, 0xe9, 0x99, 0x62, 0xbd, 0x94, 0x29, 0xea, 0xd2, 0x37, 0x4a, 0xd2, 0x97, 0xb7, 0xdd, + 0x9c, 0xdf, 0xb6, 0x7d, 0x08, 0xcb, 0xdc, 0x8f, 0xa1, 0x1b, 0x00, 0x93, 0xfc, 0xd4, 0x35, 0x7c, + 0x69, 0xcf, 0xd0, 0x88, 0xa3, 0x21, 0xa0, 0x9b, 0xd0, 0x49, 0x71, 0x14, 0x49, 0xfc, 0x5a, 0x15, + 0xbe, 0x8e, 0x61, 0x7f, 0x20, 0xfd, 0x2c, 0xcb, 0x6a, 0xa8, 0xbe, 0xa8, 0xa3, 0x12, 0x9e, 0x88, + 0x7d, 0x53, 0xdf, 0x1b, 0x1f, 0x13, 0xf1, 0xda, 0xa5, 0x9f, 0xf6, 0xf7, 0x96, 0x58, 0xf5, 0x6c, + 0x16, 0x78, 0x19, 0x75, 0x4a, 0x4d, 0x2e, 0x8b, 0xc5, 0x8c, 0xc4, 0xe4, 0x77, 0x7f, 0xc9, 0xe1, + 0xb3, 0xe8, 0x0f, 0xa1, 0xc7, 0x35, 0x94, 0x70, 0xc5, 0x0b, 0xaf, 0xb3, 0x6e, 0x6e, 0x8f, 0xcf, + 0xdd, 0x5f, 0x72, 0x4c, 0xe4, 0x9d, 0x3e, 0x74, 0x39, 0x20, 0x67, 0x4c, 0xed, 0x1f, 0xea, 0xd0, + 0xa0, 0xae, 0x75, 0xf1, 0xe3, 0xe2, 0xb5, 0x92, 0xc7, 0xcf, 0xa1, 0x1b, 0x91, 0x40, 0x0e, 0xa5, + 0x77, 0xbb, 0xa8, 0x3b, 0x6f, 0x9a, 0xbc, 0x3c, 0xc9, 0x27, 0x5f, 0xe1, 0x53, 0x11, 0xa4, 0x8c, + 0x15, 0x94, 0x7f, 0x48, 0x26, 0x71, 0x4e, 0x02, 0x11, 0x49, 0xe5, 0x50, 0x05, 0x94, 0xa6, 0x16, + 0x50, 0xe8, 0xdd, 0x3f, 0xc9, 0x03, 0xd7, 0x74, 0x78, 0x3a, 0x08, 0x5d, 0x87, 0xd5, 0x14, 0xfb, + 0x31, 0x09, 0x52, 0xd7, 0xe7, 0x4f, 0x65, 0x1c, 0xb0, 0x7b, 0xd2, 0x73, 0xe6, 0x27, 0xe8, 0x43, + 0x8f, 0xe7, 0x8a, 0xc5, 0x7b, 0xb0, 0xcd, 0x6b, 0x55, 0x26, 0xb4, 0x3a, 0x93, 0x1c, 0x7f, 0x0a, + 0x83, 0x92, 0x78, 0x15, 0xc1, 0x76, 0x5d, 0x0f, 0xb6, 0x2b, 0x7a, 0x70, 0xfd, 0xcb, 0x1a, 0xac, + 0x3e, 0xa1, 0x0f, 0x49, 0x71, 0x78, 0x45, 0x44, 0xfb, 0x7f, 0xf3, 0x4d, 0xfa, 0x3d, 0x6b, 0x94, + 0xee, 0x99, 0xf4, 0x14, 0xcd, 0xb3, 0x3d, 0xc5, 0x35, 0x18, 0x26, 0x98, 0x3d, 0x77, 0xdd, 0x82, + 0x14, 0x57, 0xfb, 0x1c, 0x9c, 0xe6, 0xcf, 0xe1, 0x74, 0x8a, 0x83, 0xd0, 0xcb, 0x28, 0xd4, 0xf5, + 0xe9, 0x8b, 0x26, 0x62, 0xda, 0x6f, 0x3b, 0x55, 0x53, 0x54, 0x05, 0x48, 0x57, 0x81, 0x88, 0xd4, + 0xb7, 0x61, 0x18, 0x92, 0x0c, 0x27, 0xc4, 0x8b, 0xdc, 0xa9, 0x97, 0xf9, 0x87, 0x78, 0xc1, 0xfd, + 0x9d, 0x43, 0x43, 0x9f, 0x40, 0x9f, 0x25, 0xe8, 0x69, 0xee, 0xfb, 0x38, 0xa5, 0x29, 0x1a, 0xbf, + 0xc8, 0x45, 0x62, 0x4e, 0x5f, 0xac, 0x07, 0x7c, 0xd2, 0x29, 0xa1, 0xa2, 0x8f, 0x68, 0xfe, 0x3b, + 0xf5, 0x42, 0x42, 0xf3, 0x7c, 0x7e, 0x2d, 0xeb, 0x15, 0xd7, 0xd2, 0x29, 0x63, 0xa1, 0xdb, 0xd0, + 0x63, 0xa4, 0x5e, 0x78, 0x61, 0x94, 0x27, 0x2c, 0x2f, 0x9c, 0x63, 0xfa, 0x47, 0x7c, 0xce, 0x31, + 0x31, 0xed, 0xff, 0xb5, 0x60, 0xa0, 0x54, 0xb0, 0x77, 0x84, 0x09, 0xf5, 0xe2, 0x4d, 0x26, 0xcf, + 0x42, 0xa7, 0xc0, 0x66, 0xd1, 0x6d, 0xe8, 0xea, 0x02, 0x08, 0x9f, 0x50, 0x25, 0xe9, 0xfd, 0x25, + 0xc7, 0x40, 0x45, 0xb7, 0x5f, 0x4f, 0xd2, 0xfb, 0x4b, 0x55, 0xb2, 0x76, 0x75, 0x09, 0x98, 0x61, + 0x55, 0x8b, 0x5a, 0x70, 0x15, 0xa8, 0x3b, 0x2d, 0x68, 0x62, 0x2a, 0xa0, 0xfd, 0x93, 0x05, 0xa0, + 0x1e, 0x6c, 0x0b, 0xd3, 0x2c, 0xcd, 0x3d, 0xd5, 0x4c, 0xf7, 0xa4, 0x27, 0x60, 0xf5, 0x5f, 0x4c, + 0xc0, 0xb4, 0x1c, 0xa9, 0x31, 0x97, 0x23, 0xf1, 0x3a, 0x67, 0x53, 0xab, 0x73, 0xda, 0x31, 0x74, + 0xb4, 0xf7, 0xdb, 0xaf, 0xd8, 0xde, 0x9b, 0x32, 0xfc, 0x00, 0x36, 0x98, 0xf3, 0xc6, 0xaa, 0x0a, + 0xff, 0xcb, 0x85, 0x8c, 0x11, 0x6c, 0x96, 0x17, 0x89, 0x4c, 0x67, 0x1f, 0x10, 0x9f, 0x31, 0x3c, + 0xcb, 0x59, 0xf5, 0x99, 0x33, 0xfc, 0x8b, 0xfd, 0x21, 0xac, 0x19, 0xd4, 0xc4, 0x25, 0xbd, 0x04, + 0x43, 0x89, 0xe2, 0xc6, 0xc4, 0x65, 0xb9, 0x82, 0xa5, 0xe5, 0x0a, 0x37, 0x60, 0x95, 0x2f, 0xd3, + 0x5b, 0x08, 0x0b, 0x5f, 0x6a, 0xf6, 0xba, 0xdc, 0xb3, 0xd1, 0x11, 0xf8, 0xaf, 0x1a, 0x05, 0xa7, + 0x59, 0x9c, 0x18, 0x05, 0xce, 0xd7, 0xaa, 0x56, 0xea, 0x55, 0xd0, 0x9a, 0x59, 0x05, 0x45, 0x5f, + 0x41, 0x87, 0x06, 0xa2, 0x89, 0xe7, 0xbf, 0xca, 0x67, 0x32, 0x72, 0x5d, 0x2b, 0x6a, 0x09, 0x73, + 0x1c, 0x69, 0x1c, 0xdb, 0xe1, 0xc8, 0x3c, 0x8e, 0x41, 0x54, 0x00, 0xd0, 0xef, 0xc2, 0x40, 0xc4, + 0x8b, 0xc0, 0xcb, 0xbc, 0x89, 0x97, 0xf2, 0x4b, 0xd1, 0x95, 0x61, 0xe4, 0x9e, 0x80, 0xa2, 0x5b, + 0xb0, 0x5e, 0x42, 0x74, 0x67, 0x5e, 0x76, 0x28, 0x6c, 0x01, 0x99, 0xd8, 0x4f, 0xbc, 0xec, 0x10, + 0xbd, 0xcd, 0xda, 0x38, 0x8a, 0xee, 0x32, 0xa3, 0x4b, 0x23, 0x9e, 0x44, 0x13, 0x51, 0x48, 0xdf, + 0xdc, 0x2f, 0x45, 0xa1, 0xae, 0x1e, 0x85, 0x7c, 0x7a, 0xba, 0x9a, 0xb8, 0xaa, 0x1e, 0x9c, 0x70, + 0xb0, 0xa8, 0xf3, 0x0a, 0x0d, 0x4b, 0x20, 0x2b, 0xf2, 0x52, 0xc1, 0x25, 0x92, 0xa8, 0xca, 0xf0, + 0x9a, 0x40, 0x5f, 0x82, 0x45, 0x79, 0x77, 0x15, 0x06, 0x07, 0x87, 0x79, 0x16, 0xc4, 0xc7, 0xb2, + 0x47, 0x41, 0xdf, 0x86, 0x0a, 0x24, 0x4e, 0xfb, 0xf7, 0x61, 0xf3, 0x20, 0x9f, 0xa4, 0x7e, 0x12, + 0x4e, 0xb0, 0xf9, 0xc2, 0x1f, 0x43, 0x1b, 0x9f, 0x84, 0x69, 0x16, 0x92, 0x97, 0x4c, 0xac, 0xb6, + 0x53, 0x8c, 0xed, 0x4f, 0x61, 0xa3, 0x58, 0x45, 0xbd, 0x4f, 0xaa, 0xf5, 0xab, 0xe4, 0xc3, 0x3c, + 0xf3, 0x5e, 0x89, 0x1c, 0xab, 0xed, 0x98, 0x40, 0xfb, 0x67, 0x0b, 0x3a, 0x9a, 0xd3, 0xfa, 0x95, + 0x65, 0x4c, 0xfd, 0x02, 0xd5, 0x4b, 0x01, 0xba, 0x5c, 0xe2, 0x6c, 0x54, 0x94, 0x38, 0xaf, 0x40, + 0x5f, 0x78, 0x49, 0x37, 0xc1, 0x5e, 0x1a, 0x4b, 0x07, 0x51, 0x82, 0xda, 0xff, 0x51, 0xe7, 0xbb, + 0x15, 0x8e, 0x1d, 0x9d, 0x9f, 0xdb, 0x6d, 0x8b, 0x8d, 0x1f, 0x98, 0x99, 0x74, 0xad, 0x94, 0x49, + 0x9f, 0x99, 0x33, 0x2c, 0xaa, 0xb5, 0x52, 0x47, 0x98, 0xb0, 0xd2, 0x97, 0xd8, 0x9c, 0x18, 0xd1, + 0x07, 0x1f, 0x7f, 0x7a, 0xb9, 0x09, 0xf6, 0x71, 0x78, 0x84, 0x03, 0x96, 0x47, 0x35, 0x9c, 0x32, + 0x98, 0x26, 0x70, 0x02, 0x94, 0x62, 0x92, 0xb1, 0x74, 0xaa, 0xe1, 0xe8, 0xa0, 0x39, 0x65, 0x41, + 0x85, 0xb2, 0xae, 0x43, 0x23, 0x89, 0x23, 0x3c, 0xea, 0xb0, 0xdc, 0x65, 0x54, 0x11, 0xf0, 0xb6, + 0x9c, 0x38, 0xc2, 0x0e, 0xc3, 0xa2, 0x29, 0xa1, 0xf4, 0x99, 0x6a, 0x7f, 0x5d, 0x46, 0x76, 0x7e, + 0x82, 0x1a, 0x4d, 0x01, 0x64, 0x7b, 0xec, 0xf1, 0x0e, 0x81, 0x01, 0xa4, 0xef, 0xb0, 0xc4, 0x9d, + 0x25, 0x38, 0x9c, 0x7a, 0x2f, 0xf1, 0xa8, 0xcf, 0x50, 0x34, 0x88, 0xca, 0xe2, 0x06, 0x5a, 0x16, + 0x67, 0x5f, 0x84, 0x06, 0xdd, 0x17, 0x5a, 0x81, 0xe6, 0xd3, 0xbb, 0x5f, 0xed, 0x39, 0xc3, 0x25, + 0xfa, 0xf9, 0x90, 0x7d, 0x5a, 0xf6, 0x2e, 0xf4, 0x9e, 0x26, 0x5e, 0x10, 0x92, 0x97, 0xfb, 0xe1, + 0x34, 0xcc, 0xe8, 0xd9, 0xb6, 0x1e, 0x7a, 0x27, 0x07, 0x38, 0x8a, 0xe4, 0xdb, 0x6a, 0xea, 0x9d, + 0xb8, 0xf4, 0x09, 0x82, 0xce, 0xc1, 0xf2, 0x43, 0xef, 0x64, 0x27, 0x97, 0xde, 0xba, 0x45, 0x67, + 0x26, 0xf9, 0xa9, 0xfd, 0xcf, 0x16, 0x34, 0x59, 0x3d, 0x83, 0xbe, 0x67, 0xa6, 0xd4, 0xc0, 0xdd, + 0xc5, 0xef, 0x0b, 0x47, 0xc7, 0x40, 0xdb, 0xd0, 0xc9, 0xb4, 0x05, 0xb5, 0xaa, 0x05, 0x7d, 0x0d, + 0x83, 0x5a, 0x8b, 0xb2, 0x88, 0xba, 0x61, 0x11, 0x67, 0x59, 0x91, 0x66, 0x7b, 0x4d, 0x33, 0x06, + 0x6c, 0xc3, 0xba, 0xa1, 0x81, 0xd7, 0x89, 0x82, 0xff, 0x68, 0xc1, 0x46, 0x69, 0x91, 0x70, 0x61, + 0x77, 0x61, 0x99, 0x95, 0x83, 0x64, 0xee, 0xf8, 0x9e, 0x5e, 0xef, 0x99, 0x43, 0xdf, 0xe2, 0x43, + 0x51, 0x4a, 0xe3, 0x0b, 0xc7, 0x4f, 0xa0, 0xa3, 0x81, 0x2b, 0xfc, 0xea, 0xfb, 0x66, 0x29, 0x6d, + 0xa3, 0x9a, 0x85, 0xe6, 0x6e, 0xbf, 0x86, 0xee, 0x33, 0x32, 0xf9, 0x15, 0xad, 0x5a, 0x74, 0x11, + 0x56, 0x12, 0x2c, 0x9e, 0x2e, 0xc2, 0xcd, 0x2a, 0x80, 0x3d, 0x80, 0x9e, 0xa0, 0xab, 0x1a, 0x83, + 0xcf, 0x48, 0x14, 0xfb, 0xaf, 0x5e, 0xb7, 0x31, 0xf8, 0x83, 0x05, 0x48, 0x5f, 0xa1, 0x02, 0x41, + 0xce, 0xa0, 0xa5, 0x40, 0x20, 0x81, 0x32, 0x10, 0x14, 0x48, 0x66, 0x20, 0x90, 0x60, 0x1e, 0x08, + 0xd0, 0x6f, 0xa0, 0xa3, 0xd3, 0xe2, 0x6d, 0x07, 0x50, 0x94, 0xec, 0xbf, 0xb1, 0x60, 0xf0, 0x4d, + 0x98, 0x1d, 0x06, 0x89, 0x77, 0xfc, 0x1a, 0xc7, 0x5f, 0x6e, 0xc9, 0xd6, 0xce, 0x6a, 0xc9, 0x9a, + 0x75, 0xa4, 0x21, 0xd4, 0xbd, 0x28, 0x12, 0xef, 0x4e, 0xfa, 0x49, 0x21, 0x2f, 0x30, 0x16, 0x4d, + 0x0d, 0xfa, 0x69, 0xdf, 0x81, 0xa1, 0xda, 0x8c, 0x50, 0xc8, 0x15, 0xe8, 0x67, 0x89, 0x47, 0x52, + 0xcf, 0xa7, 0xe4, 0x95, 0xdf, 0x2d, 0x41, 0xaf, 0x5d, 0x82, 0x95, 0xe2, 0x31, 0x85, 0x5a, 0x50, + 0xdf, 0x79, 0xf6, 0xc7, 0xc3, 0x25, 0xd4, 0x86, 0xc6, 0xc1, 0xde, 0xfe, 0xfe, 0xd0, 0xda, 0xfe, + 0x6f, 0x0b, 0x5a, 0xcf, 0xf3, 0xe0, 0x01, 0x09, 0x33, 0xb4, 0x07, 0xa0, 0x7a, 0xb2, 0xe8, 0x7c, + 0x91, 0xca, 0x96, 0x3b, 0xbb, 0xe3, 0x71, 0xd5, 0x94, 0x38, 0xf1, 0x25, 0x74, 0x1f, 0x3a, 0x5a, + 0x2c, 0x47, 0xe3, 0xc5, 0xf9, 0xcc, 0xf8, 0x42, 0xe5, 0x5c, 0x41, 0x69, 0x0f, 0x40, 0xd9, 0x82, + 0xda, 0xd0, 0x9c, 0x45, 0xa9, 0x0d, 0xcd, 0x9b, 0x8e, 0xbd, 0xb4, 0xfd, 0xd3, 0x06, 0xd4, 0x9f, + 0xe7, 0x01, 0x7a, 0x0e, 0x1d, 0xed, 0x17, 0x13, 0x34, 0x57, 0xe3, 0x57, 0xdb, 0xa9, 0xfa, 0x13, + 0x65, 0xfc, 0xfd, 0xbf, 0xfd, 0xcf, 0x8f, 0xb5, 0x75, 0x7b, 0x70, 0xf3, 0xe8, 0xf7, 0x6e, 0x7a, + 0x41, 0x20, 0x0f, 0xff, 0x8e, 0x75, 0x0d, 0x39, 0xd0, 0x12, 0x7f, 0x91, 0xa0, 0x4d, 0x8d, 0x86, + 0x96, 0x73, 0x8e, 0xcf, 0xcd, 0xc1, 0x05, 0xdd, 0x4d, 0x46, 0x77, 0x68, 0x77, 0x04, 0x5d, 0xea, + 0x86, 0x28, 0xcd, 0x1d, 0xa8, 0xef, 0x78, 0x04, 0x21, 0xd5, 0x9b, 0x93, 0xd7, 0x75, 0xbc, 0x66, + 0xc0, 0x04, 0x1d, 0xc4, 0xe8, 0x74, 0xed, 0x16, 0xa5, 0x33, 0xf1, 0x08, 0xa5, 0xe1, 0x43, 0x57, + 0x6f, 0xf8, 0x23, 0xd5, 0xa2, 0x9e, 0xff, 0x67, 0x61, 0x7c, 0xb1, 0x7a, 0x52, 0x90, 0x1f, 0x31, + 0xf2, 0xc8, 0x1e, 0x52, 0xf2, 0xec, 0xef, 0x07, 0xf1, 0xb0, 0xa1, 0xc2, 0x8b, 0xff, 0x01, 0x94, + 0xf0, 0xe6, 0xef, 0x04, 0x4a, 0xf8, 0xf2, 0x8f, 0x03, 0x86, 0xf0, 0xc2, 0x8b, 0x08, 0x85, 0x8a, + 0x16, 0xb4, 0xa2, 0x69, 0x76, 0xb0, 0x15, 0xcd, 0x52, 0xaf, 0xda, 0xa4, 0x19, 0xf0, 0x49, 0x4a, + 0xf3, 0xcf, 0xa1, 0x67, 0xf4, 0x99, 0x51, 0x21, 0x70, 0x55, 0x03, 0x7b, 0xfc, 0xd6, 0x82, 0x59, + 0xc1, 0xe5, 0x22, 0xe3, 0xb2, 0x69, 0xaf, 0x32, 0x2e, 0x02, 0x85, 0x75, 0xa6, 0x29, 0xaf, 0xe7, + 0x00, 0xaa, 0x5f, 0xab, 0x2c, 0x77, 0xae, 0x47, 0xac, 0x2c, 0x77, 0xbe, 0xbd, 0x6b, 0xaf, 0x31, + 0x16, 0x3d, 0xd4, 0xe1, 0x27, 0xca, 0x69, 0xed, 0x43, 0x4b, 0xf4, 0x26, 0x95, 0x66, 0xcc, 0x06, + 0xad, 0xd2, 0x4c, 0xa9, 0x89, 0x69, 0x0f, 0x19, 0x41, 0x40, 0x6d, 0x4a, 0x30, 0xa4, 0x24, 0xfe, + 0x14, 0x3a, 0x5a, 0x0b, 0x0e, 0xe9, 0xbb, 0x29, 0xf5, 0xf5, 0xd4, 0xe5, 0xa8, 0xe8, 0xd9, 0xd9, + 0xeb, 0x8c, 0x72, 0x1f, 0x75, 0x29, 0x65, 0xaa, 0x05, 0x46, 0xfd, 0x1b, 0x00, 0xd5, 0x2d, 0x52, + 0x5a, 0x98, 0x6b, 0x7b, 0x29, 0x2d, 0xcc, 0x37, 0x97, 0xa4, 0x5d, 0x23, 0xa0, 0xa4, 0x45, 0x95, + 0xf4, 0x25, 0xf4, 0xcd, 0x66, 0x1e, 0x7a, 0x4b, 0xa7, 0x30, 0xd7, 0xfd, 0x1b, 0x5f, 0x5a, 0x34, + 0x6d, 0xda, 0x0c, 0xea, 0x33, 0x3b, 0x54, 0x64, 0x0f, 0x60, 0xa5, 0x68, 0x33, 0xa1, 0x91, 0x4e, + 0x44, 0xef, 0x46, 0x8d, 0xcf, 0x57, 0xcc, 0x08, 0xca, 0xab, 0x8c, 0x72, 0x07, 0xad, 0x50, 0xca, + 0xbc, 0x7e, 0x28, 0x89, 0xb2, 0x4e, 0xb6, 0x49, 0x54, 0xeb, 0x51, 0x95, 0x88, 0xea, 0x9d, 0xaa, + 0x12, 0x51, 0x46, 0xe7, 0x5b, 0xae, 0x6b, 0xde, 0x6d, 0x32, 0x75, 0x6d, 0x34, 0xab, 0x4c, 0x5d, + 0x9b, 0xcd, 0x29, 0xfb, 0x3c, 0xa3, 0xbb, 0x66, 0x33, 0x35, 0x44, 0x61, 0x9a, 0xf1, 0x6e, 0x14, + 0xb5, 0x68, 0x17, 0x3a, 0x5a, 0x3b, 0x43, 0x59, 0xca, 0x7c, 0xe7, 0x45, 0x59, 0x4a, 0x55, 0xff, + 0xe3, 0x1c, 0x63, 0xb1, 0xca, 0xdd, 0x68, 0x3c, 0xc3, 0x44, 0xba, 0x91, 0x3f, 0x03, 0x50, 0x15, + 0x28, 0x25, 0xc0, 0x5c, 0x6d, 0x52, 0x99, 0x77, 0xa9, 0x60, 0x65, 0xee, 0x9e, 0x55, 0x05, 0x99, + 0xb9, 0xdc, 0xb1, 0xae, 0xdd, 0xb2, 0xd0, 0x0b, 0xe8, 0x2b, 0xfc, 0x83, 0x53, 0xe2, 0x9f, 0xc5, + 0x62, 0x5c, 0x35, 0x25, 0x04, 0x78, 0x8b, 0x71, 0x39, 0x67, 0x23, 0x93, 0x4b, 0x7a, 0x4a, 0x7c, + 0xaa, 0xa7, 0x3f, 0x81, 0x8e, 0xf6, 0x57, 0x8a, 0xd2, 0xd3, 0xfc, 0xaf, 0x2a, 0xe3, 0xaa, 0x1a, + 0x99, 0x19, 0x66, 0x30, 0x5f, 0x94, 0x1e, 0x7b, 0x33, 0x4a, 0x9b, 0x40, 0xdf, 0xac, 0xb5, 0x28, + 0xb3, 0xaf, 0x2c, 0xdc, 0x28, 0xb3, 0x5f, 0x50, 0xa2, 0x31, 0x64, 0x61, 0x75, 0x7a, 0xac, 0x87, + 0xb5, 0x09, 0x8d, 0xe4, 0x45, 0xcd, 0x45, 0x8f, 0xe4, 0xe5, 0xb2, 0x8e, 0x1e, 0xc9, 0xe7, 0x8a, + 0x34, 0xa6, 0x4c, 0x9c, 0x8d, 0x3c, 0x19, 0x6a, 0xb7, 0xaa, 0xe2, 0xa2, 0xce, 0x64, 0xae, 0x68, + 0x33, 0x1e, 0x57, 0x4d, 0x55, 0xd9, 0x2d, 0x67, 0x20, 0xc3, 0xe8, 0xd7, 0xd0, 0x96, 0x2f, 0x7c, + 0x54, 0x58, 0x4e, 0xa9, 0x0c, 0x30, 0x1e, 0xcd, 0x4f, 0x94, 0xcc, 0x95, 0x39, 0xb6, 0x54, 0xcc, + 0x52, 0xba, 0x18, 0x06, 0xa5, 0x2a, 0x01, 0x2a, 0xb4, 0x5d, 0x5d, 0x3e, 0x18, 0x9b, 0xbf, 0xa1, + 0xf0, 0xd6, 0x8b, 0x7d, 0x81, 0x31, 0xd8, 0x40, 0x6b, 0x8c, 0x81, 0x5c, 0xc8, 0x4d, 0xea, 0x96, + 0x85, 0x26, 0xd0, 0x37, 0xcb, 0x0a, 0xea, 0xc8, 0x2b, 0xcb, 0x0d, 0x67, 0x1a, 0x15, 0x42, 0x06, + 0x13, 0x6a, 0x56, 0x94, 0xc7, 0xac, 0x54, 0xba, 0x10, 0x35, 0x88, 0x37, 0x63, 0x25, 0x16, 0xd9, + 0x6f, 0x33, 0x56, 0x17, 0xd0, 0xf9, 0x39, 0x56, 0xb2, 0xd8, 0x7c, 0xcb, 0x42, 0x2f, 0xcb, 0x8f, + 0xcc, 0x8b, 0x0b, 0x5e, 0x45, 0xa5, 0x50, 0x5c, 0xf9, 0x66, 0x92, 0xa7, 0x8f, 0x58, 0x28, 0xce, + 0x38, 0x0a, 0x7f, 0x3a, 0xa1, 0x2f, 0xa1, 0xc9, 0x1e, 0x24, 0x68, 0x5d, 0x65, 0x88, 0xea, 0xdd, + 0x33, 0xde, 0x28, 0x41, 0xcd, 0x68, 0x66, 0x33, 0xf7, 0x9a, 0x13, 0x91, 0x4c, 0x7d, 0x0d, 0x6d, + 0x99, 0x86, 0x2b, 0x4b, 0x2a, 0xbd, 0x12, 0x94, 0x25, 0x95, 0x33, 0x76, 0xd3, 0x92, 0x8e, 0xc5, + 0xec, 0x1d, 0xeb, 0xda, 0x64, 0x99, 0xfd, 0x00, 0xfd, 0xc1, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, + 0x8f, 0x25, 0xdd, 0x8b, 0x2b, 0x2d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used.