UNPKG

@vechain/connex-driver

Version:
254 lines 21.6 kB
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()); }); }; import BigNumber from 'bignumber.js'; import LRU from 'lru-cache'; import { newFilter } from './bloom'; const WINDOW_LEN = 12; export class Cache { constructor() { this.irreversible = { blocks: new LRU(256), txs: new LRU(512), receipts: new LRU(512), feesHistory: new LRU(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 ? 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; } } 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(this.obj.balance) .times(timestamp - this.initTimestamp) .times(ENERGY_GROWTH_RATE) .dividedToIntegerBy(1e18) .plus(this.obj.energy) .toString(16); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxTQUFTLE1BQU0sY0FBYyxDQUFBO0FBQ3BDLE9BQU8sR0FBRyxNQUFNLFdBQVcsQ0FBQTtBQUMzQixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sU0FBUyxDQUFBO0FBRW5DLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQTtBQVlyQixNQUFNLE9BQU8sS0FBSztJQUFsQjtRQUNxQixpQkFBWSxHQUFHO1lBQzVCLE1BQU0sRUFBRSxJQUFJLEdBQUcsQ0FBcUMsR0FBRyxDQUFDO1lBQ3hELEdBQUcsRUFBRSxJQUFJLEdBQUcsQ0FBa0MsR0FBRyxDQUFDO1lBQ2xELFFBQVEsRUFBRSxJQUFJLEdBQUcsQ0FBMEMsR0FBRyxDQUFDO1lBQy9ELFdBQVcsRUFBRSxJQUFJLEdBQUcsQ0FBbUMsR0FBRyxDQUFDO1NBQzlELENBQUE7UUFDZ0IsV0FBTSxHQUFXLEVBQUUsQ0FBQTtJQXFQeEMsQ0FBQztJQW5QVSxjQUFjLENBQ2pCLElBQWdDLEVBQ2hDLEtBQW1DLEVBQ25DLEtBQXlCO1FBRXpCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtZQUMvQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNyQixPQUFNO1lBQ1YsQ0FBQztZQUNELElBQUksR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQzNCLE1BQUs7WUFDVCxDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQTtRQUNyQixDQUFDO1FB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