UNPKG

simonzgconnexframework

Version:

A library implements VeChain Connex interface

229 lines 18.4 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const LRU = require("lru-cache"); const bloom_1 = require("thor-devkit/dist/bloom"); const bignumber_js_1 = require("bignumber.js"); const WINDOW_LEN = 12; class Cache { constructor() { this.irreversible = { blocks: new LRU(256), txs: new LRU(512), receipts: new LRU(512) }; this.window = []; } handleNewBlock(head, bloom, block) { while (this.window.length > 0) { const top = this.window[this.window.length - 1]; if (top.id === head.id) { return; } if (top.id === head.parentID) { break; } this.window.pop(); } this.window.push(Object.assign({}, head, { bloom: bloom ? new bloom_1.Bloom(bloom.k, Buffer.from(bloom.bits.slice(2), 'hex')) : undefined, block, accounts: new Map(), txs: new Map(), receipts: new Map(), tied: new Map() })); // shift out old slots and move cached items into frozen cache while (this.window.length > WINDOW_LEN) { const bottom = this.window.shift(); bottom.txs.forEach((v, k) => this.irreversible.txs.set(k, v)); bottom.receipts.forEach((v, k) => this.irreversible.receipts.set(k, v)); if (bottom.block) { this.irreversible.blocks.set(bottom.block.id, bottom.block); this.irreversible.blocks.set(bottom.block.number, bottom.block); } } } getBlock(revision, fetch) { return __awaiter(this, void 0, void 0, function* () { let block = this.irreversible.blocks.get(revision) || null; if (block) { return block; } const { slot } = this.findSlot(revision); if (slot && slot.block) { return slot.block; } block = yield fetch(); if (block) { if (slot && slot.id === block.id) { slot.block = block; } if (this.isIrreversible(block.number)) { this.irreversible.blocks.set(block.id, block); if (block.isTrunk) { this.irreversible.blocks.set(block.number, block); } } } return block; }); } getTx(txid, fetch) { return __awaiter(this, void 0, void 0, function* () { let tx = this.irreversible.txs.get(txid) || null; if (tx) { return tx; } for (const slot of this.window) { tx = slot.txs.get(txid) || null; if (tx) { return tx; } } tx = yield fetch(); if (tx) { const { slot } = this.findSlot(tx.meta.blockID); if (slot) { slot.txs.set(txid, tx); } if (this.isIrreversible(tx.meta.blockNumber)) { this.irreversible.txs.set(txid, tx); } } return tx; }); } getReceipt(txid, fetch) { return __awaiter(this, void 0, void 0, function* () { let receipt = this.irreversible.receipts.get(txid) || null; if (receipt) { return receipt; } for (const slot of this.window) { receipt = slot.receipts.get(txid) || null; if (receipt) { return receipt; } } receipt = yield fetch(); if (receipt) { const { slot } = this.findSlot(receipt.meta.blockID); if (slot) { slot.receipts.set(txid, receipt); } if (this.isIrreversible(receipt.meta.blockNumber)) { this.irreversible.receipts.set(txid, receipt); } } return receipt; }); } getAccount(addr, revision, fetch) { return __awaiter(this, void 0, void 0, function* () { const found = this.findSlot(revision); for (let i = found.index; i >= 0; i--) { const slot = this.window[i]; const acc = slot.accounts.get(addr); if (acc) { if (i !== found.index) { found.slot.accounts.set(addr, acc); } return acc.snapshot(found.slot.timestamp); } if (!slot.bloom || testBytesHex(slot.bloom, addr)) { // account might be dirty break; } } const accObj = yield fetch(); if (found.slot) { found.slot.accounts.set(addr, new Account(accObj, found.slot.timestamp)); } return accObj; }); } /** * get cached entry which is tied to a batch of addresses * @param key the cache key * @param revision block id where cache bound to * @param fetch to fetch value when cache missing * @param ties array of tied addresses, as the gist to invalidate cache key. undefined means the key is always * invalidated on different revision. */ getTied(key, revision, fetch, ties) { return __awaiter(this, void 0, void 0, function* () { const found = this.findSlot(revision); for (let i = found.index; i >= 0; i--) { const slot = this.window[i]; const v = slot.tied.get(key); if (v) { if (i !== found.index) { found.slot.tied.set(key, v); } return v; } if (!slot.bloom || !ties) { break; } // if ties.length === 0, never invalidate cache if (ties.some(t => testBytesHex(slot.bloom, t))) { // might be dirty break; } } const value = yield fetch(); if (found.slot) { found.slot.tied.set(key, value); } return value; }); } findSlot(revision) { const index = this.window.findIndex(s => s.id === revision || s.number === revision); if (index >= 0) { return { slot: this.window[index], index }; } return { index }; } isIrreversible(n) { if (this.window.length > 0) { return n < this.window[this.window.length - 1].number - WINDOW_LEN; } return false; } } exports.Cache = Cache; function testBytesHex(bloom, hex) { let buf = Buffer.from(hex.slice(2), 'hex'); const nzIndex = buf.findIndex(v => v !== 0); if (nzIndex < 0) { buf = Buffer.alloc(0); } else { buf = buf.slice(nzIndex); } return bloom.test(buf); } const ENERGY_GROWTH_RATE = 5000000000; class Account { constructor(obj, initTimestamp) { this.obj = obj; this.initTimestamp = initTimestamp; } snapshot(timestamp) { return Object.assign({}, this.obj, { energy: this.energyAt(timestamp) }); } energyAt(timestamp) { if (timestamp < this.initTimestamp) { return this.obj.energy; } return '0x' + new bignumber_js_1.default(this.obj.balance) .times(timestamp - this.initTimestamp) .times(ENERGY_GROWTH_RATE) .dividedToIntegerBy(1e18) .plus(this.obj.energy) .toString(16); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZHJpdmVyL2NhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSxpQ0FBZ0M7QUFDaEMsa0RBQThDO0FBQzlDLCtDQUFvQztBQUVwQyxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUE7QUFZckIsTUFBYSxLQUFLO0lBQWxCO1FBQ3FCLGlCQUFZLEdBQUc7WUFDNUIsTUFBTSxFQUFFLElBQUksR0FBRyxDQUFxQyxHQUFHLENBQUM7WUFDeEQsR0FBRyxFQUFFLElBQUksR0FBRyxDQUFrQyxHQUFHLENBQUM7WUFDbEQsUUFBUSxFQUFFLElBQUksR0FBRyxDQUE4QixHQUFHLENBQUM7U0FDdEQsQ0FBQTtRQUNnQixXQUFNLEdBQVcsRUFBRSxDQUFBO0lBc054QyxDQUFDO0lBcE5VLGNBQWMsQ0FDakIsSUFBZ0MsRUFDaEMsS0FBbUMsRUFDbkMsS0FBeUI7UUFFekIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDM0IsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtZQUMvQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDcEIsT0FBTTthQUNUO1lBQ0QsSUFBSSxHQUFHLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQzFCLE1BQUs7YUFDUjtZQUNELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUE7U0FDcEI7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksbUJBQ1QsSUFBSSxJQUNQLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksYUFBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLEVBQ3RGLEtBQUssRUFDTCxRQUFRLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFDbkIsR0FBRyxFQUFFLElBQUksR0FBRyxFQUFFLEVBQ2QsUUFBUSxFQUFFLElBQUksR0FBRyxFQUFFLEVBQ25CLElBQUksRUFBRSxJQUFJLEdBQUcsRUFBRSxJQUNqQixDQUFBO1FBRUYsOERBQThEO1FBQzlELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsVUFBVSxFQUFFO1lBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFHLENBQUE7WUFFbkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDN0QsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDdkUsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFO2dCQUNkLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7Z0JBQzNELElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7YUFDbEU7U0FDSjtJQUNMLENBQUM7SUFFWSxRQUFRLENBQ2pCLFFBQXlCLEVBQ3pCLEtBQThDOztZQUU5QyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFBO1lBQzFELElBQUksS0FBSyxFQUFFO2dCQUNQLE9BQU8sS0FBSyxDQUFBO2FBQ2Y7WUFFRCxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQTtZQUV4QyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO2dCQUNwQixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUE7YUFDcEI7WUFFRCxLQUFLLEdBQUcsTUFBTSxLQUFLLEVBQUUsQ0FBQTtZQUNyQixJQUFJLEtBQUssRUFBRTtnQkFDUCxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsRUFBRSxLQUFLLEtBQUssQ0FBQyxFQUFFLEVBQUU7b0JBQzlCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO2lCQUNyQjtnQkFFRCxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUNuQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQTtvQkFDN0MsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFO3dCQUNmLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO3FCQUNwRDtpQkFDSjthQUNKO1lBQ0QsT0FBTyxLQUFLLENBQUE7UUFDaEIsQ0FBQztLQUFBO0lBRVksS0FBSyxDQUNkLElBQVksRUFDWixLQUFvRDs7WUFFcEQsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQTtZQUNoRCxJQUFJLEVBQUUsRUFBRTtnQkFDSixPQUFPLEVBQUUsQ0FBQTthQUNaO1lBRUQsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO2dCQUM1QixFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFBO2dCQUMvQixJQUFJLEVBQUUsRUFBRTtvQkFDSixPQUFPLEVBQUUsQ0FBQTtpQkFDWjthQUNKO1lBRUQsRUFBRSxHQUFHLE1BQU0sS0FBSyxFQUFFLENBQUE7WUFDbEIsSUFBSSxFQUFFLEVBQUU7Z0JBQ0osTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtnQkFDL0MsSUFBSSxJQUFJLEVBQUU7b0JBQ04sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFBO2lCQUN6QjtnQkFDRCxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRTtvQkFDMUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQTtpQkFDdEM7YUFDSjtZQUNELE9BQU8sRUFBRSxDQUFBO1FBQ2IsQ0FBQztLQUFBO0lBRVksVUFBVSxDQUNuQixJQUFZLEVBQ1osS0FBZ0Q7O1lBRWhELElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUE7WUFDMUQsSUFBSSxPQUFPLEVBQUU7Z0JBQ1QsT0FBTyxPQUFPLENBQUE7YUFDakI7WUFFRCxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQzVCLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUE7Z0JBQ3pDLElBQUksT0FBTyxFQUFFO29CQUNULE9BQU8sT0FBTyxDQUFBO2lCQUNqQjthQUNKO1lBRUQsT0FBTyxHQUFHLE1BQU0sS0FBSyxFQUFFLENBQUE7WUFDdkIsSUFBSSxPQUFPLEVBQUU7Z0JBQ1QsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtnQkFDcEQsSUFBSSxJQUFJLEVBQUU7b0JBQ04sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFBO2lCQUNuQztnQkFDRCxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRTtvQkFDL0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQTtpQkFDaEQ7YUFDSjtZQUNELE9BQU8sT0FBTyxDQUFBO1FBQ2xCLENBQUM7S0FBQTtJQUVZLFVBQVUsQ0FDbkIsSUFBWSxFQUNaLFFBQWdCLEVBQ2hCLEtBQXlDOztZQUV6QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBQ3JDLEtBQUssSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUNuQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFBO2dCQUMzQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDbkMsSUFBSSxHQUFHLEVBQUU7b0JBQ0wsSUFBSSxDQUFDLEtBQUssS0FBSyxDQUFDLEtBQUssRUFBRTt3QkFDbkIsS0FBSyxDQUFDLElBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQTtxQkFDdEM7b0JBQ0QsT0FBTyxHQUFHLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFLLENBQUMsU0FBUyxDQUFDLENBQUE7aUJBQzdDO2dCQUVELElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFO29CQUMvQyx5QkFBeUI7b0JBQ3pCLE1BQUs7aUJBQ1I7YUFDSjtZQUNELE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxFQUFFLENBQUE7WUFDNUIsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFO2dCQUNaLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQTthQUMzRTtZQUNELE9BQU8sTUFBTSxDQUFBO1FBQ2pCLENBQUM7S0FBQTtJQUVEOzs7Ozs7O09BT0c7SUFDVSxPQUFPLENBQ2hCLEdBQVcsRUFDWCxRQUFnQixFQUNoQixLQUF5QixFQUN6QixJQUFlOztZQUVmLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDckMsS0FBSyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ25DLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7Z0JBQzNCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUM1QixJQUFJLENBQUMsRUFBRTtvQkFDSCxJQUFJLENBQUMsS0FBSyxLQUFLLENBQUMsS0FBSyxFQUFFO3dCQUNuQixLQUFLLENBQUMsSUFBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFBO3FCQUMvQjtvQkFDRCxPQUFPLENBQUMsQ0FBQTtpQkFDWDtnQkFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLElBQUksRUFBRTtvQkFDdEIsTUFBSztpQkFDUjtnQkFFRCwrQ0FBK0M7Z0JBQy9DLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQzlDLGlCQUFpQjtvQkFDakIsTUFBSztpQkFDUjthQUNKO1lBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxLQUFLLEVBQUUsQ0FBQTtZQUMzQixJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUU7Z0JBQ1osS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQTthQUNsQztZQUNELE9BQU8sS0FBSyxDQUFBO1FBQ2hCLENBQUM7S0FBQTtJQUVPLFFBQVEsQ0FBQyxRQUF5QjtRQUN0QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxNQUFNLEtBQUssUUFBUSxDQUFDLENBQUE7UUFDcEYsSUFBSSxLQUFLLElBQUksQ0FBQyxFQUFFO1lBQ1osT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFBO1NBQzdDO1FBQ0QsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFBO0lBQ3BCLENBQUM7SUFFTyxjQUFjLENBQUMsQ0FBUztRQUM1QixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN4QixPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUE7U0FDckU7UUFDRCxPQUFPLEtBQUssQ0FBQTtJQUNoQixDQUFDO0NBQ0o7QUE1TkQsc0JBNE5DO0FBRUQsU0FBUyxZQUFZLENBQUMsS0FBWSxFQUFFLEdBQVc7SUFDM0MsSUFBSSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQzFDLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7SUFDM0MsSUFBSSxPQUFPLEdBQUcsQ0FBQyxFQUFFO1FBQ2IsR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7S0FDeEI7U0FBTTtRQUNILEdBQUcsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0tBQzNCO0lBQ0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO0FBQzFCLENBQUM7QUFFRCxNQUFNLGtCQUFrQixHQUFHLFVBQVUsQ0FBQTtBQUVyQyxNQUFNLE9BQU87SUFDVCxZQUFxQixHQUF3QixFQUFXLGFBQXFCO1FBQXhELFFBQUcsR0FBSCxHQUFHLENBQXFCO1FBQVcsa0JBQWEsR0FBYixhQUFhLENBQVE7SUFDN0UsQ0FBQztJQUVNLFFBQVEsQ0FBQyxTQUFpQjtRQUM3Qix5QkFBWSxJQUFJLENBQUMsR0FBRyxJQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFFO0lBQzVELENBQUM7SUFFTyxRQUFRLENBQUMsU0FBaUI7UUFDOUIsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNoQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFBO1NBQ3pCO1FBQ0QsT0FBTyxJQUFJLEdBQUcsSUFBSSxzQkFBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDO2FBQ3hDLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQzthQUNyQyxLQUFLLENBQUMsa0JBQWtCLENBQUM7YUFDekIsa0JBQWtCLENBQUMsSUFBSSxDQUFDO2FBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQzthQUNyQixRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDckIsQ0FBQztDQUNKIn0=