UNPKG

@ethereumjs/vm

Version:
838 lines 38.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runBlock = runBlock; exports.accumulateParentBlockHash = accumulateParentBlockHash; exports.accumulateParentBeaconBlockRoot = accumulateParentBeaconBlockRoot; exports.calculateMinerReward = calculateMinerReward; exports.rewardAccount = rewardAccount; exports.encodeReceipt = encodeReceipt; const block_1 = require("@ethereumjs/block"); const common_1 = require("@ethereumjs/common"); const evm_1 = require("@ethereumjs/evm"); const mpt_1 = require("@ethereumjs/mpt"); const rlp_1 = require("@ethereumjs/rlp"); const statemanager_1 = require("@ethereumjs/statemanager"); const tx_1 = require("@ethereumjs/tx"); const util_1 = require("@ethereumjs/util"); const debug_1 = require("debug"); const sha256_js_1 = require("ethereum-cryptography/sha256.js"); const index_ts_1 = require("./bloom/index.js"); const emitEVMProfile_ts_1 = require("./emitEVMProfile.js"); const index_ts_2 = require("./index.js"); const requests_ts_1 = require("./requests.js"); const debug = (0, debug_1.default)('vm:block'); const parentBeaconBlockRootAddress = (0, util_1.createAddressFromString)('0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02'); let enableProfiler = false; const stateRootCPLabel = 'New state root, DAO HF, checkpoints, block validation'; const processTxsLabel = 'Tx processing [ use per-tx profiler for more details ]'; const withdrawalsRewardsCommitLabel = 'Withdrawals, Rewards, EVM journal commit'; const entireBlockLabel = 'Entire block'; /** * Processes the `block` running all of the transactions it contains and updating the miner's account * * vm method modifies the state. If `generate` is `true`, the state modifications will be * reverted if an exception is raised. If it's `false`, it won't revert if the block's header is * invalid. If an error is thrown from an event handler, the state may or may not be reverted. * * @param {VM} vm * @param {RunBlockOpts} opts - Default values for options: * - `generate`: false */ async function runBlock(vm, opts) { if (vm['_opts'].profilerOpts?.reportAfterBlock === true) { enableProfiler = true; // eslint-disable-next-line no-console console.time(entireBlockLabel); } const stateManager = vm.stateManager; const { root } = opts; const clearCache = opts.clearCache ?? true; const setHardfork = opts.setHardfork ?? false; let { block } = opts; const generateFields = opts.generate === true; if (enableProfiler) { const title = `Profiler run - Block ${block.header.number} (${(0, util_1.bytesToHex)(block.hash())} with ${block.transactions.length} txs`; // eslint-disable-next-line no-console console.log(title); // eslint-disable-next-line no-console console.time(stateRootCPLabel); } /** * The `beforeBlock` event. * * @event Event: beforeBlock * @type {Object} * @property {Block} block emits the block that is about to be processed */ await vm._emit('beforeBlock', block); if (setHardfork !== false || vm['_setHardfork'] !== false) { const setHardforkUsed = setHardfork ?? vm['_setHardfork']; if (setHardforkUsed === true) { vm.common.setHardforkBy({ blockNumber: block.header.number, timestamp: block.header.timestamp, }); } } if (vm.DEBUG) { debug('-'.repeat(100)); debug(`Running block hash=${(0, util_1.bytesToHex)(block.hash())} number=${block.header.number} hardfork=${vm.common.hardfork()}`); } // Set state root if provided if (root) { if (vm.DEBUG) { debug(`Set provided state root ${(0, util_1.bytesToHex)(root)} clearCache=${clearCache}`); } await stateManager.setStateRoot(root, clearCache); } if (vm.common.isActivatedEIP(6800) || vm.common.isActivatedEIP(7864)) { // Initialize the access witness if (vm.common.customCrypto.verkle === undefined) { throw Error('verkleCrypto required when EIP-6800 is active'); } vm.evm.verkleAccessWitness = new evm_1.VerkleAccessWitness({ verkleCrypto: vm.common.customCrypto.verkle, }); vm.evm.systemVerkleAccessWitness = new evm_1.VerkleAccessWitness({ verkleCrypto: vm.common.customCrypto.verkle, }); if (typeof stateManager.initVerkleExecutionWitness !== 'function') { throw Error(`VerkleStateManager needed for execution of verkle blocks`); } if (vm.DEBUG) { debug(`Initializing executionWitness`); } if (clearCache) { stateManager.clearCaches(); } // Populate the execution witness stateManager.initVerkleExecutionWitness(block.header.number, block.executionWitness); // Check if statemanager is a Verkle State Manager (stateless and stateful both have verifyVerklePostState) if ('verifyVerklePostState' in stateManager) { // Update the stateRoot cache await stateManager.setStateRoot(block.header.stateRoot); if ((0, statemanager_1.verifyVerkleStateProof)(stateManager) === true) { if (vm.DEBUG) { debug(`Verkle proof verification succeeded`); } } else { throw Error(`Verkle proof verification failed`); } } } else { if (typeof stateManager.initVerkleExecutionWitness === 'function') { throw Error(`StatelessVerkleStateManager can't execute merkle blocks`); } } // check for DAO support and if we should apply the DAO fork if (vm.common.hardforkIsActiveOnBlock(common_1.Hardfork.Dao, block.header.number) && block.header.number === vm.common.hardforkBlock(common_1.Hardfork.Dao)) { if (vm.DEBUG) { debug(`Apply DAO hardfork`); } await vm.evm.journal.checkpoint(); await _applyDAOHardfork(vm.evm); await vm.evm.journal.commit(); } // Checkpoint state await vm.evm.journal.checkpoint(); if (vm.DEBUG) { debug(`block checkpoint`); } let result; try { result = await applyBlock(vm, block, opts); if (vm.DEBUG) { debug(`Received block results gasUsed=${result.gasUsed} bloom=${(0, util_1.short)(result.bloom.bitvector)} (${result.bloom.bitvector.length} bytes) receiptsRoot=${(0, util_1.bytesToHex)(result.receiptsRoot)} receipts=${result.receipts.length} txResults=${result.results.length}`); } } catch (err) { await vm.evm.journal.revert(); if (vm.DEBUG) { debug(`block checkpoint reverted`); } if (enableProfiler) { // eslint-disable-next-line no-console console.timeEnd(withdrawalsRewardsCommitLabel); } throw err; } let requestsHash; let requests; if (block.common.isActivatedEIP(7685)) { const sha256Function = vm.common.customCrypto.sha256 ?? sha256_js_1.sha256; requests = await (0, requests_ts_1.accumulateRequests)(vm, result.results); requestsHash = (0, block_1.genRequestsRoot)(requests, sha256Function); } // Persist state await vm.evm.journal.commit(); if (vm.DEBUG) { debug(`block checkpoint committed`); } const stateRoot = await stateManager.getStateRoot(); // Given the generate option, either set resulting header // values to the current block, or validate the resulting // header values against the current block. if (generateFields) { const logsBloom = result.bloom.bitvector; const gasUsed = result.gasUsed; const receiptTrie = result.receiptsRoot; const transactionsTrie = await _genTxTrie(block); const generatedFields = { stateRoot, logsBloom, gasUsed, receiptTrie, transactionsTrie, requestsHash, }; const blockData = { ...block, header: { ...block.header, ...generatedFields }, }; block = (0, block_1.createBlock)(blockData, { common: vm.common }); } else { if (vm.common.isActivatedEIP(7685)) { if (!(0, util_1.equalsBytes)(block.header.requestsHash, requestsHash)) { if (vm.DEBUG) debug(`Invalid requestsHash received=${(0, util_1.bytesToHex)(block.header.requestsHash)} expected=${(0, util_1.bytesToHex)(requestsHash)}`); const msg = _errorMsg('invalid requestsHash', vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } } // Check if statemanager is a StatelessVerkleStateManager by checking for a method only on StatelessVerkleStateManager API if (!('verifyVerklePostState' in vm.stateManager)) { // Only validate the following headers if Stateless isn't activated if ((0, util_1.equalsBytes)(result.receiptsRoot, block.header.receiptTrie) === false) { if (vm.DEBUG) { debug(`Invalid receiptTrie received=${(0, util_1.bytesToHex)(result.receiptsRoot)} expected=${(0, util_1.bytesToHex)(block.header.receiptTrie)}`); } const msg = _errorMsg('invalid receiptTrie', vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } if (!((0, util_1.equalsBytes)(result.bloom.bitvector, block.header.logsBloom) === true)) { if (vm.DEBUG) { debug(`Invalid bloom received=${(0, util_1.bytesToHex)(result.bloom.bitvector)} expected=${(0, util_1.bytesToHex)(block.header.logsBloom)}`); } const msg = _errorMsg('invalid bloom', vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } if (result.gasUsed !== block.header.gasUsed) { if (vm.DEBUG) { debug(`Invalid gasUsed received=${result.gasUsed} expected=${block.header.gasUsed}`); } const msg = _errorMsg('invalid gasUsed', vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } if (!((0, util_1.equalsBytes)(stateRoot, block.header.stateRoot) === true)) { if (vm.DEBUG) { debug(`Invalid stateRoot received=${(0, util_1.bytesToHex)(stateRoot)} expected=${(0, util_1.bytesToHex)(block.header.stateRoot)}`); } const msg = _errorMsg(`invalid block stateRoot, got: ${(0, util_1.bytesToHex)(stateRoot)}, want: ${(0, util_1.bytesToHex)(block.header.stateRoot)}`, vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } } if (vm.common.isActivatedEIP(6800)) { if (vm.evm.verkleAccessWitness === undefined) { throw Error(`verkleAccessWitness required if verkle (EIP-6800) is activated`); } // If verkle is activated and executing statelessly, only validate the post-state if ((await vm['_opts'].stateManager.verifyVerklePostState(vm.evm.verkleAccessWitness)) === false) { throw (0, util_1.EthereumJSErrorWithoutCode)(`Verkle post state verification failed on block ${block.header.number}`); } debug(`Verkle post state verification succeeded`); } else if (vm.common.isActivatedEIP(7864)) { if (vm.evm.binaryTreeAccessWitness === undefined) { throw Error(`binaryTreeAccessWitness required if binary tree (EIP-7864) is activated`); } // If binary tree is activated and executing statelessly, only validate the post-state if ((await vm['_opts'].stateManager.verifyBinaryTreePostState(vm.evm.binaryTreeAccessWitness)) === false) { throw (0, util_1.EthereumJSErrorWithoutCode)(`Binary tree post state verification failed on block ${block.header.number}`); } debug(`Binary tree post state verification succeeded`); } } if (enableProfiler) { // eslint-disable-next-line no-console console.timeEnd(withdrawalsRewardsCommitLabel); } const results = { receipts: result.receipts, logsBloom: result.bloom.bitvector, results: result.results, stateRoot, gasUsed: result.gasUsed, receiptsRoot: result.receiptsRoot, preimages: result.preimages, requestsHash, requests, }; const afterBlockEvent = { ...results, block }; /** * The `afterBlock` event * * @event Event: afterBlock * @type {AfterBlockEvent} * @property {AfterBlockEvent} result emits the results of processing a block */ await vm._emit('afterBlock', afterBlockEvent); if (vm.DEBUG) { debug(`Running block finished hash=${(0, util_1.bytesToHex)(block.hash())} number=${block.header.number} hardfork=${vm.common.hardfork()}`); } if (enableProfiler) { // eslint-disable-next-line no-console console.timeEnd(entireBlockLabel); const logs = vm.evm.getPerformanceLogs(); if (logs.precompiles.length === 0 && logs.opcodes.length === 0) { // eslint-disable-next-line no-console console.log('No block txs with precompile or opcode execution.'); } (0, emitEVMProfile_ts_1.emitEVMProfile)(logs.precompiles, 'Precompile performance'); (0, emitEVMProfile_ts_1.emitEVMProfile)(logs.opcodes, 'Opcodes performance'); vm.evm.clearPerformanceLogs(); } return results; } /** * Validates and applies a block, computing the results of * applying its transactions. vm method doesn't modify the * block itself. It computes the block rewards and puts * them on state (but doesn't persist the changes). * @param {Block} block * @param {RunBlockOpts} opts */ async function applyBlock(vm, block, opts) { // Validate block if (opts.skipBlockValidation !== true) { if (block.header.gasLimit >= BigInt('0x8000000000000000')) { const msg = _errorMsg('Invalid block with gas limit greater than (2^63 - 1)', vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } else { if (vm.DEBUG) { debug(`Validate block`); } // TODO: decide what block validation method is appropriate here if (opts.skipHeaderValidation !== true) { if (typeof vm.blockchain.validateHeader === 'function') { await vm.blockchain.validateHeader(block.header); } else { throw (0, util_1.EthereumJSErrorWithoutCode)('cannot validate header: blockchain has no `validateHeader` method'); } } await block.validateData(); } } if (vm.common.isActivatedEIP(4788)) { if (vm.DEBUG) { debug(`accumulate parentBeaconBlockRoot`); } await accumulateParentBeaconBlockRoot(vm, block.header.parentBeaconBlockRoot, block.header.timestamp); } if (vm.common.isActivatedEIP(2935)) { if (vm.DEBUG) { debug(`accumulate parentBlockHash `); } await accumulateParentBlockHash(vm, block.header.number, block.header.parentHash); } if (enableProfiler) { // eslint-disable-next-line no-console console.timeEnd(stateRootCPLabel); } // Apply transactions if (vm.DEBUG) { debug(`Apply transactions`); } const blockResults = await applyTransactions(vm, block, opts); if (enableProfiler) { // eslint-disable-next-line no-console console.time(withdrawalsRewardsCommitLabel); } // Add txResult preimages to the blockResults preimages // Also add the coinbase preimage if (opts.reportPreimages === true) { if (vm.evm.stateManager.getAppliedKey === undefined) { throw (0, util_1.EthereumJSErrorWithoutCode)('applyBlock: evm.stateManager.getAppliedKey can not be undefined if reportPreimages is true'); } blockResults.preimages.set((0, util_1.bytesToHex)(vm.evm.stateManager.getAppliedKey(block.header.coinbase.toBytes())), block.header.coinbase.toBytes()); for (const txResult of blockResults.results) { if (txResult.preimages !== undefined) { for (const [key, preimage] of txResult.preimages) { blockResults.preimages.set(key, preimage); } } } } if (vm.common.isActivatedEIP(4895)) { if (opts.reportPreimages === true) vm.evm.journal.startReportingPreimages(); await assignWithdrawals(vm, block); if (opts.reportPreimages === true && vm.evm.journal.preimages !== undefined) { for (const [key, preimage] of vm.evm.journal.preimages) { blockResults.preimages.set(key, preimage); } } await vm.evm.journal.cleanup(); } // Pay ommers and miners if (block.common.consensusType() === common_1.ConsensusType.ProofOfWork) { await assignBlockRewards(vm, block); } // Merge system AccessWitness with AccessWitness if (vm.common.isActivatedEIP(6800) && vm.evm.systemVerkleAccessWitness !== undefined) { vm.evm.systemVerkleAccessWitness?.commit(); if (vm.DEBUG) { debug('Verkle access witness aggregate costs:'); vm.evm.verkleAccessWitness?.debugWitnessCost(); debug('System verkle access witness aggregate costs:'); vm.evm.systemVerkleAccessWitness?.debugWitnessCost(); } vm.evm.verkleAccessWitness?.merge(vm.evm.systemVerkleAccessWitness); } if (vm.common.isActivatedEIP(7864) && vm.evm.systemBinaryTreeAccessWitness !== undefined) { vm.evm.systemBinaryTreeAccessWitness?.commit(); if (vm.DEBUG) { debug('Binary tree access witness aggregate costs:'); vm.evm.binaryTreeAccessWitness?.debugWitnessCost(); debug('System binary tree access witness aggregate costs:'); vm.evm.systemBinaryTreeAccessWitness?.debugWitnessCost(); } vm.evm.binaryTreeAccessWitness?.merge(vm.evm.systemBinaryTreeAccessWitness); } return blockResults; } /** * vm method runs the logic of EIP 2935 (save blockhashes to state) * It will put the `parentHash` of the block to the storage slot of `block.number - 1` of the history storage contract. * vm contract is used to retrieve BLOCKHASHes in EVM if EIP 2935 is activated. * In case that the previous block of `block` is pre-EIP-2935 (so we are on the EIP 2935 fork block), additionally * also add the currently available past blockhashes which are available by BLOCKHASH (so, the past 256 block hashes) * @param vm The VM to run on * @param block The current block to save the parent block hash of */ async function accumulateParentBlockHash(vm, currentBlockNumber, parentHash) { if (!vm.common.isActivatedEIP(2935)) { throw (0, util_1.EthereumJSErrorWithoutCode)('Cannot call `accumulateParentBlockHash`: EIP 2935 is not active'); } const historyAddress = new util_1.Address((0, util_1.bigIntToAddressBytes)(vm.common.param('historyStorageAddress'))); const historyServeWindow = vm.common.param('historyServeWindow'); // getAccount with historyAddress will throw error as witnesses are not bundled // but we need to put account so as to query later for slot const code = await vm.stateManager.getCode(historyAddress); if (code.length === 0) { // Exit early, system contract has no code so no storage is written return; } async function putBlockHash(vm, hash, number) { // ringKey is the key the hash is actually put in (it is a ring buffer) const ringKey = number % historyServeWindow; // generate access witness if (vm.common.isActivatedEIP(6800)) { if (vm.evm.systemVerkleAccessWitness === undefined) { throw Error(`verkleAccessWitness required if verkle (EIP-6800) is activated`); } // Add to system verkle access witness so that it doesn't warm up tx accesses vm.evm.systemVerkleAccessWitness.writeAccountStorage(historyAddress, ringKey); } else if (vm.common.isActivatedEIP(7864)) { if (vm.evm.systemBinaryTreeAccessWitness === undefined) { throw Error(`systemBinaryTreeAccessWitness required if binary tree (EIP-7864) is activated`); } // Add to system binary tree access witness so that it doesn't warm up tx accesses vm.evm.systemBinaryTreeAccessWitness.writeAccountStorage(historyAddress, ringKey); } const key = (0, util_1.setLengthLeft)((0, util_1.bigIntToBytes)(ringKey), 32); await vm.stateManager.putStorage(historyAddress, key, hash); } await putBlockHash(vm, parentHash, currentBlockNumber - util_1.BIGINT_1); // do cleanup if the code was not deployed await vm.evm.journal.cleanup(); } async function accumulateParentBeaconBlockRoot(vm, root, timestamp) { if (!vm.common.isActivatedEIP(4788)) { throw (0, util_1.EthereumJSErrorWithoutCode)('Cannot call `accumulateParentBeaconBlockRoot`: EIP 4788 is not active'); } // Save the parentBeaconBlockRoot to the beaconroot stateful precompile ring buffers const historicalRootsLength = BigInt(vm.common.param('historicalRootsLength')); const timestampIndex = timestamp % historicalRootsLength; const timestampExtended = timestampIndex + historicalRootsLength; /** * Note: (by Gabriel) * Get account will throw an error in stateless execution b/c witnesses are not bundled * But we do need an account so we are able to put the storage */ const code = await vm.stateManager.getCode(parentBeaconBlockRootAddress); if (code.length === 0) { // Exit early, system contract has no code so no storage is written // TODO: verify with Gabriel that this is fine regarding verkle (should we put an empty account?) return; } await vm.stateManager.putStorage(parentBeaconBlockRootAddress, (0, util_1.setLengthLeft)((0, util_1.bigIntToBytes)(timestampIndex), 32), (0, util_1.bigIntToBytes)(timestamp)); await vm.stateManager.putStorage(parentBeaconBlockRootAddress, (0, util_1.setLengthLeft)((0, util_1.bigIntToBytes)(timestampExtended), 32), root); // do cleanup if the code was not deployed await vm.evm.journal.cleanup(); } /** * Applies the transactions in a block, computing the receipts * as well as gas usage and some relevant data. vm method is * side-effect free (it doesn't modify the block nor the state). * @param {Block} block * @param {RunBlockOpts} opts */ async function applyTransactions(vm, block, opts) { if (enableProfiler) { // eslint-disable-next-line no-console console.time(processTxsLabel); } const bloom = new index_ts_1.Bloom(undefined, vm.common); // the total amount of gas used processing these transactions let gasUsed = util_1.BIGINT_0; let receiptTrie = undefined; if (block.transactions.length !== 0) { receiptTrie = new mpt_1.MerklePatriciaTrie({ common: vm.common }); } const receipts = []; const txResults = []; /* * Process transactions */ for (let txIdx = 0; txIdx < block.transactions.length; txIdx++) { const tx = block.transactions[txIdx]; let maxGasLimit; if (vm.common.isActivatedEIP(1559)) { maxGasLimit = block.header.gasLimit * vm.common.param('elasticityMultiplier'); } else { maxGasLimit = block.header.gasLimit; } const gasLimitIsHigherThanBlock = maxGasLimit < tx.gasLimit + gasUsed; if (gasLimitIsHigherThanBlock) { const msg = _errorMsg('tx has a higher gas limit than the block', vm, block); throw (0, util_1.EthereumJSErrorWithoutCode)(msg); } // Run the tx through the VM const { skipBalance, skipNonce, skipHardForkValidation, reportPreimages } = opts; const txRes = await (0, index_ts_2.runTx)(vm, { tx, block, skipBalance, skipNonce, skipHardForkValidation, blockGasUsed: gasUsed, reportPreimages, }); txResults.push(txRes); if (vm.DEBUG) { debug('-'.repeat(100)); } // Add to total block gas usage gasUsed += txRes.totalGasSpent; if (vm.DEBUG) { debug(`Add tx gas used (${txRes.totalGasSpent}) to total block gas usage (-> ${gasUsed})`); } // Combine blooms via bitwise OR bloom.or(txRes.bloom); // Add receipt to trie to later calculate receipt root receipts.push(txRes.receipt); const encodedReceipt = encodeReceipt(txRes.receipt, tx.type); await receiptTrie.put(rlp_1.RLP.encode(txIdx), encodedReceipt); } if (enableProfiler) { // eslint-disable-next-line no-console console.timeEnd(processTxsLabel); } const receiptsRoot = receiptTrie !== undefined ? receiptTrie.root() : util_1.KECCAK256_RLP; return { bloom, gasUsed, preimages: new Map(), receiptsRoot, receipts, results: txResults, }; } async function assignWithdrawals(vm, block) { const withdrawals = block.withdrawals; for (const withdrawal of withdrawals) { const { address, amount } = withdrawal; // Withdrawal amount is represented in Gwei so needs to be // converted to wei // Note: event if amount is 0, still reward the account // such that the account is touched and marked for cleanup if it is empty await rewardAccount(vm.evm, address, amount * util_1.GWEI_TO_WEI, vm.common); } } /** * Calculates block rewards for miner and ommers and puts * the updated balances of their accounts to state. */ async function assignBlockRewards(vm, block) { if (vm.DEBUG) { debug(`Assign block rewards`); } const minerReward = vm.common.param('minerReward'); const ommers = block.uncleHeaders; // Reward ommers for (const ommer of ommers) { const reward = calculateOmmerReward(ommer.number, block.header.number, minerReward); const account = await rewardAccount(vm.evm, ommer.coinbase, reward, vm.common); if (vm.DEBUG) { debug(`Add uncle reward ${reward} to account ${ommer.coinbase} (-> ${account.balance})`); } } // Reward miner const reward = calculateMinerReward(minerReward, ommers.length); const account = await rewardAccount(vm.evm, block.header.coinbase, reward, vm.common); if (vm.DEBUG) { debug(`Add miner reward ${reward} to account ${block.header.coinbase} (-> ${account.balance})`); } } function calculateOmmerReward(ommerBlockNumber, blockNumber, minerReward) { const heightDiff = blockNumber - ommerBlockNumber; let reward = ((util_1.BIGINT_8 - heightDiff) * minerReward) / util_1.BIGINT_8; if (reward < util_1.BIGINT_0) { reward = util_1.BIGINT_0; } return reward; } function calculateMinerReward(minerReward, ommersNum) { // calculate nibling reward const niblingReward = minerReward / BigInt(32); const totalNiblingReward = niblingReward * BigInt(ommersNum); const reward = minerReward + totalNiblingReward; return reward; } async function rewardAccount(evm, address, reward, common) { let account = await evm.stateManager.getAccount(address); if (account === undefined) { if (common.isActivatedEIP(6800) === true && reward !== util_1.BIGINT_0) { if (evm.systemVerkleAccessWitness === undefined) { throw Error(`verkleAccessWitness required if verkle (EIP-6800) is activated`); } evm.systemVerkleAccessWitness.writeAccountHeader(address); } if (common.isActivatedEIP(7864) === true && reward !== util_1.BIGINT_0) { if (evm.systemBinaryTreeAccessWitness === undefined) { throw Error(`systemBinaryTreeAccessWitness required if binary tree (EIP-7864) is activated`); } evm.systemBinaryTreeAccessWitness.writeAccountHeader(address); } account = new util_1.Account(); } account.balance += reward; await evm.journal.putAccount(address, account); if (common.isActivatedEIP(6800) === true && reward !== util_1.BIGINT_0) { if (evm.systemVerkleAccessWitness === undefined) { throw Error(`verkleAccessWitness required if verkle (EIP-6800) is activated`); } // use vm utility to build access but the computed gas is not charged and hence free evm.systemVerkleAccessWitness.writeAccountBasicData(address); evm.systemVerkleAccessWitness.readAccountCodeHash(address); } if (common.isActivatedEIP(7864) === true && reward !== util_1.BIGINT_0) { if (evm.systemBinaryTreeAccessWitness === undefined) { throw Error(`systemBinaryTreeAccessWitness required if binary tree (EIP-7864) is activated`); } evm.systemBinaryTreeAccessWitness.writeAccountBasicData(address); evm.systemBinaryTreeAccessWitness.readAccountCodeHash(address); } return account; } /** * Returns the encoded tx receipt. */ function encodeReceipt(receipt, txType) { const encoded = rlp_1.RLP.encode([ receipt.stateRoot ?? (receipt.status === 0 ? Uint8Array.from([]) : (0, util_1.hexToBytes)('0x01')), (0, util_1.bigIntToBytes)(receipt.cumulativeBlockGasUsed), receipt.bitvector, receipt.logs, ]); if (txType === tx_1.TransactionType.Legacy) { return encoded; } // Serialize receipt according to EIP-2718: // `typed-receipt = tx-type || receipt-data` return (0, util_1.concatBytes)((0, util_1.intToBytes)(txType), encoded); } /** * Apply the DAO fork changes to the VM */ async function _applyDAOHardfork(evm) { const state = evm.stateManager; /* DAO account list */ const DAOAccountList = DAOConfig.DAOAccounts; const DAORefundContract = DAOConfig.DAORefundContract; const DAORefundContractAddress = new util_1.Address((0, util_1.unprefixedHexToBytes)(DAORefundContract)); if ((await state.getAccount(DAORefundContractAddress)) === undefined) { await evm.journal.putAccount(DAORefundContractAddress, new util_1.Account()); } let DAORefundAccount = await state.getAccount(DAORefundContractAddress); if (DAORefundAccount === undefined) { DAORefundAccount = new util_1.Account(); } for (const addr of DAOAccountList) { // retrieve the account and add it to the DAO's Refund accounts' balance. const address = new util_1.Address((0, util_1.unprefixedHexToBytes)(addr)); let account = await state.getAccount(address); if (account === undefined) { account = new util_1.Account(); } DAORefundAccount.balance += account.balance; // clear the accounts' balance account.balance = util_1.BIGINT_0; await evm.journal.putAccount(address, account); } // finally, put the Refund Account await evm.journal.putAccount(DAORefundContractAddress, DAORefundAccount); } async function _genTxTrie(block) { if (block.transactions.length === 0) { return util_1.KECCAK256_RLP; } const trie = new mpt_1.MerklePatriciaTrie({ common: block.common }); for (const [i, tx] of block.transactions.entries()) { await trie.put(rlp_1.RLP.encode(i), tx.serialize()); } return trie.root(); } /** * Internal helper function to create an annotated error message * * @param msg Base error message * @hidden */ function _errorMsg(msg, vm, block) { const blockErrorStr = 'errorStr' in block ? block.errorStr() : 'block'; const errorMsg = `${msg} (${vm.errorStr()} -> ${blockErrorStr})`; return errorMsg; } const DAOConfig = { DAOAccounts: [ 'd4fe7bc31cedb7bfb8a345f31e668033056b2728', 'b3fb0e5aba0e20e5c49d252dfd30e102b171a425', '2c19c7f9ae8b751e37aeb2d93a699722395ae18f', 'ecd135fa4f61a655311e86238c92adcd779555d2', '1975bd06d486162d5dc297798dfc41edd5d160a7', 'a3acf3a1e16b1d7c315e23510fdd7847b48234f6', '319f70bab6845585f412ec7724b744fec6095c85', '06706dd3f2c9abf0a21ddcc6941d9b86f0596936', '5c8536898fbb74fc7445814902fd08422eac56d0', '6966ab0d485353095148a2155858910e0965b6f9', '779543a0491a837ca36ce8c635d6154e3c4911a6', '2a5ed960395e2a49b1c758cef4aa15213cfd874c', '5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5', '9c50426be05db97f5d64fc54bf89eff947f0a321', '200450f06520bdd6c527622a273333384d870efb', 'be8539bfe837b67d1282b2b1d61c3f723966f049', '6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb', 'f1385fb24aad0cd7432824085e42aff90886fef5', 'd1ac8b1ef1b69ff51d1d401a476e7e612414f091', '8163e7fb499e90f8544ea62bbf80d21cd26d9efd', '51e0ddd9998364a2eb38588679f0d2c42653e4a6', '627a0a960c079c21c34f7612d5d230e01b4ad4c7', 'f0b1aa0eb660754448a7937c022e30aa692fe0c5', '24c4d950dfd4dd1902bbed3508144a54542bba94', '9f27daea7aca0aa0446220b98d028715e3bc803d', 'a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90', 'd9aef3a1e38a39c16b31d1ace71bca8ef58d315b', '63ed5a272de2f6d968408b4acb9024f4cc208ebf', '6f6704e5a10332af6672e50b3d9754dc460dfa4d', '77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6', '492ea3bb0f3315521c31f273e565b868fc090f17', '0ff30d6de14a8224aa97b78aea5388d1c51c1f00', '9ea779f907f0b315b364b0cfc39a0fde5b02a416', 'ceaeb481747ca6c540a000c1f3641f8cef161fa7', 'cc34673c6c40e791051898567a1222daf90be287', '579a80d909f346fbfb1189493f521d7f48d52238', 'e308bd1ac5fda103967359b2712dd89deffb7973', '4cb31628079fb14e4bc3cd5e30c2f7489b00960c', 'ac1ecab32727358dba8962a0f3b261731aad9723', '4fd6ace747f06ece9c49699c7cabc62d02211f75', '440c59b325d2997a134c2c7c60a8c61611212bad', '4486a3d68fac6967006d7a517b889fd3f98c102b', '9c15b54878ba618f494b38f0ae7443db6af648ba', '27b137a85656544b1ccb5a0f2e561a5703c6a68f', '21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241', '23b75c2f6791eef49c69684db4c6c1f93bf49a50', '1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b', 'b9637156d330c0d605a791f1c31ba5890582fe1c', '6131c42fa982e56929107413a9d526fd99405560', '1591fc0f688c81fbeb17f5426a162a7024d430c2', '542a9515200d14b68e934e9830d91645a980dd7a', 'c4bbd073882dd2add2424cf47d35213405b01324', '782495b7b3355efb2833d56ecb34dc22ad7dfcc4', '58b95c9a9d5d26825e70a82b6adb139d3fd829eb', '3ba4d81db016dc2890c81f3acec2454bff5aada5', 'b52042c8ca3f8aa246fa79c3feaa3d959347c0ab', 'e4ae1efdfc53b73893af49113d8694a057b9c0d1', '3c02a7bc0391e86d91b7d144e61c2c01a25a79c5', '0737a6b837f97f46ebade41b9bc3e1c509c85c53', '97f43a37f595ab5dd318fb46e7a155eae057317a', '52c5317c848ba20c7504cb2c8052abd1fde29d03', '4863226780fe7c0356454236d3b1c8792785748d', '5d2b2e6fcbe3b11d26b525e085ff818dae332479', '5f9f3392e9f62f63b8eac0beb55541fc8627f42c', '057b56736d32b86616a10f619859c6cd6f59092a', '9aa008f65de0b923a2a4f02012ad034a5e2e2192', '304a554a310c7e546dfe434669c62820b7d83490', '914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79', '4deb0033bb26bc534b197e61d19e0733e5679784', '07f5c1e1bc2c93e0402f23341973a0e043f7bf8a', '35a051a0010aba705c9008d7a7eff6fb88f6ea7b', '4fa802324e929786dbda3b8820dc7834e9134a2a', '9da397b9e80755301a3b32173283a91c0ef6c87e', '8d9edb3054ce5c5774a420ac37ebae0ac02343c6', '0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9', '5dc28b15dffed94048d73806ce4b7a4612a1d48f', 'bcf899e6c7d9d5a215ab1e3444c86806fa854c76', '12e626b0eebfe86a56d633b9864e389b45dcb260', 'a2f1ccba9395d7fcb155bba8bc92db9bafaeade7', 'ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5', 'd164b088bd9108b60d0ca3751da4bceb207b0782', '6231b6d0d5e77fe001c2a460bd9584fee60d409b', '1cba23d343a983e9b5cfd19496b9a9701ada385f', 'a82f360a8d3455c5c41366975bde739c37bfeb8a', '9fcd2deaff372a39cc679d5c5e4de7bafb0b1339', '005f5cee7a43331d5a3d3eec71305925a62f34b6', '0e0da70933f4c7849fc0d203f5d1d43b9ae4532d', 'd131637d5275fd1a68a3200f4ad25c71a2a9522e', 'bc07118b9ac290e4622f5e77a0853539789effbe', '47e7aa56d6bdf3f36be34619660de61275420af8', 'acd87e28b0c9d1254e868b81cba4cc20d9a32225', 'adf80daec7ba8dcf15392f1ac611fff65d94f880', '5524c55fb03cf21f549444ccbecb664d0acad706', '40b803a9abce16f50f36a77ba41180eb90023925', 'fe24cdd8648121a43a7c86d289be4dd2951ed49f', '17802f43a0137c506ba92291391a8a8f207f487d', '253488078a4edf4d6f42f113d1e62836a942cf1a', '86af3e9626fce1957c82e88cbf04ddf3a2ed7915', 'b136707642a4ea12fb4bae820f03d2562ebff487', 'dbe9b615a3ae8709af8b93336ce9b477e4ac0940', 'f14c14075d6c4ed84b86798af0956deef67365b5', 'ca544e5c4687d109611d0f8f928b53a25af72448', 'aeeb8ff27288bdabc0fa5ebb731b6f409507516c', 'cbb9d3703e651b0d496cdefb8b92c25aeb2171f7', '6d87578288b6cb5549d5076a207456a1f6a63dc0', 'b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e', 'accc230e8a6e5be9160b8cdf2864dd2a001c28b6', '2b3455ec7fedf16e646268bf88846bd7a2319bb2', '4613f3bca5c44ea06337a9e439fbc6d42e501d0a', 'd343b217de44030afaa275f54d31a9317c7f441e', '84ef4b2357079cd7a7c69fd7a37cd0609a679106', 'da2fef9e4a3230988ff17df2165440f37e8b1708', 'f4c64518ea10f995918a454158c6b61407ea345c', '7602b46df5390e432ef1c307d4f2c9ff6d65cc97', 'bb9bc244d798123fde783fcc1c72d3bb8c189413', '807640a13483f8ac783c557fcdf27be11ea4ac7a', ], DAORefundContract: 'bf4ed7b27f1d666546e30d74d50d173d20bca754', }; //# sourceMappingURL=runBlock.js.map