UNPKG

@vechain/connex-driver

Version:
261 lines 22 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cache = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const lru_cache_1 = __importDefault(require("lru-cache")); const bloom_1 = require("./bloom"); const WINDOW_LEN = 12; class Cache { constructor() { this.irreversible = { blocks: new lru_cache_1.default(256), txs: new lru_cache_1.default(512), receipts: new lru_cache_1.default(512), feesHistory: new lru_cache_1.default(256) }; 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(Object.assign({}, head), { bloom: bloom ? (0, bloom_1.newFilter)(Buffer.from(bloom.bits.slice(2), 'hex'), bloom.k) : 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; }); } getFeesHistory(newestBlock, blockCount, rewardPercentiles, fetch) { return __awaiter(this, void 0, void 0, function* () { let key = `${newestBlock}-${blockCount}`; if (rewardPercentiles.length > 0) { key = `${key}-${rewardPercentiles.join(',')}`; } const cachedRange = this.irreversible.feesHistory.get(key); if (cachedRange) { return cachedRange; } const range = yield fetch(); if (range && range.baseFeePerGas.length > 0) { // Key change for the case where we are starting a network with less blocks than the blockCount // Also this could happen for cases including the backtrace limit // i.e. backtrace limit is 2, we have 7 blocks, we request 4 from 'best' if (range.baseFeePerGas.length < blockCount) { key = `${newestBlock}-${blockCount - range.baseFeePerGas.length}`; if (rewardPercentiles.length > 0) { key = `${key}-${rewardPercentiles.join(',')}`; } } this.irreversible.feesHistory.set(key, range); } return range; }); } 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 && tx.meta) { // only cache non-pending 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 hints 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, hints) { 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 || !hints) { break; } // if hints.length === 0, never invalidate cache if (hints.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(filter, 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 filter.contains(buf); } const ENERGY_GROWTH_RATE = 5000000000; class Account { constructor(obj, initTimestamp) { this.obj = obj; this.initTimestamp = initTimestamp; } snapshot(timestamp) { return Object.assign(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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0VBQW9DO0FBQ3BDLDBEQUEyQjtBQUMzQixtQ0FBbUM7QUFFbkMsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFBO0FBWXJCLE1BQWEsS0FBSztJQUFsQjtRQUNxQixpQkFBWSxHQUFHO1lBQzVCLE1BQU0sRUFBRSxJQUFJLG1CQUFHLENBQXFDLEdBQUcsQ0FBQztZQUN4RCxHQUFHLEVBQUUsSUFBSSxtQkFBRyxDQUFrQyxHQUFHLENBQUM7WUFDbEQsUUFBUSxFQUFFLElBQUksbUJBQUcsQ0FBMEMsR0FBRyxDQUFDO1lBQy9ELFdBQVcsRUFBRSxJQUFJLG1CQUFHLENBQW1DLEdBQUcsQ0FBQztTQUM5RCxDQUFBO1FBQ2dCLFdBQU0sR0FBVyxFQUFFLENBQUE7SUFxUHhDLENBQUM7SUFuUFUsY0FBYyxDQUNqQixJQUFnQyxFQUNoQyxLQUFtQyxFQUNuQyxLQUF5QjtRQUV6QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzVCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUE7WUFDL0MsSUFBSSxHQUFHLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDckIsT0FBTTtZQUNWLENBQUM7WUFDRCxJQUFJLEdBQUcsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUMzQixNQUFLO1lBQ1QsQ0FBQztZQUNELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDckIsQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxpQ0FDVCxJQUFJLEtBQ1AsS0FBSyxFQUFFLEtBQUss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