@celo-tools/celo-ethers-wrapper
Version:
A minimal wrapper to make Ethers.JS compatible with the Celo network.
434 lines • 36.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCeloTransaction = exports.serializeCeloTransaction = exports.getTxType = exports.celoTransactionFields = exports.celoAllowedTransactionKeys = exports.TxTypeToPrefix = void 0;
const ethers_1 = require("ethers");
const utils_1 = require("./transaction/utils");
const consts_1 = require("../consts");
var TxTypeToPrefix;
(function (TxTypeToPrefix) {
TxTypeToPrefix[TxTypeToPrefix["cip64"] = 123] = "cip64";
TxTypeToPrefix[TxTypeToPrefix["cip66"] = 122] = "cip66";
TxTypeToPrefix[TxTypeToPrefix["eip1559"] = 2] = "eip1559";
})(TxTypeToPrefix || (exports.TxTypeToPrefix = TxTypeToPrefix = {}));
exports.celoAllowedTransactionKeys = {
type: true,
chainId: true,
data: true,
gasLimit: true,
gasPrice: true,
nonce: true,
to: true,
value: true,
feeCurrency: true,
maxFeePerGas: true,
maxPriorityFeePerGas: true,
accessList: true,
maxFeeInFeeCurrency: true,
};
exports.celoTransactionFields = {
nonce: { maxLength: 32, numeric: true },
gasPrice: { maxLength: 32, numeric: true },
gasLimit: { maxLength: 32, numeric: true },
feeCurrency: { length: 20 },
to: { length: 20 },
value: { maxLength: 32, numeric: true },
data: {},
maxFeePerGas: { maxLength: 32, numeric: true },
maxPriorityFeePerGas: { maxLength: 32, numeric: true },
maxFeeInFeeCurrency: { maxLength: 32, numeric: true },
};
function formatCeloField(name, value) {
const fieldInfo = exports.celoTransactionFields[name];
const options = {};
if (!value || value === "0x")
return value;
if (fieldInfo.numeric) {
options.hexPad = "left";
value = value ? (0, ethers_1.toBeHex)(value, fieldInfo.maxLength) : "0x";
}
else {
value = (0, ethers_1.hexlify)(value);
}
let _value = (0, ethers_1.toBeArray)(value);
// Fixed-width field
if (fieldInfo.length && _value.length !== fieldInfo.length && _value.length > 0) {
(0, ethers_1.assertArgument)(false, "invalid length for " + name, "transaction:" + name, _value);
}
// Variable-width (with a maximum)
if (fieldInfo.maxLength) {
_value = (0, ethers_1.toBeArray)((0, ethers_1.stripZerosLeft)(_value));
if (_value.length > fieldInfo.maxLength) {
(0, ethers_1.assertArgument)(false, "invalid length for " + name, "transaction:" + name, _value);
}
}
return (0, ethers_1.hexlify)(_value);
}
function getTxType(tx) {
if (tx.gasPrice) {
return "";
}
if ((0, utils_1.isCIP66)(tx)) {
return TxTypeToPrefix.cip66;
}
if ((0, utils_1.isCIP64)(tx)) {
return TxTypeToPrefix.cip64;
}
return TxTypeToPrefix.eip1559;
}
exports.getTxType = getTxType;
function prepareEncodeTx(tx, signature) {
let raw = [];
switch (tx.type) {
case TxTypeToPrefix.cip66:
// https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0066.md
// 0x7a || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, maxFeeInFeeCurrency, signatureYParity, signatureR, signatureS]).
raw = [
(0, ethers_1.toBeHex)(tx.chainId),
(0, ethers_1.toBeHex)(tx.nonce),
tx.maxPriorityFeePerGas ? (0, ethers_1.toBeHex)(tx.maxPriorityFeePerGas) : "0x",
tx.maxFeePerGas ? (0, ethers_1.toBeHex)(tx.maxFeePerGas) : "0x",
tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x",
tx.to || "0x",
tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x",
tx.data || "0x",
formatAccessList(tx.accessList || []),
tx.feeCurrency || "0x",
tx.maxFeeInFeeCurrency
? (0, ethers_1.toBeHex)(tx.maxFeeInFeeCurrency)
: "0x",
];
break;
case TxTypeToPrefix.cip64:
// https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md
// 0x7b || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, signatureYParity, signatureR, signatureS]).
raw = [
(0, ethers_1.toBeHex)(tx.chainId),
(0, ethers_1.toBeHex)(tx.nonce),
tx.maxPriorityFeePerGas ? (0, ethers_1.toBeHex)(tx.maxPriorityFeePerGas) : "0x",
tx.maxFeePerGas ? (0, ethers_1.toBeHex)(tx.maxFeePerGas) : "0x",
tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x",
tx.to || "0x",
tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x",
tx.data || "0x",
formatAccessList(tx.accessList || []),
tx.feeCurrency || "0x",
];
break;
case TxTypeToPrefix.eip1559:
// https://eips.ethereum.org/EIPS/eip-1559
// 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s]).
raw = [
(0, ethers_1.toBeHex)(tx.chainId),
(0, ethers_1.toBeHex)(tx.nonce),
tx.maxPriorityFeePerGas ? (0, ethers_1.toBeHex)(tx.maxPriorityFeePerGas) : "0x",
tx.maxFeePerGas ? (0, ethers_1.toBeHex)(tx.maxFeePerGas) : "0x",
tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x",
tx.to || "0x",
tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x",
tx.data || "0x",
formatAccessList(tx.accessList || []),
];
break;
default:
// Type 0 Ethereum legacy transaction:
// rlp([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s])
raw = [
(0, ethers_1.toBeHex)(tx.nonce),
tx.gasPrice ? (0, ethers_1.toBeHex)(tx.gasPrice) : "0x",
tx.gasLimit ? (0, ethers_1.toBeHex)(tx.gasLimit) : "0x",
tx.to || "0x",
tx.value ? (0, ethers_1.toBeHex)(tx.value) : "0x",
tx.data || "0x",
];
if (!signature) {
raw.push(...[(0, ethers_1.toBeHex)(tx.chainId), "0x", "0x"]);
}
break;
}
if (signature) {
raw.push(...[
// NOTE: Somehow geth cannot parse `0x00` because it's dumb
signature.v ? (0, ethers_1.toBeHex)(signature.v) : "0x",
(0, ethers_1.stripZerosLeft)((0, ethers_1.getBytes)(signature.r)),
(0, ethers_1.stripZerosLeft)((0, ethers_1.getBytes)(signature.s)),
]);
}
return raw;
}
// Almost identical to https://github.com/ethers-io/ethers.js/blob/master/packages/transactions/src.ts/index.ts#L85
// Need to override to use the celo tx prop whitelists above
function serializeCeloTransaction(transaction, signature) {
Object.keys(transaction).forEach((property) => {
if (!(property in exports.celoAllowedTransactionKeys)) {
(0, ethers_1.assertArgument)(false, "unknown property", "serializeCeloTransaction", property);
}
});
const txArgs = {};
Object.entries(transaction).forEach(([fieldName, fieldValue]) => {
if (fieldName in exports.celoTransactionFields) {
// @ts-expect-error
txArgs[fieldName] = formatCeloField(fieldName, fieldValue);
}
else if (fieldName === 'accessList') {
txArgs[fieldName] = fieldValue;
}
});
let chainId = 0;
if (transaction.chainId != null) {
// A chainId was provided; if non-zero we'll use EIP-155
chainId = parseInt(transaction.chainId.toString(16), 16);
if (typeof chainId !== "number") {
(0, ethers_1.assertArgument)(false, "invalid transaction.chainId", "transaction", transaction);
}
}
else if (signature && !(0, ethers_1.isBytesLike)(signature) && signature.v && (0, ethers_1.getNumber)(signature.v) > 28) {
// No chainId provided, but the signature is signing with EIP-155; derive chainId
chainId = Math.floor(((0, ethers_1.getNumber)(signature.v) - consts_1.EIP155_NUMBER) / 2);
}
// We have an EIP-155 transaction (chainId was specified and non-zero)
if (chainId !== 0) {
txArgs["chainId"] = (0, ethers_1.toBeHex)(chainId); // @TODO: hexValue?
}
// Requesting an unsigned transation
// @ts-ignore
const type = getTxType(txArgs);
// @ts-expect-error
txArgs.type = type;
if (!signature) {
// @ts-expect-error
const raw = prepareEncodeTx(txArgs);
const encoded = (0, ethers_1.encodeRlp)(raw);
return type ? (0, utils_1.concatHex)([(0, ethers_1.toBeHex)(type), encoded]) : encoded;
}
// The splitSignature will ensure the transaction has a recoveryParam in the
// case that the signTransaction function only adds a v.
const sig = ethers_1.Signature.from(signature);
let v;
if (txArgs.type) {
// cip64, eip-1559
v = sig.v - consts_1.Y_PARITY_EIP_2098;
}
else {
// celo-legacy
v = consts_1.Y_PARITY_EIP_2098 + sig.yParity;
if (chainId !== 0) {
v += chainId * 2 + consts_1.EIGHT;
// If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it!
if (sig.v > consts_1.Y_PARITY_EIP_2098 + 1 && sig.v !== v) {
(0, ethers_1.assertArgument)(false, "transaction.chainId/signature.v mismatch", "signature", signature);
}
}
else if (sig.v !== v) {
(0, ethers_1.assertArgument)(false, "transaction.chainId/signature.v mismatch", "signature", signature);
}
}
// @ts-expect-error
const raw = prepareEncodeTx(txArgs, { ...sig.toJSON(), v });
const encoded = (0, ethers_1.encodeRlp)(raw);
return type ? (0, utils_1.concatHex)([(0, ethers_1.toBeHex)(type), encoded]) : encoded;
}
exports.serializeCeloTransaction = serializeCeloTransaction;
// Based on https://github.com/ethers-io/ethers.js/blob/0234cfbbef76b7f7a53efe4c434cc6d8892bf404/packages/transactions/src.ts/index.ts#L165
// Need to override to use the celo tx prop whitelists above
function parseCeloTransaction(rawTransaction) {
const [type, transaction] = splitTypeAndRawTx(rawTransaction);
let tx;
switch (type) {
case TxTypeToPrefix.cip66:
tx = {
type: TxTypeToPrefix.cip66,
chainId: handleNumber(transaction[0]),
nonce: handleNumber(transaction[1]),
maxPriorityFeePerGas: handleBigInt(transaction[2]),
maxFeePerGas: handleBigInt(transaction[3]),
gasLimit: handleBigInt(transaction[4]),
to: handleAddress(transaction[5]),
value: handleBigInt(transaction[6]),
data: transaction[7],
accessList: handleAccessList(transaction[8]),
feeCurrency: handleAddress(transaction[9]),
maxFeeInFeeCurrency: handleBigInt(transaction[10]),
};
break;
case TxTypeToPrefix.cip64:
tx = {
type: TxTypeToPrefix.cip64,
chainId: handleNumber(transaction[0]),
nonce: handleNumber(transaction[1]),
maxPriorityFeePerGas: handleBigInt(transaction[2]),
maxFeePerGas: handleBigInt(transaction[3]),
gasLimit: handleBigInt(transaction[4]),
to: handleAddress(transaction[5]),
value: handleBigInt(transaction[6]),
data: transaction[7],
accessList: handleAccessList(transaction[8]),
feeCurrency: handleAddress(transaction[9]),
};
break;
case TxTypeToPrefix.eip1559:
// untested
tx = {
type: TxTypeToPrefix.eip1559,
chainId: handleNumber(transaction[0]),
nonce: handleNumber(transaction[1]),
maxPriorityFeePerGas: handleBigInt(transaction[2]),
maxFeePerGas: handleBigInt(transaction[3]),
gasLimit: handleBigInt(transaction[4]),
to: handleAddress(transaction[5]),
value: handleBigInt(transaction[6]),
data: transaction[7],
accessList: handleAccessList(transaction[8]),
};
break;
default:
/**
* Type 0 Ethereum legacy transaction:
* RLP([nonce, gasprice, gaslimit, recipient, amount, data, chaindId, 0, 0])
*/
tx = {
nonce: handleNumber(transaction[0]),
gasPrice: handleBigInt(transaction[1]),
gasLimit: handleBigInt(transaction[2]),
to: handleAddress(transaction[3]),
value: handleBigInt(transaction[4]),
data: transaction[5],
chainId: handleBigInt(transaction[6]),
};
break;
}
// Legacy unsigned transaction
if (!isSigned(type, transaction)) {
return tx;
}
let v;
try {
v = handleNumber(transaction.at(-3));
}
catch (error) {
console.log(error);
return tx;
}
const r = (0, ethers_1.zeroPadValue)(transaction.at(-2), 32);
const s = (0, ethers_1.zeroPadValue)(transaction.at(-1), 32);
// EIP-155 unsigned transaction
if (handleBigInt(r) === 0n && handleBigInt(s) === 0n) {
if (!type) {
tx.chainId = v;
v = 0;
}
}
// Signed Transaction
else {
let recoveryParam = v;
if (!type) {
// celo-legacy
tx.chainId = Math.max(0, Math.floor((v - consts_1.EIP155_NUMBER) / 2));
recoveryParam = v - consts_1.Y_PARITY_EIP_2098;
recoveryParam -= tx.chainId * 2 + consts_1.EIGHT;
}
// NOTE: Serialization needs to happen here because chainId may not populated before
const serialized = serializeCeloTransaction(tx);
const digest = (0, ethers_1.keccak256)(serialized);
try {
tx.from = (0, ethers_1.recoverAddress)(digest, {
r,
s,
yParity: recoveryParam,
});
}
catch (error) {
console.log(error);
}
tx.hash = (0, ethers_1.keccak256)(rawTransaction);
}
return tx;
}
exports.parseCeloTransaction = parseCeloTransaction;
function handleAddress(value) {
if (value === "0x") {
return undefined;
}
try {
return (0, ethers_1.getAddress)(value);
}
catch (error) {
return value;
}
}
function handleNumber(value) {
if (value === "0x") {
return 0;
}
return (0, ethers_1.getNumber)(value);
}
function handleBigInt(value) {
if (value === "0x") {
return 0n;
}
return (0, ethers_1.getBigInt)(value);
}
function formatAccessList(value) {
return (0, ethers_1.accessListify)(value).map((set) => [set.address, set.storageKeys]);
}
/*
@param value [
[
'0x0000000000000000000000000000000000000000',
[
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0x60fdd29ff912ce880cd3edaf9f932dc61d3dae823ea77e0323f94adb9f6a72fe'
]
]
]
*/
function handleAccessList(value) {
if (value === "0x") {
return (0, ethers_1.accessListify)([]);
}
return (0, ethers_1.accessListify)(value);
}
const baseTxLengths = {
[TxTypeToPrefix.cip64]: { unsigned: 10, signed: 13 },
[TxTypeToPrefix.cip66]: { unsigned: 11, signed: 14 },
[TxTypeToPrefix.eip1559]: { unsigned: 9, signed: 12 },
/**
* Unsigned: RLP([nonce, gasprice, gaslimit, recipient, amount, data, chaindId, 0, 0])
* Signed: RLP([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s])
* Source: https://github.com/celo-org/txtypes?tab=readme-ov-file#legacy-transactions
*/
"ethereum-legacy": { unsigned: 9, signed: 9 },
};
function isSigned(type, transaction) {
if (type) {
const { signed } = baseTxLengths[type];
return transaction.length === signed;
}
const r = transaction.at(-2) || "0x";
const s = transaction.at(-1) || "0x";
return r !== "0x" && s !== "0x";
}
function isCorrectLength(type, transaction) {
const { unsigned } = baseTxLengths[type || "ethereum-legacy"];
return transaction.length === unsigned || isSigned(type, transaction);
}
function splitTypeAndRawTx(rawTransaction) {
let rawStr = rawTransaction.toString();
let type;
for (const _type of [TxTypeToPrefix.cip64, TxTypeToPrefix.cip66, TxTypeToPrefix.eip1559]) {
const prefix = (0, ethers_1.toBeHex)(_type);
if (rawStr.startsWith(prefix)) {
rawStr = `0x${rawStr.slice(prefix.length)}`;
type = _type;
break;
}
}
const transaction = (0, ethers_1.decodeRlp)(rawStr);
if (!isCorrectLength(type, transaction)) {
(0, ethers_1.assertArgument)(false, "invalid raw transaction", "{type, rawTransaction}", {
type: type,
rawTransaction,
});
}
return [type, transaction];
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBeUJnQjtBQUNoQiwrQ0FBa0U7QUFDbEUsc0NBQW9FO0FBNEJwRSxJQUFZLGNBSVg7QUFKRCxXQUFZLGNBQWM7SUFDeEIsdURBQVksQ0FBQTtJQUNaLHVEQUFZLENBQUE7SUFDWix5REFBYyxDQUFBO0FBQ2hCLENBQUMsRUFKVyxjQUFjLDhCQUFkLGNBQWMsUUFJekI7QUFRWSxRQUFBLDBCQUEwQixHQUFHO0lBQ3hDLElBQUksRUFBRSxJQUFJO0lBQ1YsT0FBTyxFQUFFLElBQUk7SUFDYixJQUFJLEVBQUUsSUFBSTtJQUNWLFFBQVEsRUFBRSxJQUFJO0lBQ2QsUUFBUSxFQUFFLElBQUk7SUFDZCxLQUFLLEVBQUUsSUFBSTtJQUNYLEVBQUUsRUFBRSxJQUFJO0lBQ1IsS0FBSyxFQUFFLElBQUk7SUFDWCxXQUFXLEVBQUUsSUFBSTtJQUNqQixZQUFZLEVBQUUsSUFBSTtJQUNsQixvQkFBb0IsRUFBRSxJQUFJO0lBQzFCLFVBQVUsRUFBRSxJQUFJO0lBQ2hCLG1CQUFtQixFQUFFLElBQUk7Q0FDakIsQ0FBQztBQXFCRSxRQUFBLHFCQUFxQixHQUFpQztJQUNqRSxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQVc7SUFDaEQsUUFBUSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFXO0lBQ25ELFFBQVEsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBVztJQUNuRCxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFXO0lBQ3BDLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQVc7SUFDM0IsS0FBSyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFXO0lBQ2hELElBQUksRUFBRSxFQUFXO0lBQ2pCLFlBQVksRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBVztJQUN2RCxvQkFBb0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBVztJQUMvRCxtQkFBbUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBVztDQUN0RCxDQUFDO0FBRVgsU0FBUyxlQUFlLENBQUMsSUFBbUIsRUFBRSxLQUFVO0lBQ3RELE1BQU0sU0FBUyxHQUFHLDZCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlDLE1BQU0sT0FBTyxHQUFRLEVBQUUsQ0FBQztJQUV4QixJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssS0FBSyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFFM0MsSUFBSSxTQUFTLENBQUMsT0FBTyxFQUFFO1FBQ3JCLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3hCLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUEsZ0JBQU8sRUFBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7S0FDNUQ7U0FBTTtRQUNMLEtBQUssR0FBRyxJQUFBLGdCQUFPLEVBQUMsS0FBSyxDQUFDLENBQUM7S0FDeEI7SUFFRCxJQUFJLE1BQU0sR0FBRyxJQUFBLGtCQUFTLEVBQUMsS0FBSyxDQUFDLENBQUM7SUFFOUIsb0JBQW9CO0lBQ3BCLElBQUksU0FBUyxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDL0UsSUFBQSx1QkFBYyxFQUFDLEtBQUssRUFBRSxxQkFBcUIsR0FBRyxJQUFJLEVBQUUsY0FBYyxHQUFHLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztLQUNwRjtJQUVELGtDQUFrQztJQUNsQyxJQUFJLFNBQVMsQ0FBQyxTQUFTLEVBQUU7UUFDdkIsTUFBTSxHQUFHLElBQUEsa0JBQVMsRUFBQyxJQUFBLHVCQUFjLEVBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUMzQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLFNBQVMsRUFBRTtZQUN2QyxJQUFBLHVCQUFjLEVBQUMsS0FBSyxFQUFFLHFCQUFxQixHQUFHLElBQUksRUFBRSxjQUFjLEdBQUcsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ3BGO0tBQ0Y7SUFFRCxPQUFPLElBQUEsZ0JBQU8sRUFBQyxNQUFNLENBQUMsQ0FBQztBQUN6QixDQUFDO0FBRUQsU0FBZ0IsU0FBUyxDQUFDLEVBQW1CO0lBQzNDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRTtRQUNmLE9BQU8sRUFBRSxDQUFDO0tBQ1g7SUFFRCxJQUFJLElBQUEsZUFBTyxFQUFDLEVBQUUsQ0FBQyxFQUFFO1FBQ2YsT0FBTyxjQUFjLENBQUMsS0FBSyxDQUFDO0tBQzdCO0lBRUQsSUFBSSxJQUFBLGVBQU8sRUFBQyxFQUFFLENBQUMsRUFBRTtRQUNmLE9BQU8sY0FBYyxDQUFDLEtBQUssQ0FBQztLQUM3QjtJQUVELE9BQU8sY0FBYyxDQUFDLE9BQU8sQ0FBQztBQUNoQyxDQUFDO0FBZEQsOEJBY0M7QUFFRCxTQUFTLGVBQWUsQ0FBQyxFQUFtQixFQUFFLFNBQXFCO0lBQ2pFLElBQUksR0FBRyxHQUF3QixFQUFFLENBQUM7SUFDbEMsUUFBUSxFQUFFLENBQUMsSUFBSSxFQUFFO1FBQ2YsS0FBSyxjQUFjLENBQUMsS0FBSztZQUN2QiwwRUFBMEU7WUFDMUUsd0xBQXdMO1lBQ3hMLEdBQUcsR0FBRztnQkFDSixJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLE9BQVEsQ0FBQztnQkFDcEIsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxLQUFNLENBQUM7Z0JBQ2xCLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUNqRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUNqRCxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUN6QyxFQUFFLENBQUMsRUFBRSxJQUFJLElBQUk7Z0JBQ2IsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDbkMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJO2dCQUNmLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUNwQyxFQUEyQixDQUFDLFdBQVcsSUFBSSxJQUFJO2dCQUMvQyxFQUEyQixDQUFDLG1CQUFtQjtvQkFDOUMsQ0FBQyxDQUFDLElBQUEsZ0JBQU8sRUFBRSxFQUEyQixDQUFDLG1CQUFtQixDQUFDO29CQUMzRCxDQUFDLENBQUMsSUFBSTthQUNULENBQUM7WUFDRixNQUFNO1FBQ1IsS0FBSyxjQUFjLENBQUMsS0FBSztZQUN2QiwwRUFBMEU7WUFDMUUsbUtBQW1LO1lBQ25LLEdBQUcsR0FBRztnQkFDSixJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLE9BQVEsQ0FBQztnQkFDcEIsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxLQUFNLENBQUM7Z0JBQ2xCLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUNqRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUNqRCxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUN6QyxFQUFFLENBQUMsRUFBRSxJQUFJLElBQUk7Z0JBQ2IsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDbkMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJO2dCQUNmLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUNwQyxFQUEyQixDQUFDLFdBQVcsSUFBSSxJQUFJO2FBQ2pELENBQUM7WUFDRixNQUFNO1FBQ1IsS0FBSyxjQUFjLENBQUMsT0FBTztZQUN6QiwwQ0FBMEM7WUFDMUMsOEtBQThLO1lBQzlLLEdBQUcsR0FBRztnQkFDSixJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLE9BQVEsQ0FBQztnQkFDcEIsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxLQUFNLENBQUM7Z0JBQ2xCLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUNqRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUNqRCxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUN6QyxFQUFFLENBQUMsRUFBRSxJQUFJLElBQUk7Z0JBQ2IsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDbkMsRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJO2dCQUNmLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO2FBQ3RDLENBQUM7WUFDRixNQUFNO1FBQ1I7WUFDRSxzQ0FBc0M7WUFDdEMscUVBQXFFO1lBQ3JFLEdBQUcsR0FBRztnQkFDSixJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLEtBQU0sQ0FBQztnQkFDbEIsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDekMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDekMsRUFBRSxDQUFDLEVBQUUsSUFBSSxJQUFJO2dCQUNiLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUEsZ0JBQU8sRUFBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0JBQ25DLEVBQUUsQ0FBQyxJQUFJLElBQUksSUFBSTthQUNoQixDQUFDO1lBQ0YsSUFBSSxDQUFDLFNBQVMsRUFBRTtnQkFDZCxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsRUFBRSxDQUFDLE9BQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2FBQ2pEO1lBQ0QsTUFBTTtLQUNUO0lBRUQsSUFBSSxTQUFTLEVBQUU7UUFDYixHQUFHLENBQUMsSUFBSSxDQUNOLEdBQUc7WUFDRCwyREFBMkQ7WUFDM0QsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBQSxnQkFBTyxFQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtZQUN6QyxJQUFBLHVCQUFjLEVBQUMsSUFBQSxpQkFBUSxFQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyQyxJQUFBLHVCQUFjLEVBQUMsSUFBQSxpQkFBUSxFQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN0QyxDQUNGLENBQUM7S0FDSDtJQUVELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELG1IQUFtSDtBQUNuSCw0REFBNEQ7QUFDNUQsU0FBZ0Isd0JBQXdCLENBQ3RDLFdBQW1DLEVBQ25DLFNBQXlCO0lBRXpCLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7UUFDNUMsSUFBSSxDQUFDLENBQUMsUUFBUSxJQUFJLGtDQUEwQixDQUFDLEVBQUU7WUFDN0MsSUFBQSx1QkFBYyxFQUFDLEtBQUssRUFBRSxrQkFBa0IsRUFBRSwwQkFBMEIsRUFBRSxRQUFRLENBQUMsQ0FBQztTQUNqRjtJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxNQUFNLEdBQWdFLEVBQUUsQ0FBQztJQUUvRSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxFQUFFLEVBQUU7UUFDOUQsSUFBSSxTQUFTLElBQUksNkJBQXFCLEVBQUU7WUFDdEMsbUJBQW1CO1lBQ25CLE1BQU0sQ0FBQyxTQUEwQixDQUFDLEdBQUcsZUFBZSxDQUFDLFNBQTBCLEVBQUUsVUFBVSxDQUFDLENBQUM7U0FDOUY7YUFBTSxJQUFJLFNBQVMsS0FBSyxZQUFZLEVBQUU7WUFDckMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLFVBQVUsQ0FBQTtTQUMvQjtJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCLElBQUksV0FBVyxDQUFDLE9BQU8sSUFBSSxJQUFJLEVBQUU7UUFDL0Isd0RBQXdEO1FBQ3hELE9BQU8sR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFekQsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7WUFDL0IsSUFBQSx1QkFBYyxFQUFDLEtBQUssRUFBRSw2QkFBNkIsRUFBRSxhQUFhLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDbEY7S0FDRjtTQUFNLElBQUksU0FBUyxJQUFJLENBQUMsSUFBQSxvQkFBVyxFQUFDLFNBQVMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxDQUFDLElBQUksSUFBQSxrQkFBUyxFQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDN0YsaUZBQWlGO1FBQ2pGLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBQSxrQkFBUyxFQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxzQkFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7S0FDcEU7SUFFRCxzRUFBc0U7SUFDdEUsSUFBSSxPQUFPLEtBQUssQ0FBQyxFQUFFO1FBQ2pCLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFBLGdCQUFPLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxtQkFBbUI7S0FDMUQ7SUFFRCxvQ0FBb0M7SUFDcEMsYUFBYTtJQUNiLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMvQixtQkFBbUI7SUFDbkIsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7SUFDbkIsSUFBSSxDQUFDLFNBQVMsRUFBRTtRQUNkLG1CQUFtQjtRQUNuQixNQUFNLEdBQUcsR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBQSxrQkFBUyxFQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFBLGlCQUFTLEVBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0tBQzdEO0lBRUQsNEVBQTRFO0lBQzVFLHdEQUF3RDtJQUN4RCxNQUFNLEdBQUcsR0FBRyxrQkFBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUV0QyxJQUFJLENBQVMsQ0FBQztJQUNkLElBQUksTUFBTSxDQUFDLElBQUksRUFBRTtRQUNmLGtCQUFrQjtRQUNsQixDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRywwQkFBaUIsQ0FBQztLQUMvQjtTQUFNO1FBQ0wsY0FBYztRQUNkLENBQUMsR0FBRywwQkFBaUIsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDO1FBRXBDLElBQUksT0FBTyxLQUFLLENBQUMsRUFBRTtZQUNqQixDQUFDLElBQUksT0FBTyxHQUFHLENBQUMsR0FBRyxjQUFLLENBQUM7WUFFekIsOEVBQThFO1lBQzlFLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRywwQkFBaUIsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ2hELElBQUEsdUJBQWMsRUFBQyxLQUFLLEVBQUUsMENBQTBDLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2FBQzNGO1NBQ0Y7YUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3RCLElBQUEsdUJBQWMsRUFBQyxLQUFLLEVBQUUsMENBQTBDLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1NBQzNGO0tBQ0Y7SUFFRCxtQkFBbUI7SUFDbkIsTUFBTSxHQUFHLEdBQUcsZUFBZSxDQUFDLE1BQU0sRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUQsTUFBTSxPQUFPLEdBQUcsSUFBQSxrQkFBUyxFQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFBLGlCQUFTLEVBQUMsQ0FBQyxJQUFBLGdCQUFPLEVBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBQzlELENBQUM7QUEvRUQsNERBK0VDO0FBRUQsMklBQTJJO0FBQzNJLDREQUE0RDtBQUM1RCxTQUFnQixvQkFBb0IsQ0FBQyxjQUF5QjtJQUM1RCxNQUFNLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBRTlELElBQUksRUFBbUIsQ0FBQztJQUN4QixRQUFRLElBQUssRUFBRTtRQUNiLEtBQUssY0FBYyxDQUFDLEtBQUs7WUFDdkIsRUFBRSxHQUFHO2dCQUNILElBQUksRUFBRSxjQUFjLENBQUMsS0FBSztnQkFDMUIsT0FBTyxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQy9DLEtBQUssRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUM3QyxvQkFBb0IsRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUM1RCxZQUFZLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDcEQsUUFBUSxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQ2hELEVBQUUsRUFBRSxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUMzQyxLQUFLLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDN0MsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQVc7Z0JBQzlCLFVBQVUsRUFBRSxnQkFBZ0IsQ0FDMUIsV0FBVyxDQUFDLENBQUMsQ0FBbUMsQ0FDakQ7Z0JBQ0QsV0FBVyxFQUFFLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQ3BELG1CQUFtQixFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFXLENBQUM7YUFDckMsQ0FBQztZQUMxQixNQUFNO1FBQ1IsS0FBSyxjQUFjLENBQUMsS0FBSztZQUN2QixFQUFFLEdBQUc7Z0JBQ0gsSUFBSSxFQUFFLGNBQWMsQ0FBQyxLQUFLO2dCQUMxQixPQUFPLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDL0MsS0FBSyxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzdDLG9CQUFvQixFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzVELFlBQVksRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUNwRCxRQUFRLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDaEQsRUFBRSxFQUFFLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzNDLEtBQUssRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUM3QyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFDcEIsVUFBVSxFQUFFLGdCQUFnQixDQUMxQixXQUFXLENBQUMsQ0FBQyxDQUFtQyxDQUNqRDtnQkFDRCxXQUFXLEVBQUUsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQzthQUM3QixDQUFDO1lBQzFCLE1BQU07UUFDUixLQUFLLGNBQWMsQ0FBQyxPQUFPO1lBQ3pCLFdBQVc7WUFDWCxFQUFFLEdBQUc7Z0JBQ0gsSUFBSSxFQUFFLGNBQWMsQ0FBQyxPQUFPO2dCQUM1QixPQUFPLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDL0MsS0FBSyxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzdDLG9CQUFvQixFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzVELFlBQVksRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUNwRCxRQUFRLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDaEQsRUFBRSxFQUFFLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzNDLEtBQUssRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUM3QyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBVztnQkFDOUIsVUFBVSxFQUFFLGdCQUFnQixDQUMxQixXQUFXLENBQUMsQ0FBQyxDQUFtQyxDQUNqRDthQUN3QixDQUFDO1lBQzVCLE1BQU07UUFDUjtZQUNFOzs7ZUFHRztZQUNILEVBQUUsR0FBRztnQkFDSCxLQUFLLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDN0MsUUFBUSxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQ2hELFFBQVEsRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBVyxDQUFDO2dCQUNoRCxFQUFFLEVBQUUsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQztnQkFDM0MsS0FBSyxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFXLENBQUM7Z0JBQzdDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFXO2dCQUM5QixPQUFPLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQVcsQ0FBQzthQUM3QixDQUFDO1lBQ3JCLE1BQU07S0FDVDtJQUVELDhCQUE4QjtJQUM5QixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUssRUFBRSxXQUFXLENBQUMsRUFBRTtRQUNqQyxPQUFPLEVBQUUsQ0FBQztLQUNYO0lBRUQsSUFBSSxDQUFTLENBQUM7SUFDZCxJQUFJO1FBQ0YsQ0FBQyxHQUFHLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFXLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ2QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQixPQUFPLEVBQUUsQ0FBQztLQUNYO0lBRUQsTUFBTSxDQUFDLEdBQUcsSUFBQSxxQkFBWSxFQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN6RCxNQUFNLENBQUMsR0FBRyxJQUFBLHFCQUFZLEVBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXpELCtCQUErQjtJQUMvQixJQUFJLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksWUFBWSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUNwRCxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ1QsRUFBRSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7WUFDZixDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ1A7S0FDRjtJQUNELHFCQUFxQjtTQUNoQjtRQUNILElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ1QsY0FBYztZQUNkLEVBQUUsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxzQkFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5RCxhQUFhLEdBQUcsQ0FBQyxHQUFHLDBCQUFpQixDQUFDO1lBQ3RDLGFBQWEsSUFBSSxFQUFFLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxjQUFLLENBQUM7U0FDekM7UUFFRCxvRkFBb0Y7UUFDcEYsTUFBTSxVQUFVLEdBQUcsd0JBQXdCLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEQsTUFBTSxNQUFNLEdBQUcsSUFBQSxrQkFBUyxFQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXJDLElBQUk7WUFDRixFQUFFLENBQUMsSUFBSSxHQUFHLElBQUEsdUJBQWMsRUFBQyxNQUFNLEVBQUU7Z0JBQy9CLENBQUM7Z0JBQ0QsQ0FBQztnQkFDRCxPQUFPLEVBQUUsYUFBc0I7YUFDaEMsQ0FBQyxDQUFDO1NBQ0o7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDcEI7UUFFRCxFQUFFLENBQUMsSUFBSSxHQUFHLElBQUEsa0JBQVMsRUFBQyxjQUFjLENBQUMsQ0FBQztLQUNyQztJQUVELE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQztBQTdIRCxvREE2SEM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxLQUFhO0lBQ2xDLElBQUksS0FBSyxLQUFLLElBQUksRUFBRTtRQUNsQixPQUFPLFNBQVMsQ0FBQztLQUNsQjtJQUNELElBQUk7UUFDRixPQUFPLElBQUEsbUJBQVUsRUFBQyxLQUFLLENBQUMsQ0FBQztLQUMxQjtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ2QsT0FBTyxLQUFLLENBQUM7S0FDZDtBQUNILENBQUM7QUFFRCxTQUFTLFlBQVksQ0FBQyxLQUFhO0lBQ2pDLElBQUksS0FBSyxLQUFLLElBQUksRUFBRTtRQUNsQixPQUFPLENBQUMsQ0FBQztLQUNWO0lBQ0QsT0FBTyxJQUFBLGtCQUFTLEVBQUMsS0FBSyxDQUFDLENBQUM7QUFDMUIsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLEtBQWE7SUFDakMsSUFBSSxLQUFLLEtBQUssSUFBSSxFQUFFO1FBQ2xCLE9BQU8sRUFBRSxDQUFDO0tBQ1g7SUFDRCxPQUFPLElBQUEsa0JBQVMsRUFBQyxLQUFLLENBQUMsQ0FBQztBQUMxQixDQUFDO0FBRUQsU0FBUyxnQkFBZ0IsQ0FDdkIsS0FBb0I7SUFFcEIsT0FBTyxJQUFBLHNCQUFhLEVBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFDM0UsQ0FBQztBQUVEOzs7Ozs7Ozs7O0VBVUU7QUFDRixTQUFTLGdCQUFnQixDQUN2QixLQUE0QztJQUU1QyxJQUFJLEtBQUssS0FBSyxJQUFJLEVBQUU7UUFDbEIsT0FBTyxJQUFBLHNCQUFhLEVBQUMsRUFBRSxDQUFDLENBQUM7S0FDMUI7SUFDRCxPQUFPLElBQUEsc0JBQWEsRUFBQyxLQUFLLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBRUQsTUFBTSxhQUFhLEdBQUc7SUFDcEIsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7SUFDcEQsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7SUFDcEQsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7SUFDckQ7Ozs7T0FJRztJQUNILGlCQUFpQixFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFO0NBQ3JDLENBQUM7QUFFWCxTQUFTLFFBQVEsQ0FBQyxJQUFvQixFQUFFLFdBQWdDO0lBQ3RFLElBQUksSUFBSSxFQUFFO1FBQ1IsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxPQUFPLFdBQVcsQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFDO0tBQ3RDO0lBRUQsTUFBTSxDQUFDLEdBQUcsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQztJQUNyQyxNQUFNLENBQUMsR0FBRyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO0lBQ3JDLE9BQU8sQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDO0FBQ2xDLENBQUM7QUFFRCxTQUFTLGVBQWUsQ0FBQyxJQUFvQixFQUFFLFdBQWdDO0lBQzdFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxhQUFhLENBQUMsSUFBSSxJQUFJLGlCQUFpQixDQUFDLENBQUM7SUFDOUQsT0FBTyxXQUFXLENBQUMsTUFBTSxLQUFLLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBQ3hFLENBQUM7QUFFRCxTQUFTLGlCQUFpQixDQUN4QixjQUF5QjtJQUV6QixJQUFJLE1BQU0sR0FBRyxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDdkMsSUFBSSxJQUFnQyxDQUFDO0lBQ3JDLEtBQUssTUFBTSxLQUFLLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLGNBQWMsQ0FBQyxLQUFLLEVBQUUsY0FBYyxDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ3hGLE1BQU0sTUFBTSxHQUFHLElBQUEsZ0JBQU8sRUFBQyxLQUFLLENBQUMsQ0FBQztRQUM5QixJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDN0IsTUFBTSxHQUFHLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxJQUFJLEdBQUcsS0FBSyxDQUFDO1lBQ2IsTUFBTTtTQUNQO0tBQ0Y7SUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFBLGtCQUFTLEVBQUMsTUFBTSxDQUF3QixDQUFDO0lBQzdELElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSyxFQUFFLFdBQVcsQ0FBQyxFQUFFO1FBQ3hDLElBQUEsdUJBQWMsRUFBQyxLQUFLLEVBQUUseUJBQXlCLEVBQUUsd0JBQXdCLEVBQUU7WUFDekUsSUFBSSxFQUFFLElBQUs7WUFDWCxjQUFjO1NBQ2YsQ0FBQyxDQUFDO0tBQ0o7SUFFRCxPQUFPLENBQUMsSUFBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBQzlCLENBQUMifQ==