UNPKG

deth

Version:

Ethereum node focused on Developer Experience

119 lines (118 loc) 5.18 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ethereumjs_util_1 = require("ethereumjs-util"); const ethereumjs_tx_1 = require("ethereumjs-tx"); const model_1 = require("../model"); const primitives_1 = require("../primitives"); const initializeVM_1 = require("./initializeVM"); const getLatestBlock_1 = require("./getLatestBlock"); const putBlock_1 = require("./putBlock"); const runIsolatedTransaction_1 = require("./runIsolatedTransaction"); const DethStateManger_1 = require("./storage/DethStateManger"); const DethBlockchain_1 = require("./storage/DethBlockchain"); // eslint-disable-next-line const promisified_1 = __importDefault(require("ethereumts-vm/dist/state/promisified")); const BlockchainAdapter_1 = require("./storage/BlockchainAdapter"); const StateManagerAdapter_1 = require("./storage/StateManagerAdapter"); const SnapshotObject_1 = require("./storage/SnapshotObject"); /** * TestVM is a wrapper around ethereumts-vm (our fork). It provides a promise-based * interface and abstracts away weird ethereumjs specific details */ class TestVM { constructor(options) { this.options = options; this.pendingTransactions = []; this.transactions = new Map(); this.receipts = new Map(); this.snapshots = []; this.state = new SnapshotObject_1.SnapshotObject({ stateManger: new DethStateManger_1.DethStateManger(), blockchain: new DethBlockchain_1.DethBlockchain(), }, (t) => ({ blockchain: t.blockchain.copy(), stateManger: t.stateManger.copy(), })); } async init() { this.vm = await initializeVM_1.initializeVM(this.options, this.state.value.stateManger, this.state.value.blockchain); } // @todo this requires better typings (whole step hooks mechanism) installStepHook(hook) { this.vm.on('step', hook); } makeSnapshot() { return this.state.makeSnapshot(); } revertToSnapshot(id) { this.state.revert(id); this.hotswapStateStorageForVm(); } // change internals of VM to point to new blockchain and state machine hotswapStateStorageForVm() { const blockchainAdapter = new BlockchainAdapter_1.BlockchainAdapter(this.state.value.blockchain); this.vm.blockchain = blockchainAdapter; const stateManagerAdapter = new StateManagerAdapter_1.StateManagerAdapter(this.state.value.stateManger); this.vm.stateManager = stateManagerAdapter; this.vm.pStateManager = new promisified_1.default(stateManagerAdapter); } async getBlockNumber() { const block = await getLatestBlock_1.getLatestBlock(this.vm); return primitives_1.bufferToQuantity(block.header.number); } async getLatestBlock() { const block = await getLatestBlock_1.getLatestBlock(this.vm); return model_1.toBlockResponse(block); } async addPendingTransaction(signedTransaction) { const transaction = new ethereumjs_tx_1.Transaction(signedTransaction, { common: this.vm._common }); this.pendingTransactions.push(transaction); return primitives_1.bufferToHash(transaction.hash()); } async mineBlock(clockSkew) { const transactions = this.pendingTransactions; this.pendingTransactions = []; const { receipts, responses } = await putBlock_1.putBlock(this.vm, transactions, this.options, clockSkew); for (const receipt of receipts) { this.receipts.set(receipt.transactionHash, receipt); } for (const response of responses) { this.transactions.set(response.hash, response); } } getTransaction(hash) { return this.transactions.get(hash); } getTransactionReceipt(hash) { return this.receipts.get(hash); } async getNonce(address) { const account = await this.getAccount(address); return primitives_1.bufferToQuantity(account.nonce); } async getBalance(address) { const account = await this.getAccount(address); return primitives_1.bufferToQuantity(account.balance); } async getAccount(address) { return this.state.value.stateManger.getAccount(address); } async getCode(address) { const code = this.state.value.stateManger.getContractCode(address); return primitives_1.bufferToHexData(code); } async runIsolatedTransaction(transaction, clockSkew) { return runIsolatedTransaction_1.runIsolatedTransaction(this.vm, transaction, this.options, clockSkew); } async getBlock(hashOrNumber) { const query = hashOrNumber.length === 66 ? ethereumjs_util_1.toBuffer(hashOrNumber) : new ethereumjs_util_1.BN(hashOrNumber.substr(2), 'hex'); const block = await new Promise((resolve, reject) => { this.vm.blockchain.getBlock(query, (err, block) => (err != null ? reject(err) : resolve(block))); }); return model_1.toBlockResponse(block); } } exports.TestVM = TestVM;