UNPKG

@tomo-inc/ledger-bitcoin-babylon

Version:

Ledger Hardware Wallet Babylon Application Client

438 lines 40.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.tryParsePsbt = exports.stakingTxPolicy = exports.timelockPathPolicy = exports.unbondingPathPolicy = exports.slashingPathPolicy = exports.formatKey = exports.computeLeafHash = exports.signMessage = exports.validadteAddress = exports.signPsbt = void 0; const crypto_1 = require("crypto"); const tapscript_1 = require("@cmdcode/tapscript"); const encoding_1 = require("@cosmjs/encoding"); const base_1 = require("@scure/base"); const btc_signer_1 = require("@scure/btc-signer"); const appClient_1 = __importDefault(require("../appClient")); const buffertools_1 = require("../buffertools"); const policy_1 = require("../policy"); const bip322_1 = require("./bip322"); const psbt_1 = require("./psbt"); const types_1 = require("./types"); const xpub_1 = require("./xpub"); async function signPsbt({ transport, psbt, policy, }) { const app = new appClient_1.default(transport); const psbtBase64 = psbt instanceof Uint8Array ? base_1.base64.encode(psbt) : psbt; const signatures = await app.signPsbt(psbtBase64, policy, null); const hasScript = !!(0, psbt_1.getTaprootScript)(psbtBase64); const transaction = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(psbtBase64)); for (const signature of signatures) { const idx = signature[0]; if (hasScript) { transaction.updateInput(idx, { tapScriptSig: [ [ { pubKey: signature[1].pubkey, leafHash: signature[1].tapleafHash, }, signature[1].signature, ], ], }, true); } else { transaction.updateInput(idx, { tapKeySig: signature[1].signature, }, true); } } return transaction; } exports.signPsbt = signPsbt; function validadteAddress(input) { try { const { prefix, data } = (0, encoding_1.fromBech32)(input); if (data.length === 20 && prefix.length <= 10) { return { prefix, data }; } else { console.log("Validation FAILED - data.length:", data.length, "prefix.length:", prefix.length); } } catch (e) { console.log("fromBech32 threw error:", e); } return undefined; } exports.validadteAddress = validadteAddress; async function signMessage(options) { var _a; const derivationPath = (_a = options.derivationPath) !== null && _a !== void 0 ? _a : `m/86'/0'/0'`; if (options.type === 'bip322-simple') { const { transport, message, addressType = types_1.AddressType.p2tr, isTestnet = false, } = options; return signMessageBIP322({ transport, message, addressType, derivationPath, isTestnet, }); } const { transport, message } = options; return signMessageECDSA({ transport, message, derivationPath, }); } exports.signMessage = signMessage; async function signMessageECDSA({ transport, message, derivationPath = `m/86'/0'/0'`, }) { const app = new appClient_1.default(transport); const signature = await app.signMessage(Buffer.from(message), `${derivationPath}/0/0`); return { signature, protocol: types_1.MessageSigningProtocols.ECDSA, }; } async function signMessageBIP322({ transport, message, addressType = types_1.AddressType.p2tr, derivationPath = `m/86'/0'/0'`, isTestnet = false, }) { const app = new appClient_1.default(transport); if (addressType === types_1.AddressType.p2tr) { return (0, bip322_1.createTaprootBip322Signature)({ message, app, derivationPath, isTestnet, }); } return (0, bip322_1.createSegwitBip322Signature)({ message, app, derivationPath, isTestnet, }); } function computeLeafHash(psbt) { const psbtBase64 = psbt instanceof Uint8Array ? base_1.base64.encode(psbt) : psbt; const script = (0, psbt_1.getTaprootScript)(psbtBase64); if (!script) { throw new Error('The psbt does not contain a taproot script.'); } return (0, psbt_1.getLeafHash)(script); } exports.computeLeafHash = computeLeafHash; function formatKey(key, isTestnet) { const pubkey = key instanceof Buffer ? key : Buffer.from(key, 'hex'); return (0, xpub_1.createExtendedPubkey)(!isTestnet ? 'Mainnet' : 'Testnet', 0, Buffer.from('00000000', 'hex'), 0, (0, crypto_1.createHash)('sha256').update(pubkey).digest().subarray(0, 32), Buffer.concat([Buffer.from('02', 'hex'), pubkey])); } exports.formatKey = formatKey; async function _prepare(transport, derivationPath) { const app = new appClient_1.default(transport); const masterFingerPrint = await app.getMasterFingerprint(); const extendedPublicKey = await app.getExtendedPubkey(derivationPath); return [masterFingerPrint, extendedPublicKey]; } // Only a single finality provider is supported for now. function _filterFinalityProviders(finalityProviders) { if (!finalityProviders || finalityProviders.length === 0) { throw new Error('Must provide at least one finality provider.'); } if (finalityProviders.length > 1) { throw new Error(`Currently only a single finality provider is supported.`); } return finalityProviders[0]; } function _checkCovenantInfo(covenantThreshold, covenantPks) { if (covenantThreshold < 2) { throw new Error(`Invalid value for covenantThreshold: ${covenantThreshold}. It should be greater than or equal to 2.`); } const length = !covenantPks ? 0 : covenantPks.length; if (length < 2) { throw new Error(`covenantPks must have at least 2 elements. Current length: ${length}`); } if (length < covenantThreshold) { throw new Error(`The length of covenantPks (${length}) is less than the required covenantThreshold (${covenantThreshold}).`); } if (new Set(covenantPks).size < length) { throw new Error(`All covenantPks must be unique`); } return covenantPks .map((pk) => Buffer.from(pk, 'hex')) .sort(Buffer.compare) .map((pk) => pk.toString('hex')); } async function slashingPathPolicy({ policyName = 'Consent to slashing', transport, params, derivationPath, displayLeafHash = true, isTestnet = false, }) { derivationPath = derivationPath ? derivationPath : `m/86'/${isTestnet ? 1 : 0}'/0'`; const { leafHash, timelockBlocks, finalityProviders, covenantThreshold, covenantPks: _covenantPks, slashingPkScriptHex, slashingFeeSat, } = params; const [masterFingerPrint, extendedPublicKey] = await _prepare(transport, derivationPath); const keys = []; const magicFP = displayLeafHash ? types_1.MagicCode.LEAFHASH_DISPLAY_FP : types_1.MagicCode.LEAFHASH_CHECK_ONLY_FP; keys.push(`[${derivationPath.replace('m/', `${magicFP}/`)}]` + `${formatKey(leafHash, isTestnet)}`); keys.push(`[${derivationPath.replace('m/', `${masterFingerPrint}/`)}]${extendedPublicKey}`); const finalityProviderPk = _filterFinalityProviders(finalityProviders); keys.push(`[${derivationPath.replace('m/', `${types_1.MagicCode.FINALITY_PUB_FP}/`)}]${formatKey(finalityProviderPk, isTestnet)}`); const covenantPks = _checkCovenantInfo(covenantThreshold, _covenantPks); const length = covenantPks.length; for (let index = 0; index < length; index++) { const pk = covenantPks[index]; keys.push(formatKey(pk, isTestnet)); } keys.push(formatKey(slashingPkScriptHex.padEnd(64, '0'), isTestnet)); keys.push(formatKey((0, buffertools_1.numberToLE)(slashingFeeSat), isTestnet)); const descriptorTemplate = `tr(@0/**,and_v(and_v(pk_k(@1/**),and_v(pk_k(@2/**),multi_a(${covenantThreshold},${Array.from({ length }, (_, index) => index) .map((n) => `@${3 + n}/**`) .join(',')}` + `,@${3 + length}/**,@${3 + length + 1}/**))),older(${timelockBlocks})))`; return new policy_1.WalletPolicy(policyName, descriptorTemplate, keys); } exports.slashingPathPolicy = slashingPathPolicy; async function unbondingPathPolicy({ policyName = 'Unbonding', transport, params, derivationPath, displayLeafHash = true, isTestnet = false, }) { derivationPath = derivationPath ? derivationPath : `m/86'/${isTestnet ? 1 : 0}'/0'`; const { leafHash, timelockBlocks, finalityProviders, covenantThreshold, covenantPks: _covenantPks, unbondingFeeSat, } = params; const [masterFingerPrint, extendedPublicKey] = await _prepare(transport, derivationPath); const keys = []; const magicFP = displayLeafHash ? types_1.MagicCode.LEAFHASH_DISPLAY_FP : types_1.MagicCode.LEAFHASH_CHECK_ONLY_FP; keys.push(`[${derivationPath.replace('m/', `${magicFP}/`)}]${formatKey(leafHash, isTestnet)}`); keys.push(`[${derivationPath.replace('m/', `${masterFingerPrint}/`)}]${extendedPublicKey}`); const finalityProviderPk = _filterFinalityProviders(finalityProviders); keys.push(`[${derivationPath.replace('m/', `${types_1.MagicCode.FINALITY_PUB_FP}/`)}]${formatKey(finalityProviderPk, isTestnet)}`); const covenantPks = _checkCovenantInfo(covenantThreshold, _covenantPks); const length = covenantPks.length; for (let index = 0; index < length; index++) { const pk = covenantPks[index]; keys.push(formatKey(pk, isTestnet)); } keys.push(formatKey((0, buffertools_1.numberToLE)(unbondingFeeSat), isTestnet)); const descriptorTemplate = `tr(@0/**,and_v(and_v(pk_k(@1/**),and_v(pk_k(@2/**),multi_a(${covenantThreshold},${Array.from({ length }, (_, index) => index) .map((n) => `@${3 + n}/**`) .join(',')}` + `,@${3 + length}/**))),older(${timelockBlocks})))`; return new policy_1.WalletPolicy(policyName, descriptorTemplate, keys); } exports.unbondingPathPolicy = unbondingPathPolicy; async function timelockPathPolicy({ policyName = 'Withdraw', transport, params, derivationPath, displayLeafHash = true, isTestnet = false, }) { derivationPath = derivationPath ? derivationPath : `m/86'/${isTestnet ? 1 : 0}'/0'`; const { leafHash, timelockBlocks } = params; const [masterFingerPrint, extendedPublicKey] = await _prepare(transport, derivationPath); const keys = []; const magicFP = displayLeafHash ? types_1.MagicCode.LEAFHASH_DISPLAY_FP : types_1.MagicCode.LEAFHASH_CHECK_ONLY_FP; keys.push(`[${derivationPath.replace('m/', `${magicFP}/`)}]${formatKey(leafHash, isTestnet)}`); keys.push(`[${derivationPath.replace('m/', `${masterFingerPrint}/`)}]${extendedPublicKey}`); // tr(@0/**,and_v(pk_k(staker_pk),older(timelock_blocks))) const descriptorTemplate = `tr(@0/**,and_v(pk_k(@1/**),older(${timelockBlocks})))`; return new policy_1.WalletPolicy(policyName, descriptorTemplate, keys); } exports.timelockPathPolicy = timelockPathPolicy; async function stakingTxPolicy({ policyName = 'Staking transaction', transport, params, derivationPath, isTestnet = false, }) { derivationPath = derivationPath ? derivationPath : `m/86'/${isTestnet ? 1 : 0}'/0'`; const { timelockBlocks, finalityProviders, covenantThreshold, covenantPks: _covenantPks, } = params; const [masterFingerPrint, extendedPublicKey] = await _prepare(transport, derivationPath); const keys = []; // A placeholder parameter added to facilitate firmware data parsing keys.push("[69846d00/86'/1'/0']tpubD6NzVbkrYhZ4WLczPJWReQycCJdd6YVWXubbVUFnJ5KgU5MDQrD998ZJLSmaB7GVcCnJSDWprxmrGkJ6SvgQC6QAffVpqSvonXmeizXcrkN"); keys.push(`[${derivationPath.replace('m/', `${masterFingerPrint}/`)}]${extendedPublicKey}`); const finalityProviderPk = _filterFinalityProviders(finalityProviders); keys.push(`[${derivationPath.replace('m/', `${types_1.MagicCode.FINALITY_PUB_FP}/`)}]${formatKey(finalityProviderPk, isTestnet)}`); const covenantPks = _checkCovenantInfo(covenantThreshold, _covenantPks); const length = covenantPks.length; for (let index = 0; index < length; index++) { const pk = covenantPks[index]; keys.push(formatKey(pk, isTestnet)); } // "tr(@0/**,and_v(and_v(pk_k(@1/**),and_v(pk_k(@2/**),multi_a(6,@3/**,@4/**,@5/**,@6/**,@7/**,@8/**,@9/**,@10/**,@11/**))),older(64000)))" const descriptorTemplate = `tr(@0/**,and_v(and_v(pk_k(@1/**),and_v(pk_k(@2/**),multi_a(${covenantThreshold},${Array.from({ length }, (_, index) => index) .map((n) => `@${3 + n}/**`) .join(',')}))),older(${timelockBlocks})))`; return new policy_1.WalletPolicy(policyName, descriptorTemplate, keys); } exports.stakingTxPolicy = stakingTxPolicy; // const SlashingPathRegexPrefix = // /^([a-f0-9]{64}) OP_CHECKSIGVERIFY ([a-f0-9]{64}) OP_CHECKSIGVERIFY ([a-f0-9]{64}) OP_CHECKSIG/; // const UnbondingPathRegexPrefix = // /^([a-f0-9]{64}) OP_CHECKSIGVERIFY ([a-f0-9]{64}) OP_CHECKSIG/; const TimelockPathRegex1 = /^([a-f0-9]{64}) OP_CHECKSIGVERIFY OP_(0|[1-9]|1[0-6]) OP_CHECKSEQUENCEVERIFY$/; const TimelockPathRegex2 = /^([a-f0-9]{64}) OP_CHECKSIGVERIFY ([a-f0-9]{2,6}) OP_CHECKSEQUENCEVERIFY$/; // function tryParseSlashingPath(decoded: string[]): string[] | void { // const script = decoded.join(' '); // if (!SlashingPathRegexPrefix.test(script)) return; // const result: string[] = []; // decoded.forEach((value) => { // if (/^([a-f0-9]{64})$/.test(value)) { // result.push(value); // } else if (/^OP_([0-9]{1,2})$/.test(value)) { // result.push(value); // } // }); // return result; // } // function tryParseUnbondingPath(decoded: string[]): string[] | void { // const script = decoded.join(' '); // if (!UnbondingPathRegexPrefix.test(script)) { // return; // } // const result: string[] = []; // decoded.forEach((value) => { // if (/^([a-f0-9]{64})$/.test(value)) { // result.push(value); // } else if (/^OP_([0-9]{1,2})$/.test(value)) { // result.push(value); // } // }); // return result; // } function _tryParseNumber(number) { var _a, _b; if (number.length % 2 !== 0) { throw new Error('Invalid timelock: odd-length hex string'); } return (_b = (_a = number.match(/.{2}/g)) === null || _a === void 0 ? void 0 : _a.reverse().join('')) !== null && _b !== void 0 ? _b : ''; } function tryParseTimelockPath(decoded) { const script = decoded.join(' '); let match = script.match(TimelockPathRegex1); if (match) { const [, stakerPK, timelockBlocks] = match; return [stakerPK, Number(timelockBlocks).toString(16)]; } match = script.match(TimelockPathRegex2); if (!match) { return; } const [_, stakerPK, timelockBlocks] = match; return [stakerPK, _tryParseNumber(timelockBlocks)]; } async function tryParsePsbt(transport, psbtBase64, isTestnet = false, leafHash) { const derivationPath = `m/86'/${isTestnet ? 1 : 0}'/0'`; const script = (0, psbt_1.getTaprootScript)(psbtBase64); if (!script) { throw new Error(`No script found in psbt`); } leafHash = leafHash ? leafHash : computeLeafHash(psbtBase64); const decodedScript = tapscript_1.Script.decode(script); // let parsed = tryParseSlashingPath(decodedScript); // if (parsed) { // return slashingPathPolicy({ // transport, // params: { // leafHash, // finalityProviders: [parsed[1]], // covenantPks: parsed.slice(2, parsed.length - 1), // covenantThreshold: parseInt(parsed[parsed.length - 1].slice(3), 10), // }, // derivationPath, // isTestnet, // }); // } // parsed = tryParseUnbondingPath(decodedScript); // if (parsed) { // return unbondingPathPolicy({ // transport, // params: { // leafHash, // covenantPks: parsed.slice(1, parsed.length - 1), // covenantThreshold: parseInt(parsed[parsed.length - 1].slice(3), 10), // }, // derivationPath, // isTestnet, // }); // } const parsed = tryParseTimelockPath(decodedScript); if (parsed) { return timelockPathPolicy({ transport, params: { leafHash, timelockBlocks: Number(`0x${parsed[parsed.length - 1]}`), }, derivationPath, isTestnet, }); } } exports.tryParsePsbt = tryParsePsbt; // /* Example */ // // Method 1: Explicitly pass all required parameters to construct the policy. // async function testStakingStep1() { // const psbt = base64.decode( // 'cHNidP8BAH0CAAAAAZUPGfxRcPueN3/UdNQC64mF3lAumoEi9Gv6AgvbdVycAAAAAAD/////AsQJAAAAAAAAFgAUW+EmJNCKK0JAldfAciHDNFDRS/EEpgAAAAAAACJRICyVutUKY9E6qBjfjktoZBga2/RyCoiq+OPBI1ugik2fAAAAAAABAStQwwAAAAAAACJRIEOj7UvRXfRV9er0SUNeReHNqaiqtOoEhmW60JCFUoUyQhXAUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsCJtgX5iDHD5SbZ6yF5ZRRSk4qMD/f16u7MthJR1dRt6/15ASDcjS+e/wxPTb3gcKSOMw78kItip2ZWjZHmWPKEsyS4eK0gH5MjVzLmTKwzVprRw9vwQTgsO3dPz7BTO5sx1MKna/mtIAruBQmxbbccmZI4pIJ9uUVSaFmxPJVIerRnJTV8mp8lrCARPDoyqdMgtyGQoEoCCg2zl27zaXJnMljpo4o2Tz3DsLogF5Ic8VbMtOc9Qo+ZbtEbJFMT434nyXisTSzCHspGcuS6IDu5PfyLYYh9dx82MOmmPpfLr8/MeFVqR034OjGg74mcuiBAr69HxP+lbehkENjke6ortvBLYE9OokMjc33cP+CS37ogeacf/XHFA+8uL5G8z8j82nlG9GU87w2fPd4geV7zufC6INIfr3jGdRoNOOa9gCi5B/8H6ahppD/IN9az+N/2EZo2uiD1GZ764/KLuCR2Fjp+RYx61EXZv/sGgtENO9sstB+Ojrog+p2ILUX0BgvbgEIYOCjNh1RPHqmXOA5YbKt31f1phze6VpzAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=' // ); // const transport = await getLedgerTransport(); // const leafHash = computeLeafHash(psbt); // const finalityProviderPk = // '1f93235732e64cac33569ad1c3dbf041382c3b774fcfb0533b9b31d4c2a76bf9'; // const covenantPks = [ // '0aee0509b16db71c999238a4827db945526859b13c95487ab46725357c9a9f25', // '113c3a32a9d320b72190a04a020a0db3976ef36972673258e9a38a364f3dc3b0', // '17921cf156ccb4e73d428f996ed11b245313e37e27c978ac4d2cc21eca4672e4', // '3bb93dfc8b61887d771f3630e9a63e97cbafcfcc78556a474df83a31a0ef899c', // '40afaf47c4ffa56de86410d8e47baa2bb6f04b604f4ea24323737ddc3fe092df', // '79a71ffd71c503ef2e2f91bccfc8fcda7946f4653cef0d9f3dde20795ef3b9f0', // 'd21faf78c6751a0d38e6bd8028b907ff07e9a869a43fc837d6b3f8dff6119a36', // 'f5199efae3f28bb82476163a7e458c7ad445d9bffb0682d10d3bdb2cb41f8e8e', // 'fa9d882d45f4060bdb8042183828cd87544f1ea997380e586cab77d5fd698737', // ]; // const params = { // leafHash, // finalityProviderPk, // covenantThreshold: 6, // covenantPks, // }; // const policy = await slashingPathPolicy({ // policyName: 'Step 1: slashing consent', // transport, // params, // derivationPath: `m/86'/1'/0'`, // isTestnet: true, // }); // await signPsbt({ transport, psbt, policy }); // } // // Method 2: Automatically parse the policy from the content of the provided PSBT. // async function testStakingStep2() { // const psbtBase64 = // 'cHNidP8BAH0CAAAAAZUPGfxRcPueN3/UdNQC64mF3lAumoEi9Gv6AgvbdVycAAAAAAD/////AsQJAAAAAAAAFgAUW+EmJNCKK0JAldfAciHDNFDRS/EEpgAAAAAAACJRICyVutUKY9E6qBjfjktoZBga2/RyCoiq+OPBI1ugik2fAAAAAAABAStQwwAAAAAAACJRIEOj7UvRXfRV9er0SUNeReHNqaiqtOoEhmW60JCFUoUyQhXAUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsCJtgX5iDHD5SbZ6yF5ZRRSk4qMD/f16u7MthJR1dRt6/15ASDcjS+e/wxPTb3gcKSOMw78kItip2ZWjZHmWPKEsyS4eK0gH5MjVzLmTKwzVprRw9vwQTgsO3dPz7BTO5sx1MKna/mtIAruBQmxbbccmZI4pIJ9uUVSaFmxPJVIerRnJTV8mp8lrCARPDoyqdMgtyGQoEoCCg2zl27zaXJnMljpo4o2Tz3DsLogF5Ic8VbMtOc9Qo+ZbtEbJFMT434nyXisTSzCHspGcuS6IDu5PfyLYYh9dx82MOmmPpfLr8/MeFVqR034OjGg74mcuiBAr69HxP+lbehkENjke6ortvBLYE9OokMjc33cP+CS37ogeacf/XHFA+8uL5G8z8j82nlG9GU87w2fPd4geV7zufC6INIfr3jGdRoNOOa9gCi5B/8H6ahppD/IN9az+N/2EZo2uiD1GZ764/KLuCR2Fjp+RYx61EXZv/sGgtENO9sstB+Ojrog+p2ILUX0BgvbgEIYOCjNh1RPHqmXOA5YbKt31f1phze6VpzAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA='; // const transport = await getLedgerTransport(); // const policy = await tryParsePsbt(transport, psbtBase64, true); // await signPsbt({ transport, psbt: psbtBase64, policy: policy! }); // } // async function testStakingTx() { // const psbt = base64.decode(''); // const transport = await getLedgerTransport(); // const finalityProviderPk = // '1f93235732e64cac33569ad1c3dbf041382c3b774fcfb0533b9b31d4c2a76bf9'; // const covenantPks = [ // '0aee0509b16db71c999238a4827db945526859b13c95487ab46725357c9a9f25', // '113c3a32a9d320b72190a04a020a0db3976ef36972673258e9a38a364f3dc3b0', // '17921cf156ccb4e73d428f996ed11b245313e37e27c978ac4d2cc21eca4672e4', // '3bb93dfc8b61887d771f3630e9a63e97cbafcfcc78556a474df83a31a0ef899c', // '40afaf47c4ffa56de86410d8e47baa2bb6f04b604f4ea24323737ddc3fe092df', // '79a71ffd71c503ef2e2f91bccfc8fcda7946f4653cef0d9f3dde20795ef3b9f0', // 'd21faf78c6751a0d38e6bd8028b907ff07e9a869a43fc837d6b3f8dff6119a36', // 'f5199efae3f28bb82476163a7e458c7ad445d9bffb0682d10d3bdb2cb41f8e8e', // 'fa9d882d45f4060bdb8042183828cd87544f1ea997380e586cab77d5fd698737', // ]; // const params = { // timelockBlocks: 64000, // finalityProviderPk, // covenantThreshold: 6, // covenantPks, // }; // const policy = await stakingTxPolicy({ // policyName: 'Staking transaction', // transport, // params, // derivationPath: `m/86'/1'/0'`, // isTestnet: true, // }); // await signPsbt({ transport, psbt, policy }); // } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2JhYnlsb24vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsbUNBQW9DO0FBRXBDLGtEQUE0QztBQUM1QywrQ0FBOEM7QUFFOUMsc0NBQXFDO0FBQ3JDLGtEQUFnRDtBQUVoRCw2REFBcUM7QUFDckMsZ0RBQTRDO0FBQzVDLHNDQUF5QztBQUV6QyxxQ0FHa0I7QUFDbEIsaUNBQXVEO0FBQ3ZELG1DQUtpQjtBQUNqQixpQ0FBOEM7QUFFdkMsS0FBSyxVQUFVLFFBQVEsQ0FBQyxFQUM3QixTQUFTLEVBQ1QsSUFBSSxFQUNKLE1BQU0sR0FLUDtJQUNDLE1BQU0sR0FBRyxHQUFHLElBQUksbUJBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUVyQyxNQUFNLFVBQVUsR0FBRyxJQUFJLFlBQVksVUFBVSxDQUFDLENBQUMsQ0FBQyxhQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDM0UsTUFBTSxVQUFVLEdBQUcsTUFBTSxHQUFHLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFaEUsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDLElBQUEsdUJBQWdCLEVBQUMsVUFBVSxDQUFDLENBQUM7SUFFakQsTUFBTSxXQUFXLEdBQUcsd0JBQVcsQ0FBQyxRQUFRLENBQUMsYUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3BFLEtBQUssTUFBTSxTQUFTLElBQUksVUFBVSxFQUFFO1FBQ2xDLE1BQU0sR0FBRyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV6QixJQUFJLFNBQVMsRUFBRTtZQUNiLFdBQVcsQ0FBQyxXQUFXLENBQ3JCLEdBQUcsRUFDSDtnQkFDRSxZQUFZLEVBQUU7b0JBQ1o7d0JBQ0U7NEJBQ0Us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