diff --git a/docs/api.md b/docs/api.md index 649903cfa..40231ec6b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -11,6 +11,8 @@ - [BanRequest](#xudrpc.BanRequest) - [BanResponse](#xudrpc.BanResponse) - [Chain](#xudrpc.Chain) + - [ChangePasswordRequest](#xudrpc.ChangePasswordRequest) + - [ChangePasswordResponse](#xudrpc.ChangePasswordResponse) - [Channels](#xudrpc.Channels) - [CloseChannelRequest](#xudrpc.CloseChannelRequest) - [CloseChannelResponse](#xudrpc.CloseChannelResponse) @@ -210,6 +212,32 @@ + + +### ChangePasswordRequest + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| new_password | [string](#string) | | | +| old_password | [string](#string) | | | + + + + + + + + +### ChangePasswordResponse + + + + + + + ### Channels @@ -1577,6 +1605,7 @@ The primary service for interacting with a running xud node. | AddCurrency | [Currency](#xudrpc.Currency) | [AddCurrencyResponse](#xudrpc.AddCurrencyResponse) | Adds a currency to the list of supported currencies. Once added, the currency may be used for new trading pairs. shell: xucli addcurrency <currency> <swap_client> [decimal_places] [token_address] | | AddPair | [AddPairRequest](#xudrpc.AddPairRequest) | [AddPairResponse](#xudrpc.AddPairResponse) | Adds a trading pair to the list of supported trading pairs. The newly supported pair is advertised to peers so they may begin sending orders for it. shell: xucli addpair <base_currency> <quote_currency> | | Ban | [BanRequest](#xudrpc.BanRequest) | [BanResponse](#xudrpc.BanResponse) | Bans a node and immediately disconnects from it. This can be used to prevent any connections to a specific node. shell: xucli ban <node_identifier> | +| ChangePassword | [ChangePasswordRequest](#xudrpc.ChangePasswordRequest) | [ChangePasswordResponse](#xudrpc.ChangePasswordResponse) | Changes the xud master password, including the wallet passwords for any underlying clients. shell: xucli changepass | | CloseChannel | [CloseChannelRequest](#xudrpc.CloseChannelRequest) | [CloseChannelResponse](#xudrpc.CloseChannelResponse) | Closes any existing payment channels with a peer for the specified currency. shell: xucli closechannel <currency> [node_identifier ] [--force] | | Connect | [ConnectRequest](#xudrpc.ConnectRequest) | [ConnectResponse](#xudrpc.ConnectResponse) | Attempts to connect to a node. Once connected, the node is added to the list of peers and becomes available for swaps and trading. A handshake exchanges information about the peer's supported trading and swap clients. Orders will be shared with the peer upon connection and upon new order placements. shell: xucli connect <node_uri> | | WalletDeposit | [DepositRequest](#xudrpc.DepositRequest) | [DepositResponse](#xudrpc.DepositResponse) | Gets an address to deposit a given currency into the xud wallets. shell: xucli walletdeposit <currency> | diff --git a/lib/Xud.ts b/lib/Xud.ts index 9a206ce3e..490e252c0 100644 --- a/lib/Xud.ts +++ b/lib/Xud.ts @@ -119,16 +119,16 @@ class Xud extends EventEmitter { const nodeKeyPath = NodeKey.getPath(this.config.xudir, this.config.instanceid); const nodeKeyExists = await fs.access(nodeKeyPath).then(() => true).catch(() => false); - this.swapClientManager = new SwapClientManager(this.config, loggers, this.unitConverter); - await this.swapClientManager.init(this.db.models); + this.swapClientManager = new SwapClientManager(this.config, loggers, this.unitConverter, this.db.models); + await this.swapClientManager.init(); let nodeKey: NodeKey | undefined; if (this.config.noencrypt) { if (nodeKeyExists) { nodeKey = await NodeKey.fromFile(nodeKeyPath); } else { - nodeKey = await NodeKey.generate(); - await nodeKey.toFile(nodeKeyPath); + nodeKey = await NodeKey.generate(nodeKeyPath); + await nodeKey.toFile(); } // we need to initialize connext every time xud starts, even in noencrypt mode diff --git a/lib/cli/command.ts b/lib/cli/command.ts index 1e2af8141..ce85b7ea3 100644 --- a/lib/cli/command.ts +++ b/lib/cli/command.ts @@ -99,16 +99,16 @@ export const callback = (argv: Arguments, formatOutput?: Function, displayJson?: } } else { const responseObj = response.toObject(); - if (Object.keys(responseObj).length === 0) { - console.log('success'); - } else { - if (!argv.json && formatOutput) { - formatOutput(responseObj, argv); + if (argv.json || !formatOutput) { + if (Object.keys(responseObj).length === 0) { + console.log('success'); } else { displayJson - ? displayJson(responseObj, argv) - : console.log(JSON.stringify(responseObj, undefined, 2)); + ? displayJson(responseObj, argv) + : console.log(JSON.stringify(responseObj, undefined, 2)); } + } else { + formatOutput(responseObj, argv); } } }; diff --git a/lib/cli/commands/changepass.ts b/lib/cli/commands/changepass.ts new file mode 100644 index 000000000..cd563c35b --- /dev/null +++ b/lib/cli/commands/changepass.ts @@ -0,0 +1,51 @@ +import readline from 'readline'; +import { Arguments } from 'yargs'; +import { ChangePasswordRequest } from '../../proto/xudrpc_pb'; +import { callback, loadXudClient } from '../command'; + +export const command = 'changepass'; + +export const describe = 'change the password for an existing xud instance'; + +export const builder = {}; + +const formatOutput = () => { + console.log('The master xud password was succesfully changed.'); + console.log('Passwords for lnd wallets will be changed the next time xud is restarted and unlocked.'); +}; + +export const handler = (argv: Arguments) => { + const rl = readline.createInterface({ + input: process.stdin, + terminal: true, + }); + + console.log(`\ +You are changing the master password for xud and underlying wallets.\ +`); + process.stdout.write('Enter old password: '); + rl.question('', (oldPassword) => { + process.stdout.write('\nEnter new password: '); + rl.question('', (password1) => { + process.stdout.write('\nRe-enter password: '); + rl.question('', async (password2) => { + process.stdout.write('\n\n'); + rl.close(); + if (password1 === password2) { + const request = new ChangePasswordRequest(); + request.setNewPassword(password1); + request.setOldPassword(oldPassword); + + const client = await loadXudClient(argv); + // wait up to 3 seconds for rpc server to listen before call in case xud was just started + client.waitForReady(Date.now() + 3000, () => { + client.changePassword(request, callback(argv, formatOutput)); + }); + } else { + process.exitCode = 1; + console.error('Passwords do not match, please try again'); + } + }); + }); + }); +}; diff --git a/lib/db/DB.ts b/lib/db/DB.ts index 52f1a7ffa..e3a4273ef 100644 --- a/lib/db/DB.ts +++ b/lib/db/DB.ts @@ -1,8 +1,11 @@ -import { derivePairId } from '../utils/utils'; +import assert from 'assert'; +import { promises as fs } from 'fs'; import { ModelCtor, Sequelize } from 'sequelize'; import { XuNetwork } from '../constants/enums'; import { defaultCurrencies, defaultNodes, defaultPairs } from '../db/seeds'; import Logger from '../Logger'; +import { derivePairId } from '../utils/utils'; +import migrations from './migrations'; import * as Models from './models'; import * as db from './types'; @@ -14,6 +17,7 @@ type Models = { ReputationEvent: ModelCtor; Order: ModelCtor; Trade: ModelCtor; + Password: ModelCtor; }; function loadModels(sequelize: Sequelize): Models { @@ -25,6 +29,7 @@ function loadModels(sequelize: Sequelize): Models { ReputationEvent: Models.ReputationEvent(sequelize), SwapDeal: Models.SwapDeal(sequelize), Trade: Models.Trade(sequelize), + Password: Models.Password(sequelize), }; models.Currency.hasMany(models.Pair, { @@ -118,6 +123,8 @@ class DB { public sequelize: Sequelize; public models: Models; + private static VERSION = 1; + /** * @param storage the file path for the sqlite database file, if ':memory:' or not specified the db is stored in memory */ @@ -136,6 +143,8 @@ class DB { * @param initDb whether to intialize a new database with default values if no database exists */ public init = async (network = XuNetwork.SimNet, initDb = false): Promise => { + const isNewDb = await this.isNewDb(); + try { await this.sequelize.authenticate(); this.logger.info(`connected to database ${this.storage ? this.storage : 'in memory'}`); @@ -143,12 +152,40 @@ class DB { this.logger.error('unable to connect to the database', err); throw err; } - const { Node, Currency, Pair, ReputationEvent, SwapDeal, Order, Trade } = this.models; + + if (isNewDb) { + await this.sequelize.query(`PRAGMA user_version=${DB.VERSION};`); + } + + // version is useful for tracking migrations & upgrades to the xud database when + // the database schema is modified or restructured + let version: number; + const userVersionPragma = (await this.sequelize.query('PRAGMA user_version;')); + assert(Array.isArray(userVersionPragma) && Array.isArray(userVersionPragma[0])); + const userVersion = userVersionPragma[0][0].user_version; + assert(typeof userVersion === 'number'); + version = userVersion; + this.logger.trace(`db version is ${version}`); + + if (version <= DB.VERSION) { + // if our db is not the latest version, we call each migration procedure necessary + // to bring us from our current version up to the latest version. + for (let n = version; n < DB.VERSION; n += 1) { + this.logger.info(`migrating db from version ${n} to version ${n + 1}`); + await migrations[n](this.sequelize); + await this.sequelize.query(`PRAGMA user_version=${n + 1};`); + this.logger.info(`migration to version ${n + 1} complete`); + } + } + + const { Node, Currency, Pair, ReputationEvent, SwapDeal, Order, Trade, Password } = this.models; // sync schemas with the database in phases, according to FKs dependencies await Promise.all([ Node.sync(), Currency.sync(), + Password.sync(), ]); + // Pair is dependent on Currency, ReputationEvent is dependent on Node await Promise.all([ Pair.sync(), @@ -199,6 +236,26 @@ class DB { } } + /** + * Checks whether the database is new, in other words whether we are not + * loading a preexisting database from disk. + */ + private isNewDb = async () => { + if (this.storage && this.storage !== ':memory:') { + // check if database file exists + try { + await fs.access(this.storage); + return false; + } catch (err) { + if (err.code !== 'ENOENT') { + // we ignore errors due to file not existing, otherwise throw + throw err; + } + } + } + return true; + } + public close = () => { return this.sequelize.close(); } diff --git a/lib/db/migrations.ts b/lib/db/migrations.ts new file mode 100644 index 000000000..49c8697cd --- /dev/null +++ b/lib/db/migrations.ts @@ -0,0 +1,22 @@ +import Sequelize, { DataTypes } from 'sequelize'; + +/** + * An ordered array of functions that will migrate the database from one + * version to the next. The 1st element (index 0) will migrate from version + * 0 to 1, the 2nd element will migrate from version 1 to 2, and so on... + * Each migration must be called in order and allowed to complete before + * calling the next. + */ +const migrations: ((sequelize: Sequelize.Sequelize) => Promise)[] = []; + +migrations[0] = async (sequelize: Sequelize.Sequelize) => { + await sequelize.getQueryInterface().createTable('passwords', { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + encryptedPassword: { type: DataTypes.STRING, allowNull: false }, + currency: { type: DataTypes.STRING(5), allowNull: true }, + swapClient: { type: DataTypes.TINYINT, allowNull: false }, + createdAt: { type: DataTypes.BIGINT, allowNull: false }, + }); +}; + +export default migrations; diff --git a/lib/db/models/Password.ts b/lib/db/models/Password.ts new file mode 100644 index 000000000..722739e31 --- /dev/null +++ b/lib/db/models/Password.ts @@ -0,0 +1,21 @@ +import { DataTypes, ModelAttributes, ModelOptions, Sequelize } from 'sequelize'; +import { PasswordInstance } from '../types'; + +export default function Password(sequelize: Sequelize) { + const attributes: ModelAttributes = { + id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, + encryptedPassword: { type: DataTypes.STRING, allowNull: false }, + currency: { type: DataTypes.STRING(5), allowNull: true }, + swapClient: { type: DataTypes.TINYINT, allowNull: false }, + createdAt: { type: DataTypes.BIGINT, allowNull: false }, + }; + + const options: ModelOptions = { + tableName: 'passwords', + timestamps: true, + updatedAt: false, + }; + + const Password = sequelize.define('Password', attributes, options); + return Password; +} diff --git a/lib/db/models/index.ts b/lib/db/models/index.ts index 3db022ece..0f4f9ee4c 100644 --- a/lib/db/models/index.ts +++ b/lib/db/models/index.ts @@ -5,3 +5,4 @@ export { default as Pair } from './Pair'; export { default as ReputationEvent } from './ReputationEvent'; export { default as SwapDeal } from './SwapDeal'; export { default as Trade } from './Trade'; +export { default as Password } from './Password'; diff --git a/lib/db/types.ts b/lib/db/types.ts index 275b7a8c0..e0825c1c5 100644 --- a/lib/db/types.ts +++ b/lib/db/types.ts @@ -1,5 +1,5 @@ import { BelongsToGetAssociationMixin, Model } from 'sequelize'; -import { ReputationEvent } from '../constants/enums'; +import { ReputationEvent, SwapClientType } from '../constants/enums'; import { Currency, Order, Pair } from '../orderbook/types'; import { Address, NodeConnectionInfo } from '../p2p/types'; import { SwapDeal } from '../swaps/types'; @@ -110,3 +110,17 @@ export type ReputationEventAttributes = ReputationEventCreationAttributes & { }; export interface ReputationEventInstance extends Model, ReputationEventAttributes {} + +/* Passwords */ +export type PasswordCreationAttributes = { + encryptedPassword: string; + currency?: string; + swapClient: SwapClientType; +}; + +export type PasswordAttributes = PasswordCreationAttributes & { + createdAt: number; + id: number; +}; + +export interface PasswordInstance extends Model, PasswordAttributes {} diff --git a/lib/grpc/GrpcService.ts b/lib/grpc/GrpcService.ts index 54559d393..7a581cba5 100644 --- a/lib/grpc/GrpcService.ts +++ b/lib/grpc/GrpcService.ts @@ -877,6 +877,20 @@ class GrpcService { } } + public changePassword: grpc.handleUnaryCall = async (call, callback) => { + if (!this.isReady(this.service, callback)) { + return; + } + try { + await this.service.changePassword(call.request.toObject()); + + const response = new xudrpc.ChangePasswordResponse(); + callback(null, response); + } catch (err) { + callback(getGrpcError(err), null); + } + } + public shutdown: grpc.handleUnaryCall = (_, callback) => { if (!this.isReady(this.service, callback)) { return; diff --git a/lib/grpc/getGrpcError.ts b/lib/grpc/getGrpcError.ts index 1ff61d687..a059de9f2 100644 --- a/lib/grpc/getGrpcError.ts +++ b/lib/grpc/getGrpcError.ts @@ -67,6 +67,7 @@ const getGrpcError = (err: any) => { break; case serviceErrorCodes.NODE_ALREADY_EXISTS: case serviceErrorCodes.NODE_DOES_NOT_EXIST: + case serviceErrorCodes.NO_ENCRYPT_MODE_ENABLED: code = status.UNIMPLEMENTED; break; case p2pErrorCodes.POOL_CLOSED: diff --git a/lib/lndclient/LndClient.ts b/lib/lndclient/LndClient.ts index 8ea03e7b4..583fca8b5 100644 --- a/lib/lndclient/LndClient.ts +++ b/lib/lndclient/LndClient.ts @@ -50,6 +50,7 @@ class LndClient extends SwapClient { public readonly finalLock: number; public config: LndClientConfig; public currency: string; + public walletPassword?: string; private lightning?: LightningClient; private walletUnlocker?: WalletUnlockerClient; /** The maximum time to wait for a client to be ready for making grpc calls, can be used for exponential backoff. */ @@ -418,34 +419,10 @@ class LndClient extends SwapClient { if (isWalletInitialized) { // admin.macaroon will not necessarily be created by the time lnd responds to a successful // InitWallet call, so we watch the folder that we expect it to be in for it to be created - const watchMacaroonPromise = new Promise((resolve) => { - this.watchMacaroonResolve = resolve; - }); - const macaroonDir = path.join(this.macaroonpath!, '..'); - const fsWatcher = watch(macaroonDir, (event, filename) => { - if (event === 'change' && filename === 'admin.macaroon') { - this.logger.debug('admin.macaroon was created'); - if (this.watchMacaroonResolve) { - this.watchMacaroonResolve(true); - } - } - }); - this.logger.debug(`watching ${macaroonDir} for admin.macaroon to be created`); - const macaroonCreated = await watchMacaroonPromise; - fsWatcher.close(); - this.watchMacaroonResolve = undefined; - - if (macaroonCreated) { - try { - await this.loadMacaroon(); + await this.watchThenLoadMacaroon(); - // once we've loaded the macaroon we can attempt to verify the conneciton - this.verifyConnection().catch(this.logger.error); - } catch (err) { - this.logger.error(`could not load macaroon from ${this.macaroonpath}`); - this.setStatus(ClientStatus.Disabled); - } - } + // once we've loaded the macaroon we can attempt to verify the conneciton + this.verifyConnection().catch(this.logger.error); } } @@ -950,6 +927,7 @@ class LndClient extends SwapClient { public initWallet = async (walletPassword: string, seedMnemonic: string[], restore = false, backup?: Uint8Array): Promise => { + this.walletPassword = walletPassword; const request = new lndwalletunlocker.InitWalletRequest(); // from the master seed/mnemonic we derive a child mnemonic for this specific client @@ -980,6 +958,7 @@ class LndClient extends SwapClient { } public unlockWallet = async (walletPassword: string): Promise => { + this.walletPassword = walletPassword; const request = new lndwalletunlocker.UnlockWalletRequest(); request.setWalletPassword(Uint8Array.from(Buffer.from(walletPassword, 'utf8'))); await this.unaryWalletUnlockerCall( @@ -989,6 +968,57 @@ class LndClient extends SwapClient { this.logger.info('wallet unlocked'); } + /** + * Watches for a change in the admin.macaroon file at the configured path, + * then loads the macaroon. + */ + private watchThenLoadMacaroon = async () => { + const watchMacaroonPromise = new Promise((resolve) => { + this.watchMacaroonResolve = resolve; + }); + const macaroonDir = path.join(this.macaroonpath!, '..'); + const fsWatcher = watch(macaroonDir, (event, filename) => { + if (event === 'change' && filename === 'admin.macaroon') { + this.logger.debug('admin.macaroon was created'); + if (this.watchMacaroonResolve) { + this.watchMacaroonResolve(true); + } + } + }); + this.logger.debug(`watching ${macaroonDir} for admin.macaroon to be created`); + const macaroonCreated = await watchMacaroonPromise; + fsWatcher.close(); + this.watchMacaroonResolve = undefined; + + if (macaroonCreated) { + try { + await this.loadMacaroon(); + } catch (err) { + this.logger.error(`could not load macaroon from ${this.macaroonpath}`); + this.setStatus(ClientStatus.Disabled); + } + } + } + + public changePassword = async (oldPassword: string, newPassword: string) => { + this.walletPassword = newPassword; + const request = new lndwalletunlocker.ChangePasswordRequest(); + request.setCurrentPassword(Uint8Array.from(Buffer.from(oldPassword, 'utf8'))); + request.setNewPassword(Uint8Array.from(Buffer.from(newPassword, 'utf8'))); + await this.unaryWalletUnlockerCall( + 'changePassword', request, + ); + + // the macaroons change every time lnd changes its password, so we must remove the old one and reload the new one + this.meta.remove('macaroon'); + // admin.macaroon will not necessarily be created by the time lnd responds to a successful + // ChangePassword call, so we watch the folder that we expect it to be in for it to be created + await this.watchThenLoadMacaroon(); + + this.setUnlocked(); + this.logger.info('password changed & wallet unlocked'); + } + public addInvoice = async ( { rHash, units, expiry = this.finalLock }: { rHash: string, units: number, expiry?: number }, diff --git a/lib/nodekey/NodeKey.ts b/lib/nodekey/NodeKey.ts index 3731dbdf6..2c8535241 100644 --- a/lib/nodekey/NodeKey.ts +++ b/lib/nodekey/NodeKey.ts @@ -1,9 +1,9 @@ -import secp256k1 from 'secp256k1'; -import { randomBytes } from '../utils/utils'; -import { promises as fs } from 'fs'; -import { createCipheriv, createDecipheriv, createHash } from 'crypto'; import { entropyToMnemonic } from 'bip39'; +import { createHash } from 'crypto'; +import { promises as fs } from 'fs'; +import secp256k1 from 'secp256k1'; import { SwapClientType } from '../constants/enums'; +import { decrypt, encrypt, randomBytes } from '../utils/cryptoUtils'; import { encipher } from '../utils/seedutil'; /** @@ -11,31 +11,31 @@ import { encipher } from '../utils/seedutil'; * and can sign messages to prove their veracity. */ class NodeKey { - private static ENCRYPTION_IV_LENGTH = 16; + public password?: string; /** * @param privKey The 32 byte private key * @param pubKey The public key in hex string format. */ - constructor(public readonly privKey: Buffer, public readonly pubKey: string) { } + constructor(public readonly privKey: Buffer, public readonly pubKey: string, private readonly path: string) { } /** * Generates a random NodeKey. */ - public static generate = async (): Promise => { + public static generate = async (path?: string): Promise => { let privKey: Buffer; do { privKey = await randomBytes(32); } while (!secp256k1.privateKeyVerify(privKey)); - return NodeKey.fromBytes(privKey); + return NodeKey.fromBytes(privKey, path); } /** * Converts a buffer of bytes to a NodeKey. Uses the first 32 bytes from the buffer to generate * the private key. If the buffer has fewer than 32 bytes, the buffer is right-padded with zeros. */ - public static fromBytes = (bytes: Buffer): NodeKey => { + public static fromBytes = (bytes: Buffer, path?: string): NodeKey => { let privKey: Buffer; if (bytes.byteLength === 32) { privKey = bytes; @@ -48,11 +48,7 @@ class NodeKey { const pubKeyBytes = secp256k1.publicKeyCreate(privKey); const pubKey = pubKeyBytes.toString('hex'); - return new NodeKey(privKey, pubKey); - } - - private static getCipherKey = (password: string) => { - return createHash('sha256').update(password).digest(); + return new NodeKey(privKey, pubKey, path ?? ''); } /** @@ -67,17 +63,14 @@ class NodeKey { if (password) { // decrypt file using the password - // the first 16 bytes contain the initialization vector - const iv = fileBuffer.slice(0, NodeKey.ENCRYPTION_IV_LENGTH); - const key = NodeKey.getCipherKey(password); - const encrypted = fileBuffer.slice(NodeKey.ENCRYPTION_IV_LENGTH); - const decipher = createDecipheriv('aes-256-cbc', key, iv); - privKey = Buffer.concat([decipher.update(encrypted), decipher.final()]); + privKey = decrypt(fileBuffer, password); } else { privKey = fileBuffer; } if (secp256k1.privateKeyVerify(privKey)) { - return NodeKey.fromBytes(privKey); + const nodeKey = NodeKey.fromBytes(privKey, path); + nodeKey.password = password; + return nodeKey; } else { throw new Error(`${path} does not contain a valid ECDSA private key`); } @@ -103,17 +96,15 @@ class NodeKey { * @param path the path at which to save the file * @param password an optional password parameter for encrypting the private key */ - public toFile = async (path: string, password?: string): Promise => { + public toFile = async (password?: string): Promise => { let buf: Buffer; if (password) { - const iv = await randomBytes(NodeKey.ENCRYPTION_IV_LENGTH); - const key = NodeKey.getCipherKey(password); - const cipher = createCipheriv('aes-256-cbc', key, iv); - buf = Buffer.concat([iv, cipher.update(this.privKey), cipher.final()]); + this.password = password; + buf = await encrypt(this.privKey, password); } else { buf = this.privKey; } - await fs.writeFile(path, buf); + await fs.writeFile(this.path, buf); } /** diff --git a/lib/p2p/Framer.ts b/lib/p2p/Framer.ts index b8434c088..d03a4ddf3 100644 --- a/lib/p2p/Framer.ts +++ b/lib/p2p/Framer.ts @@ -1,10 +1,10 @@ import assert from 'assert'; import { createCipheriv, createDecipheriv } from 'crypto'; +import { magicValsXuNetwork } from '../constants/enums'; +import { randomBytes } from '../utils/cryptoUtils'; +import errors from './errors'; import Network from './Network'; import Packet from './packets/Packet'; -import errors from './errors'; -import { magicValsXuNetwork } from '../constants/enums'; -import { randomBytes } from '../utils/utils'; type WireMsgHeader = { magic?: number, diff --git a/lib/proto/xudrpc.swagger.json b/lib/proto/xudrpc.swagger.json index 53128eda3..ccdc5b3dc 100644 --- a/lib/proto/xudrpc.swagger.json +++ b/lib/proto/xudrpc.swagger.json @@ -122,6 +122,23 @@ ] } }, + "/v1/changepass": { + "post": { + "summary": "Changes the xud master password, including the wallet passwords for any underlying clients.\nshell: xucli changepass", + "operationId": "ChangePassword", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/xudrpcChangePasswordResponse" + } + } + }, + "tags": [ + "Xud" + ] + } + }, "/v1/closechannel": { "post": { "summary": "Closes any existing payment channels with a peer for the specified currency.\nshell: xucli closechannel \u003ccurrency\u003e [node_identifier ] [--force]", @@ -986,6 +1003,9 @@ } } }, + "xudrpcChangePasswordResponse": { + "type": "object" + }, "xudrpcChannels": { "type": "object", "properties": { diff --git a/lib/proto/xudrpc_grpc_pb.d.ts b/lib/proto/xudrpc_grpc_pb.d.ts index 9469240a3..22051652c 100644 --- a/lib/proto/xudrpc_grpc_pb.d.ts +++ b/lib/proto/xudrpc_grpc_pb.d.ts @@ -78,6 +78,7 @@ interface IXudService extends grpc.ServiceDefinition; responseDeserialize: grpc.deserialize; } +interface IXudService_IChangePassword extends grpc.MethodDefinition { + path: string; // "/xudrpc.Xud/ChangePassword" + requestStream: boolean; // false + responseStream: boolean; // false + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} interface IXudService_ICloseChannel extends grpc.MethodDefinition { path: string; // "/xudrpc.Xud/CloseChannel" requestStream: boolean; // false @@ -414,6 +424,7 @@ export interface IXudServer { addCurrency: grpc.handleUnaryCall; addPair: grpc.handleUnaryCall; ban: grpc.handleUnaryCall; + changePassword: grpc.handleUnaryCall; closeChannel: grpc.handleUnaryCall; connect: grpc.handleUnaryCall; walletDeposit: grpc.handleUnaryCall; @@ -456,6 +467,9 @@ export interface IXudClient { ban(request: xudrpc_pb.BanRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.BanResponse) => void): grpc.ClientUnaryCall; ban(request: xudrpc_pb.BanRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.BanResponse) => void): grpc.ClientUnaryCall; ban(request: xudrpc_pb.BanRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.BanResponse) => void): grpc.ClientUnaryCall; + changePassword(request: xudrpc_pb.ChangePasswordRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.ChangePasswordResponse) => void): grpc.ClientUnaryCall; + changePassword(request: xudrpc_pb.ChangePasswordRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.ChangePasswordResponse) => void): grpc.ClientUnaryCall; + changePassword(request: xudrpc_pb.ChangePasswordRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.ChangePasswordResponse) => void): grpc.ClientUnaryCall; closeChannel(request: xudrpc_pb.CloseChannelRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CloseChannelResponse) => void): grpc.ClientUnaryCall; closeChannel(request: xudrpc_pb.CloseChannelRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CloseChannelResponse) => void): grpc.ClientUnaryCall; closeChannel(request: xudrpc_pb.CloseChannelRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CloseChannelResponse) => void): grpc.ClientUnaryCall; @@ -554,6 +568,9 @@ export class XudClient extends grpc.Client implements IXudClient { public ban(request: xudrpc_pb.BanRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.BanResponse) => void): grpc.ClientUnaryCall; public ban(request: xudrpc_pb.BanRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.BanResponse) => void): grpc.ClientUnaryCall; public ban(request: xudrpc_pb.BanRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.BanResponse) => void): grpc.ClientUnaryCall; + public changePassword(request: xudrpc_pb.ChangePasswordRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.ChangePasswordResponse) => void): grpc.ClientUnaryCall; + public changePassword(request: xudrpc_pb.ChangePasswordRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.ChangePasswordResponse) => void): grpc.ClientUnaryCall; + public changePassword(request: xudrpc_pb.ChangePasswordRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.ChangePasswordResponse) => void): grpc.ClientUnaryCall; public closeChannel(request: xudrpc_pb.CloseChannelRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CloseChannelResponse) => void): grpc.ClientUnaryCall; public closeChannel(request: xudrpc_pb.CloseChannelRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CloseChannelResponse) => void): grpc.ClientUnaryCall; public closeChannel(request: xudrpc_pb.CloseChannelRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CloseChannelResponse) => void): grpc.ClientUnaryCall; diff --git a/lib/proto/xudrpc_grpc_pb.js b/lib/proto/xudrpc_grpc_pb.js index 35a63851a..8d359ad92 100644 --- a/lib/proto/xudrpc_grpc_pb.js +++ b/lib/proto/xudrpc_grpc_pb.js @@ -81,6 +81,28 @@ function deserialize_xudrpc_BanResponse(buffer_arg) { return xudrpc_pb.BanResponse.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_xudrpc_ChangePasswordRequest(arg) { + if (!(arg instanceof xudrpc_pb.ChangePasswordRequest)) { + throw new Error('Expected argument of type xudrpc.ChangePasswordRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_xudrpc_ChangePasswordRequest(buffer_arg) { + return xudrpc_pb.ChangePasswordRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_xudrpc_ChangePasswordResponse(arg) { + if (!(arg instanceof xudrpc_pb.ChangePasswordResponse)) { + throw new Error('Expected argument of type xudrpc.ChangePasswordResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_xudrpc_ChangePasswordResponse(buffer_arg) { + return xudrpc_pb.ChangePasswordResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_xudrpc_CloseChannelRequest(arg) { if (!(arg instanceof xudrpc_pb.CloseChannelRequest)) { throw new Error('Expected argument of type xudrpc.CloseChannelRequest'); @@ -876,6 +898,19 @@ var XudService = exports.XudService = { responseSerialize: serialize_xudrpc_BanResponse, responseDeserialize: deserialize_xudrpc_BanResponse, }, + // Changes the xud master password, including the wallet passwords for any underlying clients. + // shell: xucli changepass + changePassword: { + path: '/xudrpc.Xud/ChangePassword', + requestStream: false, + responseStream: false, + requestType: xudrpc_pb.ChangePasswordRequest, + responseType: xudrpc_pb.ChangePasswordResponse, + requestSerialize: serialize_xudrpc_ChangePasswordRequest, + requestDeserialize: deserialize_xudrpc_ChangePasswordRequest, + responseSerialize: serialize_xudrpc_ChangePasswordResponse, + responseDeserialize: deserialize_xudrpc_ChangePasswordResponse, + }, // Closes any existing payment channels with a peer for the specified currency. // shell: xucli closechannel [node_identifier ] [--force] closeChannel: { diff --git a/lib/proto/xudrpc_pb.d.ts b/lib/proto/xudrpc_pb.d.ts index ea4f29b08..bd4afaa62 100644 --- a/lib/proto/xudrpc_pb.d.ts +++ b/lib/proto/xudrpc_pb.d.ts @@ -202,6 +202,48 @@ export namespace Channels { } } +export class ChangePasswordRequest extends jspb.Message { + getNewPassword(): string; + setNewPassword(value: string): void; + + getOldPassword(): string; + setOldPassword(value: string): void; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): ChangePasswordRequest.AsObject; + static toObject(includeInstance: boolean, msg: ChangePasswordRequest): ChangePasswordRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: ChangePasswordRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ChangePasswordRequest; + static deserializeBinaryFromReader(message: ChangePasswordRequest, reader: jspb.BinaryReader): ChangePasswordRequest; +} + +export namespace ChangePasswordRequest { + export type AsObject = { + newPassword: string, + oldPassword: string, + } +} + +export class ChangePasswordResponse extends jspb.Message { + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): ChangePasswordResponse.AsObject; + static toObject(includeInstance: boolean, msg: ChangePasswordResponse): ChangePasswordResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: ChangePasswordResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ChangePasswordResponse; + static deserializeBinaryFromReader(message: ChangePasswordResponse, reader: jspb.BinaryReader): ChangePasswordResponse; +} + +export namespace ChangePasswordResponse { + export type AsObject = { + } +} + export class CloseChannelRequest extends jspb.Message { getNodeIdentifier(): string; setNodeIdentifier(value: string): void; diff --git a/lib/proto/xudrpc_pb.js b/lib/proto/xudrpc_pb.js index 3431addf3..fd01ace0c 100644 --- a/lib/proto/xudrpc_pb.js +++ b/lib/proto/xudrpc_pb.js @@ -20,6 +20,8 @@ goog.exportSymbol('proto.xudrpc.Balance', null, global); goog.exportSymbol('proto.xudrpc.BanRequest', null, global); goog.exportSymbol('proto.xudrpc.BanResponse', null, global); goog.exportSymbol('proto.xudrpc.Chain', null, global); +goog.exportSymbol('proto.xudrpc.ChangePasswordRequest', null, global); +goog.exportSymbol('proto.xudrpc.ChangePasswordResponse', null, global); goog.exportSymbol('proto.xudrpc.Channels', null, global); goog.exportSymbol('proto.xudrpc.CloseChannelRequest', null, global); goog.exportSymbol('proto.xudrpc.CloseChannelResponse', null, global); @@ -1429,6 +1431,291 @@ proto.xudrpc.Channels.prototype.setClosed = function(value) { +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.xudrpc.ChangePasswordRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.xudrpc.ChangePasswordRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.xudrpc.ChangePasswordRequest.displayName = 'proto.xudrpc.ChangePasswordRequest'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.xudrpc.ChangePasswordRequest.prototype.toObject = function(opt_includeInstance) { + return proto.xudrpc.ChangePasswordRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.xudrpc.ChangePasswordRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.xudrpc.ChangePasswordRequest.toObject = function(includeInstance, msg) { + var f, obj = { + newPassword: jspb.Message.getFieldWithDefault(msg, 1, ""), + oldPassword: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.xudrpc.ChangePasswordRequest} + */ +proto.xudrpc.ChangePasswordRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.xudrpc.ChangePasswordRequest; + return proto.xudrpc.ChangePasswordRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.xudrpc.ChangePasswordRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.xudrpc.ChangePasswordRequest} + */ +proto.xudrpc.ChangePasswordRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setNewPassword(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setOldPassword(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.xudrpc.ChangePasswordRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.xudrpc.ChangePasswordRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.xudrpc.ChangePasswordRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.xudrpc.ChangePasswordRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getNewPassword(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getOldPassword(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string new_password = 1; + * @return {string} + */ +proto.xudrpc.ChangePasswordRequest.prototype.getNewPassword = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** @param {string} value */ +proto.xudrpc.ChangePasswordRequest.prototype.setNewPassword = function(value) { + jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string old_password = 2; + * @return {string} + */ +proto.xudrpc.ChangePasswordRequest.prototype.getOldPassword = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** @param {string} value */ +proto.xudrpc.ChangePasswordRequest.prototype.setOldPassword = function(value) { + jspb.Message.setProto3StringField(this, 2, value); +}; + + + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.xudrpc.ChangePasswordResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.xudrpc.ChangePasswordResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.xudrpc.ChangePasswordResponse.displayName = 'proto.xudrpc.ChangePasswordResponse'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.xudrpc.ChangePasswordResponse.prototype.toObject = function(opt_includeInstance) { + return proto.xudrpc.ChangePasswordResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.xudrpc.ChangePasswordResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.xudrpc.ChangePasswordResponse.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.xudrpc.ChangePasswordResponse} + */ +proto.xudrpc.ChangePasswordResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.xudrpc.ChangePasswordResponse; + return proto.xudrpc.ChangePasswordResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.xudrpc.ChangePasswordResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.xudrpc.ChangePasswordResponse} + */ +proto.xudrpc.ChangePasswordResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.xudrpc.ChangePasswordResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.xudrpc.ChangePasswordResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.xudrpc.ChangePasswordResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.xudrpc.ChangePasswordResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a diff --git a/lib/service/InitService.ts b/lib/service/InitService.ts index 4f2834f6f..da5f7d64c 100644 --- a/lib/service/InitService.ts +++ b/lib/service/InitService.ts @@ -39,7 +39,7 @@ class InitService extends EventEmitter { // we use the deciphered seed (without the salt and extra fields that make up the enciphered seed) // to generate an xud nodekey from the same seed used for wallets const decipheredSeed = await decipher(seedMnemonic); - const nodeKey = NodeKey.fromBytes(decipheredSeed); + const nodeKey = NodeKey.fromBytes(decipheredSeed, this.nodeKeyPath); // use this seed to init any lnd wallets that are uninitialized const initWalletResult = await this.swapClientManager.initWallets({ @@ -48,7 +48,7 @@ class InitService extends EventEmitter { walletPassword: password, }); - await nodeKey.toFile(this.nodeKeyPath, password); + await nodeKey.toFile(password); this.emit('nodekey', nodeKey); return { initializedLndWallets: initWalletResult.initializedLndWallets, @@ -112,7 +112,7 @@ class InitService extends EventEmitter { await this.prepareCall(); const decipheredSeed = await decipher(seedMnemonicList); - const nodeKey = NodeKey.fromBytes(decipheredSeed); + const nodeKey = NodeKey.fromBytes(decipheredSeed, this.nodeKeyPath); // use the seed and database backups to restore any swap clients' wallets // that are uninitialized @@ -127,7 +127,7 @@ class InitService extends EventEmitter { if (xudDatabase.byteLength) { await fs.writeFile(this.databasePath, xudDatabase); } - await nodeKey.toFile(this.nodeKeyPath, password); + await nodeKey.toFile(password); this.emit('nodekey', nodeKey); return { initializedLndWallets: initWalletResult.initializedLndWallets, diff --git a/lib/service/Service.ts b/lib/service/Service.ts index eadc4599a..f9ded99a7 100644 --- a/lib/service/Service.ts +++ b/lib/service/Service.ts @@ -847,5 +847,21 @@ class Service extends EventEmitter { this.swapClientManager.connextClient?.emit('depositConfirmed', hash); } + public changePassword = async ({ newPassword, oldPassword }: { newPassword: string, oldPassword: string }) => { + if (!this.nodekey.password) { + throw errors.NO_ENCRYPT_MODE_ENABLED; + } + if (newPassword.length < 8) { + // lnd requires 8+ character passwords, so we must as well + throw errors.INVALID_ARGUMENT('password must be at least 8 characters'); + } + if (oldPassword !== this.nodekey.password) { + throw errors.INVALID_ARGUMENT('old password is incorrect'); + } + + // we change the password for our node key right away, then we queue up lnd password changes + await this.nodekey.toFile(newPassword); + await this.swapClientManager.changeLndPasswords(oldPassword, newPassword); + } } export default Service; diff --git a/lib/service/errors.ts b/lib/service/errors.ts index 07b653edc..e12e95465 100644 --- a/lib/service/errors.ts +++ b/lib/service/errors.ts @@ -10,6 +10,7 @@ const errorCodes = { NODE_DOES_NOT_EXIST: codesPrefix.concat('.6'), INVALID_REQUEST: codesPrefix.concat('.7'), NO_CHANNELS_TO_CLOSE: codesPrefix.concat('.8'), + NO_ENCRYPT_MODE_ENABLED: codesPrefix.concat('.9'), }; const errors = { @@ -52,6 +53,10 @@ const errors = { message: `no channels found to close for ${remoteIdentifier}`, code: errorCodes.NO_CHANNELS_TO_CLOSE, }), + NO_ENCRYPT_MODE_ENABLED: { + message: 'xud is not encrypted with a password', + code: errorCodes.NO_ENCRYPT_MODE_ENABLED, + }, }; export { errorCodes }; diff --git a/lib/swaps/SwapClientManager.ts b/lib/swaps/SwapClientManager.ts index 27d75b7bb..e8baa9735 100644 --- a/lib/swaps/SwapClientManager.ts +++ b/lib/swaps/SwapClientManager.ts @@ -11,6 +11,7 @@ import { Level, Loggers } from '../Logger'; import NodeKey from '../nodekey/NodeKey'; import { Currency, OwnLimitOrder } from '../orderbook/types'; import Peer from '../p2p/Peer'; +import { encrypt, decrypt } from '../utils/cryptoUtils'; import { UnitConverter } from '../utils/UnitConverter'; import errors from './errors'; import SwapClient, { ClientStatus } from './SwapClient'; @@ -45,7 +46,6 @@ class SwapClientManager extends EventEmitter { public swapClients = new Map(); public connextClient?: ConnextClient; public misconfiguredClients = new Set(); - private walletPassword?: string; /** A map of supported currency tickers to the inbound amount that is reserved by existing orders. */ private inboundReservedAmounts = new Map(); @@ -56,6 +56,7 @@ class SwapClientManager extends EventEmitter { private config: Config, private loggers: Loggers, private unitConverter: UnitConverter, + private models: Models, ) { super(); } @@ -65,7 +66,7 @@ class SwapClientManager extends EventEmitter { * and waits for the swap clients to initialize. * @returns A promise that resolves upon successful initialization, rejects otherwise. */ - public init = async (models: Models): Promise => { + public init = async (): Promise => { const initPromises = []; // setup configured LND clients and initialize them for (const currency in this.config.lnd) { @@ -83,7 +84,7 @@ class SwapClientManager extends EventEmitter { if (!this.config.connext.disable) { // setup Connext - const currencyInstances = await models.Currency.findAll(); + const currencyInstances = await this.models.Currency.findAll(); this.connextClient = new ConnextClient({ currencyInstances, unitConverter: this.unitConverter, @@ -289,8 +290,6 @@ class SwapClientManager extends EventEmitter { lndBackups?: Map, nodeKey: NodeKey, }) => { - this.walletPassword = walletPassword; - // loop through swap clients to initialize locked lnd clients const initWalletPromises: Promise[] = []; const initializedLndWallets: string[] = []; @@ -336,37 +335,57 @@ class SwapClientManager extends EventEmitter { nodeKey: NodeKey, connextSeed: string, }) => { - this.walletPassword = walletPassword; - // loop through swap clients to find locked lnd clients const unlockWalletPromises: Promise[] = []; const unlockedLndClients: string[] = []; const lockedLndClients: string[] = []; + const oldEncryptedPasswords = await this.models.Password.findAll(); + for (const swapClient of this.swapClients.values()) { if (isLndClient(swapClient)) { if (swapClient.isWaitingUnlock()) { - const unlockWalletPromise = swapClient.unlockWallet(walletPassword).then(() => { - unlockedLndClients.push(swapClient.currency); - }).catch(async (err) => { - let walletCreated = false; - if (err.details === 'wallet not found') { - // this wallet hasn't been initialized, so we will try to initialize it now - const seedMnemonic = await nodeKey.getMnemonic(); - try { - await swapClient.initWallet(this.walletPassword ?? '', seedMnemonic); - walletCreated = true; - } catch (err) { - swapClient.logger.error('could not initialize lnd wallet', err); + // first we check whether this lnd is using an old wallet password + const oldEncryptedPassword = oldEncryptedPasswords.find((oldEncryptedPassword) => { + return oldEncryptedPassword.swapClient === SwapClientType.Lnd && oldEncryptedPassword.currency === swapClient.currency; + }); + const oldPassword = oldEncryptedPassword ? decrypt(oldEncryptedPassword.encryptedPassword, walletPassword).toString() : undefined; + + if (oldPassword) { + // if we have an old password for this lnd client, then we use it to change its password + // to the new password, which in turn will unlock the client + const changePasswordPromise = swapClient.changePassword(oldPassword, walletPassword).then(() => { + unlockedLndClients.push(swapClient.currency); + return oldEncryptedPassword?.destroy(); // we can remove the old password from the database + }).catch(async (err) => { + this.loggers.lnd.error(`could not change password for ${swapClient.currency}`, err); + lockedLndClients.push(swapClient.currency); + }); + + unlockWalletPromises.push(changePasswordPromise); + } else { + const unlockWalletPromise = swapClient.unlockWallet(walletPassword).then(() => { + unlockedLndClients.push(swapClient.currency); + }).catch(async (err) => { + let walletCreated = false; + if (err.details === 'wallet not found') { + // this wallet hasn't been initialized, so we will try to initialize it now + const seedMnemonic = await nodeKey.getMnemonic(); + try { + await swapClient.initWallet(walletPassword ?? '', seedMnemonic); + walletCreated = true; + } catch (err) { + swapClient.logger.error('could not initialize lnd wallet', err); + } } - } - if (!walletCreated) { - lockedLndClients.push(swapClient.currency); - swapClient.logger.debug(`could not unlock wallet: ${err.message}`); - } - }); - unlockWalletPromises.push(unlockWalletPromise); + if (!walletCreated) { + lockedLndClients.push(swapClient.currency); + swapClient.logger.debug(`could not unlock wallet: ${err.message}`); + } + }); + unlockWalletPromises.push(unlockWalletPromise); + } } else if (swapClient.isDisconnected() || swapClient.isMisconfigured() || swapClient.isNotInitialized()) { // if the swap client is not connected, we treat it as locked since lnd will likely be locked when it comes online lockedLndClients.push(swapClient.currency); @@ -384,6 +403,31 @@ class SwapClientManager extends EventEmitter { return { unlockedLndClients, lockedLndClients }; } + /** + * Changes the wallet passwords for all lnd clients by either calling ChangePassword + * right away if lnd is in a WaitingUnlock state or, more often, by persisting the + * current wallet password so that xud will try to automatically change it the next + * time it is unlocked. + */ + public changeLndPasswords = async (oldPassword: string, newPassword: string) => { + const lndClients = this.getLndClientsMap().values(); + const promises: Promise[] = []; + for (const lndClient of lndClients) { + if (lndClient.isWaitingUnlock()) { + // we can change the password and unlock right now + promises.push(lndClient.changePassword(oldPassword, newPassword)); + } else if (lndClient.isOperational()) { + const encryptedPassword = (await encrypt(oldPassword, newPassword)).toString('base64'); + promises.push(this.models.Password.create({ + encryptedPassword, + swapClient: SwapClientType.Lnd, + currency: lndClient.currency, + })); + } + } + await Promise.all(promises); + } + /** * Gets a swap client instance. * @param currency a currency that the swap client is linked to. @@ -648,8 +692,8 @@ class SwapClientManager extends EventEmitter { this.emit('htlcAccepted', swapClient, rHash, amount, currency); }); swapClient.on('locked', () => { - if (this.walletPassword) { - swapClient.unlockWallet(this.walletPassword).catch(swapClient.logger.error); + if (isLndClient(swapClient) && swapClient.walletPassword) { + swapClient.unlockWallet(swapClient.walletPassword).catch(swapClient.logger.error); } // TODO(connext): unlock ConnextClient when it's implemented }); diff --git a/lib/swaps/Swaps.ts b/lib/swaps/Swaps.ts index 2752660b7..c69463479 100644 --- a/lib/swaps/Swaps.ts +++ b/lib/swaps/Swaps.ts @@ -10,8 +10,9 @@ import { PacketType } from '../p2p/packets'; import * as packets from '../p2p/packets/types'; import Peer from '../p2p/Peer'; import Pool from '../p2p/Pool'; +import { generatePreimageAndHash } from '../utils/cryptoUtils'; import { UnitConverter } from '../utils/UnitConverter'; -import { generatePreimageAndHash, setTimeoutPromise } from '../utils/utils'; +import { setTimeoutPromise } from '../utils/utils'; import { MAX_PAYMENT_TIME } from './consts'; import errors, { errorCodes } from './errors'; import SwapClient, { PaymentState } from './SwapClient'; diff --git a/lib/utils/cryptoUtils.ts b/lib/utils/cryptoUtils.ts new file mode 100644 index 000000000..45807a7af --- /dev/null +++ b/lib/utils/cryptoUtils.ts @@ -0,0 +1,49 @@ +import { createCipheriv, createDecipheriv, createHash, randomBytes as cryptoRandomBytes } from 'crypto'; +import { promisify } from 'util'; + +const ENCRYPTION_IV_LENGTH = 16; + +/** A promisified wrapper for the NodeJS `crypto.randomBytes` method. */ +export const randomBytes = promisify(cryptoRandomBytes); + +function getCipherKey(password: string) { + return createHash('sha256').update(password).digest(); +} + +/** + * Encrypts a Buffer or base64 string using a password + * @param payload a Buffer or base64 string + * @returns an encrypted Buffer + */ +export async function encrypt(payload: Buffer | string, password: string) { + const buf = typeof payload === 'string' ? Buffer.from(payload, 'utf8') : payload; + + const iv = await randomBytes(ENCRYPTION_IV_LENGTH); + const key = getCipherKey(password); + const cipher = createCipheriv('aes-256-cbc', key, iv); + return Buffer.concat([iv, cipher.update(buf), cipher.final()]); +} + +/** + * Decrypts a Buffer or base64 string using a password + * @param payload a Buffer or base64 string + * @returns a decrypted Buffer + */ +export function decrypt(payload: Buffer | string, password: string) { + const buf = typeof payload === 'string' ? Buffer.from(payload, 'base64') : payload; + + // the first 16 bytes contain the initialization vector + const iv = buf.slice(0, ENCRYPTION_IV_LENGTH); + const key = getCipherKey(password); + const encrypted = buf.slice(ENCRYPTION_IV_LENGTH); + const decipher = createDecipheriv('aes-256-cbc', key, iv); + return Buffer.concat([decipher.update(encrypted), decipher.final()]); +} + +/** Returns a random payment preimage and hash in hex encoding. */ +export async function generatePreimageAndHash() { + const bytes = await randomBytes(32); + const rPreimage = bytes.toString('hex'); + const rHash = createHash('sha256').update(bytes).digest('hex'); + return { rPreimage, rHash }; +} diff --git a/lib/utils/utils.ts b/lib/utils/utils.ts index 1e243e545..6a865cb05 100644 --- a/lib/utils/utils.ts +++ b/lib/utils/utils.ts @@ -1,4 +1,3 @@ -import { createHash, randomBytes as cryptoRandomBytes } from 'crypto'; import http from 'http'; // @ts-ignore import createKeccakHash from 'keccak'; @@ -158,9 +157,6 @@ export const isPlainObject = (obj: any) => { /** A promisified wrapper for the NodeJS `setTimeout` method. */ export const setTimeoutPromise = promisify(setTimeout); -/** A promisified wrapper for the NodeJS `crypto.randomBytes` method. */ -export const randomBytes = promisify(cryptoRandomBytes); - export const removeUndefinedProps = (typedObj: T): T => { const obj = typedObj as any; Object.keys(obj).forEach((key) => { @@ -205,14 +201,6 @@ export const sortOrders = (orders: T[], isBuy: boolean) }); }; -/** Returns a random payment preimage and hash in hex encoding. */ -export const generatePreimageAndHash = async () => { - const bytes = await randomBytes(32); - const rPreimage = bytes.toString('hex'); - const rHash = createHash('sha256').update(bytes).digest('hex'); - return { rPreimage, rHash }; -}; - export const base64ToHex = (b64: string) => { return Buffer.from(b64, 'base64').toString('hex'); }; diff --git a/proto/xudrpc.proto b/proto/xudrpc.proto index 75fe3e903..c53c746c7 100644 --- a/proto/xudrpc.proto +++ b/proto/xudrpc.proto @@ -73,6 +73,14 @@ service Xud { }; } + /* Changes the xud master password, including the wallet passwords for any underlying clients. + * shell: xucli changepass*/ + rpc ChangePassword(ChangePasswordRequest) returns (ChangePasswordResponse) { + option (google.api.http) = { + post: "/v1/changepass" + }; + } + /* Closes any existing payment channels with a peer for the specified currency. * shell: xucli closechannel [node_identifier ] [--force]*/ rpc CloseChannel(CloseChannelRequest) returns (CloseChannelResponse) { @@ -423,6 +431,12 @@ message Channels { uint32 closed = 4 [json_name = "closed"]; } +message ChangePasswordRequest { + string new_password = 1 [json_name = "new_password"]; + string old_password = 2 [json_name = "old_password"]; +} +message ChangePasswordResponse {} + message CloseChannelRequest { // The node pub key or alias of the peer with which to close any channels with. string node_identifier = 1 [json_name = "node_identifier"]; diff --git a/test/jest/NodeKey.spec.ts b/test/jest/NodeKey.spec.ts index 4daad3211..946ec5a9e 100644 --- a/test/jest/NodeKey.spec.ts +++ b/test/jest/NodeKey.spec.ts @@ -1,8 +1,8 @@ import secp256k1 from 'secp256k1'; +import { SwapClientType } from '../../lib/constants/enums'; import NodeKey from '../../lib/nodekey/NodeKey'; -import { randomBytes } from '../../lib/utils/utils'; +import { randomBytes } from '../../lib/utils/cryptoUtils'; import { getTempDir } from '../utils'; -import { SwapClientType } from '../../lib/constants/enums'; function validateNodeKey(nodeKey: NodeKey) { expect(nodeKey.pubKey).toHaveLength(66); @@ -11,33 +11,32 @@ function validateNodeKey(nodeKey: NodeKey) { } describe('NodeKey', () => { + const path = NodeKey.getPath(getTempDir(true)); + test('it should generate a valid node key', async () => { const nodeKey = await NodeKey['generate'](); validateNodeKey(nodeKey); }); test('it should write a nodekey to disk and read it back without encryption', async () => { - const nodeKey = await NodeKey['generate'](); - const path = NodeKey.getPath(getTempDir(true)); - await nodeKey.toFile(path); + const nodeKey = await NodeKey['generate'](path); + await nodeKey.toFile(); const nodeKeyFromDisk = await NodeKey.fromFile(path); expect(nodeKey.privKey.compare(nodeKeyFromDisk.privKey)).toEqual(0); }); test('it should write a nodekey to disk and read it back with encryption', async () => { const password = 'wasspord'; - const nodeKey = await NodeKey['generate'](); - const path = NodeKey.getPath(getTempDir(true)); - await nodeKey.toFile(path, password); + const nodeKey = await NodeKey['generate'](path); + await nodeKey.toFile(password); const nodeKeyFromDisk = await NodeKey.fromFile(path, password); expect(nodeKey.privKey.compare(nodeKeyFromDisk.privKey)).toEqual(0); }); test('it should write a nodekey to disk with encryption and fail reading it with the wrong password', async () => { const password = 'wasspord'; - const nodeKey = await NodeKey['generate'](); - const path = NodeKey.getPath(getTempDir(true)); - await nodeKey.toFile(path, password); + const nodeKey = await NodeKey['generate'](path); + await nodeKey.toFile(password); await expect(NodeKey.fromFile(path, 'wrongpassword')).rejects.toThrow(); }); diff --git a/test/jest/Orderbook.spec.ts b/test/jest/Orderbook.spec.ts index 8be87dcbf..6db0e0cf2 100644 --- a/test/jest/Orderbook.spec.ts +++ b/test/jest/Orderbook.spec.ts @@ -162,7 +162,7 @@ describe('OrderBook', () => { pool.broadcastOrder = jest.fn(); unitConverter = new UnitConverter(); unitConverter.init(); - swapClientManager = new SwapClientManager(config, loggers, unitConverter); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); swaps = new Swaps({ pool, swapClientManager, diff --git a/test/jest/SwapClientManager.spec.ts b/test/jest/SwapClientManager.spec.ts index 1308be9f1..9e9e2f4d8 100644 --- a/test/jest/SwapClientManager.spec.ts +++ b/test/jest/SwapClientManager.spec.ts @@ -116,8 +116,9 @@ describe('Swaps.SwapClientManager', () => { }); test('it initializes lnd-ltc and lnd-btc', async () => { - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); + expect(swapClientManager['swapClients'].size).toEqual(2); expect(onListenerMock).toHaveBeenCalledTimes(6); expect(swapClientManager.get('BTC')).not.toBeUndefined(); @@ -132,8 +133,9 @@ describe('Swaps.SwapClientManager', () => { }); test('it initializes lnd-ltc and lnd-btc', async () => { - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); + expect(swapClientManager['swapClients'].size).toEqual(2); expect(onListenerMock).toHaveBeenCalledTimes(6); expect(swapClientManager.get('BTC')).not.toBeUndefined(); @@ -144,8 +146,9 @@ describe('Swaps.SwapClientManager', () => { test('it initializes lnd-btc', async () => { config.lnd.LTC!.disable = true; - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); + expect(swapClientManager['swapClients'].size).toEqual(1); expect(onListenerMock).toHaveBeenCalledTimes(3); expect(swapClientManager.get('BTC')).not.toBeUndefined(); @@ -156,8 +159,9 @@ describe('Swaps.SwapClientManager', () => { test('it initializes nothing', async () => { config.lnd.BTC!.disable = true; config.lnd.LTC!.disable = true; - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); + expect(swapClientManager['swapClients'].size).toEqual(0); expect(onListenerMock).toHaveBeenCalledTimes(0); expect(swapClientManager.get('BTC')).toBeUndefined(); @@ -167,8 +171,9 @@ describe('Swaps.SwapClientManager', () => { }); test('closes lnd-btc and lnd-ltc', async () => { - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); + expect(swapClientManager['swapClients'].size).toEqual(2); swapClientManager.close(); expect(closeMock).toHaveBeenCalledTimes(2); @@ -180,8 +185,8 @@ describe('Swaps.SwapClientManager', () => { const setReservedInboundBtcAmount = jest.fn(); beforeEach(async () => { - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); swapClientManager.swapClients.get(currency)!.setReservedInboundAmount = setReservedInboundBtcAmount; }); @@ -228,17 +233,17 @@ describe('Swaps.SwapClientManager', () => { describe('openChannel', () => { let remoteIdentifier: string; - beforeEach(() => { + beforeEach(async () => { remoteIdentifier = '02afaef2634e5c7ca8d682b828a62bd040929b1e4b5030b21e2a0a891cf545b2e1'; + swapClientManager = new SwapClientManager(config, loggers, unitConverter, db.models); + await swapClientManager.init(); }); test('it fails without swap client', async () => { expect.assertions(1); const currency = 'BTC'; const amount = 16000000; - swapClientManager = new SwapClientManager(config, loggers, unitConverter); swapClientManager.get = jest.fn().mockReturnValue(undefined); - await swapClientManager.init(db.models); try { await swapClientManager.openChannel({ remoteIdentifier, currency, amount }); } catch (e) { @@ -249,8 +254,6 @@ describe('Swaps.SwapClientManager', () => { test('it fails without peerSwapClientPubKey', async () => { const currency = 'BTC'; const amount = 16000000; - swapClientManager = new SwapClientManager(config, loggers, unitConverter); - await swapClientManager.init(db.models); try { await swapClientManager.openChannel({ remoteIdentifier, currency, amount }); } catch (e) { @@ -261,13 +264,11 @@ describe('Swaps.SwapClientManager', () => { test('it opens a channel using lnd', async () => { const currency = 'BTC'; const amount = 16000000; - swapClientManager = new SwapClientManager(config, loggers, unitConverter); const getClientSpy = jest.spyOn(swapClientManager, 'get'); const lndListeningUris = [ '123.456.789.321:9735', '192.168.63.155:9777', ]; - await swapClientManager.init(db.models); await swapClientManager.openChannel({ remoteIdentifier, currency, amount, uris: lndListeningUris }); expect(getClientSpy).toHaveBeenCalledWith(currency); expect(mockLndOpenChannel).toHaveBeenCalledTimes(1); diff --git a/test/jest/cryptoUtils.spec.ts b/test/jest/cryptoUtils.spec.ts new file mode 100644 index 000000000..7fe2aad00 --- /dev/null +++ b/test/jest/cryptoUtils.spec.ts @@ -0,0 +1,24 @@ +import { decrypt, encrypt } from '../../lib/utils/cryptoUtils'; + +const password = 'wasspord'; +const payload = 'itsasecrettoeverybody'; + +describe('encrypt & decrypt', () => { + test('encrypts a message and then decrypts it', async () => { + const encrypted = await encrypt(payload, password); + const decrypted = decrypt(encrypted, password); + expect(decrypted.toString()).toEqual(payload); + }); + + test('encrypts a message, converts the decrypted bytes to base64 string, and then decrypts it', async () => { + const encrypted = await encrypt(payload, password); + const encryptedString = encrypted.toString('base64'); + const decrypted = decrypt(encryptedString, password); + expect(decrypted.toString()).toEqual(payload); + }); + + test('can not decrypt message using wrong password', async () => { + const encrypted = await encrypt(payload, password); + expect(() => decrypt(encrypted, 'wrongpass')).toThrow('error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt'); + }); +}); diff --git a/test/simulation/xudrpc/xudrpc.pb.go b/test/simulation/xudrpc/xudrpc.pb.go index b738a134e..2c4caacab 100644 --- a/test/simulation/xudrpc/xudrpc.pb.go +++ b/test/simulation/xudrpc/xudrpc.pb.go @@ -141,7 +141,7 @@ func (x Currency_SwapClient) String() string { } func (Currency_SwapClient) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{14, 0} + return fileDescriptor_6960a02cc0a63cf6, []int{16, 0} } type ListOrdersRequest_Owner int32 @@ -169,7 +169,7 @@ func (x ListOrdersRequest_Owner) String() string { } func (ListOrdersRequest_Owner) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{30, 0} + return fileDescriptor_6960a02cc0a63cf6, []int{32, 0} } type AddCurrencyResponse struct { @@ -555,6 +555,84 @@ func (m *Channels) GetClosed() uint32 { return 0 } +type ChangePasswordRequest struct { + NewPassword string `protobuf:"bytes,1,opt,name=new_password,proto3" json:"new_password,omitempty"` + OldPassword string `protobuf:"bytes,2,opt,name=old_password,proto3" json:"old_password,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ChangePasswordRequest) Reset() { *m = ChangePasswordRequest{} } +func (m *ChangePasswordRequest) String() string { return proto.CompactTextString(m) } +func (*ChangePasswordRequest) ProtoMessage() {} +func (*ChangePasswordRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_6960a02cc0a63cf6, []int{8} +} + +func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ChangePasswordRequest.Unmarshal(m, b) +} +func (m *ChangePasswordRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ChangePasswordRequest.Marshal(b, m, deterministic) +} +func (m *ChangePasswordRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChangePasswordRequest.Merge(m, src) +} +func (m *ChangePasswordRequest) XXX_Size() int { + return xxx_messageInfo_ChangePasswordRequest.Size(m) +} +func (m *ChangePasswordRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ChangePasswordRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ChangePasswordRequest proto.InternalMessageInfo + +func (m *ChangePasswordRequest) GetNewPassword() string { + if m != nil { + return m.NewPassword + } + return "" +} + +func (m *ChangePasswordRequest) GetOldPassword() string { + if m != nil { + return m.OldPassword + } + return "" +} + +type ChangePasswordResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ChangePasswordResponse) Reset() { *m = ChangePasswordResponse{} } +func (m *ChangePasswordResponse) String() string { return proto.CompactTextString(m) } +func (*ChangePasswordResponse) ProtoMessage() {} +func (*ChangePasswordResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_6960a02cc0a63cf6, []int{9} +} + +func (m *ChangePasswordResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ChangePasswordResponse.Unmarshal(m, b) +} +func (m *ChangePasswordResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ChangePasswordResponse.Marshal(b, m, deterministic) +} +func (m *ChangePasswordResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ChangePasswordResponse.Merge(m, src) +} +func (m *ChangePasswordResponse) XXX_Size() int { + return xxx_messageInfo_ChangePasswordResponse.Size(m) +} +func (m *ChangePasswordResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ChangePasswordResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ChangePasswordResponse proto.InternalMessageInfo + type CloseChannelRequest struct { // The node pub key or alias of the peer with which to close any channels with. NodeIdentifier string `protobuf:"bytes,1,opt,name=node_identifier,proto3" json:"node_identifier,omitempty"` @@ -580,7 +658,7 @@ func (m *CloseChannelRequest) Reset() { *m = CloseChannelRequest{} } func (m *CloseChannelRequest) String() string { return proto.CompactTextString(m) } func (*CloseChannelRequest) ProtoMessage() {} func (*CloseChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{8} + return fileDescriptor_6960a02cc0a63cf6, []int{10} } func (m *CloseChannelRequest) XXX_Unmarshal(b []byte) error { @@ -655,7 +733,7 @@ func (m *CloseChannelResponse) Reset() { *m = CloseChannelResponse{} } func (m *CloseChannelResponse) String() string { return proto.CompactTextString(m) } func (*CloseChannelResponse) ProtoMessage() {} func (*CloseChannelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{9} + return fileDescriptor_6960a02cc0a63cf6, []int{11} } func (m *CloseChannelResponse) XXX_Unmarshal(b []byte) error { @@ -695,7 +773,7 @@ func (m *ConnectRequest) Reset() { *m = ConnectRequest{} } func (m *ConnectRequest) String() string { return proto.CompactTextString(m) } func (*ConnectRequest) ProtoMessage() {} func (*ConnectRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{10} + return fileDescriptor_6960a02cc0a63cf6, []int{12} } func (m *ConnectRequest) XXX_Unmarshal(b []byte) error { @@ -733,7 +811,7 @@ func (m *ConnectResponse) Reset() { *m = ConnectResponse{} } func (m *ConnectResponse) String() string { return proto.CompactTextString(m) } func (*ConnectResponse) ProtoMessage() {} func (*ConnectResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{11} + return fileDescriptor_6960a02cc0a63cf6, []int{13} } func (m *ConnectResponse) XXX_Unmarshal(b []byte) error { @@ -767,7 +845,7 @@ func (m *CreateNodeRequest) Reset() { *m = CreateNodeRequest{} } func (m *CreateNodeRequest) String() string { return proto.CompactTextString(m) } func (*CreateNodeRequest) ProtoMessage() {} func (*CreateNodeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{12} + return fileDescriptor_6960a02cc0a63cf6, []int{14} } func (m *CreateNodeRequest) XXX_Unmarshal(b []byte) error { @@ -811,7 +889,7 @@ func (m *CreateNodeResponse) Reset() { *m = CreateNodeResponse{} } func (m *CreateNodeResponse) String() string { return proto.CompactTextString(m) } func (*CreateNodeResponse) ProtoMessage() {} func (*CreateNodeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{13} + return fileDescriptor_6960a02cc0a63cf6, []int{15} } func (m *CreateNodeResponse) XXX_Unmarshal(b []byte) error { @@ -875,7 +953,7 @@ func (m *Currency) Reset() { *m = Currency{} } func (m *Currency) String() string { return proto.CompactTextString(m) } func (*Currency) ProtoMessage() {} func (*Currency) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{14} + return fileDescriptor_6960a02cc0a63cf6, []int{16} } func (m *Currency) XXX_Unmarshal(b []byte) error { @@ -936,7 +1014,7 @@ func (m *DepositRequest) Reset() { *m = DepositRequest{} } func (m *DepositRequest) String() string { return proto.CompactTextString(m) } func (*DepositRequest) ProtoMessage() {} func (*DepositRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{15} + return fileDescriptor_6960a02cc0a63cf6, []int{17} } func (m *DepositRequest) XXX_Unmarshal(b []byte) error { @@ -976,7 +1054,7 @@ func (m *DepositResponse) Reset() { *m = DepositResponse{} } func (m *DepositResponse) String() string { return proto.CompactTextString(m) } func (*DepositResponse) ProtoMessage() {} func (*DepositResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{16} + return fileDescriptor_6960a02cc0a63cf6, []int{18} } func (m *DepositResponse) XXX_Unmarshal(b []byte) error { @@ -1016,7 +1094,7 @@ func (m *DiscoverNodesRequest) Reset() { *m = DiscoverNodesRequest{} } func (m *DiscoverNodesRequest) String() string { return proto.CompactTextString(m) } func (*DiscoverNodesRequest) ProtoMessage() {} func (*DiscoverNodesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{17} + return fileDescriptor_6960a02cc0a63cf6, []int{19} } func (m *DiscoverNodesRequest) XXX_Unmarshal(b []byte) error { @@ -1055,7 +1133,7 @@ func (m *DiscoverNodesResponse) Reset() { *m = DiscoverNodesResponse{} } func (m *DiscoverNodesResponse) String() string { return proto.CompactTextString(m) } func (*DiscoverNodesResponse) ProtoMessage() {} func (*DiscoverNodesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{18} + return fileDescriptor_6960a02cc0a63cf6, []int{20} } func (m *DiscoverNodesResponse) XXX_Unmarshal(b []byte) error { @@ -1101,7 +1179,7 @@ func (m *ExecuteSwapRequest) Reset() { *m = ExecuteSwapRequest{} } func (m *ExecuteSwapRequest) String() string { return proto.CompactTextString(m) } func (*ExecuteSwapRequest) ProtoMessage() {} func (*ExecuteSwapRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{19} + return fileDescriptor_6960a02cc0a63cf6, []int{21} } func (m *ExecuteSwapRequest) XXX_Unmarshal(b []byte) error { @@ -1163,7 +1241,7 @@ func (m *GetBalanceRequest) Reset() { *m = GetBalanceRequest{} } func (m *GetBalanceRequest) String() string { return proto.CompactTextString(m) } func (*GetBalanceRequest) ProtoMessage() {} func (*GetBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{20} + return fileDescriptor_6960a02cc0a63cf6, []int{22} } func (m *GetBalanceRequest) XXX_Unmarshal(b []byte) error { @@ -1203,7 +1281,7 @@ func (m *GetBalanceResponse) Reset() { *m = GetBalanceResponse{} } func (m *GetBalanceResponse) String() string { return proto.CompactTextString(m) } func (*GetBalanceResponse) ProtoMessage() {} func (*GetBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{21} + return fileDescriptor_6960a02cc0a63cf6, []int{23} } func (m *GetBalanceResponse) XXX_Unmarshal(b []byte) error { @@ -1241,7 +1319,7 @@ func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} } func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetInfoRequest) ProtoMessage() {} func (*GetInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{22} + return fileDescriptor_6960a02cc0a63cf6, []int{24} } func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error { @@ -1291,7 +1369,7 @@ func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} } func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetInfoResponse) ProtoMessage() {} func (*GetInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{23} + return fileDescriptor_6960a02cc0a63cf6, []int{25} } func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error { @@ -1399,7 +1477,7 @@ func (m *GetMnemonicRequest) Reset() { *m = GetMnemonicRequest{} } func (m *GetMnemonicRequest) String() string { return proto.CompactTextString(m) } func (*GetMnemonicRequest) ProtoMessage() {} func (*GetMnemonicRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{24} + return fileDescriptor_6960a02cc0a63cf6, []int{26} } func (m *GetMnemonicRequest) XXX_Unmarshal(b []byte) error { @@ -1431,7 +1509,7 @@ func (m *GetMnemonicResponse) Reset() { *m = GetMnemonicResponse{} } func (m *GetMnemonicResponse) String() string { return proto.CompactTextString(m) } func (*GetMnemonicResponse) ProtoMessage() {} func (*GetMnemonicResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{25} + return fileDescriptor_6960a02cc0a63cf6, []int{27} } func (m *GetMnemonicResponse) XXX_Unmarshal(b []byte) error { @@ -1471,7 +1549,7 @@ func (m *GetNodeInfoRequest) Reset() { *m = GetNodeInfoRequest{} } func (m *GetNodeInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetNodeInfoRequest) ProtoMessage() {} func (*GetNodeInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{26} + return fileDescriptor_6960a02cc0a63cf6, []int{28} } func (m *GetNodeInfoRequest) XXX_Unmarshal(b []byte) error { @@ -1514,7 +1592,7 @@ func (m *GetNodeInfoResponse) Reset() { *m = GetNodeInfoResponse{} } func (m *GetNodeInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetNodeInfoResponse) ProtoMessage() {} func (*GetNodeInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{27} + return fileDescriptor_6960a02cc0a63cf6, []int{29} } func (m *GetNodeInfoResponse) XXX_Unmarshal(b []byte) error { @@ -1559,7 +1637,7 @@ func (m *ListCurrenciesRequest) Reset() { *m = ListCurrenciesRequest{} } func (m *ListCurrenciesRequest) String() string { return proto.CompactTextString(m) } func (*ListCurrenciesRequest) ProtoMessage() {} func (*ListCurrenciesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{28} + return fileDescriptor_6960a02cc0a63cf6, []int{30} } func (m *ListCurrenciesRequest) XXX_Unmarshal(b []byte) error { @@ -1592,7 +1670,7 @@ func (m *ListCurrenciesResponse) Reset() { *m = ListCurrenciesResponse{} func (m *ListCurrenciesResponse) String() string { return proto.CompactTextString(m) } func (*ListCurrenciesResponse) ProtoMessage() {} func (*ListCurrenciesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{29} + return fileDescriptor_6960a02cc0a63cf6, []int{31} } func (m *ListCurrenciesResponse) XXX_Unmarshal(b []byte) error { @@ -1638,7 +1716,7 @@ func (m *ListOrdersRequest) Reset() { *m = ListOrdersRequest{} } func (m *ListOrdersRequest) String() string { return proto.CompactTextString(m) } func (*ListOrdersRequest) ProtoMessage() {} func (*ListOrdersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{30} + return fileDescriptor_6960a02cc0a63cf6, []int{32} } func (m *ListOrdersRequest) XXX_Unmarshal(b []byte) error { @@ -1699,7 +1777,7 @@ func (m *ListOrdersResponse) Reset() { *m = ListOrdersResponse{} } func (m *ListOrdersResponse) String() string { return proto.CompactTextString(m) } func (*ListOrdersResponse) ProtoMessage() {} func (*ListOrdersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{31} + return fileDescriptor_6960a02cc0a63cf6, []int{33} } func (m *ListOrdersResponse) XXX_Unmarshal(b []byte) error { @@ -1737,7 +1815,7 @@ func (m *ListPairsRequest) Reset() { *m = ListPairsRequest{} } func (m *ListPairsRequest) String() string { return proto.CompactTextString(m) } func (*ListPairsRequest) ProtoMessage() {} func (*ListPairsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{32} + return fileDescriptor_6960a02cc0a63cf6, []int{34} } func (m *ListPairsRequest) XXX_Unmarshal(b []byte) error { @@ -1770,7 +1848,7 @@ func (m *ListPairsResponse) Reset() { *m = ListPairsResponse{} } func (m *ListPairsResponse) String() string { return proto.CompactTextString(m) } func (*ListPairsResponse) ProtoMessage() {} func (*ListPairsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{33} + return fileDescriptor_6960a02cc0a63cf6, []int{35} } func (m *ListPairsResponse) XXX_Unmarshal(b []byte) error { @@ -1808,7 +1886,7 @@ func (m *ListPeersRequest) Reset() { *m = ListPeersRequest{} } func (m *ListPeersRequest) String() string { return proto.CompactTextString(m) } func (*ListPeersRequest) ProtoMessage() {} func (*ListPeersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{34} + return fileDescriptor_6960a02cc0a63cf6, []int{36} } func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error { @@ -1841,7 +1919,7 @@ func (m *ListPeersResponse) Reset() { *m = ListPeersResponse{} } func (m *ListPeersResponse) String() string { return proto.CompactTextString(m) } func (*ListPeersResponse) ProtoMessage() {} func (*ListPeersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{35} + return fileDescriptor_6960a02cc0a63cf6, []int{37} } func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error { @@ -1886,7 +1964,7 @@ func (m *LndInfo) Reset() { *m = LndInfo{} } func (m *LndInfo) String() string { return proto.CompactTextString(m) } func (*LndInfo) ProtoMessage() {} func (*LndInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{36} + return fileDescriptor_6960a02cc0a63cf6, []int{38} } func (m *LndInfo) XXX_Unmarshal(b []byte) error { @@ -1970,7 +2048,7 @@ func (m *NodeIdentifier) Reset() { *m = NodeIdentifier{} } func (m *NodeIdentifier) String() string { return proto.CompactTextString(m) } func (*NodeIdentifier) ProtoMessage() {} func (*NodeIdentifier) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{37} + return fileDescriptor_6960a02cc0a63cf6, []int{39} } func (m *NodeIdentifier) XXX_Unmarshal(b []byte) error { @@ -2025,7 +2103,7 @@ func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} } func (m *OpenChannelRequest) String() string { return proto.CompactTextString(m) } func (*OpenChannelRequest) ProtoMessage() {} func (*OpenChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{38} + return fileDescriptor_6960a02cc0a63cf6, []int{40} } func (m *OpenChannelRequest) XXX_Unmarshal(b []byte) error { @@ -2093,7 +2171,7 @@ func (m *OpenChannelResponse) Reset() { *m = OpenChannelResponse{} } func (m *OpenChannelResponse) String() string { return proto.CompactTextString(m) } func (*OpenChannelResponse) ProtoMessage() {} func (*OpenChannelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{39} + return fileDescriptor_6960a02cc0a63cf6, []int{41} } func (m *OpenChannelResponse) XXX_Unmarshal(b []byte) error { @@ -2151,7 +2229,7 @@ func (m *Order) Reset() { *m = Order{} } func (m *Order) String() string { return proto.CompactTextString(m) } func (*Order) ProtoMessage() {} func (*Order) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{40} + return fileDescriptor_6960a02cc0a63cf6, []int{42} } func (m *Order) XXX_Unmarshal(b []byte) error { @@ -2262,7 +2340,7 @@ func (m *OrderRemoval) Reset() { *m = OrderRemoval{} } func (m *OrderRemoval) String() string { return proto.CompactTextString(m) } func (*OrderRemoval) ProtoMessage() {} func (*OrderRemoval) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{41} + return fileDescriptor_6960a02cc0a63cf6, []int{43} } func (m *OrderRemoval) XXX_Unmarshal(b []byte) error { @@ -2332,7 +2410,7 @@ func (m *Orders) Reset() { *m = Orders{} } func (m *Orders) String() string { return proto.CompactTextString(m) } func (*Orders) ProtoMessage() {} func (*Orders) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{42} + return fileDescriptor_6960a02cc0a63cf6, []int{44} } func (m *Orders) XXX_Unmarshal(b []byte) error { @@ -2381,7 +2459,7 @@ func (m *OrdersCount) Reset() { *m = OrdersCount{} } func (m *OrdersCount) String() string { return proto.CompactTextString(m) } func (*OrdersCount) ProtoMessage() {} func (*OrdersCount) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{43} + return fileDescriptor_6960a02cc0a63cf6, []int{45} } func (m *OrdersCount) XXX_Unmarshal(b []byte) error { @@ -2430,7 +2508,7 @@ func (m *OrderUpdate) Reset() { *m = OrderUpdate{} } func (m *OrderUpdate) String() string { return proto.CompactTextString(m) } func (*OrderUpdate) ProtoMessage() {} func (*OrderUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{44} + return fileDescriptor_6960a02cc0a63cf6, []int{46} } func (m *OrderUpdate) XXX_Unmarshal(b []byte) error { @@ -2522,7 +2600,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} func (*Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{45} + return fileDescriptor_6960a02cc0a63cf6, []int{47} } func (m *Peer) XXX_Unmarshal(b []byte) error { @@ -2624,7 +2702,7 @@ func (m *PlaceOrderRequest) Reset() { *m = PlaceOrderRequest{} } func (m *PlaceOrderRequest) String() string { return proto.CompactTextString(m) } func (*PlaceOrderRequest) ProtoMessage() {} func (*PlaceOrderRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{46} + return fileDescriptor_6960a02cc0a63cf6, []int{48} } func (m *PlaceOrderRequest) XXX_Unmarshal(b []byte) error { @@ -2712,7 +2790,7 @@ func (m *PlaceOrderResponse) Reset() { *m = PlaceOrderResponse{} } func (m *PlaceOrderResponse) String() string { return proto.CompactTextString(m) } func (*PlaceOrderResponse) ProtoMessage() {} func (*PlaceOrderResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{47} + return fileDescriptor_6960a02cc0a63cf6, []int{49} } func (m *PlaceOrderResponse) XXX_Unmarshal(b []byte) error { @@ -2777,7 +2855,7 @@ func (m *PlaceOrderEvent) Reset() { *m = PlaceOrderEvent{} } func (m *PlaceOrderEvent) String() string { return proto.CompactTextString(m) } func (*PlaceOrderEvent) ProtoMessage() {} func (*PlaceOrderEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{48} + return fileDescriptor_6960a02cc0a63cf6, []int{50} } func (m *PlaceOrderEvent) XXX_Unmarshal(b []byte) error { @@ -2885,7 +2963,7 @@ func (m *ConnextInfo) Reset() { *m = ConnextInfo{} } func (m *ConnextInfo) String() string { return proto.CompactTextString(m) } func (*ConnextInfo) ProtoMessage() {} func (*ConnextInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{49} + return fileDescriptor_6960a02cc0a63cf6, []int{51} } func (m *ConnextInfo) XXX_Unmarshal(b []byte) error { @@ -2946,7 +3024,7 @@ func (m *RemoveCurrencyRequest) Reset() { *m = RemoveCurrencyRequest{} } func (m *RemoveCurrencyRequest) String() string { return proto.CompactTextString(m) } func (*RemoveCurrencyRequest) ProtoMessage() {} func (*RemoveCurrencyRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{50} + return fileDescriptor_6960a02cc0a63cf6, []int{52} } func (m *RemoveCurrencyRequest) XXX_Unmarshal(b []byte) error { @@ -2984,7 +3062,7 @@ func (m *RemoveCurrencyResponse) Reset() { *m = RemoveCurrencyResponse{} func (m *RemoveCurrencyResponse) String() string { return proto.CompactTextString(m) } func (*RemoveCurrencyResponse) ProtoMessage() {} func (*RemoveCurrencyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{51} + return fileDescriptor_6960a02cc0a63cf6, []int{53} } func (m *RemoveCurrencyResponse) XXX_Unmarshal(b []byte) error { @@ -3020,7 +3098,7 @@ func (m *RemoveOrderRequest) Reset() { *m = RemoveOrderRequest{} } func (m *RemoveOrderRequest) String() string { return proto.CompactTextString(m) } func (*RemoveOrderRequest) ProtoMessage() {} func (*RemoveOrderRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{52} + return fileDescriptor_6960a02cc0a63cf6, []int{54} } func (m *RemoveOrderRequest) XXX_Unmarshal(b []byte) error { @@ -3074,7 +3152,7 @@ func (m *RemoveOrderResponse) Reset() { *m = RemoveOrderResponse{} } func (m *RemoveOrderResponse) String() string { return proto.CompactTextString(m) } func (*RemoveOrderResponse) ProtoMessage() {} func (*RemoveOrderResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{53} + return fileDescriptor_6960a02cc0a63cf6, []int{55} } func (m *RemoveOrderResponse) XXX_Unmarshal(b []byte) error { @@ -3133,7 +3211,7 @@ func (m *RemoveAllOrdersRequest) Reset() { *m = RemoveAllOrdersRequest{} func (m *RemoveAllOrdersRequest) String() string { return proto.CompactTextString(m) } func (*RemoveAllOrdersRequest) ProtoMessage() {} func (*RemoveAllOrdersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{54} + return fileDescriptor_6960a02cc0a63cf6, []int{56} } func (m *RemoveAllOrdersRequest) XXX_Unmarshal(b []byte) error { @@ -3168,7 +3246,7 @@ func (m *RemoveAllOrdersResponse) Reset() { *m = RemoveAllOrdersResponse func (m *RemoveAllOrdersResponse) String() string { return proto.CompactTextString(m) } func (*RemoveAllOrdersResponse) ProtoMessage() {} func (*RemoveAllOrdersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{55} + return fileDescriptor_6960a02cc0a63cf6, []int{57} } func (m *RemoveAllOrdersResponse) XXX_Unmarshal(b []byte) error { @@ -3215,7 +3293,7 @@ func (m *RemovePairRequest) Reset() { *m = RemovePairRequest{} } func (m *RemovePairRequest) String() string { return proto.CompactTextString(m) } func (*RemovePairRequest) ProtoMessage() {} func (*RemovePairRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{56} + return fileDescriptor_6960a02cc0a63cf6, []int{58} } func (m *RemovePairRequest) XXX_Unmarshal(b []byte) error { @@ -3253,7 +3331,7 @@ func (m *RemovePairResponse) Reset() { *m = RemovePairResponse{} } func (m *RemovePairResponse) String() string { return proto.CompactTextString(m) } func (*RemovePairResponse) ProtoMessage() {} func (*RemovePairResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{57} + return fileDescriptor_6960a02cc0a63cf6, []int{59} } func (m *RemovePairResponse) XXX_Unmarshal(b []byte) error { @@ -3293,7 +3371,7 @@ func (m *RestoreNodeRequest) Reset() { *m = RestoreNodeRequest{} } func (m *RestoreNodeRequest) String() string { return proto.CompactTextString(m) } func (*RestoreNodeRequest) ProtoMessage() {} func (*RestoreNodeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{58} + return fileDescriptor_6960a02cc0a63cf6, []int{60} } func (m *RestoreNodeRequest) XXX_Unmarshal(b []byte) error { @@ -3356,7 +3434,7 @@ func (m *RestoreNodeResponse) Reset() { *m = RestoreNodeResponse{} } func (m *RestoreNodeResponse) String() string { return proto.CompactTextString(m) } func (*RestoreNodeResponse) ProtoMessage() {} func (*RestoreNodeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{59} + return fileDescriptor_6960a02cc0a63cf6, []int{61} } func (m *RestoreNodeResponse) XXX_Unmarshal(b []byte) error { @@ -3402,7 +3480,7 @@ func (m *SetLogLevelRequest) Reset() { *m = SetLogLevelRequest{} } func (m *SetLogLevelRequest) String() string { return proto.CompactTextString(m) } func (*SetLogLevelRequest) ProtoMessage() {} func (*SetLogLevelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{60} + return fileDescriptor_6960a02cc0a63cf6, []int{62} } func (m *SetLogLevelRequest) XXX_Unmarshal(b []byte) error { @@ -3440,7 +3518,7 @@ func (m *SetLogLevelResponse) Reset() { *m = SetLogLevelResponse{} } func (m *SetLogLevelResponse) String() string { return proto.CompactTextString(m) } func (*SetLogLevelResponse) ProtoMessage() {} func (*SetLogLevelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{61} + return fileDescriptor_6960a02cc0a63cf6, []int{63} } func (m *SetLogLevelResponse) XXX_Unmarshal(b []byte) error { @@ -3471,7 +3549,7 @@ func (m *ShutdownRequest) Reset() { *m = ShutdownRequest{} } func (m *ShutdownRequest) String() string { return proto.CompactTextString(m) } func (*ShutdownRequest) ProtoMessage() {} func (*ShutdownRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{62} + return fileDescriptor_6960a02cc0a63cf6, []int{64} } func (m *ShutdownRequest) XXX_Unmarshal(b []byte) error { @@ -3502,7 +3580,7 @@ func (m *ShutdownResponse) Reset() { *m = ShutdownResponse{} } func (m *ShutdownResponse) String() string { return proto.CompactTextString(m) } func (*ShutdownResponse) ProtoMessage() {} func (*ShutdownResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{63} + return fileDescriptor_6960a02cc0a63cf6, []int{65} } func (m *ShutdownResponse) XXX_Unmarshal(b []byte) error { @@ -3535,7 +3613,7 @@ func (m *SubscribeOrdersRequest) Reset() { *m = SubscribeOrdersRequest{} func (m *SubscribeOrdersRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeOrdersRequest) ProtoMessage() {} func (*SubscribeOrdersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{64} + return fileDescriptor_6960a02cc0a63cf6, []int{66} } func (m *SubscribeOrdersRequest) XXX_Unmarshal(b []byte) error { @@ -3573,7 +3651,7 @@ func (m *SubscribeSwapsAcceptedRequest) Reset() { *m = SubscribeSwapsAcc func (m *SubscribeSwapsAcceptedRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeSwapsAcceptedRequest) ProtoMessage() {} func (*SubscribeSwapsAcceptedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{65} + return fileDescriptor_6960a02cc0a63cf6, []int{67} } func (m *SubscribeSwapsAcceptedRequest) XXX_Unmarshal(b []byte) error { @@ -3607,7 +3685,7 @@ func (m *SubscribeSwapsRequest) Reset() { *m = SubscribeSwapsRequest{} } func (m *SubscribeSwapsRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeSwapsRequest) ProtoMessage() {} func (*SubscribeSwapsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{66} + return fileDescriptor_6960a02cc0a63cf6, []int{68} } func (m *SubscribeSwapsRequest) XXX_Unmarshal(b []byte) error { @@ -3667,7 +3745,7 @@ func (m *SwapAccepted) Reset() { *m = SwapAccepted{} } func (m *SwapAccepted) String() string { return proto.CompactTextString(m) } func (*SwapAccepted) ProtoMessage() {} func (*SwapAccepted) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{67} + return fileDescriptor_6960a02cc0a63cf6, []int{69} } func (m *SwapAccepted) XXX_Unmarshal(b []byte) error { @@ -3785,7 +3863,7 @@ func (m *SwapFailure) Reset() { *m = SwapFailure{} } func (m *SwapFailure) String() string { return proto.CompactTextString(m) } func (*SwapFailure) ProtoMessage() {} func (*SwapFailure) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{68} + return fileDescriptor_6960a02cc0a63cf6, []int{70} } func (m *SwapFailure) XXX_Unmarshal(b []byte) error { @@ -3877,7 +3955,7 @@ func (m *SwapSuccess) Reset() { *m = SwapSuccess{} } func (m *SwapSuccess) String() string { return proto.CompactTextString(m) } func (*SwapSuccess) ProtoMessage() {} func (*SwapSuccess) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{69} + return fileDescriptor_6960a02cc0a63cf6, []int{71} } func (m *SwapSuccess) XXX_Unmarshal(b []byte) error { @@ -4021,7 +4099,7 @@ func (m *Trade) Reset() { *m = Trade{} } func (m *Trade) String() string { return proto.CompactTextString(m) } func (*Trade) ProtoMessage() {} func (*Trade) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{70} + return fileDescriptor_6960a02cc0a63cf6, []int{72} } func (m *Trade) XXX_Unmarshal(b []byte) error { @@ -4124,7 +4202,7 @@ func (m *TradeHistoryRequest) Reset() { *m = TradeHistoryRequest{} } func (m *TradeHistoryRequest) String() string { return proto.CompactTextString(m) } func (*TradeHistoryRequest) ProtoMessage() {} func (*TradeHistoryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{71} + return fileDescriptor_6960a02cc0a63cf6, []int{73} } func (m *TradeHistoryRequest) XXX_Unmarshal(b []byte) error { @@ -4163,7 +4241,7 @@ func (m *TradeHistoryResponse) Reset() { *m = TradeHistoryResponse{} } func (m *TradeHistoryResponse) String() string { return proto.CompactTextString(m) } func (*TradeHistoryResponse) ProtoMessage() {} func (*TradeHistoryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{72} + return fileDescriptor_6960a02cc0a63cf6, []int{74} } func (m *TradeHistoryResponse) XXX_Unmarshal(b []byte) error { @@ -4209,7 +4287,7 @@ func (m *TradingLimits) Reset() { *m = TradingLimits{} } func (m *TradingLimits) String() string { return proto.CompactTextString(m) } func (*TradingLimits) ProtoMessage() {} func (*TradingLimits) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{73} + return fileDescriptor_6960a02cc0a63cf6, []int{75} } func (m *TradingLimits) XXX_Unmarshal(b []byte) error { @@ -4271,7 +4349,7 @@ func (m *TradingLimitsRequest) Reset() { *m = TradingLimitsRequest{} } func (m *TradingLimitsRequest) String() string { return proto.CompactTextString(m) } func (*TradingLimitsRequest) ProtoMessage() {} func (*TradingLimitsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{74} + return fileDescriptor_6960a02cc0a63cf6, []int{76} } func (m *TradingLimitsRequest) XXX_Unmarshal(b []byte) error { @@ -4311,7 +4389,7 @@ func (m *TradingLimitsResponse) Reset() { *m = TradingLimitsResponse{} } func (m *TradingLimitsResponse) String() string { return proto.CompactTextString(m) } func (*TradingLimitsResponse) ProtoMessage() {} func (*TradingLimitsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{75} + return fileDescriptor_6960a02cc0a63cf6, []int{77} } func (m *TradingLimitsResponse) XXX_Unmarshal(b []byte) error { @@ -4353,7 +4431,7 @@ func (m *UnbanRequest) Reset() { *m = UnbanRequest{} } func (m *UnbanRequest) String() string { return proto.CompactTextString(m) } func (*UnbanRequest) ProtoMessage() {} func (*UnbanRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{76} + return fileDescriptor_6960a02cc0a63cf6, []int{78} } func (m *UnbanRequest) XXX_Unmarshal(b []byte) error { @@ -4398,7 +4476,7 @@ func (m *UnbanResponse) Reset() { *m = UnbanResponse{} } func (m *UnbanResponse) String() string { return proto.CompactTextString(m) } func (*UnbanResponse) ProtoMessage() {} func (*UnbanResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{77} + return fileDescriptor_6960a02cc0a63cf6, []int{79} } func (m *UnbanResponse) XXX_Unmarshal(b []byte) error { @@ -4432,7 +4510,7 @@ func (m *UnlockNodeRequest) Reset() { *m = UnlockNodeRequest{} } func (m *UnlockNodeRequest) String() string { return proto.CompactTextString(m) } func (*UnlockNodeRequest) ProtoMessage() {} func (*UnlockNodeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{78} + return fileDescriptor_6960a02cc0a63cf6, []int{80} } func (m *UnlockNodeRequest) XXX_Unmarshal(b []byte) error { @@ -4474,7 +4552,7 @@ func (m *UnlockNodeResponse) Reset() { *m = UnlockNodeResponse{} } func (m *UnlockNodeResponse) String() string { return proto.CompactTextString(m) } func (*UnlockNodeResponse) ProtoMessage() {} func (*UnlockNodeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{79} + return fileDescriptor_6960a02cc0a63cf6, []int{81} } func (m *UnlockNodeResponse) XXX_Unmarshal(b []byte) error { @@ -4530,7 +4608,7 @@ func (m *WithdrawRequest) Reset() { *m = WithdrawRequest{} } func (m *WithdrawRequest) String() string { return proto.CompactTextString(m) } func (*WithdrawRequest) ProtoMessage() {} func (*WithdrawRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{80} + return fileDescriptor_6960a02cc0a63cf6, []int{82} } func (m *WithdrawRequest) XXX_Unmarshal(b []byte) error { @@ -4598,7 +4676,7 @@ func (m *WithdrawResponse) Reset() { *m = WithdrawResponse{} } func (m *WithdrawResponse) String() string { return proto.CompactTextString(m) } func (*WithdrawResponse) ProtoMessage() {} func (*WithdrawResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6960a02cc0a63cf6, []int{81} + return fileDescriptor_6960a02cc0a63cf6, []int{83} } func (m *WithdrawResponse) XXX_Unmarshal(b []byte) error { @@ -4640,6 +4718,8 @@ func init() { proto.RegisterType((*BanResponse)(nil), "xudrpc.BanResponse") proto.RegisterType((*Chain)(nil), "xudrpc.Chain") proto.RegisterType((*Channels)(nil), "xudrpc.Channels") + proto.RegisterType((*ChangePasswordRequest)(nil), "xudrpc.ChangePasswordRequest") + proto.RegisterType((*ChangePasswordResponse)(nil), "xudrpc.ChangePasswordResponse") proto.RegisterType((*CloseChannelRequest)(nil), "xudrpc.CloseChannelRequest") proto.RegisterType((*CloseChannelResponse)(nil), "xudrpc.CloseChannelResponse") proto.RegisterType((*ConnectRequest)(nil), "xudrpc.ConnectRequest") @@ -4725,264 +4805,268 @@ func init() { func init() { proto.RegisterFile("xudrpc.proto", fileDescriptor_6960a02cc0a63cf6) } var fileDescriptor_6960a02cc0a63cf6 = []byte{ - // 4097 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x4d, 0x6c, 0x1c, 0xc9, - 0x5a, 0xee, 0xf9, 0xf1, 0x8c, 0xbf, 0xf9, 0x75, 0xf9, 0x27, 0x93, 0xd9, 0xec, 0x6e, 0x5e, 0xb1, - 0x59, 0x65, 0xbd, 0xbb, 0x4e, 0xf0, 0xf2, 0xd8, 0xb7, 0x79, 0x64, 0xb5, 0xb6, 0x33, 0x2f, 0xc9, - 0xae, 0x9f, 0x1d, 0xb5, 0x93, 0x4d, 0x78, 0x82, 0xd7, 0xea, 0xe9, 0xae, 0xd8, 0x4d, 0xda, 0xdd, - 0xb3, 0xdd, 0x3d, 0x76, 0x0c, 0x17, 0xf4, 0xc4, 0x09, 0x0e, 0x1c, 0x10, 0x67, 0x38, 0x21, 0x24, - 0x10, 0x57, 0x4e, 0x48, 0x9c, 0xb9, 0x72, 0x40, 0x02, 0x2e, 0x48, 0xdc, 0x91, 0x10, 0x57, 0x24, - 0x54, 0x7f, 0x5d, 0x55, 0xdd, 0x3d, 0x7e, 0xc9, 0x0a, 0xb8, 0x4d, 0x7d, 0xf5, 0xf5, 0xf7, 0x55, - 0x7d, 0xff, 0xf5, 0x55, 0x0d, 0x74, 0x5f, 0xcf, 0xfd, 0x64, 0xe6, 0x6d, 0xcf, 0x92, 0x38, 0x8b, - 0xd1, 0x32, 0x1f, 0x8d, 0x57, 0xdd, 0x28, 0x8a, 0x33, 0x37, 0x0b, 0xe2, 0x28, 0xe5, 0x53, 0x78, - 0x03, 0xd6, 0x76, 0x7d, 0x7f, 0x7f, 0x9e, 0x24, 0x24, 0xf2, 0x2e, 0x6d, 0x92, 0xce, 0xe2, 0x28, - 0x25, 0xf8, 0xe7, 0xd0, 0xdf, 0xf5, 0xfd, 0x27, 0x6e, 0x90, 0xd8, 0xe4, 0xbb, 0x39, 0x49, 0x33, - 0xf4, 0x01, 0xf4, 0xa6, 0x6e, 0x4a, 0x1c, 0x4f, 0xa0, 0x8e, 0xac, 0x9b, 0xd6, 0xed, 0x15, 0xdb, - 0x04, 0xa2, 0x0f, 0xa1, 0xff, 0xdd, 0x3c, 0xce, 0x34, 0xb4, 0x1a, 0x43, 0x2b, 0x40, 0xf1, 0x2a, - 0x0c, 0x72, 0xfa, 0x82, 0xe5, 0xdf, 0xd6, 0xa0, 0xb5, 0xe7, 0x86, 0x6e, 0xe4, 0x11, 0xca, 0x2c, - 0x8b, 0x33, 0x37, 0x74, 0xa6, 0x1c, 0xc0, 0x98, 0x35, 0x6c, 0x13, 0x88, 0x6e, 0xc3, 0xc0, 0x3b, - 0x75, 0xa3, 0x88, 0x28, 0xbc, 0x1a, 0xc3, 0x2b, 0x82, 0xd1, 0x8f, 0xe0, 0xda, 0x8c, 0x44, 0x7e, - 0x10, 0x9d, 0x38, 0xc5, 0x2f, 0xea, 0xec, 0x8b, 0x45, 0xd3, 0xe8, 0x1e, 0x8c, 0x82, 0xc8, 0xf5, - 0xb2, 0xe0, 0x9c, 0x94, 0x3e, 0x6d, 0xb0, 0x4f, 0x17, 0xce, 0x53, 0x61, 0x5c, 0xb8, 0x61, 0x48, - 0xb2, 0xfc, 0x8b, 0x26, 0xfb, 0xa2, 0x00, 0x45, 0x5f, 0xc2, 0x78, 0x1e, 0x79, 0x71, 0xf4, 0x32, - 0x48, 0xce, 0x88, 0xef, 0x14, 0xbe, 0x59, 0x66, 0xdf, 0x5c, 0x81, 0x81, 0x7f, 0x1d, 0x60, 0xcf, - 0x8d, 0xa4, 0xa2, 0x6e, 0xc3, 0x20, 0x8a, 0x7d, 0xe2, 0x04, 0x3e, 0x89, 0xb2, 0xe0, 0x65, 0x40, - 0x12, 0xa1, 0xaa, 0x22, 0x18, 0xf7, 0xa0, 0xc3, 0xbe, 0x13, 0x0a, 0xf8, 0x1c, 0x9a, 0xfb, 0xa7, - 0x6e, 0x10, 0xa1, 0x75, 0x68, 0x7a, 0xf4, 0x87, 0xf8, 0x8e, 0x0f, 0xd0, 0x08, 0x5a, 0x11, 0xc9, - 0x2e, 0xe2, 0xe4, 0x95, 0xd0, 0xa9, 0x1c, 0xe2, 0x19, 0xb4, 0xf7, 0xf9, 0xd6, 0x53, 0xb4, 0x09, - 0xcb, 0x5c, 0x1a, 0xec, 0xe3, 0x9e, 0x2d, 0x46, 0x68, 0x0c, 0x6d, 0x29, 0x27, 0xf6, 0x79, 0xcf, - 0xce, 0xc7, 0x94, 0xb2, 0x10, 0x3f, 0xd3, 0x46, 0xcf, 0x96, 0x43, 0x4a, 0xcd, 0x0b, 0xe3, 0x94, - 0xf8, 0x4c, 0xd6, 0x3d, 0x5b, 0x8c, 0xf0, 0xdf, 0x59, 0xb0, 0xb6, 0x4f, 0x7f, 0x0a, 0xbe, 0x6f, - 0xbd, 0x77, 0xba, 0x9e, 0x82, 0x89, 0xe6, 0x63, 0xba, 0xff, 0x97, 0x71, 0x22, 0x6c, 0xa3, 0x6d, - 0xf3, 0x01, 0xba, 0x09, 0x1d, 0x9f, 0xa4, 0x59, 0x10, 0x31, 0xff, 0x61, 0x0b, 0x5a, 0xb1, 0x75, - 0x10, 0xdb, 0xfb, 0x59, 0x3c, 0x8f, 0x32, 0xa1, 0x67, 0x31, 0x42, 0x43, 0xa8, 0xbf, 0x24, 0x52, - 0x91, 0xf4, 0x27, 0xfe, 0x0a, 0xd6, 0xcd, 0xe5, 0x73, 0x15, 0xd0, 0xf5, 0x67, 0x89, 0x1b, 0xa5, - 0x54, 0x30, 0x71, 0xe4, 0x04, 0x7e, 0x3a, 0xb2, 0x6e, 0xd6, 0xe9, 0xfa, 0x0b, 0x60, 0xfc, 0x09, - 0xf4, 0xf7, 0xe3, 0x28, 0x22, 0x5e, 0x26, 0xf7, 0x3e, 0x86, 0x36, 0xdb, 0xe4, 0x3c, 0x09, 0xc4, - 0xa6, 0xf3, 0x31, 0x75, 0xb7, 0x1c, 0x5b, 0x68, 0xfb, 0x0e, 0xac, 0xee, 0x27, 0xc4, 0xcd, 0xc8, - 0x61, 0xec, 0x13, 0x8d, 0xc6, 0xcc, 0x4d, 0xd3, 0x8b, 0x38, 0xf1, 0x25, 0x0d, 0x39, 0xc6, 0x7f, - 0x6a, 0x01, 0xd2, 0xbf, 0x10, 0x4b, 0xfe, 0x15, 0xe8, 0xa5, 0x84, 0xf8, 0xce, 0x59, 0x44, 0xce, - 0xe2, 0x28, 0xf0, 0xc4, 0x82, 0xbb, 0x14, 0xf8, 0x53, 0x01, 0x43, 0x1f, 0xc1, 0x30, 0x88, 0x82, - 0x2c, 0x70, 0xc3, 0xe0, 0x77, 0x89, 0xef, 0x84, 0x91, 0x9f, 0x8e, 0x6a, 0x7c, 0x63, 0x1a, 0xfc, - 0x20, 0xf2, 0x53, 0x74, 0x07, 0xd6, 0x74, 0x54, 0x8f, 0x2e, 0xfb, 0x75, 0x26, 0x54, 0x81, 0xb4, - 0xa9, 0x7d, 0x3e, 0x83, 0xff, 0xc9, 0x82, 0xb6, 0x8c, 0x5f, 0x86, 0x5a, 0xad, 0x82, 0x5a, 0xef, - 0x43, 0x27, 0xbd, 0x70, 0x67, 0x8e, 0x17, 0x06, 0x24, 0xca, 0x98, 0xd6, 0xfb, 0x3b, 0xef, 0x6c, - 0x8b, 0x48, 0x29, 0x49, 0x6c, 0x1f, 0x5f, 0xb8, 0xb3, 0x7d, 0x86, 0x62, 0xeb, 0xf8, 0x3c, 0x26, - 0xbd, 0x22, 0x91, 0xe3, 0xfa, 0x7e, 0x42, 0xd2, 0x94, 0x2d, 0x69, 0xc5, 0x36, 0x81, 0xd4, 0xe7, - 0x7d, 0xe2, 0x05, 0x67, 0x6e, 0xe8, 0xcc, 0x42, 0xd7, 0x23, 0xa9, 0xb0, 0xdc, 0x02, 0x14, 0x63, - 0x00, 0xc5, 0x08, 0xb5, 0xa0, 0x7e, 0x70, 0xf8, 0x60, 0xb8, 0x84, 0x3a, 0xd0, 0xda, 0x3f, 0x3a, - 0x3c, 0x9c, 0xbc, 0x78, 0x3a, 0xac, 0x51, 0x1d, 0x3f, 0x20, 0xb3, 0x38, 0x0d, 0x74, 0x1d, 0x2f, - 0xda, 0x1e, 0xfe, 0x18, 0x06, 0x39, 0xb6, 0xd0, 0xcd, 0x08, 0x5a, 0x72, 0xb1, 0x1c, 0x5b, 0x0e, - 0xa9, 0x01, 0x3e, 0x08, 0x52, 0x2f, 0x3e, 0x27, 0x09, 0xd5, 0x66, 0xfa, 0xf6, 0xc1, 0xe3, 0x87, - 0xb0, 0x51, 0xa0, 0x20, 0x98, 0xde, 0x80, 0x95, 0x68, 0x7e, 0xe6, 0x50, 0xfc, 0x54, 0x04, 0x01, - 0x05, 0xc0, 0x7f, 0x68, 0x01, 0x9a, 0xbc, 0x26, 0xde, 0x3c, 0x23, 0x74, 0xff, 0xda, 0xc6, 0xe2, - 0xc4, 0x27, 0x89, 0x13, 0xe4, 0x86, 0x27, 0xc7, 0x2c, 0x3c, 0xb8, 0x01, 0x9b, 0x12, 0x81, 0x47, - 0x0c, 0x11, 0x86, 0xee, 0x8c, 0x90, 0xc4, 0x99, 0xcd, 0xa7, 0xce, 0x2b, 0x72, 0x29, 0x34, 0x62, - 0xc0, 0x28, 0xe5, 0xef, 0xe6, 0x6e, 0x94, 0x05, 0xd9, 0xa5, 0x08, 0xd8, 0xf9, 0x98, 0xfa, 0xc0, - 0x43, 0x92, 0x89, 0xa4, 0xf3, 0x26, 0x32, 0xfe, 0x4b, 0x0b, 0x90, 0xfe, 0x85, 0xd8, 0xf2, 0x03, - 0x68, 0x8b, 0x58, 0xcc, 0xfd, 0xb5, 0xb3, 0x73, 0x5b, 0x9a, 0x55, 0x19, 0x7b, 0x5b, 0x8c, 0xd3, - 0x49, 0x94, 0x25, 0x97, 0x76, 0xfe, 0xe5, 0xf8, 0x00, 0x7a, 0xc6, 0x14, 0x8d, 0x1b, 0x74, 0x57, - 0x7c, 0x11, 0xf4, 0x27, 0xba, 0x05, 0xcd, 0x73, 0x37, 0x9c, 0xf3, 0x10, 0xda, 0xd9, 0x19, 0x48, - 0x2e, 0x92, 0x05, 0x9f, 0xbd, 0x57, 0xfb, 0x91, 0x85, 0x87, 0xd0, 0x7f, 0x48, 0xb2, 0xc7, 0xd1, - 0xcb, 0x58, 0x6c, 0x0c, 0xff, 0x73, 0x1d, 0x06, 0x39, 0x48, 0x59, 0xc8, 0x39, 0x49, 0x52, 0x1a, - 0xd0, 0x84, 0x85, 0x88, 0x21, 0x95, 0x2d, 0x53, 0xb9, 0x94, 0x2d, 0x17, 0xbd, 0x01, 0x43, 0x08, - 0x1a, 0xf3, 0x24, 0xa0, 0x9e, 0x40, 0x5d, 0x99, 0xfd, 0x96, 0xea, 0xa7, 0x3a, 0x90, 0xb6, 0xaf, - 0x00, 0xf9, 0xac, 0x1b, 0x24, 0x29, 0x8b, 0x92, 0x72, 0x96, 0x02, 0xd0, 0xc7, 0xb0, 0xcc, 0xb4, - 0x9e, 0xb2, 0x58, 0xd9, 0xd9, 0x59, 0x93, 0xfb, 0x3b, 0x62, 0xd0, 0x7d, 0x1a, 0x4d, 0x6d, 0x81, - 0x82, 0x76, 0xa0, 0x1e, 0x46, 0xfe, 0xa8, 0xc5, 0xe4, 0x7d, 0x53, 0x93, 0xb7, 0xbe, 0xc1, 0xed, - 0x83, 0xc8, 0xe7, 0x72, 0xa6, 0xc8, 0x34, 0xb2, 0xbb, 0x61, 0xe0, 0xa6, 0xa3, 0x15, 0x9e, 0xd9, - 0xd8, 0x40, 0xcf, 0x6c, 0x60, 0x64, 0x36, 0x74, 0x17, 0xd6, 0x64, 0x61, 0xc0, 0x42, 0xc1, 0xa9, - 0x9b, 0x9e, 0x92, 0x74, 0xd4, 0x61, 0xfb, 0xad, 0x9a, 0x42, 0x9f, 0x42, 0x4b, 0x86, 0xac, 0xae, - 0xb9, 0x07, 0x11, 0xaf, 0xd8, 0xea, 0x24, 0xce, 0xf8, 0x21, 0xb4, 0xe5, 0x0a, 0xdf, 0x42, 0xdd, - 0x07, 0x91, 0xcf, 0xc8, 0x68, 0xea, 0x5e, 0x67, 0x86, 0x29, 0x03, 0xae, 0x54, 0xf9, 0x8f, 0x61, - 0xcd, 0x80, 0x0a, 0xad, 0x7f, 0x50, 0x1d, 0xb3, 0x4d, 0x20, 0xfe, 0x92, 0x91, 0xa4, 0xce, 0xad, - 0x59, 0xd1, 0x5b, 0x44, 0x08, 0x9b, 0x31, 0x57, 0xdf, 0xe7, 0x09, 0x63, 0x90, 0x90, 0xd9, 0x9c, - 0x97, 0xa1, 0xc7, 0x5e, 0x9c, 0xf0, 0x52, 0x61, 0xd5, 0x06, 0x05, 0xa6, 0xa9, 0x74, 0x4a, 0x53, - 0x23, 0x77, 0xf9, 0xb6, 0x2d, 0x46, 0xf8, 0x1a, 0x6c, 0x1c, 0x04, 0x69, 0x26, 0x82, 0x75, 0x90, - 0x07, 0x2e, 0xfc, 0x35, 0x6c, 0x16, 0x27, 0x04, 0xbf, 0xbb, 0x00, 0x5e, 0x0e, 0x15, 0xee, 0x39, - 0x2c, 0x46, 0x7d, 0x5b, 0xc3, 0xc1, 0xff, 0x60, 0xc1, 0x2a, 0x25, 0xc6, 0xad, 0x4e, 0x6e, 0x5c, - 0x0b, 0x43, 0x96, 0x19, 0x86, 0x7e, 0x08, 0xcd, 0xf8, 0x22, 0x22, 0x89, 0x48, 0x29, 0xef, 0xe7, - 0x6a, 0x2a, 0xd2, 0xd8, 0x3e, 0xa2, 0x68, 0x36, 0xc7, 0xa6, 0xc6, 0x18, 0x06, 0x67, 0x41, 0x26, - 0x8a, 0x1e, 0x3e, 0xa0, 0xf2, 0x0d, 0x22, 0x2f, 0x9c, 0xfb, 0xc4, 0x61, 0xd6, 0x29, 0x32, 0x48, - 0xdb, 0x2e, 0x82, 0xf1, 0x07, 0xd0, 0x64, 0xf4, 0x50, 0x1b, 0x1a, 0x7b, 0x47, 0x4f, 0x1f, 0x0d, - 0x97, 0x68, 0x1e, 0x39, 0x7a, 0x7e, 0x38, 0xb4, 0x28, 0xe8, 0xc9, 0x64, 0x62, 0x0f, 0x6b, 0xf8, - 0xcf, 0x2c, 0x40, 0xfa, 0x42, 0x84, 0x54, 0xbe, 0xcc, 0x5d, 0x8d, 0x4b, 0xe4, 0xc3, 0xaa, 0x45, - 0x0b, 0x1f, 0xe2, 0x43, 0xee, 0x46, 0xe2, 0xab, 0xf1, 0x63, 0xe8, 0x68, 0xe0, 0x0a, 0xdb, 0xfd, - 0xc0, 0xb4, 0xdd, 0xbe, 0xe9, 0xca, 0xba, 0xe9, 0x22, 0x18, 0x52, 0xa6, 0xf4, 0x30, 0x90, 0xab, - 0xf3, 0x23, 0xae, 0x01, 0x01, 0x13, 0x6b, 0x5e, 0x87, 0x26, 0x0f, 0x1c, 0xdc, 0x5c, 0xf9, 0x20, - 0xff, 0x9c, 0x28, 0x39, 0xe3, 0xcf, 0xc5, 0xe7, 0x44, 0xdf, 0x32, 0x86, 0x26, 0x8f, 0x4a, 0x7c, - 0xc7, 0x5d, 0xb9, 0x22, 0x8a, 0x65, 0xf3, 0x29, 0xfc, 0xaf, 0x16, 0xb4, 0x84, 0x77, 0x51, 0x1b, - 0x4c, 0x33, 0x37, 0x9b, 0xcb, 0xe4, 0x29, 0x46, 0xe8, 0x13, 0x68, 0x8b, 0x4a, 0x3f, 0x15, 0x9b, - 0x53, 0xe6, 0x24, 0xe0, 0x76, 0x8e, 0x81, 0x6e, 0xc1, 0x32, 0xab, 0x9f, 0x79, 0x94, 0xec, 0xec, - 0xf4, 0x34, 0xdc, 0x20, 0xb2, 0xc5, 0x24, 0xad, 0x2e, 0xa7, 0x61, 0xec, 0xbd, 0x3a, 0x25, 0xc1, - 0xc9, 0x69, 0x26, 0x02, 0xa7, 0x0e, 0xca, 0x83, 0x6d, 0x53, 0x0b, 0xb6, 0x5a, 0xf8, 0x5e, 0x36, - 0xc3, 0x77, 0x1e, 0xe9, 0x5a, 0x5a, 0xa4, 0xc3, 0x5f, 0x43, 0x9f, 0xf9, 0xa3, 0xaa, 0x83, 0x8b, - 0x61, 0xde, 0xaa, 0x08, 0xf3, 0x39, 0xad, 0x9a, 0x4e, 0xeb, 0x2f, 0x2c, 0x40, 0x47, 0x33, 0x12, - 0xfd, 0x9f, 0x94, 0xe0, 0xaa, 0x94, 0xae, 0x1b, 0xa5, 0xf4, 0x4d, 0xe8, 0xcc, 0xe6, 0xe9, 0xa9, - 0x23, 0x26, 0x79, 0x42, 0xd7, 0x41, 0xb2, 0xd8, 0x6e, 0xaa, 0x62, 0xfb, 0x3e, 0xac, 0x19, 0xeb, - 0x14, 0xe6, 0xf0, 0x21, 0xf4, 0xcd, 0xa2, 0x5a, 0xac, 0xb3, 0x00, 0xc5, 0x7f, 0x5f, 0x83, 0x26, - 0x33, 0x5a, 0x66, 0x7f, 0x49, 0x20, 0x4e, 0xa3, 0x96, 0xcd, 0x07, 0x46, 0x81, 0x51, 0x33, 0x0b, - 0x0c, 0x3d, 0x66, 0xd4, 0xcd, 0x98, 0xd1, 0x87, 0x5a, 0xe0, 0x8b, 0x43, 0x44, 0x2d, 0xf0, 0xd1, - 0x57, 0x65, 0xb1, 0x35, 0x99, 0x6d, 0x6d, 0x4a, 0x7b, 0x31, 0x15, 0x57, 0x29, 0xce, 0x30, 0xf6, - 0xdc, 0x90, 0x32, 0xe3, 0xc6, 0x90, 0x8f, 0xd1, 0x7b, 0x00, 0x1e, 0x2b, 0xdd, 0x7d, 0xc7, 0xcd, - 0x98, 0x49, 0x34, 0x6c, 0x0d, 0x82, 0x6e, 0x41, 0x23, 0x0d, 0x7c, 0x32, 0x6a, 0xb3, 0x00, 0xb6, - 0x6a, 0xf8, 0xea, 0x71, 0xe0, 0x13, 0x9b, 0x4d, 0x53, 0x63, 0x09, 0x52, 0x27, 0xbe, 0x88, 0x1c, - 0x16, 0x05, 0x58, 0x16, 0x6d, 0xdb, 0x06, 0x8c, 0x9a, 0xe9, 0x69, 0x1c, 0xfa, 0x2c, 0x93, 0x36, - 0x6c, 0xf6, 0x1b, 0xff, 0xb9, 0x05, 0x5d, 0x46, 0xcb, 0x26, 0x67, 0xf1, 0xb9, 0x1b, 0x1a, 0x32, - 0xb3, 0x16, 0xcb, 0xac, 0x50, 0xee, 0xe9, 0x45, 0x62, 0xbd, 0x50, 0x24, 0xea, 0xbb, 0x6f, 0x14, - 0x76, 0x5f, 0x5c, 0x76, 0xb3, 0xbc, 0x6c, 0x7c, 0x0a, 0xcb, 0x3c, 0x32, 0xa1, 0x4f, 0x01, 0xa6, - 0xf3, 0x4b, 0xc7, 0x88, 0x8e, 0x3d, 0x43, 0x22, 0xb6, 0x86, 0x80, 0xee, 0x40, 0x27, 0x25, 0x61, - 0x28, 0xf1, 0x6b, 0x55, 0xf8, 0x3a, 0x06, 0xfe, 0x4c, 0x46, 0x4e, 0x56, 0xce, 0x50, 0x79, 0xd1, - 0xd0, 0x23, 0x2a, 0x65, 0xf6, 0x9b, 0xda, 0x70, 0x7c, 0x11, 0x89, 0x73, 0x32, 0xfd, 0x89, 0x7f, - 0x61, 0x89, 0xaf, 0x9e, 0xcd, 0x7c, 0x37, 0x23, 0xb4, 0x32, 0xe0, 0x7b, 0xb1, 0x98, 0x91, 0x98, - 0xfc, 0x1e, 0x2d, 0xd9, 0x7c, 0x16, 0xfd, 0x06, 0xf4, 0xb8, 0x84, 0x12, 0x2e, 0x78, 0x11, 0xaf, - 0xd6, 0xcd, 0xe5, 0xf1, 0xb9, 0x47, 0x4b, 0xb6, 0x89, 0xbc, 0xd7, 0x87, 0x2e, 0x07, 0xcc, 0x19, - 0x53, 0xfc, 0x2f, 0x35, 0x68, 0xd0, 0x60, 0xb9, 0xf8, 0x5c, 0xf1, 0x46, 0x55, 0xe3, 0x57, 0xd0, - 0x0d, 0x23, 0x5f, 0x0e, 0x65, 0x5c, 0xbc, 0xa1, 0x87, 0x63, 0x5a, 0xe1, 0x3c, 0x99, 0x4f, 0xbf, - 0x21, 0x97, 0x22, 0xed, 0x18, 0x5f, 0x50, 0xfe, 0x41, 0x34, 0x8d, 0xe7, 0x91, 0x2f, 0x72, 0xa3, - 0x1c, 0xaa, 0x14, 0xd1, 0xd4, 0x52, 0x04, 0x8d, 0x1a, 0xaf, 0xe7, 0xbe, 0x63, 0x86, 0x4a, 0x1d, - 0x84, 0x3e, 0x81, 0xd5, 0x94, 0x78, 0x71, 0xe4, 0xa7, 0xfc, 0xc4, 0xe9, 0x65, 0xc4, 0x67, 0x7e, - 0xd2, 0xb3, 0xcb, 0x13, 0xd5, 0x65, 0xe4, 0xf8, 0x3e, 0x0c, 0x0a, 0xcb, 0xae, 0x48, 0x8b, 0xeb, - 0x7a, 0x5a, 0x5c, 0xd1, 0xd3, 0xe0, 0xef, 0xd7, 0x60, 0xf5, 0x09, 0x3d, 0x1c, 0x0a, 0xa5, 0xf0, - 0x70, 0xfa, 0xbf, 0x19, 0x73, 0x74, 0xff, 0x69, 0x14, 0xfc, 0x47, 0x46, 0x80, 0xe6, 0xd5, 0x11, - 0x60, 0x0b, 0x86, 0x09, 0x61, 0x47, 0x58, 0x27, 0x27, 0xc5, 0xc5, 0x59, 0x82, 0xd3, 0xe2, 0x39, - 0x38, 0x3b, 0x23, 0x7e, 0xe0, 0x66, 0x14, 0xea, 0x78, 0xf4, 0x88, 0x12, 0x32, 0xa9, 0xb6, 0xed, - 0xaa, 0x29, 0x2a, 0x02, 0xa4, 0x8b, 0x40, 0x44, 0xea, 0x2f, 0x60, 0x18, 0x44, 0x19, 0x49, 0x22, - 0x37, 0x74, 0xce, 0xdc, 0xcc, 0x3b, 0x25, 0x0b, 0xfc, 0xb2, 0x84, 0x86, 0x7e, 0x0c, 0x7d, 0x56, - 0x9d, 0xa7, 0x73, 0xcf, 0x23, 0x29, 0x2d, 0xa6, 0xb8, 0x83, 0xe6, 0x55, 0x39, 0x3d, 0x84, 0x1e, - 0xf3, 0x49, 0xbb, 0x80, 0x8a, 0x3e, 0xa7, 0x95, 0xea, 0x99, 0x1b, 0x44, 0xb4, 0xc8, 0xe7, 0xee, - 0x56, 0xaf, 0x70, 0x37, 0xbb, 0x88, 0x85, 0xbe, 0x80, 0x1e, 0x23, 0xf5, 0xd2, 0x0d, 0xc2, 0x79, - 0xc2, 0x2a, 0xb8, 0x12, 0xd3, 0x9f, 0xf0, 0x39, 0xdb, 0xc4, 0xc4, 0xff, 0x69, 0xc1, 0x40, 0x89, - 0x60, 0x72, 0x4e, 0x22, 0x1a, 0x9d, 0x9b, 0x6c, 0x3f, 0x0b, 0x9d, 0x9d, 0xcd, 0xa2, 0x2f, 0xa0, - 0xab, 0x6f, 0x40, 0xf8, 0x7a, 0xd5, 0x4e, 0x1f, 0x2d, 0xd9, 0x06, 0x2a, 0xfa, 0xe2, 0xcd, 0x76, - 0xfa, 0x68, 0xa9, 0x6a, 0xaf, 0x5d, 0x7d, 0x07, 0xcc, 0xb0, 0xaa, 0xb7, 0x9a, 0x73, 0x15, 0xa8, - 0x7b, 0x2d, 0x68, 0x12, 0xba, 0x41, 0x1c, 0x43, 0x47, 0x3b, 0x1d, 0x2d, 0x2c, 0xbc, 0xb4, 0xb0, - 0x53, 0x33, 0xc3, 0x8e, 0x56, 0x07, 0x35, 0x4a, 0x75, 0x10, 0xef, 0x65, 0x36, 0xb5, 0x5e, 0x26, - 0xfe, 0x0c, 0x36, 0x58, 0xd4, 0x23, 0xaa, 0xf1, 0xfd, 0xcb, 0x0f, 0xff, 0x23, 0xd8, 0x2c, 0x7e, - 0x24, 0x7a, 0x69, 0x07, 0x80, 0xf8, 0x8c, 0xe1, 0xba, 0x57, 0xf5, 0x34, 0xae, 0x70, 0x60, 0xfc, - 0x57, 0x16, 0xac, 0x19, 0xe4, 0x84, 0x1b, 0xbc, 0x07, 0x43, 0x89, 0xe3, 0xc4, 0x91, 0xc3, 0xb2, - 0xac, 0xa5, 0xb2, 0x2c, 0xda, 0x06, 0xa4, 0x94, 0x53, 0xa0, 0x5e, 0x31, 0xc3, 0x7d, 0x99, 0xb2, - 0xf1, 0x15, 0x36, 0xaf, 0xb6, 0x4a, 0x70, 0x3d, 0xa8, 0x34, 0x8c, 0xa0, 0xa2, 0xa4, 0xb2, 0x1b, - 0x86, 0xc6, 0x61, 0x07, 0xcf, 0xe1, 0x5a, 0x69, 0x46, 0x6c, 0xe5, 0x13, 0x58, 0x95, 0x2c, 0xa4, - 0x48, 0x64, 0x55, 0x5f, 0x9e, 0xa0, 0xd8, 0x62, 0xbf, 0x1a, 0x36, 0x6f, 0x1f, 0x96, 0x27, 0xf0, - 0xa7, 0xb0, 0xca, 0xd9, 0xea, 0xb7, 0x17, 0x0b, 0x0f, 0x6f, 0xf4, 0xe0, 0xac, 0xa3, 0x0b, 0x8d, - 0xfe, 0x41, 0x8d, 0x82, 0xd3, 0x2c, 0x4e, 0x8c, 0xfe, 0xe8, 0x1b, 0x35, 0x3b, 0xf5, 0x26, 0x6a, - 0xcd, 0x6c, 0xa2, 0xa2, 0x6f, 0xa0, 0x43, 0x33, 0xd9, 0xd4, 0xf5, 0x5e, 0xcd, 0x67, 0x32, 0xf5, - 0x6d, 0x49, 0x67, 0x29, 0x73, 0xa4, 0x89, 0x70, 0x8f, 0x23, 0xf3, 0x44, 0x08, 0x61, 0x0e, 0x40, - 0x3f, 0x60, 0xd7, 0x3c, 0x8e, 0xef, 0x66, 0xee, 0xd4, 0x4d, 0x79, 0x83, 0xb9, 0xcb, 0xf2, 0xda, - 0x03, 0x01, 0x12, 0x39, 0x49, 0xa7, 0xf0, 0xcb, 0x72, 0x52, 0x57, 0xcf, 0x49, 0x84, 0x5a, 0xa2, - 0xb6, 0x26, 0xd5, 0xf3, 0x4d, 0x38, 0x58, 0xf4, 0x72, 0x85, 0x18, 0x24, 0x90, 0x35, 0x72, 0x3f, - 0xa2, 0xe6, 0x25, 0x90, 0x64, 0x4b, 0x84, 0x1f, 0xe6, 0x07, 0x12, 0x2e, 0x5b, 0xb8, 0x0f, 0x00, - 0x1d, 0x93, 0xec, 0x20, 0x3e, 0x39, 0x20, 0xe7, 0xea, 0x24, 0xb1, 0x0d, 0x2b, 0x61, 0x7c, 0xe2, - 0x84, 0x14, 0xc6, 0x96, 0xdb, 0x57, 0x07, 0xad, 0x1c, 0x57, 0xa1, 0xe0, 0x0d, 0x58, 0x33, 0xa8, - 0x08, 0x55, 0xae, 0xc2, 0xe0, 0xf8, 0x74, 0x9e, 0xf9, 0xf1, 0x85, 0xbc, 0x22, 0xa1, 0x47, 0x46, - 0x05, 0x12, 0x68, 0xbf, 0x06, 0x9b, 0xc7, 0xf3, 0x69, 0xea, 0x25, 0xc1, 0x94, 0x98, 0x07, 0xff, - 0x31, 0xb4, 0xc9, 0xeb, 0x20, 0xcd, 0x82, 0xe8, 0x84, 0x2d, 0xa3, 0x6d, 0xe7, 0x63, 0xfc, 0x3e, - 0xbc, 0x9b, 0x7f, 0x45, 0x43, 0x5d, 0xba, 0xeb, 0x79, 0x64, 0x96, 0x11, 0x5f, 0xb2, 0xba, 0x0f, - 0x1b, 0x26, 0x82, 0x76, 0x9f, 0x26, 0x0f, 0xf4, 0x99, 0xfb, 0x4a, 0x54, 0x72, 0x6d, 0xdb, 0x04, - 0xe2, 0xff, 0xae, 0x41, 0x97, 0x7e, 0x26, 0xc9, 0xa2, 0xeb, 0xa5, 0xa0, 0xd2, 0x62, 0xe3, 0xc7, - 0x66, 0x09, 0x5c, 0x2b, 0x94, 0xc0, 0x57, 0x16, 0x05, 0x8b, 0xfa, 0xa3, 0xaa, 0xf8, 0x68, 0xea, - 0xc5, 0x47, 0xb1, 0xeb, 0xba, 0x5c, 0xd1, 0x75, 0xdd, 0x84, 0xe5, 0x84, 0xb5, 0xc4, 0xc4, 0xf9, - 0x53, 0x8c, 0x68, 0xcc, 0xe1, 0xe7, 0x34, 0x27, 0x21, 0x1e, 0x09, 0xce, 0xa9, 0x4c, 0xdb, 0x3c, - 0xe6, 0x14, 0xe1, 0xf4, 0x80, 0x26, 0x60, 0xa9, 0xb8, 0x1d, 0x5a, 0xe1, 0xd7, 0x67, 0x26, 0x94, - 0xc6, 0x3d, 0x19, 0xa3, 0x35, 0xaa, 0xbc, 0x93, 0x57, 0x31, 0x43, 0xd7, 0x90, 0x43, 0x25, 0xe5, - 0x0e, 0xaf, 0x61, 0x8a, 0x70, 0x1a, 0x8b, 0x3b, 0x5a, 0x0a, 0xfb, 0x9e, 0x7d, 0x6a, 0x5d, 0xc6, - 0xf5, 0x82, 0x8c, 0x8b, 0xd2, 0x6c, 0x54, 0x48, 0xf3, 0x43, 0xe8, 0x8b, 0x9c, 0xe9, 0x24, 0xc4, - 0x4d, 0x63, 0x99, 0xcd, 0x0a, 0x50, 0xfc, 0x37, 0x75, 0xbe, 0x5a, 0x91, 0xe6, 0xff, 0x7f, 0x8d, - 0x45, 0xa9, 0xbc, 0x69, 0xa8, 0xfc, 0x36, 0x0c, 0x0c, 0xd5, 0x12, 0x5f, 0x68, 0xbc, 0x08, 0xa6, - 0x65, 0xba, 0x52, 0x6d, 0x26, 0xb4, 0xad, 0x83, 0x4a, 0xc2, 0x82, 0x0a, 0x61, 0xdd, 0x84, 0x46, - 0x12, 0x87, 0x84, 0xa9, 0xb4, 0xaf, 0xba, 0x3c, 0x76, 0x1c, 0x12, 0x9b, 0xcd, 0xd0, 0x7c, 0x52, - 0x30, 0x0b, 0xe2, 0xb3, 0x6e, 0xed, 0x8a, 0x5d, 0x9e, 0xa0, 0x8e, 0xaa, 0x9b, 0x45, 0x36, 0xea, - 0xf1, 0x7b, 0x1f, 0x03, 0x48, 0x4f, 0xd8, 0x89, 0x33, 0x4b, 0x48, 0x70, 0xe6, 0x9e, 0x90, 0x51, - 0x9f, 0xa1, 0x68, 0x10, 0xe5, 0x4a, 0x03, 0xcd, 0x95, 0xf0, 0x7f, 0xd5, 0xa0, 0xf9, 0x34, 0x71, - 0x7d, 0x42, 0x8f, 0x91, 0x67, 0xd4, 0xe3, 0x9d, 0xc5, 0xc7, 0x3a, 0x5b, 0xc7, 0xa0, 0x1f, 0x64, - 0xda, 0x07, 0xb5, 0xca, 0x0f, 0x34, 0x0c, 0x4d, 0x3f, 0x75, 0x43, 0x3f, 0x57, 0xe9, 0x54, 0xb3, - 0x84, 0xa6, 0x69, 0x09, 0xf9, 0x7e, 0x96, 0xf5, 0xd0, 0x20, 0x65, 0xdf, 0x5a, 0x28, 0xfb, 0x9b, - 0xd0, 0x21, 0xfc, 0xfa, 0x87, 0xb5, 0x22, 0xb8, 0x25, 0xe8, 0xa0, 0xfc, 0x24, 0xb2, 0x72, 0xf5, - 0x49, 0xe4, 0x1e, 0x74, 0x3d, 0x6a, 0x18, 0x24, 0x99, 0xb9, 0x49, 0xc6, 0x4d, 0x61, 0x71, 0xb7, - 0xc4, 0xc0, 0xc5, 0x1f, 0xc3, 0x1a, 0x93, 0xfa, 0xa3, 0x80, 0xe6, 0xa1, 0x4b, 0xed, 0xac, 0xc5, - 0x1b, 0xb2, 0x96, 0xd6, 0x90, 0xc5, 0xf7, 0x61, 0xdd, 0x44, 0x16, 0x49, 0xf0, 0x16, 0x2c, 0x67, - 0x14, 0x5e, 0x3a, 0x8b, 0x30, 0x6c, 0x5b, 0x4c, 0xe2, 0x3f, 0xb6, 0xa0, 0x47, 0x21, 0x41, 0x74, - 0x72, 0x40, 0xe9, 0xa5, 0x54, 0xe0, 0x67, 0xee, 0x6b, 0x27, 0x25, 0x61, 0x28, 0x9b, 0x1f, 0x72, - 0x4c, 0x05, 0x4e, 0x7f, 0x4f, 0xe7, 0xb2, 0x70, 0x93, 0x43, 0x6a, 0x86, 0x09, 0x49, 0x49, 0x42, - 0x4b, 0x23, 0xf6, 0x29, 0x0f, 0x24, 0x26, 0x90, 0x3a, 0x48, 0x0e, 0xa0, 0x44, 0xb8, 0x42, 0x0d, - 0x18, 0xde, 0xe1, 0x1b, 0xca, 0x17, 0xf4, 0x26, 0xb5, 0xef, 0x5f, 0x5b, 0xb0, 0x51, 0xf8, 0x48, - 0x88, 0x61, 0x17, 0x96, 0x99, 0x9c, 0xa4, 0x18, 0x3e, 0xd2, 0xc5, 0x50, 0x42, 0xdf, 0xe6, 0x43, - 0xd1, 0x4b, 0xe6, 0x1f, 0x8e, 0x9f, 0x40, 0x47, 0x03, 0x57, 0x14, 0x28, 0x1f, 0x9b, 0xbd, 0xe4, - 0x8d, 0x6a, 0x16, 0x5a, 0xdd, 0xf2, 0x2d, 0x74, 0x9f, 0x45, 0xd3, 0xef, 0xf1, 0x26, 0x02, 0xdd, - 0x80, 0x95, 0x84, 0x88, 0x93, 0xbe, 0x28, 0x57, 0x14, 0x00, 0x0f, 0xa0, 0x27, 0xe8, 0xaa, 0x5b, - 0xf4, 0x67, 0x51, 0x18, 0x7b, 0xaf, 0xde, 0xf4, 0x16, 0xfd, 0x67, 0x80, 0xf4, 0x0f, 0x54, 0x41, - 0x35, 0x67, 0xd0, 0x42, 0x41, 0x25, 0x81, 0xac, 0xa0, 0x7a, 0x1f, 0x3a, 0x3a, 0x0a, 0xbf, 0x74, - 0x03, 0x85, 0x80, 0xff, 0xc8, 0x82, 0xc1, 0xf3, 0x20, 0x3b, 0xf5, 0x13, 0xf7, 0xe2, 0x0d, 0x94, - 0x5a, 0x7c, 0xd1, 0x50, 0xbb, 0xea, 0x45, 0x43, 0xbd, 0xf8, 0xa2, 0xc1, 0x0d, 0x43, 0xd1, 0x7c, - 0xa1, 0x3f, 0xf5, 0xb6, 0x6b, 0x8f, 0xb7, 0x5d, 0xef, 0xc1, 0x50, 0x2d, 0xe6, 0xed, 0x7a, 0xae, - 0x5b, 0xb7, 0x61, 0x25, 0xf7, 0x77, 0xd4, 0x82, 0xfa, 0xde, 0xb3, 0xdf, 0x1c, 0x2e, 0xa1, 0x36, - 0x34, 0x8e, 0x27, 0x07, 0x07, 0xfc, 0x7a, 0x83, 0xdd, 0x78, 0xd4, 0xb6, 0xb6, 0xa0, 0x41, 0xa3, - 0x0b, 0x5a, 0x81, 0xe6, 0xd3, 0xdd, 0x6f, 0x26, 0xf6, 0x70, 0x89, 0xfe, 0xfc, 0x29, 0xfb, 0x69, - 0xa1, 0x2e, 0xb4, 0x1f, 0x1f, 0x3e, 0x9d, 0xd8, 0x87, 0xbb, 0x07, 0xc3, 0xda, 0xd6, 0x73, 0x68, - 0xcb, 0xea, 0x90, 0x22, 0xed, 0x1e, 0x4c, 0xec, 0xa7, 0x1c, 0x7f, 0x62, 0xdb, 0x47, 0x36, 0xa7, - 0xfb, 0x7c, 0xd7, 0x3e, 0x1c, 0xd6, 0xe8, 0xaf, 0xc7, 0x87, 0x3f, 0x39, 0x1a, 0xd6, 0x51, 0x07, - 0x5a, 0xdf, 0x4e, 0xec, 0xbd, 0xa3, 0xe3, 0xc9, 0xb0, 0x41, 0x71, 0x1f, 0x4c, 0xf6, 0x9e, 0x3d, - 0x1c, 0x36, 0x19, 0x47, 0x7b, 0x77, 0x7f, 0x32, 0x5c, 0xde, 0xf9, 0x37, 0x0b, 0x5a, 0x2f, 0xe6, - 0xfe, 0xe3, 0x28, 0xc8, 0xd0, 0x04, 0x40, 0xbd, 0x92, 0x40, 0xd7, 0xf3, 0x6e, 0x7f, 0xf1, 0xad, - 0xc5, 0x78, 0x5c, 0x35, 0x25, 0xcc, 0x6a, 0x09, 0x3d, 0x82, 0x8e, 0x56, 0x79, 0xa3, 0xf1, 0xe2, - 0x23, 0xc2, 0xf8, 0x9d, 0xca, 0xb9, 0x9c, 0xd2, 0x04, 0x40, 0x59, 0x9c, 0x5a, 0x50, 0xc9, 0x6c, - 0xd5, 0x82, 0xca, 0x06, 0x8a, 0x97, 0x76, 0xfe, 0x63, 0x04, 0xf5, 0x17, 0x73, 0x1f, 0xbd, 0x80, - 0x8e, 0xf6, 0x60, 0x0c, 0x95, 0x6e, 0xd2, 0xd4, 0x72, 0xaa, 0xde, 0x95, 0x8d, 0x7f, 0xf1, 0x8f, - 0xff, 0xfe, 0x27, 0xb5, 0x75, 0x3c, 0xb8, 0x73, 0xfe, 0xab, 0x77, 0x5c, 0xdf, 0x97, 0xb6, 0x78, - 0xcf, 0xda, 0x42, 0x36, 0xb4, 0xc4, 0x9b, 0x30, 0xb4, 0xa9, 0xd1, 0xd0, 0x8e, 0x71, 0xe3, 0x6b, - 0x25, 0xb8, 0xa0, 0xbb, 0xc9, 0xe8, 0x0e, 0x71, 0x47, 0xd0, 0xa5, 0x69, 0x8a, 0xd2, 0xdc, 0x83, - 0xfa, 0x9e, 0x1b, 0x21, 0xa4, 0x2e, 0xca, 0x65, 0x4c, 0x18, 0xaf, 0x19, 0x30, 0x41, 0x07, 0x31, - 0x3a, 0x5d, 0xdc, 0xa2, 0x74, 0xa6, 0x6e, 0x44, 0x69, 0x78, 0xd0, 0xd5, 0x1f, 0xeb, 0x20, 0xf5, - 0x64, 0xa4, 0xfc, 0x02, 0x69, 0x7c, 0xa3, 0x7a, 0x52, 0x90, 0x1f, 0x31, 0xf2, 0x08, 0x0f, 0x29, - 0x79, 0xf6, 0x96, 0x49, 0xdc, 0x13, 0xd1, 0xcd, 0x8b, 0x17, 0x3a, 0x6a, 0xf3, 0xe6, 0x03, 0x1f, - 0xb5, 0xf9, 0xe2, 0x53, 0x1e, 0x63, 0xf3, 0x22, 0x54, 0xd1, 0x85, 0xff, 0x1c, 0x7a, 0xcf, 0xd9, - 0x4b, 0x31, 0xf1, 0x2e, 0x44, 0x51, 0x36, 0x9f, 0x95, 0x28, 0xca, 0x85, 0x07, 0x24, 0xf8, 0x06, - 0xa3, 0xbc, 0x89, 0x57, 0x29, 0x65, 0xfe, 0xea, 0xcc, 0xe7, 0x28, 0x94, 0xfe, 0xef, 0x40, 0xcf, - 0x78, 0x02, 0x82, 0xf2, 0xcd, 0x57, 0xbd, 0x2d, 0x19, 0xbf, 0xbb, 0x60, 0xb6, 0x8a, 0x97, 0x2f, - 0x50, 0xd8, 0xa3, 0x11, 0xca, 0xeb, 0x05, 0x80, 0x7a, 0x4a, 0xa1, 0xac, 0xb8, 0xf4, 0x7c, 0x43, - 0x59, 0x71, 0xf9, 0xe5, 0x05, 0x5e, 0x63, 0x2c, 0x7a, 0xa8, 0xc3, 0xb5, 0xcb, 0x69, 0x1d, 0x40, - 0x4b, 0x3c, 0x1a, 0x50, 0xf2, 0x31, 0x5f, 0x4e, 0x28, 0xf9, 0x14, 0x5e, 0x17, 0xe0, 0x21, 0x23, - 0x08, 0xa8, 0x4d, 0x09, 0x06, 0x94, 0xc4, 0x6f, 0x41, 0x47, 0xbb, 0x71, 0x47, 0xfa, 0x6a, 0x0a, - 0x97, 0xf3, 0xca, 0x51, 0x2a, 0xae, 0xe8, 0xf1, 0x3a, 0xa3, 0xdc, 0x47, 0x5d, 0x4a, 0x59, 0xb6, - 0x1b, 0x04, 0x75, 0x79, 0xa5, 0x6e, 0x50, 0x2f, 0xdc, 0xd3, 0x1b, 0xd4, 0x8b, 0x77, 0xf0, 0x26, - 0x75, 0x2a, 0x63, 0xb6, 0xf6, 0xe7, 0x00, 0xea, 0xf6, 0x57, 0xc9, 0xb8, 0x74, 0x8d, 0xad, 0x64, - 0x5c, 0xbe, 0x2c, 0x96, 0x1e, 0x84, 0x80, 0x92, 0x16, 0x77, 0x24, 0x27, 0xd0, 0x37, 0x2f, 0xe7, - 0xd1, 0xbb, 0x3a, 0x85, 0xd2, 0x6d, 0xfe, 0xf8, 0xbd, 0x45, 0xd3, 0xa6, 0xc5, 0xa3, 0x3e, 0xb3, - 0x78, 0x45, 0xf6, 0x18, 0x56, 0xf2, 0x6b, 0x63, 0x34, 0xd2, 0x89, 0xe8, 0xb7, 0xcb, 0xe3, 0xeb, - 0x15, 0x33, 0xb2, 0x5b, 0xc0, 0x28, 0x77, 0xd0, 0x0a, 0xa5, 0xcc, 0x6f, 0x0f, 0x24, 0x51, 0xf6, - 0x80, 0xc5, 0x24, 0xaa, 0xdd, 0x39, 0x17, 0x88, 0xea, 0x37, 0xcf, 0x05, 0xa2, 0x8c, 0x8e, 0x03, - 0x1d, 0xed, 0x52, 0x52, 0x69, 0xb2, 0x7c, 0xa3, 0xaa, 0x34, 0x59, 0x71, 0x8b, 0x89, 0xaf, 0x31, - 0xd2, 0xab, 0x3c, 0xa0, 0xc6, 0x33, 0x12, 0xc9, 0x80, 0xf2, 0xdb, 0x00, 0xaa, 0x8f, 0xac, 0x94, - 0x59, 0xba, 0x61, 0x50, 0xc6, 0x5d, 0x68, 0x3b, 0xe3, 0xeb, 0x8c, 0xf4, 0x1a, 0x66, 0x42, 0x66, - 0xbd, 0x7d, 0xa6, 0xce, 0x7b, 0xd6, 0xd6, 0x5d, 0x0b, 0xbd, 0x84, 0xbe, 0xc2, 0x3f, 0xbe, 0x8c, - 0xbc, 0xab, 0x58, 0x8c, 0xab, 0xa6, 0xc4, 0x06, 0xde, 0x65, 0x5c, 0xae, 0x61, 0x64, 0x72, 0x49, - 0x2f, 0x23, 0x8f, 0xfa, 0xfd, 0xcf, 0xa0, 0xa3, 0x3d, 0x17, 0x53, 0x72, 0x2a, 0xbf, 0x21, 0x1b, - 0x57, 0x75, 0xba, 0xcd, 0x84, 0x23, 0x8e, 0x19, 0xe9, 0x85, 0x3b, 0xa3, 0xb4, 0x23, 0xe8, 0x9b, - 0x0d, 0x5d, 0x65, 0x96, 0x95, 0xdd, 0x61, 0x65, 0x96, 0x0b, 0xfa, 0xc0, 0xc6, 0x5e, 0x78, 0x1f, - 0x53, 0x4f, 0x70, 0x53, 0x9a, 0xd3, 0xf3, 0xbe, 0xae, 0x9e, 0xd3, 0x8b, 0xbd, 0x63, 0x3d, 0xa7, - 0x97, 0x1a, 0xc1, 0xe6, 0x9e, 0x38, 0x1b, 0xa9, 0x19, 0x94, 0xc0, 0xa0, 0xd0, 0x74, 0x45, 0x85, - 0x55, 0x17, 0xfb, 0xb4, 0xe3, 0xf7, 0x17, 0xce, 0x0b, 0x7e, 0xef, 0x31, 0x7e, 0x23, 0xbc, 0xa6, - 0xf8, 0xb9, 0x61, 0xc8, 0xd5, 0xc4, 0xf3, 0x0c, 0xa8, 0x16, 0xaa, 0xb2, 0x83, 0x52, 0x17, 0x76, - 0x3c, 0xae, 0x9a, 0x12, 0x4c, 0x0c, 0x6b, 0xe3, 0x4c, 0x64, 0x12, 0x9f, 0x42, 0x47, 0x6b, 0xec, - 0x29, 0xb9, 0x95, 0x7b, 0x86, 0x4a, 0x6e, 0x55, 0x9d, 0x40, 0x43, 0x6e, 0x29, 0xc9, 0xc2, 0xf8, - 0x84, 0x75, 0x0e, 0x29, 0x8f, 0x6f, 0xa1, 0x2d, 0x5b, 0x82, 0x28, 0xf7, 0x88, 0x42, 0xdf, 0x70, - 0x3c, 0x2a, 0x4f, 0x14, 0xdc, 0x90, 0x05, 0xd4, 0x54, 0xcc, 0x52, 0xba, 0x04, 0x06, 0x85, 0xb6, - 0xa2, 0xd2, 0x47, 0x75, 0xbf, 0x71, 0x6c, 0xbe, 0x7a, 0xe3, 0x17, 0xbe, 0xf8, 0x1d, 0xc6, 0x60, - 0x03, 0x31, 0x1d, 0xa4, 0xf2, 0x43, 0xae, 0x83, 0xbb, 0x16, 0x9a, 0x15, 0xda, 0x8c, 0xa2, 0x5f, - 0xa5, 0x05, 0xda, 0xca, 0x2e, 0xe4, 0xb8, 0xea, 0x9e, 0x06, 0xff, 0x80, 0xf1, 0x7a, 0x07, 0x5d, - 0x37, 0x78, 0x51, 0xaf, 0x91, 0xd7, 0x54, 0x77, 0x2d, 0x34, 0x85, 0xbe, 0x49, 0xf2, 0xad, 0x58, - 0x15, 0xdc, 0x13, 0xa1, 0x12, 0x2b, 0xca, 0xe3, 0xf7, 0xb4, 0x9e, 0xac, 0xd1, 0x5d, 0x45, 0xb7, - 0xaa, 0x79, 0x15, 0xba, 0xaf, 0xe3, 0x75, 0x9d, 0xa7, 0x9c, 0xc4, 0x98, 0x31, 0xbd, 0x81, 0xc6, - 0x65, 0xa6, 0xae, 0xc0, 0x61, 0x11, 0xae, 0xab, 0x9f, 0xfb, 0x55, 0xd9, 0x57, 0xd1, 0x3a, 0x50, - 0x65, 0x5f, 0x55, 0xab, 0x40, 0x2a, 0x8f, 0x97, 0x7d, 0xac, 0x2f, 0x70, 0xca, 0x31, 0xa8, 0x85, - 0x9c, 0x14, 0xfb, 0x03, 0x37, 0x16, 0x9c, 0xa0, 0x0b, 0x55, 0x54, 0xe5, 0xf9, 0x5a, 0xba, 0x11, - 0x5a, 0x95, 0xac, 0x82, 0xe8, 0x84, 0x1f, 0xb3, 0xd1, 0xd7, 0xd0, 0x64, 0x87, 0x57, 0xb4, 0xae, - 0x0a, 0x7d, 0x75, 0x46, 0x1e, 0x6f, 0x14, 0xa0, 0x66, 0xa9, 0x80, 0x59, 0xee, 0x9a, 0x47, 0xa2, - 0x26, 0x9e, 0x42, 0x9f, 0x97, 0x96, 0xf2, 0x88, 0xa7, 0x9c, 0xa6, 0x70, 0x02, 0x55, 0x4e, 0x53, - 0x3c, 0x0d, 0x9a, 0xe1, 0x92, 0x57, 0x97, 0x17, 0x02, 0xe7, 0x9e, 0xb5, 0x35, 0x5d, 0x66, 0xff, - 0x50, 0xf9, 0xec, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x5e, 0xda, 0xc9, 0x11, 0xcc, 0x32, 0x00, - 0x00, + // 4162 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x4d, 0x8f, 0x1c, 0x49, + 0x56, 0x9d, 0xd5, 0x5d, 0xdd, 0xd5, 0xaf, 0x3e, 0x3b, 0xfa, 0xc3, 0xe5, 0x1a, 0xcf, 0x8c, 0x37, + 0x18, 0x8f, 0x3c, 0x9e, 0x59, 0xdb, 0x78, 0x58, 0x66, 0xc7, 0x8b, 0x47, 0xd3, 0xdd, 0xee, 0x1d, + 0x7b, 0xa6, 0xd7, 0xb6, 0xb2, 0xed, 0xb1, 0x59, 0xc1, 0xa6, 0xb2, 0x32, 0xc3, 0xdd, 0x89, 0xb3, + 0x33, 0x6b, 0x32, 0xb3, 0xdc, 0x36, 0x5c, 0xd0, 0x8a, 0x13, 0x1c, 0x38, 0x20, 0xce, 0x70, 0x42, + 0x48, 0x20, 0xae, 0x9c, 0x90, 0x38, 0x73, 0xe5, 0x00, 0x02, 0x2e, 0x48, 0xfc, 0x02, 0xc4, 0x15, + 0x09, 0xbd, 0xf8, 0xc8, 0x88, 0xc8, 0xcc, 0xea, 0xb5, 0x57, 0xc0, 0xad, 0xe2, 0xc5, 0xcb, 0xf7, + 0x22, 0xde, 0x57, 0xbc, 0xf7, 0x22, 0x0a, 0x7a, 0xaf, 0xe6, 0x61, 0x36, 0x0b, 0xae, 0xcf, 0xb2, + 0xb4, 0x48, 0xc9, 0xaa, 0x18, 0x4d, 0x36, 0xfc, 0x24, 0x49, 0x0b, 0xbf, 0x88, 0xd2, 0x24, 0x17, + 0x53, 0x74, 0x1b, 0x36, 0x77, 0xc3, 0x70, 0x7f, 0x9e, 0x65, 0x2c, 0x09, 0x5e, 0xbb, 0x2c, 0x9f, + 0xa5, 0x49, 0xce, 0xe8, 0xcf, 0x60, 0xb0, 0x1b, 0x86, 0x8f, 0xfc, 0x28, 0x73, 0xd9, 0x77, 0x73, + 0x96, 0x17, 0xe4, 0x03, 0xe8, 0x4f, 0xfd, 0x9c, 0x79, 0x81, 0x44, 0x1d, 0x3b, 0x97, 0x9d, 0xab, + 0xeb, 0xae, 0x0d, 0x24, 0x1f, 0xc2, 0xe0, 0xbb, 0x79, 0x5a, 0x18, 0x68, 0x2d, 0x8e, 0x56, 0x81, + 0xd2, 0x0d, 0x18, 0x96, 0xf4, 0x25, 0xcb, 0xbf, 0x6d, 0xc1, 0xda, 0x9e, 0x1f, 0xfb, 0x49, 0xc0, + 0x90, 0x59, 0x91, 0x16, 0x7e, 0xec, 0x4d, 0x05, 0x80, 0x33, 0x5b, 0x71, 0x6d, 0x20, 0xb9, 0x0a, + 0xc3, 0xe0, 0xc4, 0x4f, 0x12, 0xa6, 0xf1, 0x5a, 0x1c, 0xaf, 0x0a, 0x26, 0x3f, 0x84, 0x0b, 0x33, + 0x96, 0x84, 0x51, 0x72, 0xec, 0x55, 0xbf, 0x58, 0xe6, 0x5f, 0x2c, 0x9a, 0x26, 0xb7, 0x61, 0x1c, + 0x25, 0x7e, 0x50, 0x44, 0x2f, 0x59, 0xed, 0xd3, 0x15, 0xfe, 0xe9, 0xc2, 0x79, 0x14, 0xc6, 0x99, + 0x1f, 0xc7, 0xac, 0x28, 0xbf, 0x68, 0xf3, 0x2f, 0x2a, 0x50, 0xf2, 0x05, 0x4c, 0xe6, 0x49, 0x90, + 0x26, 0xcf, 0xa3, 0xec, 0x94, 0x85, 0x5e, 0xe5, 0x9b, 0x55, 0xfe, 0xcd, 0x39, 0x18, 0xf4, 0xd7, + 0x01, 0xf6, 0xfc, 0x44, 0x29, 0xea, 0x2a, 0x0c, 0x93, 0x34, 0x64, 0x5e, 0x14, 0xb2, 0xa4, 0x88, + 0x9e, 0x47, 0x2c, 0x93, 0xaa, 0xaa, 0x82, 0x69, 0x1f, 0xba, 0xfc, 0x3b, 0xa9, 0x80, 0xcf, 0xa0, + 0xbd, 0x7f, 0xe2, 0x47, 0x09, 0xd9, 0x82, 0x76, 0x80, 0x3f, 0xe4, 0x77, 0x62, 0x40, 0xc6, 0xb0, + 0x96, 0xb0, 0xe2, 0x2c, 0xcd, 0x5e, 0x48, 0x9d, 0xaa, 0x21, 0x9d, 0x41, 0x67, 0x5f, 0x6c, 0x3d, + 0x27, 0x3b, 0xb0, 0x2a, 0xa4, 0xc1, 0x3f, 0xee, 0xbb, 0x72, 0x44, 0x26, 0xd0, 0x51, 0x72, 0xe2, + 0x9f, 0xf7, 0xdd, 0x72, 0x8c, 0x94, 0xa5, 0xf8, 0xb9, 0x36, 0xfa, 0xae, 0x1a, 0x22, 0xb5, 0x20, + 0x4e, 0x73, 0x16, 0x72, 0x59, 0xf7, 0x5d, 0x39, 0xa2, 0x1e, 0x6c, 0x23, 0xc7, 0x63, 0xf6, 0xc8, + 0xcf, 0xf3, 0xb3, 0x34, 0x0b, 0xd5, 0xe6, 0x29, 0xf4, 0x12, 0x76, 0xe6, 0xcd, 0x24, 0x58, 0xee, + 0xc0, 0x82, 0x21, 0x4e, 0x1a, 0x87, 0x1a, 0x47, 0xec, 0xc6, 0x82, 0xd1, 0x31, 0xec, 0x54, 0x19, + 0x48, 0x29, 0xfd, 0x9d, 0x03, 0x9b, 0xfb, 0xb8, 0x0a, 0xb9, 0xe5, 0xb7, 0x16, 0x3b, 0x8a, 0xa2, + 0xe2, 0x1d, 0xe5, 0x18, 0x45, 0xff, 0x3c, 0xcd, 0xa4, 0x59, 0x76, 0x5c, 0x31, 0x20, 0x97, 0xa1, + 0x1b, 0xb2, 0xbc, 0x88, 0x12, 0xee, 0xba, 0x5c, 0x16, 0xeb, 0xae, 0x09, 0xe2, 0x62, 0x3f, 0x4d, + 0xe7, 0x49, 0x21, 0x4d, 0x4c, 0x8e, 0xc8, 0x08, 0x96, 0x9f, 0x33, 0x65, 0x43, 0xf8, 0x93, 0x7e, + 0x09, 0x5b, 0xf6, 0xf2, 0xc5, 0xbe, 0x70, 0xfd, 0x45, 0xe6, 0x27, 0x39, 0xea, 0x24, 0x4d, 0xbc, + 0x28, 0xcc, 0xc7, 0xce, 0xe5, 0x65, 0x5c, 0x7f, 0x05, 0x4c, 0x3f, 0x81, 0xc1, 0x7e, 0x9a, 0x24, + 0x2c, 0x28, 0xd4, 0xde, 0x27, 0xd0, 0xe1, 0x9b, 0x9c, 0x67, 0x91, 0xdc, 0x74, 0x39, 0x46, 0x4f, + 0x2f, 0xb1, 0xa5, 0x08, 0x6f, 0xc0, 0xc6, 0x7e, 0xc6, 0xfc, 0x82, 0x3d, 0x48, 0x43, 0x66, 0xd0, + 0xa8, 0x68, 0xad, 0x1c, 0xd3, 0x3f, 0x75, 0x80, 0x98, 0x5f, 0xc8, 0x25, 0xff, 0x0a, 0xf4, 0x73, + 0xc6, 0x42, 0xef, 0x34, 0x61, 0xa7, 0x69, 0x12, 0x05, 0x72, 0xc1, 0x3d, 0x04, 0xfe, 0x44, 0xc2, + 0xc8, 0x47, 0x30, 0x8a, 0x92, 0xa8, 0x88, 0xfc, 0x38, 0xfa, 0x5d, 0x16, 0x7a, 0x71, 0x12, 0xe6, + 0xe3, 0x96, 0xd8, 0x98, 0x01, 0x3f, 0x4c, 0xc2, 0x9c, 0xdc, 0x80, 0x4d, 0x13, 0x35, 0xc0, 0x65, + 0xbf, 0x2a, 0xa4, 0x2a, 0x88, 0x31, 0xb5, 0x2f, 0x66, 0xe8, 0x3f, 0x39, 0xd0, 0x51, 0xa1, 0xd3, + 0x52, 0xab, 0x53, 0x51, 0xeb, 0x1d, 0xe8, 0xe6, 0x67, 0xfe, 0xcc, 0x0b, 0xe2, 0x88, 0x25, 0x05, + 0xd7, 0xfa, 0xe0, 0xd6, 0x3b, 0xd7, 0x65, 0x90, 0x56, 0x24, 0xae, 0x1f, 0x9d, 0xf9, 0xb3, 0x7d, + 0x8e, 0xe2, 0x9a, 0xf8, 0x22, 0x1c, 0xbe, 0x60, 0x89, 0xe7, 0x87, 0x61, 0xc6, 0xf2, 0x9c, 0x2f, + 0x69, 0xdd, 0xb5, 0x81, 0x18, 0x6e, 0x42, 0x16, 0x44, 0xa7, 0x7e, 0xec, 0xcd, 0x62, 0x3f, 0x60, + 0xb9, 0x74, 0x9a, 0x0a, 0x94, 0x52, 0x00, 0xcd, 0x88, 0xac, 0xc1, 0xf2, 0xe1, 0x83, 0xbb, 0xa3, + 0x25, 0xd2, 0x85, 0xb5, 0xfd, 0x87, 0x0f, 0x1e, 0x1c, 0x3c, 0x7b, 0x3c, 0x6a, 0xa1, 0x8e, 0xef, + 0xb2, 0x59, 0x9a, 0x47, 0xa6, 0x8e, 0x17, 0x6d, 0x8f, 0x7e, 0x0c, 0xc3, 0x12, 0x5b, 0xea, 0x66, + 0x0c, 0x6b, 0x6a, 0xb1, 0x02, 0x5b, 0x0d, 0xd1, 0x00, 0xef, 0x46, 0x79, 0x90, 0xbe, 0x64, 0x19, + 0x6a, 0x33, 0x7f, 0xfb, 0xb8, 0xf5, 0x03, 0xd8, 0xae, 0x50, 0x90, 0x4c, 0x2f, 0xc1, 0x7a, 0x32, + 0x3f, 0xf5, 0x10, 0x3f, 0x97, 0xf1, 0x47, 0x03, 0xe8, 0x1f, 0x3a, 0x40, 0x0e, 0x5e, 0xb1, 0x60, + 0x5e, 0x30, 0xdc, 0xbf, 0xb1, 0xb1, 0x34, 0x0b, 0x59, 0xe6, 0x45, 0xa5, 0xe1, 0xa9, 0x31, 0x8f, + 0x4c, 0x7e, 0xc4, 0xa7, 0x64, 0xcc, 0x93, 0x43, 0x0c, 0x22, 0x33, 0xc6, 0x32, 0x6f, 0x36, 0x9f, + 0x7a, 0x2f, 0xd8, 0x6b, 0xa9, 0x11, 0x0b, 0x86, 0x94, 0xbf, 0x9b, 0xfb, 0x49, 0x11, 0x15, 0xaf, + 0xe5, 0x59, 0x51, 0x8e, 0xd1, 0x07, 0xbe, 0x62, 0x85, 0x3c, 0xef, 0xde, 0x44, 0xc6, 0x7f, 0xe9, + 0x00, 0x31, 0xbf, 0x90, 0x5b, 0xbe, 0x0b, 0x1d, 0x79, 0x0c, 0x08, 0x7f, 0xed, 0xde, 0xba, 0xaa, + 0xcc, 0xaa, 0x8e, 0x7d, 0x5d, 0x8e, 0xf3, 0x83, 0xa4, 0xc8, 0x5e, 0xbb, 0xe5, 0x97, 0x93, 0x43, + 0xe8, 0x5b, 0x53, 0x18, 0x37, 0x70, 0x57, 0x62, 0x11, 0xf8, 0x93, 0x5c, 0x81, 0xf6, 0x4b, 0x3f, + 0x9e, 0x8b, 0xe8, 0xdd, 0xbd, 0x35, 0x54, 0x5c, 0x14, 0x0b, 0x31, 0x7b, 0xbb, 0xf5, 0x43, 0x87, + 0x8e, 0x60, 0xf0, 0x15, 0x2b, 0xee, 0x27, 0xcf, 0x53, 0xb9, 0x31, 0xfa, 0x2f, 0xcb, 0x30, 0x2c, + 0x41, 0xda, 0x42, 0x5e, 0xb2, 0x2c, 0xc7, 0x80, 0x26, 0x2d, 0x44, 0x0e, 0x79, 0x10, 0x47, 0x95, + 0x2b, 0xd9, 0xca, 0x00, 0x6d, 0xc2, 0x08, 0x81, 0x95, 0x79, 0x16, 0xa1, 0x27, 0xa0, 0x2b, 0xf3, + 0xdf, 0x4a, 0xfd, 0xa8, 0x03, 0x65, 0xfb, 0x1a, 0x50, 0xce, 0xfa, 0x51, 0x96, 0xf3, 0x28, 0xa9, + 0x66, 0x11, 0x40, 0x3e, 0x86, 0x55, 0xae, 0xf5, 0x9c, 0xc7, 0xca, 0xee, 0xad, 0x4d, 0xb5, 0xbf, + 0x87, 0x1c, 0xba, 0x8f, 0xd1, 0xd4, 0x95, 0x28, 0xe4, 0x16, 0x2c, 0xc7, 0x49, 0x38, 0x5e, 0xe3, + 0xf2, 0xbe, 0x6c, 0xc8, 0xdb, 0xdc, 0xe0, 0xf5, 0xc3, 0x24, 0x14, 0x72, 0x46, 0x64, 0x8c, 0xec, + 0x7e, 0x1c, 0xf9, 0xf9, 0x78, 0x5d, 0x1c, 0xaa, 0x7c, 0x60, 0x1e, 0xaa, 0x60, 0x1d, 0xaa, 0xe4, + 0x26, 0x6c, 0xaa, 0x9c, 0x84, 0x87, 0x82, 0x13, 0x3f, 0x3f, 0x61, 0xf9, 0xb8, 0xcb, 0xf7, 0xdb, + 0x34, 0x45, 0xbe, 0x0f, 0x6b, 0x2a, 0x64, 0xf5, 0xec, 0x3d, 0xc8, 0x78, 0xc5, 0x57, 0xa7, 0x70, + 0x26, 0x5f, 0x41, 0x47, 0xad, 0xf0, 0x2d, 0xd4, 0x7d, 0x98, 0x84, 0x9c, 0x8c, 0xa1, 0xee, 0x2d, + 0x6e, 0x98, 0x2a, 0xe0, 0x2a, 0x95, 0xff, 0x08, 0x36, 0x2d, 0xa8, 0xd4, 0xfa, 0x07, 0xcd, 0x31, + 0xdb, 0x06, 0xd2, 0x2f, 0x38, 0x49, 0x74, 0x6e, 0xc3, 0x8a, 0xde, 0x22, 0x42, 0xb8, 0x9c, 0xb9, + 0xfe, 0xbe, 0x3c, 0x30, 0x86, 0x19, 0x9b, 0xcd, 0x45, 0x06, 0x7c, 0x14, 0xa4, 0x99, 0xc8, 0x52, + 0x36, 0x5c, 0xd0, 0x60, 0x3c, 0x4a, 0xa7, 0x78, 0x34, 0x0a, 0x97, 0xef, 0xb8, 0x72, 0x44, 0x2f, + 0xc0, 0xf6, 0x61, 0x94, 0x17, 0x32, 0x58, 0x47, 0x65, 0xe0, 0xa2, 0x5f, 0xc3, 0x4e, 0x75, 0x42, + 0xf2, 0xbb, 0x09, 0x10, 0x94, 0x50, 0xe9, 0x9e, 0xa3, 0x6a, 0xd4, 0x77, 0x0d, 0x1c, 0xfa, 0x0f, + 0x0e, 0x6c, 0x20, 0x31, 0x61, 0x75, 0x6a, 0xe3, 0x46, 0x18, 0x72, 0xec, 0x30, 0xf4, 0x03, 0x68, + 0xa7, 0x67, 0x09, 0xcb, 0xe4, 0x91, 0xf2, 0x7e, 0xa9, 0xa6, 0x2a, 0x8d, 0xeb, 0x0f, 0x11, 0xcd, + 0x15, 0xd8, 0x68, 0x8c, 0x71, 0x74, 0x1a, 0x15, 0x32, 0xdf, 0x12, 0x03, 0x94, 0x6f, 0x94, 0x04, + 0xf1, 0x3c, 0x64, 0x1e, 0xb7, 0x4e, 0x79, 0x82, 0x74, 0xdc, 0x2a, 0x98, 0x7e, 0x00, 0x6d, 0x4e, + 0x8f, 0x74, 0x60, 0x65, 0xef, 0xe1, 0xe3, 0x7b, 0xa3, 0x25, 0x3c, 0x47, 0x1e, 0x3e, 0x7d, 0x30, + 0x72, 0x10, 0xf4, 0xe8, 0xe0, 0xc0, 0x1d, 0xb5, 0xe8, 0x9f, 0x39, 0x40, 0xcc, 0x85, 0x48, 0xa9, + 0x7c, 0x51, 0xba, 0x9a, 0x90, 0xc8, 0x87, 0x4d, 0x8b, 0x96, 0x3e, 0x24, 0x86, 0xc2, 0x8d, 0xe4, + 0x57, 0x93, 0xfb, 0xd0, 0x35, 0xc0, 0x0d, 0xb6, 0xfb, 0x81, 0x6d, 0xbb, 0x03, 0xdb, 0x95, 0x4d, + 0xd3, 0x25, 0x30, 0x42, 0xa6, 0x58, 0x87, 0x94, 0xea, 0xfc, 0x48, 0x68, 0x40, 0xc2, 0xe4, 0x9a, + 0xb7, 0xa0, 0x2d, 0x02, 0x87, 0x30, 0x57, 0x31, 0x28, 0x3f, 0x67, 0x5a, 0xce, 0xf4, 0x33, 0xf9, + 0x39, 0x33, 0xb7, 0x4c, 0xa1, 0x2d, 0xa2, 0x92, 0xd8, 0x71, 0x4f, 0xad, 0x08, 0xb1, 0x5c, 0x31, + 0x45, 0xff, 0xcd, 0x81, 0x35, 0xe9, 0x5d, 0x68, 0x83, 0x79, 0xe1, 0x17, 0x73, 0x75, 0x78, 0xca, + 0x11, 0xf9, 0x04, 0x3a, 0xb2, 0xc8, 0xc8, 0xe5, 0xe6, 0xb4, 0x39, 0x49, 0xb8, 0x5b, 0x62, 0x90, + 0x2b, 0xb0, 0xca, 0x53, 0x77, 0x11, 0x25, 0xbb, 0xb7, 0xfa, 0x06, 0x6e, 0x94, 0xb8, 0x72, 0x12, + 0xb3, 0xcb, 0x69, 0x9c, 0x06, 0x2f, 0x4e, 0x58, 0x74, 0x7c, 0x52, 0xc8, 0xc0, 0x69, 0x82, 0xca, + 0x60, 0xdb, 0x36, 0x82, 0xad, 0x11, 0xbe, 0x57, 0xed, 0xf0, 0x5d, 0x46, 0xba, 0x35, 0x23, 0xd2, + 0xd1, 0xaf, 0x61, 0xc0, 0xfd, 0x51, 0xe7, 0xc1, 0xd5, 0x30, 0xef, 0x34, 0x84, 0xf9, 0x92, 0x56, + 0xcb, 0xa4, 0xf5, 0x17, 0x0e, 0x90, 0x87, 0x33, 0x96, 0xfc, 0x9f, 0xa4, 0xe0, 0x3a, 0x95, 0x5e, + 0xb6, 0x52, 0xe9, 0xcb, 0xd0, 0x9d, 0xcd, 0xf3, 0x13, 0x4f, 0x4e, 0x8a, 0x03, 0xdd, 0x04, 0xa9, + 0x64, 0xbb, 0xad, 0x93, 0xed, 0x3b, 0xb0, 0x69, 0xad, 0x53, 0x9a, 0xc3, 0x87, 0x30, 0xb0, 0x93, + 0x6a, 0xb9, 0xce, 0x0a, 0x94, 0xfe, 0x7d, 0x0b, 0xda, 0xdc, 0x68, 0xb9, 0xfd, 0x65, 0x91, 0x2c, + 0x84, 0x1d, 0x57, 0x0c, 0xac, 0x04, 0xa3, 0x65, 0x27, 0x18, 0x66, 0xcc, 0x58, 0xb6, 0x63, 0xc6, + 0x00, 0x5a, 0x51, 0x28, 0x8b, 0x88, 0x56, 0x14, 0x92, 0x2f, 0xeb, 0x62, 0x6b, 0x73, 0xdb, 0xda, + 0x51, 0xf6, 0x62, 0x2b, 0xae, 0x51, 0x9c, 0x71, 0x1a, 0xf8, 0x31, 0x32, 0x13, 0xc6, 0x50, 0x8e, + 0xc9, 0x7b, 0x00, 0x01, 0x4f, 0xdd, 0x43, 0xcf, 0x2f, 0xb8, 0x49, 0xac, 0xb8, 0x06, 0x84, 0x5c, + 0x81, 0x95, 0x3c, 0x0a, 0xd9, 0xb8, 0xc3, 0x03, 0xd8, 0x86, 0xe5, 0xab, 0x47, 0x51, 0xc8, 0x5c, + 0x3e, 0x8d, 0xc6, 0x12, 0xe5, 0x5e, 0x7a, 0x96, 0x78, 0x3c, 0x0a, 0xf0, 0x53, 0xb4, 0xe3, 0x5a, + 0x30, 0x34, 0xd3, 0x93, 0x34, 0x0e, 0xf9, 0x49, 0xba, 0xe2, 0xf2, 0xdf, 0xf4, 0xcf, 0x1d, 0xe8, + 0x71, 0x5a, 0x2e, 0x3b, 0x4d, 0x5f, 0xfa, 0xb1, 0x25, 0x33, 0x67, 0xb1, 0xcc, 0x2a, 0xe9, 0x9e, + 0x99, 0x24, 0x2e, 0x57, 0x92, 0x44, 0x73, 0xf7, 0x2b, 0x95, 0xdd, 0x57, 0x97, 0xdd, 0xae, 0x2f, + 0x9b, 0x9e, 0xc0, 0xaa, 0x88, 0x4c, 0xe4, 0xfb, 0x00, 0xd3, 0xf9, 0x6b, 0xcf, 0x8a, 0x8e, 0x7d, + 0x4b, 0x22, 0xae, 0x81, 0x40, 0x6e, 0x40, 0x37, 0x67, 0x71, 0xac, 0xf0, 0x5b, 0x4d, 0xf8, 0x26, + 0x06, 0xfd, 0x54, 0x45, 0x4e, 0x9e, 0xce, 0xa0, 0xbc, 0x30, 0xf4, 0xc8, 0x4c, 0x99, 0xff, 0x46, + 0x1b, 0x4e, 0xcf, 0x12, 0x59, 0xa2, 0xe3, 0x4f, 0xfa, 0x73, 0x47, 0x7e, 0xf5, 0x64, 0x16, 0xfa, + 0x05, 0xc3, 0xcc, 0x40, 0xec, 0xc5, 0xe1, 0x46, 0x62, 0xf3, 0xbb, 0xb7, 0xe4, 0x8a, 0x59, 0xf2, + 0x1b, 0xd0, 0x17, 0x12, 0xca, 0x84, 0xe0, 0x65, 0xbc, 0xda, 0xb2, 0x97, 0x27, 0xe6, 0xee, 0x2d, + 0xb9, 0x36, 0xf2, 0xde, 0x00, 0x7a, 0x02, 0x30, 0xe7, 0x4c, 0xe9, 0xbf, 0xb6, 0x60, 0x05, 0x83, + 0xe5, 0xe2, 0xba, 0xe2, 0x8d, 0xb2, 0xc6, 0x2f, 0xa1, 0x17, 0x27, 0xa1, 0x1a, 0xaa, 0xb8, 0x78, + 0xc9, 0x0c, 0xc7, 0x98, 0xe1, 0x3c, 0x9a, 0x4f, 0xbf, 0x61, 0xaf, 0xe5, 0xb1, 0x63, 0x7d, 0x81, + 0xfc, 0xa3, 0x64, 0x9a, 0xce, 0x93, 0x50, 0x9e, 0x8d, 0x6a, 0xa8, 0x8f, 0x88, 0xb6, 0x71, 0x44, + 0x60, 0xd4, 0x78, 0x35, 0x0f, 0x3d, 0x3b, 0x54, 0x9a, 0x20, 0xf2, 0x09, 0x6c, 0xe4, 0x2c, 0x48, + 0x93, 0x30, 0x17, 0x15, 0x67, 0x50, 0xb0, 0x90, 0xfb, 0x49, 0xdf, 0xad, 0x4f, 0x34, 0xa7, 0x91, + 0x93, 0x3b, 0x30, 0xac, 0x2c, 0xbb, 0xe1, 0x58, 0xdc, 0x32, 0x8f, 0xc5, 0x75, 0xf3, 0x18, 0xfc, + 0xfd, 0x16, 0x6c, 0x3c, 0xc2, 0xe2, 0x50, 0x2a, 0x45, 0x84, 0xd3, 0xff, 0xcd, 0x98, 0x63, 0xfa, + 0xcf, 0x4a, 0xc5, 0x7f, 0x54, 0x04, 0x68, 0x9f, 0x1f, 0x01, 0xae, 0xc1, 0x28, 0x63, 0xbc, 0x84, + 0xf5, 0x4a, 0x52, 0x42, 0x9c, 0x35, 0x38, 0x26, 0xcf, 0xd1, 0xe9, 0x29, 0x0b, 0x23, 0xbf, 0x40, + 0xa8, 0x17, 0x60, 0x89, 0x12, 0x73, 0xa9, 0x76, 0xdc, 0xa6, 0x29, 0x14, 0x01, 0x31, 0x45, 0x20, + 0x23, 0xf5, 0xe7, 0x30, 0x8a, 0x92, 0x82, 0x65, 0x89, 0x1f, 0x7b, 0xa7, 0x7e, 0x11, 0x9c, 0xb0, + 0x05, 0x7e, 0x59, 0x43, 0x23, 0x3f, 0x82, 0x01, 0xcf, 0xce, 0xf3, 0x79, 0x10, 0xb0, 0x1c, 0x93, + 0x29, 0xe1, 0xa0, 0x65, 0x56, 0x8e, 0x45, 0xe8, 0x91, 0x98, 0x74, 0x2b, 0xa8, 0xe4, 0x33, 0xcc, + 0x54, 0x4f, 0xfd, 0x28, 0xc1, 0x24, 0x5f, 0xb8, 0xdb, 0x72, 0x83, 0xbb, 0xb9, 0x55, 0x2c, 0xf2, + 0x39, 0xf4, 0x39, 0xa9, 0xe7, 0x7e, 0x14, 0xcf, 0x33, 0x9e, 0xc1, 0xd5, 0x98, 0xfe, 0x58, 0xcc, + 0xb9, 0x36, 0x26, 0xfd, 0x4f, 0x07, 0x86, 0x5a, 0x04, 0x07, 0x2f, 0x59, 0x82, 0xd1, 0xb9, 0xcd, + 0xf7, 0xb3, 0xd0, 0xd9, 0xf9, 0x2c, 0xf9, 0x1c, 0x7a, 0xe6, 0x06, 0xa4, 0xaf, 0x37, 0xed, 0xf4, + 0xde, 0x92, 0x6b, 0xa1, 0x92, 0xcf, 0xdf, 0x6c, 0xa7, 0xf7, 0x96, 0x9a, 0xf6, 0xda, 0x33, 0x77, + 0xc0, 0x0d, 0xab, 0x79, 0xab, 0x25, 0x57, 0x89, 0xba, 0xb7, 0x06, 0x6d, 0x86, 0x1b, 0xa4, 0x29, + 0x74, 0x8d, 0xea, 0x68, 0x61, 0xe2, 0x65, 0x84, 0x9d, 0x96, 0x1d, 0x76, 0x8c, 0x3c, 0x68, 0xa5, + 0x96, 0x07, 0x89, 0x36, 0x6a, 0xdb, 0x68, 0xa3, 0xd2, 0x4f, 0x61, 0x9b, 0x47, 0x3d, 0xa6, 0x7b, + 0xee, 0xbf, 0xb8, 0xf8, 0x1f, 0xc3, 0x4e, 0xf5, 0x23, 0xd9, 0x4b, 0x3b, 0x04, 0x22, 0x66, 0x2c, + 0xd7, 0x3d, 0xaf, 0xa7, 0x71, 0x8e, 0x03, 0xd3, 0xbf, 0x72, 0x60, 0xd3, 0x22, 0x27, 0xdd, 0xe0, + 0x3d, 0x18, 0x29, 0x1c, 0x2f, 0x4d, 0x3c, 0x7e, 0xca, 0x3a, 0xfa, 0x94, 0x25, 0xd7, 0x81, 0x68, + 0xe5, 0x54, 0xa8, 0x37, 0xcc, 0x08, 0x5f, 0x46, 0x36, 0xa1, 0xc6, 0x16, 0xd9, 0x56, 0x0d, 0x6e, + 0x06, 0x95, 0x15, 0x2b, 0xa8, 0x68, 0xa9, 0xec, 0xc6, 0xb1, 0x55, 0xec, 0xd0, 0x39, 0x5c, 0xa8, + 0xcd, 0xc8, 0xad, 0x7c, 0x02, 0x1b, 0x8a, 0x85, 0x12, 0x89, 0xca, 0xea, 0xeb, 0x13, 0x88, 0x2d, + 0xf7, 0x6b, 0x60, 0x8b, 0xf6, 0x61, 0x7d, 0x82, 0x7e, 0x1f, 0x36, 0x04, 0x5b, 0xf3, 0xe2, 0x64, + 0x61, 0xf1, 0x86, 0x85, 0xb3, 0x89, 0x2e, 0x35, 0xfa, 0x07, 0x2d, 0x04, 0xe7, 0x45, 0x9a, 0x59, + 0xfd, 0xd1, 0x37, 0x6a, 0x76, 0x9a, 0x4d, 0xd4, 0x96, 0xdd, 0x44, 0x25, 0xdf, 0x40, 0x17, 0x4f, + 0xb2, 0xa9, 0x1f, 0xbc, 0x98, 0xcf, 0xd4, 0xd1, 0x77, 0x4d, 0x39, 0x4b, 0x9d, 0x23, 0x1e, 0x84, + 0x7b, 0x02, 0x59, 0x1c, 0x84, 0x10, 0x97, 0x00, 0xf2, 0x3d, 0x7e, 0xc3, 0xe4, 0x85, 0x7e, 0xe1, + 0x4f, 0xfd, 0x5c, 0x34, 0x98, 0x7b, 0xfc, 0x5c, 0xbb, 0x2b, 0x41, 0xf2, 0x4c, 0x32, 0x29, 0xfc, + 0xa2, 0x33, 0xa9, 0x67, 0x9e, 0x49, 0x0c, 0x2d, 0xd1, 0x58, 0x93, 0xee, 0xf9, 0x66, 0x02, 0x2c, + 0x7b, 0xb9, 0x52, 0x0c, 0x0a, 0xc8, 0x1b, 0xb9, 0x1f, 0xa1, 0x79, 0x49, 0x24, 0xd5, 0x12, 0x11, + 0xc5, 0xfc, 0x50, 0xc1, 0x55, 0x0b, 0xf7, 0x2e, 0x90, 0x23, 0x56, 0x1c, 0xa6, 0xc7, 0x87, 0xec, + 0xa5, 0xae, 0x24, 0xae, 0xc3, 0x7a, 0x9c, 0x1e, 0x7b, 0x31, 0xc2, 0xf8, 0x72, 0x07, 0xba, 0xd0, + 0x2a, 0x71, 0x35, 0x0a, 0xdd, 0x86, 0x4d, 0x8b, 0x8a, 0x54, 0xe5, 0x06, 0x0c, 0x8f, 0x4e, 0xe6, + 0x45, 0x98, 0x9e, 0xa9, 0xdb, 0x19, 0x2c, 0x19, 0x35, 0x48, 0xa2, 0xfd, 0x1a, 0xec, 0x1c, 0xcd, + 0xa7, 0x79, 0x90, 0x45, 0x53, 0x66, 0x17, 0xfe, 0x13, 0xe8, 0xb0, 0x57, 0x51, 0x5e, 0x44, 0xc9, + 0x31, 0x5f, 0x46, 0xc7, 0x2d, 0xc7, 0xf4, 0x7d, 0x78, 0xb7, 0xfc, 0x0a, 0x43, 0x5d, 0xbe, 0x1b, + 0x04, 0x6c, 0x56, 0x30, 0x75, 0x17, 0x42, 0xef, 0xc0, 0xb6, 0x8d, 0x60, 0x5c, 0xe5, 0xa9, 0x82, + 0xbe, 0xf0, 0x5f, 0xc8, 0x4c, 0xae, 0xe3, 0xda, 0x40, 0xfa, 0xdf, 0x2d, 0xe8, 0xe1, 0x67, 0x8a, + 0x2c, 0xb9, 0x58, 0x0b, 0x2a, 0x6b, 0x7c, 0x7c, 0xdf, 0x4e, 0x81, 0x5b, 0x95, 0x14, 0xf8, 0xdc, + 0xa4, 0x60, 0x51, 0x7f, 0x54, 0x27, 0x1f, 0x6d, 0x33, 0xf9, 0xa8, 0x76, 0x5d, 0x57, 0x1b, 0xba, + 0xae, 0x3b, 0xb0, 0x9a, 0xf1, 0x96, 0x98, 0xac, 0x3f, 0xe5, 0x08, 0x63, 0x8e, 0xa8, 0xd3, 0xbc, + 0x8c, 0x05, 0x2c, 0x7a, 0x89, 0x32, 0xed, 0x88, 0x98, 0x53, 0x85, 0x63, 0x81, 0x26, 0x61, 0xb9, + 0xbc, 0x98, 0x5a, 0x17, 0x37, 0x77, 0x36, 0x14, 0xe3, 0x9e, 0x8a, 0xd1, 0x06, 0x55, 0xd1, 0xc9, + 0x6b, 0x98, 0xc1, 0x35, 0x94, 0x50, 0x45, 0xb9, 0x2b, 0x72, 0x98, 0x2a, 0x1c, 0x63, 0x71, 0xd7, + 0x38, 0xc2, 0x7e, 0xc9, 0x3e, 0xb5, 0x29, 0xe3, 0xe5, 0x8a, 0x8c, 0xab, 0xd2, 0x5c, 0x69, 0x90, + 0xe6, 0x87, 0x30, 0x90, 0x67, 0xa6, 0x97, 0x31, 0x3f, 0x4f, 0xd5, 0x69, 0x56, 0x81, 0xd2, 0xbf, + 0x59, 0x16, 0xab, 0x95, 0xc7, 0xfc, 0xff, 0xaf, 0xb1, 0x68, 0x95, 0xb7, 0x2d, 0x95, 0x5f, 0x85, + 0xa1, 0xa5, 0x5a, 0x16, 0x4a, 0x8d, 0x57, 0xc1, 0x98, 0xa6, 0x6b, 0xd5, 0x16, 0x52, 0xdb, 0x26, + 0xa8, 0x26, 0x2c, 0x68, 0x10, 0xd6, 0x65, 0x58, 0xc9, 0xd2, 0x98, 0x71, 0x95, 0x0e, 0x74, 0x97, + 0xc7, 0x4d, 0x63, 0xe6, 0xf2, 0x19, 0x3c, 0x4f, 0x2a, 0x66, 0xc1, 0x42, 0xde, 0xad, 0x5d, 0x77, + 0xeb, 0x13, 0xe8, 0xa8, 0xa6, 0x59, 0x14, 0xe3, 0xbe, 0xb8, 0xf7, 0xb1, 0x80, 0x58, 0x61, 0x67, + 0xde, 0x2c, 0x63, 0xd1, 0xa9, 0x7f, 0xcc, 0xc6, 0x03, 0x8e, 0x62, 0x40, 0xb4, 0x2b, 0x0d, 0x0d, + 0x57, 0xa2, 0xff, 0xd5, 0x82, 0xf6, 0xe3, 0xcc, 0x0f, 0x19, 0x96, 0x91, 0xa7, 0xe8, 0xf1, 0xde, + 0xe2, 0xb2, 0xce, 0x35, 0x31, 0xf0, 0x83, 0xc2, 0xf8, 0xa0, 0xd5, 0xf8, 0x81, 0x81, 0x61, 0xe8, + 0x67, 0xd9, 0xd2, 0xcf, 0x79, 0x3a, 0x35, 0x2c, 0xa1, 0x6d, 0x5b, 0x42, 0xb9, 0x9f, 0x55, 0x33, + 0x34, 0x28, 0xd9, 0xaf, 0x2d, 0x94, 0xfd, 0x65, 0xe8, 0x32, 0x71, 0xfd, 0xc3, 0x5b, 0x11, 0xc2, + 0x12, 0x4c, 0x50, 0x59, 0x89, 0xac, 0x9f, 0x5f, 0x89, 0xdc, 0x86, 0x5e, 0x80, 0x86, 0xc1, 0xb2, + 0x99, 0x9f, 0x15, 0xc2, 0x14, 0x16, 0x77, 0x4b, 0x2c, 0x5c, 0xfa, 0x31, 0x6c, 0x72, 0xa9, 0xdf, + 0x8b, 0xf0, 0x1c, 0x7a, 0x6d, 0xd4, 0x5a, 0xa2, 0x21, 0xeb, 0x18, 0x0d, 0x59, 0x7a, 0x07, 0xb6, + 0x6c, 0x64, 0x79, 0x08, 0x5e, 0x81, 0xd5, 0x02, 0xe1, 0xb5, 0x5a, 0x84, 0x63, 0xbb, 0x72, 0x92, + 0xfe, 0xb1, 0x03, 0x7d, 0x84, 0x44, 0xc9, 0xf1, 0x21, 0xd2, 0xcb, 0x51, 0xe0, 0xa7, 0xfe, 0x2b, + 0x2f, 0x67, 0x71, 0xac, 0x9a, 0x1f, 0x6a, 0x8c, 0x02, 0xc7, 0xdf, 0xd3, 0xb9, 0x4a, 0xdc, 0xd4, + 0x10, 0xcd, 0x30, 0x63, 0x39, 0xcb, 0x30, 0x35, 0xe2, 0x9f, 0x8a, 0x40, 0x62, 0x03, 0xd1, 0x41, + 0x4a, 0x00, 0x12, 0x11, 0x0a, 0xb5, 0x60, 0xf4, 0x96, 0xd8, 0x50, 0xb9, 0xa0, 0x37, 0xc9, 0x7d, + 0xff, 0xda, 0x81, 0xed, 0xca, 0x47, 0x52, 0x0c, 0xbb, 0xb0, 0xca, 0xe5, 0xa4, 0xc4, 0xf0, 0x91, + 0x29, 0x86, 0x1a, 0xfa, 0x75, 0x31, 0x94, 0xbd, 0x64, 0xf1, 0xe1, 0xe4, 0x11, 0x74, 0x0d, 0x70, + 0x43, 0x82, 0xf2, 0xb1, 0xdd, 0x4b, 0xde, 0x6e, 0x66, 0x61, 0xe4, 0x2d, 0xdf, 0x42, 0xef, 0x49, + 0x32, 0xfd, 0x25, 0x9e, 0x63, 0x90, 0x4b, 0xb0, 0x9e, 0x31, 0x59, 0xe9, 0xcb, 0x74, 0x45, 0x03, + 0xe8, 0x10, 0xfa, 0x92, 0xae, 0xbe, 0x45, 0x7f, 0x92, 0xc4, 0x69, 0xf0, 0xe2, 0x4d, 0x6f, 0xd1, + 0x7f, 0x0a, 0xc4, 0xfc, 0x40, 0x27, 0x54, 0x73, 0x0e, 0xad, 0x24, 0x54, 0x0a, 0xc8, 0x13, 0xaa, + 0xf7, 0xa1, 0x6b, 0xa2, 0x88, 0x4b, 0x37, 0xd0, 0x08, 0xf4, 0x8f, 0x1c, 0x18, 0x3e, 0x8d, 0x8a, + 0x93, 0x30, 0xf3, 0xcf, 0xde, 0x40, 0xa9, 0xd5, 0x17, 0x0d, 0xad, 0xf3, 0x5e, 0x34, 0x2c, 0x57, + 0x5f, 0x34, 0xf8, 0x71, 0x2c, 0x9b, 0x2f, 0xf8, 0xd3, 0x6c, 0xbb, 0xf6, 0x45, 0xdb, 0xf5, 0x36, + 0x8c, 0xf4, 0x62, 0xde, 0xae, 0xe7, 0x7a, 0xed, 0x2a, 0xac, 0x97, 0xfe, 0x4e, 0xd6, 0x60, 0x79, + 0xef, 0xc9, 0x6f, 0x8e, 0x96, 0x48, 0x07, 0x56, 0x8e, 0x0e, 0x0e, 0x0f, 0xc5, 0xf5, 0x06, 0xbf, + 0xf1, 0x68, 0x5d, 0xbb, 0x06, 0x2b, 0x18, 0x5d, 0xc8, 0x3a, 0xb4, 0x1f, 0xef, 0x7e, 0x73, 0xe0, + 0x8e, 0x96, 0xf0, 0xe7, 0x4f, 0xf8, 0x4f, 0x87, 0xf4, 0xa0, 0x73, 0xff, 0xc1, 0xe3, 0x03, 0xf7, + 0xc1, 0xee, 0xe1, 0xa8, 0x75, 0xed, 0x29, 0x74, 0x54, 0x76, 0x88, 0x48, 0xbb, 0x87, 0x07, 0xee, + 0x63, 0x81, 0x7f, 0xe0, 0xba, 0x0f, 0x5d, 0x41, 0xf7, 0xe9, 0xae, 0xfb, 0x60, 0xd4, 0xc2, 0x5f, + 0xf7, 0x1f, 0xfc, 0xf8, 0xe1, 0x68, 0x99, 0x74, 0x61, 0xed, 0xdb, 0x03, 0x77, 0xef, 0xe1, 0xd1, + 0xc1, 0x68, 0x05, 0x71, 0xef, 0x1e, 0xec, 0x3d, 0xf9, 0x6a, 0xd4, 0xe6, 0x1c, 0xdd, 0xdd, 0xfd, + 0x83, 0xd1, 0xea, 0xad, 0x7f, 0x77, 0x60, 0xed, 0xd9, 0x3c, 0xbc, 0x9f, 0x44, 0x05, 0x39, 0x00, + 0xd0, 0xaf, 0x24, 0xc8, 0xc5, 0xb2, 0xdb, 0x5f, 0x7d, 0x6b, 0x31, 0x99, 0x34, 0x4d, 0x49, 0xb3, + 0x5a, 0x22, 0xf7, 0xa0, 0x6b, 0x64, 0xde, 0x64, 0xb2, 0xb8, 0x44, 0x98, 0xbc, 0xd3, 0x38, 0x57, + 0x52, 0x3a, 0x00, 0xd0, 0x16, 0xa7, 0x17, 0x54, 0x33, 0x5b, 0xbd, 0xa0, 0xba, 0x81, 0xd2, 0xa5, + 0x5b, 0xff, 0x7c, 0x11, 0x96, 0x9f, 0xcd, 0x43, 0xf2, 0x0c, 0xba, 0xc6, 0x5b, 0x35, 0x52, 0xbb, + 0x49, 0xd3, 0xcb, 0x69, 0x7a, 0xd2, 0x36, 0xf9, 0xf9, 0x3f, 0xfe, 0xc7, 0x9f, 0xb4, 0xb6, 0xe8, + 0xf0, 0xc6, 0xcb, 0x5f, 0xbd, 0xe1, 0x87, 0xa1, 0xb2, 0xc5, 0xdb, 0xce, 0x35, 0xe2, 0xc2, 0x9a, + 0x7c, 0x8e, 0x46, 0x76, 0x0c, 0x1a, 0x46, 0x19, 0x37, 0xb9, 0x50, 0x83, 0x4b, 0xba, 0x3b, 0x9c, + 0xee, 0x88, 0x76, 0x25, 0x5d, 0x3c, 0xa6, 0x90, 0xe6, 0x1e, 0x2c, 0xef, 0xf9, 0x09, 0x21, 0xfa, + 0xa2, 0x5c, 0xc5, 0x84, 0xc9, 0xa6, 0x05, 0x93, 0x74, 0x08, 0xa7, 0xd3, 0xa3, 0x6b, 0x48, 0x67, + 0xea, 0x27, 0x48, 0xe3, 0x18, 0x06, 0xf6, 0x33, 0x24, 0xf2, 0xae, 0x79, 0xdf, 0x53, 0x7b, 0xff, + 0x34, 0x79, 0x6f, 0xd1, 0x74, 0x65, 0xb1, 0x03, 0x64, 0x12, 0x70, 0x1c, 0x8c, 0x0f, 0x24, 0x80, + 0x9e, 0xf9, 0x2a, 0x88, 0xe8, 0xb7, 0x29, 0xf5, 0xa7, 0x4e, 0x93, 0x4b, 0xcd, 0x93, 0x92, 0xc5, + 0x98, 0xb3, 0x20, 0x74, 0xc4, 0x59, 0x20, 0x86, 0xbc, 0x90, 0x42, 0x29, 0xcb, 0xa7, 0x40, 0x5a, + 0xca, 0xf6, 0x4b, 0x22, 0x2d, 0xe5, 0xea, 0x9b, 0x21, 0x4b, 0xca, 0x32, 0x26, 0xa2, 0x84, 0x7e, + 0x06, 0xfd, 0xa7, 0xfc, 0x35, 0x9c, 0x7c, 0x80, 0xa2, 0x29, 0xdb, 0xef, 0x57, 0x34, 0xe5, 0xca, + 0x4b, 0x15, 0x7a, 0x89, 0x53, 0xde, 0xa1, 0x1b, 0x48, 0x59, 0xbc, 0xac, 0x0b, 0x05, 0x0a, 0xd2, + 0xff, 0x1d, 0xe8, 0x5b, 0x6f, 0x4d, 0x48, 0xb9, 0xf9, 0xa6, 0x47, 0x2c, 0x93, 0x77, 0x17, 0xcc, + 0x36, 0xf1, 0x0a, 0x25, 0x0a, 0x7f, 0x9d, 0x82, 0xbc, 0x9e, 0x01, 0xe8, 0x37, 0x1b, 0xda, 0x5d, + 0x6a, 0xef, 0x44, 0xb4, 0xbb, 0xd4, 0x9f, 0x78, 0xd0, 0x4d, 0xce, 0xa2, 0x4f, 0xba, 0xc2, 0x8c, + 0x04, 0xad, 0x43, 0x58, 0x93, 0xaf, 0x13, 0xb4, 0x7c, 0xec, 0x27, 0x1a, 0x5a, 0x3e, 0x95, 0x67, + 0x0c, 0x74, 0xc4, 0x09, 0x02, 0xe9, 0x20, 0xc1, 0x08, 0x49, 0xfc, 0x16, 0x74, 0x8d, 0xab, 0x7d, + 0x62, 0xae, 0xa6, 0xf2, 0x0a, 0x40, 0x7b, 0x64, 0xc3, 0x5b, 0x00, 0xba, 0xc5, 0x29, 0x0f, 0x48, + 0x0f, 0x29, 0xab, 0xbe, 0x86, 0xa4, 0xae, 0xee, 0xee, 0x2d, 0xea, 0x95, 0x07, 0x01, 0x16, 0xf5, + 0xea, 0x65, 0xbf, 0x4d, 0x1d, 0x65, 0xcc, 0xd7, 0xfe, 0x14, 0x40, 0x5f, 0x33, 0x6b, 0x19, 0xd7, + 0xee, 0xcb, 0xb5, 0x8c, 0xeb, 0xb7, 0xd2, 0xca, 0x55, 0x09, 0x20, 0x69, 0x79, 0x19, 0x73, 0x0c, + 0x03, 0xfb, 0x15, 0x80, 0x76, 0xd5, 0xc6, 0x67, 0x03, 0xda, 0x55, 0x9b, 0x1f, 0x0f, 0x28, 0x8b, + 0x27, 0xc2, 0x55, 0x35, 0xd9, 0x23, 0x58, 0x2f, 0xef, 0xa7, 0xc9, 0xd8, 0x24, 0x62, 0x5e, 0x63, + 0x4f, 0x2e, 0x36, 0xcc, 0xa8, 0xb6, 0x04, 0xa7, 0xdc, 0x25, 0xeb, 0x48, 0x59, 0x5c, 0x53, 0x28, + 0xa2, 0xfc, 0xa5, 0x8c, 0x4d, 0xd4, 0xb8, 0xdc, 0xae, 0x10, 0x35, 0xaf, 0xb8, 0x2b, 0x44, 0x39, + 0x1d, 0x0f, 0xba, 0xc6, 0xed, 0xa7, 0xd6, 0x64, 0xfd, 0xea, 0x56, 0x6b, 0xb2, 0xe1, 0xba, 0x94, + 0x5e, 0xe0, 0xa4, 0x37, 0x44, 0xe4, 0x4e, 0x67, 0x2c, 0x51, 0x01, 0xe5, 0xb7, 0x01, 0x74, 0xc3, + 0x5a, 0x2b, 0xb3, 0x76, 0x95, 0xa1, 0x8d, 0xbb, 0xd2, 0xdf, 0xa6, 0x17, 0x39, 0xe9, 0x4d, 0x11, + 0x0f, 0xf9, 0x25, 0x02, 0x57, 0xe7, 0x6d, 0xe7, 0xda, 0x4d, 0x87, 0x3c, 0x87, 0x81, 0xc6, 0x3f, + 0x7a, 0x9d, 0x04, 0xe7, 0xb1, 0x98, 0x34, 0x4d, 0xc9, 0x0d, 0xbc, 0xcb, 0xb9, 0x5c, 0xa0, 0xc4, + 0xe6, 0x92, 0xbf, 0x4e, 0x02, 0xf4, 0xfb, 0x9f, 0x42, 0xd7, 0x78, 0x97, 0xa6, 0xe5, 0x54, 0x7f, + 0xac, 0x36, 0x69, 0x6a, 0xa9, 0xdb, 0x27, 0x9b, 0xac, 0x67, 0xf2, 0x33, 0x7f, 0x86, 0xb4, 0x13, + 0x18, 0xd8, 0x9d, 0x63, 0x6d, 0x96, 0x8d, 0x6d, 0x68, 0x6d, 0x96, 0x0b, 0x1a, 0xce, 0xd6, 0x5e, + 0x44, 0xc3, 0xd4, 0x3c, 0x49, 0xa7, 0x98, 0x3c, 0x94, 0x0d, 0x64, 0x33, 0x79, 0xa8, 0x36, 0xa9, + 0xcd, 0xe4, 0xa1, 0xd6, 0x71, 0xb6, 0xf7, 0x24, 0xd8, 0x28, 0xcd, 0x90, 0x0c, 0x86, 0x95, 0xee, + 0x2e, 0xa9, 0xac, 0xba, 0xda, 0x10, 0x9e, 0xbc, 0xbf, 0x70, 0x5e, 0xf2, 0x7b, 0x8f, 0xf3, 0x1b, + 0xd3, 0x4d, 0xcd, 0xcf, 0x8f, 0x63, 0xa1, 0x26, 0x71, 0xce, 0x80, 0xee, 0xd5, 0x6a, 0x3b, 0xa8, + 0xb5, 0x7b, 0x27, 0x93, 0xa6, 0x29, 0xc9, 0xc4, 0xb2, 0x36, 0xc1, 0x44, 0x65, 0x0b, 0x53, 0xe8, + 0x1a, 0x1d, 0x44, 0x2d, 0xb7, 0x7a, 0x73, 0x52, 0xcb, 0xad, 0xa9, 0xe5, 0x68, 0xc9, 0x2d, 0x67, + 0x45, 0x9c, 0x1e, 0xf3, 0x16, 0x25, 0xf2, 0xf8, 0x16, 0x3a, 0xaa, 0xf7, 0x48, 0x4a, 0x8f, 0xa8, + 0x34, 0x28, 0x27, 0xe3, 0xfa, 0x44, 0xc5, 0x0d, 0x79, 0x40, 0xcd, 0xe5, 0x2c, 0xd2, 0x65, 0x30, + 0xac, 0xf4, 0x2f, 0xb5, 0x3e, 0x9a, 0x1b, 0x9b, 0x13, 0xfb, 0x79, 0x9d, 0xb8, 0x59, 0xa6, 0xef, + 0x70, 0x06, 0xdb, 0x84, 0xeb, 0x20, 0x57, 0x1f, 0x0a, 0x1d, 0xdc, 0x74, 0xc8, 0xac, 0xd2, 0xcf, + 0x94, 0x8d, 0x31, 0x23, 0xd0, 0x36, 0xb6, 0x3b, 0x27, 0x4d, 0x17, 0x42, 0xf4, 0x7b, 0x9c, 0xd7, + 0x3b, 0xe4, 0xa2, 0xc5, 0x0b, 0xbd, 0x46, 0xdd, 0x87, 0xdd, 0x74, 0xc8, 0x14, 0x06, 0x36, 0xc9, + 0xb7, 0x62, 0x55, 0x71, 0x4f, 0x42, 0x6a, 0xac, 0x90, 0xc7, 0xef, 0x19, 0xcd, 0x5f, 0xab, 0x8d, + 0x4b, 0xae, 0x34, 0xf3, 0xaa, 0xb4, 0x79, 0x27, 0x5b, 0x26, 0x4f, 0x35, 0x49, 0x29, 0x67, 0x7a, + 0x89, 0x4c, 0xea, 0x4c, 0x7d, 0x89, 0xc3, 0x23, 0x5c, 0xcf, 0x6c, 0x30, 0xe8, 0xb4, 0xaf, 0xa1, + 0x47, 0xa1, 0xd3, 0xbe, 0xa6, 0x9e, 0x84, 0x52, 0x9e, 0x48, 0xfb, 0x78, 0x03, 0xe2, 0x44, 0x60, + 0x88, 0x3c, 0xb6, 0xd2, 0x88, 0xb8, 0xb4, 0xa0, 0x54, 0xaf, 0x64, 0x51, 0x8d, 0x85, 0xbc, 0x72, + 0x23, 0xb2, 0xa1, 0x58, 0x45, 0xc9, 0xb1, 0xa8, 0xe7, 0xc9, 0xd7, 0xd0, 0xe6, 0x55, 0x32, 0xd9, + 0xd2, 0x15, 0x85, 0x2e, 0xc6, 0x27, 0xdb, 0x15, 0xa8, 0x9d, 0x2a, 0x50, 0x7e, 0x76, 0xcd, 0x13, + 0x99, 0x7c, 0x4f, 0x61, 0x20, 0x52, 0x4b, 0x55, 0x4b, 0x6a, 0xa7, 0xa9, 0x94, 0xba, 0xda, 0x69, + 0xaa, 0x65, 0xa7, 0x1d, 0x2e, 0x45, 0x76, 0x79, 0x26, 0x71, 0x6e, 0x3b, 0xd7, 0xa6, 0xab, 0xfc, + 0x5f, 0x38, 0x9f, 0xfe, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x9c, 0x44, 0x52, 0xb0, 0x33, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -5155,6 +5239,9 @@ type XudClient interface { // to a specific node. // shell: xucli ban Ban(ctx context.Context, in *BanRequest, opts ...grpc.CallOption) (*BanResponse, error) + // Changes the xud master password, including the wallet passwords for any underlying clients. + // shell: xucli changepass + ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) // Closes any existing payment channels with a peer for the specified currency. // shell: xucli closechannel [node_identifier ] [--force] CloseChannel(ctx context.Context, in *CloseChannelRequest, opts ...grpc.CallOption) (*CloseChannelResponse, error) @@ -5304,6 +5391,15 @@ func (c *xudClient) Ban(ctx context.Context, in *BanRequest, opts ...grpc.CallOp return out, nil } +func (c *xudClient) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) { + out := new(ChangePasswordResponse) + err := c.cc.Invoke(ctx, "/xudrpc.Xud/ChangePassword", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *xudClient) CloseChannel(ctx context.Context, in *CloseChannelRequest, opts ...grpc.CallOption) (*CloseChannelResponse, error) { out := new(CloseChannelResponse) err := c.cc.Invoke(ctx, "/xudrpc.Xud/CloseChannel", in, out, opts...) @@ -5703,6 +5799,9 @@ type XudServer interface { // to a specific node. // shell: xucli ban Ban(context.Context, *BanRequest) (*BanResponse, error) + // Changes the xud master password, including the wallet passwords for any underlying clients. + // shell: xucli changepass + ChangePassword(context.Context, *ChangePasswordRequest) (*ChangePasswordResponse, error) // Closes any existing payment channels with a peer for the specified currency. // shell: xucli closechannel [node_identifier ] [--force] CloseChannel(context.Context, *CloseChannelRequest) (*CloseChannelResponse, error) @@ -5875,6 +5974,24 @@ func _Xud_Ban_Handler(srv interface{}, ctx context.Context, dec func(interface{} return interceptor(ctx, in, info, handler) } +func _Xud_ChangePassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ChangePasswordRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(XudServer).ChangePassword(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/xudrpc.Xud/ChangePassword", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(XudServer).ChangePassword(ctx, req.(*ChangePasswordRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Xud_CloseChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CloseChannelRequest) if err := dec(in); err != nil { @@ -6446,6 +6563,10 @@ var _Xud_serviceDesc = grpc.ServiceDesc{ MethodName: "Ban", Handler: _Xud_Ban_Handler, }, + { + MethodName: "ChangePassword", + Handler: _Xud_ChangePassword_Handler, + }, { MethodName: "CloseChannel", Handler: _Xud_CloseChannel_Handler,