Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ethereumjs/vm

Package Overview
Dependencies
Maintainers
4
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ethereumjs/vm - npm Package Compare versions

Comparing version 7.1.0 to 7.2.0

4

dist/cjs/bloom/index.d.ts

@@ -0,7 +1,9 @@

import type { Common } from '@ethereumjs/common';
export declare class Bloom {
bitvector: Uint8Array;
keccakFunction: (msg: Uint8Array) => Uint8Array;
/**
* Represents a Bloom filter.
*/
constructor(bitvector?: Uint8Array);
constructor(bitvector?: Uint8Array, common?: Common);
/**

@@ -8,0 +10,0 @@ * Adds an element to a bit vector of a 64 byte bloom filter.

@@ -11,3 +11,9 @@ "use strict";

*/
constructor(bitvector) {
constructor(bitvector, common) {
if (common?.customCrypto.keccak256 !== undefined) {
this.keccakFunction = common.customCrypto.keccak256;
}
else {
this.keccakFunction = keccak_js_1.keccak256;
}
if (!bitvector) {

@@ -27,3 +33,3 @@ this.bitvector = (0, util_1.zeros)(BYTE_SIZE);

add(e) {
e = (0, keccak_js_1.keccak256)(e);
e = this.keccakFunction(e);
const mask = 2047; // binary 11111111111

@@ -43,3 +49,3 @@ for (let i = 0; i < 3; i++) {

check(e) {
e = (0, keccak_js_1.keccak256)(e);
e = this.keccakFunction(e);
const mask = 2047; // binary 11111111111

@@ -46,0 +52,0 @@ let match = true;

@@ -93,3 +93,3 @@ "use strict";

async transactionsTrie() {
return block_1.Block.genTransactionsTrieRoot(this.transactions);
return block_1.Block.genTransactionsTrieRoot(this.transactions, new trie_1.Trie({ common: this.vm.common }));
}

@@ -100,3 +100,3 @@ /**

logsBloom() {
const bloom = new index_js_1.Bloom();
const bloom = new index_js_1.Bloom(undefined, this.vm.common);
for (const txResult of this.transactionResults) {

@@ -115,3 +115,3 @@ // Combine blooms via bitwise OR

}
const receiptTrie = new trie_1.Trie();
const receiptTrie = new trie_1.Trie({ common: this.vm.common });
for (const [i, txResult] of this.transactionResults.entries()) {

@@ -133,3 +133,3 @@ const tx = this.transactions[i];

: util_1.Address.zero();
await (0, runBlock_js_1.rewardAccount)(this.vm.evm, coinbase, reward);
await (0, runBlock_js_1.rewardAccount)(this.vm.evm, coinbase, reward, this.vm.common);
}

@@ -150,3 +150,3 @@ /**

// converted to wei
await (0, runBlock_js_1.rewardAccount)(this.vm.evm, address, amount * util_1.GWEI_TO_WEI);
await (0, runBlock_js_1.rewardAccount)(this.vm.evm, address, amount * util_1.GWEI_TO_WEI, this.vm.common);
}

@@ -245,3 +245,3 @@ }

const withdrawalsRoot = this.withdrawals
? await block_1.Block.genWithdrawalsTrieRoot(this.withdrawals)
? await block_1.Block.genWithdrawalsTrieRoot(this.withdrawals, new trie_1.Trie({ common: this.vm.common }))
: undefined;

@@ -248,0 +248,0 @@ const receiptTrie = await this.receiptTrie();

@@ -5,2 +5,3 @@ import { TransactionType } from '@ethereumjs/tx';

import type { VM } from './vm.js';
import type { Common } from '@ethereumjs/common';
import type { EVMInterface } from '@ethereumjs/evm';

@@ -13,3 +14,3 @@ /**

export declare function calculateMinerReward(minerReward: bigint, ommersNum: number): bigint;
export declare function rewardAccount(evm: EVMInterface, address: Address, reward: bigint): Promise<Account>;
export declare function rewardAccount(evm: EVMInterface, address: Address, reward: bigint, common?: Common): Promise<Account>;
/**

@@ -16,0 +17,0 @@ * Returns the encoded tx receipt.

@@ -7,2 +7,3 @@ "use strict";

const rlp_1 = require("@ethereumjs/rlp");
const statemanager_1 = require("@ethereumjs/statemanager");
const trie_1 = require("@ethereumjs/trie");

@@ -78,2 +79,17 @@ const tx_1 = require("@ethereumjs/tx");

}
if (this.common.isActivatedEIP(6800)) {
if (!(state instanceof statemanager_1.StatelessVerkleStateManager)) {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`);
}
if (this.DEBUG) {
debug(`Initializing StatelessVerkleStateManager executionWitness`);
}
;
this._opts.stateManager.initVerkleExecutionWitness(block.executionWitness);
}
else {
if (state instanceof statemanager_1.StatelessVerkleStateManager) {
throw Error(`StatelessVerkleStateManager can't execute merkle blocks`);
}
}
// check for DAO support and if we should apply the DAO fork

@@ -133,3 +149,4 @@ if (this.common.hardforkIsActiveOnBlock(common_1.Hardfork.Dao, block.header.number) === true &&

}
else {
else if (this.common.isActivatedEIP(6800) === false) {
// Only validate the following headers if verkle blocks aren't activated
if ((0, util_1.equalsBytes)(result.receiptsRoot, block.header.receiptTrie) === false) {

@@ -160,6 +177,13 @@ if (this.DEBUG) {

}
const msg = _errorMsg('invalid block stateRoot', this, block);
const msg = _errorMsg(`invalid block stateRoot, got: ${(0, util_1.bytesToHex)(stateRoot)}, want: ${(0, util_1.bytesToHex)(block.header.stateRoot)}`, this, block);
throw new Error(msg);
}
}
else if (this.common.isActivatedEIP(6800) === true) {
// If verkle is activated, only validate the post-state
if (this._opts.stateManager.verifyPostState() === false) {
throw new Error(`Verkle post state verification failed on block ${block.header.number}`);
}
debug(`Verkle post state verification succeeded`);
}
if (enableProfiler) {

@@ -276,3 +300,3 @@ // eslint-disable-next-line no-console

if ((await this.stateManager.getAccount(parentBeaconBlockRootAddress)) === undefined) {
await this.stateManager.putAccount(parentBeaconBlockRootAddress, new util_1.Account());
await this.evm.journal.putAccount(parentBeaconBlockRootAddress, new util_1.Account());
}

@@ -295,3 +319,3 @@ await this.stateManager.putContractStorage(parentBeaconBlockRootAddress, (0, util_1.setLengthLeft)((0, util_1.bigIntToBytes)(timestampIndex), 32), (0, util_1.bigIntToBytes)(timestamp));

}
const bloom = new index_js_1.Bloom();
const bloom = new index_js_1.Bloom(undefined, this.common);
// the total amount of gas used processing these transactions

@@ -301,3 +325,3 @@ let gasUsed = util_1.BIGINT_0;

if (block.transactions.length !== 0) {
receiptTrie = new trie_1.Trie();
receiptTrie = new trie_1.Trie({ common: this.common });
}

@@ -370,3 +394,3 @@ const receipts = [];

// such that the account is touched and marked for cleanup if it is empty
await rewardAccount(this.evm, address, amount * util_1.GWEI_TO_WEI);
await rewardAccount(this.evm, address, amount * util_1.GWEI_TO_WEI, this.common);
}

@@ -387,3 +411,3 @@ }

const reward = calculateOmmerReward(ommer.number, block.header.number, minerReward);
const account = await rewardAccount(this.evm, ommer.coinbase, reward);
const account = await rewardAccount(this.evm, ommer.coinbase, reward, this.common);
if (this.DEBUG) {

@@ -395,3 +419,3 @@ debug(`Add uncle reward ${reward} to account ${ommer.coinbase} (-> ${account.balance})`);

const reward = calculateMinerReward(minerReward, ommers.length);
const account = await rewardAccount(this.evm, block.header.coinbase, reward);
const account = await rewardAccount(this.evm, block.header.coinbase, reward, this.common);
if (this.DEBUG) {

@@ -417,5 +441,9 @@ debug(`Add miner reward ${reward} to account ${block.header.coinbase} (-> ${account.balance})`);

exports.calculateMinerReward = calculateMinerReward;
async function rewardAccount(evm, address, reward) {
async function rewardAccount(evm, address, reward, common) {
let account = await evm.stateManager.getAccount(address);
if (account === undefined) {
if (common?.isActivatedEIP(6800) === true) {
;
evm.stateManager.accessWitness.touchAndChargeProofOfAbsence(address);
}
account = new util_1.Account();

@@ -425,2 +453,7 @@ }

await evm.journal.putAccount(address, account);
if (common?.isActivatedEIP(6800) === true) {
// use this utility to build access but the computed gas is not charged and hence free
;
evm.stateManager.accessWitness.touchTxExistingAndComputeGas(address, { sendsValue: true });
}
return account;

@@ -483,3 +516,3 @@ }

}
const trie = new trie_1.Trie();
const trie = new trie_1.Trie({ common: block.common });
for (const [i, tx] of block.transactions.entries()) {

@@ -486,0 +519,0 @@ await trie.put(rlp_1.RLP.encode(i), tx.serialize());

@@ -6,2 +6,3 @@ "use strict";

const common_1 = require("@ethereumjs/common");
const statemanager_1 = require("@ethereumjs/statemanager");
const tx_1 = require("@ethereumjs/tx");

@@ -17,4 +18,8 @@ const util_1 = require("@ethereumjs/util");

const balanceNonceLabel = 'Balance/Nonce checks and update';
const executionLabel = 'Execution';
const logsGasBalanceLabel = 'Logs, gas usage, account/miner balances';
const cleanupAndReceiptsLabel = 'Accounts clean up, access list, journal/cache cleanup, receipts';
const accountsCleanUpLabel = 'Accounts clean up';
const accessListLabel = 'Access list label';
const journalCacheCleanUpLabel = 'Journal/cache cleanup';
const receiptsLabel = 'Receipts';
const entireTxLabel = 'Entire tx';

@@ -144,2 +149,10 @@ /**

const state = this.stateManager;
let stateAccesses;
if (this.common.isActivatedEIP(6800)) {
if (!(this.stateManager instanceof statemanager_1.StatelessVerkleStateManager)) {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`);
}
stateAccesses = this.stateManager.accessWitness;
}
let txAccesses = stateAccesses?.shallowCopy();
const { tx, block } = opts;

@@ -194,3 +207,3 @@ if (!block) {

if (maxFeePerGas < baseFeePerGas) {
const msg = _errorMsg(`Transaction's maxFeePerGas (${maxFeePerGas}) is less than the block's baseFeePerGas (${baseFeePerGas})`, this, block, tx);
const msg = _errorMsg(`Transaction's ${'maxFeePerGas' in tx ? 'maxFeePerGas' : 'gasPrice'} (${maxFeePerGas}) is less than the block's baseFeePerGas (${baseFeePerGas})`, this, block, tx);
throw new Error(msg);

@@ -220,4 +233,20 @@ }

}
let upfrontAwGas = util_1.BIGINT_0;
if (this.common.isActivatedEIP(6800)) {
upfrontAwGas += txAccesses.touchTxOriginAndComputeGas(caller);
const sendsValue = tx.value !== util_1.BIGINT_0;
if (tx.to !== undefined) {
upfrontAwGas += txAccesses.touchTxExistingAndComputeGas(tx.to, { sendsValue });
debug(`Sender upfront awGas requirement for non contract creation tx is ${upfrontAwGas}`);
}
else {
const contractTo = new util_1.Address((0, util_1.generateAddress)(caller.bytes, (0, util_1.bigIntToBytes)(nonce)));
upfrontAwGas += txAccesses.touchAndChargeContractCreateInit(contractTo, { sendsValue });
debug(`Sender upfront awGas requirement is contract creation at=${(0, util_1.short)(contractTo.bytes)} is ${upfrontAwGas}`);
}
// reset txAccesses to remove the caches so that access gas can be correctly consumed inside the evm run
txAccesses = stateAccesses?.shallowCopy();
}
// Check balance against upfront tx cost
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas);
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas) + upfrontAwGas;
if (balance < upFrontCost) {

@@ -322,7 +351,7 @@ if (opts.skipBalance === true && fromAccount.balance < upFrontCost) {

}
let executionTimerPrecise;
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(balanceNonceLabel);
// eslint-disable-next-line no-console
console.log('[ For execution see detailed table output ]');
executionTimerPrecise = performance.now();
}

@@ -345,5 +374,13 @@ /*

blobVersionedHashes,
accessWitness: txAccesses,
}));
if (this.common.isActivatedEIP(6800)) {
stateAccesses?.merge(txAccesses);
}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.log(`${executionLabel}: ${performance.now() - executionTimerPrecise}ms`);
// eslint-disable-next-line no-console
console.log('[ For execution details see table output ]');
// eslint-disable-next-line no-console
console.time(logsGasBalanceLabel);

@@ -363,3 +400,3 @@ }

// Generate the bloom for the tx
results.bloom = txLogsBloom(results.execResult.logs);
results.bloom = txLogsBloom(results.execResult.logs, this.common);
if (this.DEBUG) {

@@ -417,2 +454,6 @@ debug(`Generated tx bloom with logs=${results.execResult.logs?.length}`);

if (minerAccount === undefined) {
if (this.common.isActivatedEIP(6800)) {
;
state.accessWitness.touchAndChargeProofOfAbsence(miner);
}
minerAccount = new util_1.Account();

@@ -426,2 +467,9 @@ }

minerAccount.balance += results.minerValue;
if (this.common.isActivatedEIP(6800)) {
// use this utility to build access but the computed gas is not charged and hence free
;
state.accessWitness.touchTxExistingAndComputeGas(miner, {
sendsValue: true,
});
}
// Put the miner account into the state. If the balance of the miner account remains zero, note that

@@ -438,3 +486,3 @@ // the state.putAccount function puts this into the "touched" accounts. This will thus be removed when

// eslint-disable-next-line no-console
console.time(cleanupAndReceiptsLabel);
console.time(accountsCleanUpLabel);
}

@@ -459,2 +507,8 @@ /*

}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(accountsCleanUpLabel);
// eslint-disable-next-line no-console
console.time(accessListLabel);
}
if (opts.reportAccessList === true && this.common.isActivatedEIP(2930)) {

@@ -477,4 +531,16 @@ // Convert the Map to the desired type

}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(accessListLabel);
// eslint-disable-next-line no-console
console.time(journalCacheCleanUpLabel);
}
await this.evm.journal.cleanup();
state.originalStorageCache.clear();
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(journalCacheCleanUpLabel);
// eslint-disable-next-line no-console
console.time(receiptsLabel);
}
// Generate the tx receipt

@@ -486,3 +552,3 @@ const gasUsed = opts.blockGasUsed !== undefined ? opts.blockGasUsed : block.header.gasUsed;

// eslint-disable-next-line no-console
console.timeEnd(cleanupAndReceiptsLabel);
console.timeEnd(receiptsLabel);
}

@@ -507,4 +573,4 @@ /**

*/
function txLogsBloom(logs) {
const bloom = new index_js_1.Bloom();
function txLogsBloom(logs, common) {
const bloom = new index_js_1.Bloom(undefined, common);
if (logs) {

@@ -511,0 +577,0 @@ for (let i = 0; i < logs.length; i++) {

@@ -0,7 +1,9 @@

import type { Common } from '@ethereumjs/common';
export declare class Bloom {
bitvector: Uint8Array;
keccakFunction: (msg: Uint8Array) => Uint8Array;
/**
* Represents a Bloom filter.
*/
constructor(bitvector?: Uint8Array);
constructor(bitvector?: Uint8Array, common?: Common);
/**

@@ -8,0 +10,0 @@ * Adds an element to a bit vector of a 64 byte bloom filter.

@@ -8,3 +8,9 @@ import { zeros } from '@ethereumjs/util';

*/
constructor(bitvector) {
constructor(bitvector, common) {
if (common?.customCrypto.keccak256 !== undefined) {
this.keccakFunction = common.customCrypto.keccak256;
}
else {
this.keccakFunction = keccak256;
}
if (!bitvector) {

@@ -24,3 +30,3 @@ this.bitvector = zeros(BYTE_SIZE);

add(e) {
e = keccak256(e);
e = this.keccakFunction(e);
const mask = 2047; // binary 11111111111

@@ -40,3 +46,3 @@ for (let i = 0; i < 3; i++) {

check(e) {
e = keccak256(e);
e = this.keccakFunction(e);
const mask = 2047; // binary 11111111111

@@ -43,0 +49,0 @@ let match = true;

@@ -90,3 +90,3 @@ import { Block } from '@ethereumjs/block';

async transactionsTrie() {
return Block.genTransactionsTrieRoot(this.transactions);
return Block.genTransactionsTrieRoot(this.transactions, new Trie({ common: this.vm.common }));
}

@@ -97,3 +97,3 @@ /**

logsBloom() {
const bloom = new Bloom();
const bloom = new Bloom(undefined, this.vm.common);
for (const txResult of this.transactionResults) {

@@ -112,3 +112,3 @@ // Combine blooms via bitwise OR

}
const receiptTrie = new Trie();
const receiptTrie = new Trie({ common: this.vm.common });
for (const [i, txResult] of this.transactionResults.entries()) {

@@ -130,3 +130,3 @@ const tx = this.transactions[i];

: Address.zero();
await rewardAccount(this.vm.evm, coinbase, reward);
await rewardAccount(this.vm.evm, coinbase, reward, this.vm.common);
}

@@ -147,3 +147,3 @@ /**

// converted to wei
await rewardAccount(this.vm.evm, address, amount * GWEI_TO_WEI);
await rewardAccount(this.vm.evm, address, amount * GWEI_TO_WEI, this.vm.common);
}

@@ -242,3 +242,3 @@ }

const withdrawalsRoot = this.withdrawals
? await Block.genWithdrawalsTrieRoot(this.withdrawals)
? await Block.genWithdrawalsTrieRoot(this.withdrawals, new Trie({ common: this.vm.common }))
: undefined;

@@ -245,0 +245,0 @@ const receiptTrie = await this.receiptTrie();

@@ -5,2 +5,3 @@ import { TransactionType } from '@ethereumjs/tx';

import type { VM } from './vm.js';
import type { Common } from '@ethereumjs/common';
import type { EVMInterface } from '@ethereumjs/evm';

@@ -13,3 +14,3 @@ /**

export declare function calculateMinerReward(minerReward: bigint, ommersNum: number): bigint;
export declare function rewardAccount(evm: EVMInterface, address: Address, reward: bigint): Promise<Account>;
export declare function rewardAccount(evm: EVMInterface, address: Address, reward: bigint, common?: Common): Promise<Account>;
/**

@@ -16,0 +17,0 @@ * Returns the encoded tx receipt.

import { Block } from '@ethereumjs/block';
import { ConsensusType, Hardfork } from '@ethereumjs/common';
import { RLP } from '@ethereumjs/rlp';
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager';
import { Trie } from '@ethereumjs/trie';

@@ -74,2 +75,17 @@ import { TransactionType } from '@ethereumjs/tx';

}
if (this.common.isActivatedEIP(6800)) {
if (!(state instanceof StatelessVerkleStateManager)) {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`);
}
if (this.DEBUG) {
debug(`Initializing StatelessVerkleStateManager executionWitness`);
}
;
this._opts.stateManager.initVerkleExecutionWitness(block.executionWitness);
}
else {
if (state instanceof StatelessVerkleStateManager) {
throw Error(`StatelessVerkleStateManager can't execute merkle blocks`);
}
}
// check for DAO support and if we should apply the DAO fork

@@ -129,3 +145,4 @@ if (this.common.hardforkIsActiveOnBlock(Hardfork.Dao, block.header.number) === true &&

}
else {
else if (this.common.isActivatedEIP(6800) === false) {
// Only validate the following headers if verkle blocks aren't activated
if (equalsBytes(result.receiptsRoot, block.header.receiptTrie) === false) {

@@ -156,6 +173,13 @@ if (this.DEBUG) {

}
const msg = _errorMsg('invalid block stateRoot', this, block);
const msg = _errorMsg(`invalid block stateRoot, got: ${bytesToHex(stateRoot)}, want: ${bytesToHex(block.header.stateRoot)}`, this, block);
throw new Error(msg);
}
}
else if (this.common.isActivatedEIP(6800) === true) {
// If verkle is activated, only validate the post-state
if (this._opts.stateManager.verifyPostState() === false) {
throw new Error(`Verkle post state verification failed on block ${block.header.number}`);
}
debug(`Verkle post state verification succeeded`);
}
if (enableProfiler) {

@@ -271,3 +295,3 @@ // eslint-disable-next-line no-console

if ((await this.stateManager.getAccount(parentBeaconBlockRootAddress)) === undefined) {
await this.stateManager.putAccount(parentBeaconBlockRootAddress, new Account());
await this.evm.journal.putAccount(parentBeaconBlockRootAddress, new Account());
}

@@ -289,3 +313,3 @@ await this.stateManager.putContractStorage(parentBeaconBlockRootAddress, setLengthLeft(bigIntToBytes(timestampIndex), 32), bigIntToBytes(timestamp));

}
const bloom = new Bloom();
const bloom = new Bloom(undefined, this.common);
// the total amount of gas used processing these transactions

@@ -295,3 +319,3 @@ let gasUsed = BIGINT_0;

if (block.transactions.length !== 0) {
receiptTrie = new Trie();
receiptTrie = new Trie({ common: this.common });
}

@@ -364,3 +388,3 @@ const receipts = [];

// such that the account is touched and marked for cleanup if it is empty
await rewardAccount(this.evm, address, amount * GWEI_TO_WEI);
await rewardAccount(this.evm, address, amount * GWEI_TO_WEI, this.common);
}

@@ -381,3 +405,3 @@ }

const reward = calculateOmmerReward(ommer.number, block.header.number, minerReward);
const account = await rewardAccount(this.evm, ommer.coinbase, reward);
const account = await rewardAccount(this.evm, ommer.coinbase, reward, this.common);
if (this.DEBUG) {

@@ -389,3 +413,3 @@ debug(`Add uncle reward ${reward} to account ${ommer.coinbase} (-> ${account.balance})`);

const reward = calculateMinerReward(minerReward, ommers.length);
const account = await rewardAccount(this.evm, block.header.coinbase, reward);
const account = await rewardAccount(this.evm, block.header.coinbase, reward, this.common);
if (this.DEBUG) {

@@ -410,5 +434,9 @@ debug(`Add miner reward ${reward} to account ${block.header.coinbase} (-> ${account.balance})`);

}
export async function rewardAccount(evm, address, reward) {
export async function rewardAccount(evm, address, reward, common) {
let account = await evm.stateManager.getAccount(address);
if (account === undefined) {
if (common?.isActivatedEIP(6800) === true) {
;
evm.stateManager.accessWitness.touchAndChargeProofOfAbsence(address);
}
account = new Account();

@@ -418,2 +446,7 @@ }

await evm.journal.putAccount(address, account);
if (common?.isActivatedEIP(6800) === true) {
// use this utility to build access but the computed gas is not charged and hence free
;
evm.stateManager.accessWitness.touchTxExistingAndComputeGas(address, { sendsValue: true });
}
return account;

@@ -474,3 +507,3 @@ }

}
const trie = new Trie();
const trie = new Trie({ common: block.common });
for (const [i, tx] of block.transactions.entries()) {

@@ -477,0 +510,0 @@ await trie.put(RLP.encode(i), tx.serialize());

import { Block } from '@ethereumjs/block';
import { ConsensusType, Hardfork } from '@ethereumjs/common';
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager';
import { BlobEIP4844Transaction, Capability, isBlobEIP4844Tx } from '@ethereumjs/tx';
import { Account, Address, BIGINT_0, KECCAK256_NULL, bytesToHex, bytesToUnprefixedHex, equalsBytes, hexToBytes, short, } from '@ethereumjs/util';
import { Account, Address, BIGINT_0, KECCAK256_NULL, bigIntToBytes, bytesToHex, bytesToUnprefixedHex, equalsBytes, generateAddress, hexToBytes, short, } from '@ethereumjs/util';
import debugDefault from 'debug';

@@ -13,4 +14,8 @@ import { Bloom } from './bloom/index.js';

const balanceNonceLabel = 'Balance/Nonce checks and update';
const executionLabel = 'Execution';
const logsGasBalanceLabel = 'Logs, gas usage, account/miner balances';
const cleanupAndReceiptsLabel = 'Accounts clean up, access list, journal/cache cleanup, receipts';
const accountsCleanUpLabel = 'Accounts clean up';
const accessListLabel = 'Access list label';
const journalCacheCleanUpLabel = 'Journal/cache cleanup';
const receiptsLabel = 'Receipts';
const entireTxLabel = 'Entire tx';

@@ -139,2 +144,10 @@ /**

const state = this.stateManager;
let stateAccesses;
if (this.common.isActivatedEIP(6800)) {
if (!(this.stateManager instanceof StatelessVerkleStateManager)) {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`);
}
stateAccesses = this.stateManager.accessWitness;
}
let txAccesses = stateAccesses?.shallowCopy();
const { tx, block } = opts;

@@ -189,3 +202,3 @@ if (!block) {

if (maxFeePerGas < baseFeePerGas) {
const msg = _errorMsg(`Transaction's maxFeePerGas (${maxFeePerGas}) is less than the block's baseFeePerGas (${baseFeePerGas})`, this, block, tx);
const msg = _errorMsg(`Transaction's ${'maxFeePerGas' in tx ? 'maxFeePerGas' : 'gasPrice'} (${maxFeePerGas}) is less than the block's baseFeePerGas (${baseFeePerGas})`, this, block, tx);
throw new Error(msg);

@@ -215,4 +228,20 @@ }

}
let upfrontAwGas = BIGINT_0;
if (this.common.isActivatedEIP(6800)) {
upfrontAwGas += txAccesses.touchTxOriginAndComputeGas(caller);
const sendsValue = tx.value !== BIGINT_0;
if (tx.to !== undefined) {
upfrontAwGas += txAccesses.touchTxExistingAndComputeGas(tx.to, { sendsValue });
debug(`Sender upfront awGas requirement for non contract creation tx is ${upfrontAwGas}`);
}
else {
const contractTo = new Address(generateAddress(caller.bytes, bigIntToBytes(nonce)));
upfrontAwGas += txAccesses.touchAndChargeContractCreateInit(contractTo, { sendsValue });
debug(`Sender upfront awGas requirement is contract creation at=${short(contractTo.bytes)} is ${upfrontAwGas}`);
}
// reset txAccesses to remove the caches so that access gas can be correctly consumed inside the evm run
txAccesses = stateAccesses?.shallowCopy();
}
// Check balance against upfront tx cost
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas);
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas) + upfrontAwGas;
if (balance < upFrontCost) {

@@ -317,7 +346,7 @@ if (opts.skipBalance === true && fromAccount.balance < upFrontCost) {

}
let executionTimerPrecise;
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(balanceNonceLabel);
// eslint-disable-next-line no-console
console.log('[ For execution see detailed table output ]');
executionTimerPrecise = performance.now();
}

@@ -340,5 +369,13 @@ /*

blobVersionedHashes,
accessWitness: txAccesses,
}));
if (this.common.isActivatedEIP(6800)) {
stateAccesses?.merge(txAccesses);
}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.log(`${executionLabel}: ${performance.now() - executionTimerPrecise}ms`);
// eslint-disable-next-line no-console
console.log('[ For execution details see table output ]');
// eslint-disable-next-line no-console
console.time(logsGasBalanceLabel);

@@ -358,3 +395,3 @@ }

// Generate the bloom for the tx
results.bloom = txLogsBloom(results.execResult.logs);
results.bloom = txLogsBloom(results.execResult.logs, this.common);
if (this.DEBUG) {

@@ -412,2 +449,6 @@ debug(`Generated tx bloom with logs=${results.execResult.logs?.length}`);

if (minerAccount === undefined) {
if (this.common.isActivatedEIP(6800)) {
;
state.accessWitness.touchAndChargeProofOfAbsence(miner);
}
minerAccount = new Account();

@@ -421,2 +462,9 @@ }

minerAccount.balance += results.minerValue;
if (this.common.isActivatedEIP(6800)) {
// use this utility to build access but the computed gas is not charged and hence free
;
state.accessWitness.touchTxExistingAndComputeGas(miner, {
sendsValue: true,
});
}
// Put the miner account into the state. If the balance of the miner account remains zero, note that

@@ -433,3 +481,3 @@ // the state.putAccount function puts this into the "touched" accounts. This will thus be removed when

// eslint-disable-next-line no-console
console.time(cleanupAndReceiptsLabel);
console.time(accountsCleanUpLabel);
}

@@ -454,2 +502,8 @@ /*

}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(accountsCleanUpLabel);
// eslint-disable-next-line no-console
console.time(accessListLabel);
}
if (opts.reportAccessList === true && this.common.isActivatedEIP(2930)) {

@@ -472,4 +526,16 @@ // Convert the Map to the desired type

}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(accessListLabel);
// eslint-disable-next-line no-console
console.time(journalCacheCleanUpLabel);
}
await this.evm.journal.cleanup();
state.originalStorageCache.clear();
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(journalCacheCleanUpLabel);
// eslint-disable-next-line no-console
console.time(receiptsLabel);
}
// Generate the tx receipt

@@ -481,3 +547,3 @@ const gasUsed = opts.blockGasUsed !== undefined ? opts.blockGasUsed : block.header.gasUsed;

// eslint-disable-next-line no-console
console.timeEnd(cleanupAndReceiptsLabel);
console.timeEnd(receiptsLabel);
}

@@ -502,4 +568,4 @@ /**

*/
function txLogsBloom(logs) {
const bloom = new Bloom();
function txLogsBloom(logs, common) {
const bloom = new Bloom(undefined, common);
if (logs) {

@@ -506,0 +572,0 @@ for (let i = 0; i < logs.length; i++) {

{
"name": "@ethereumjs/vm",
"version": "7.1.0",
"version": "7.2.0",
"description": "An Ethereum VM implementation",

@@ -43,3 +43,4 @@ "keywords": [

"docs:build": "typedoc --options typedoc.cjs",
"examples": "ts-node ../../scripts/examples-runner.ts -- vm",
"examples": "tsx ../../scripts/examples-runner.ts -- vm",
"examples:build": "npx embedme README.md",
"formatTest": "node ./scripts/formatTest",

@@ -62,17 +63,17 @@ "lint": "../../config/cli/lint.sh",

"test:state:slow": "npm run test:state -- --runSkipped=slow",
"tester": "ts-node ./test/tester --stack-size=1500",
"tester": "tsx ./test/tester --stack-size=1500",
"tsc": "../../config/cli/ts-compile.sh"
},
"dependencies": {
"@ethereumjs/block": "^5.0.1",
"@ethereumjs/blockchain": "^7.0.1",
"@ethereumjs/common": "^4.1.0",
"@ethereumjs/evm": "^2.1.0",
"@ethereumjs/rlp": "^5.0.1",
"@ethereumjs/statemanager": "^2.1.0",
"@ethereumjs/trie": "^6.0.1",
"@ethereumjs/tx": "^5.1.0",
"@ethereumjs/util": "^9.0.1",
"@ethereumjs/block": "^5.1.1",
"@ethereumjs/blockchain": "^7.1.0",
"@ethereumjs/common": "^4.2.0",
"@ethereumjs/evm": "^2.2.0",
"@ethereumjs/rlp": "^5.0.2",
"@ethereumjs/statemanager": "^2.2.1",
"@ethereumjs/trie": "^6.1.1",
"@ethereumjs/tx": "^5.2.1",
"@ethereumjs/util": "^9.0.2",
"debug": "^4.3.3",
"ethereum-cryptography": "^2.1.2"
"ethereum-cryptography": "^2.1.3"
},

@@ -79,0 +80,0 @@ "devDependencies": {

@@ -35,3 +35,5 @@ # @ethereumjs/vm

```typescript
```ts
// ./examples/runTx.ts
import { Address } from '@ethereumjs/util'

@@ -42,14 +44,20 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common'

const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai })
const vm = await VM.create({ common })
const main = async () => {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai })
const vm = await VM.create({ common })
const tx = LegacyTransaction.fromTxData({
gasLimit: BigInt(21000),
value: BigInt(1),
to: Address.zero(),
v: BigInt(37),
r: BigInt('62886504200765677832366398998081608852310526822767264927793100349258111544447'),
s: BigInt('21948396863567062449199529794141973192314514851405455194940751428901681436138'),
})
await vm.runTx({ tx, skipBalance: true })
const tx = LegacyTransaction.fromTxData({
gasLimit: BigInt(21000),
gasPrice: BigInt(1000000000),
value: BigInt(1),
to: Address.zero(),
v: BigInt(37),
r: BigInt('62886504200765677832366398998081608852310526822767264927793100349258111544447'),
s: BigInt('21948396863567062449199529794141973192314514851405455194940751428901681436138'),
})
const res = await vm.runTx({ tx, skipBalance: true })
console.log(res.totalGasSpent) // 21000n - gas cost for simple ETH transfer
}
main()
```

@@ -65,24 +73,53 @@

```typescript
```ts
// ./examples/buildBlock.ts
import { Block } from '@ethereumjs/block'
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { LegacyTransaction } from '@ethereumjs/tx'
import { Account, Address, bytesToHex, hexToBytes, randomBytes } from '@ethereumjs/util'
import { VM } from '@ethereumjs/vm'
const common = new Common({ chain: Chain.Mainnet })
const vm = await VM.create({ common })
const main = async () => {
const common = new Common({ chain: Chain.Mainnet })
const vm = await VM.create({ common })
const blockBuilder = await vm.buildBlock({
parentBlock, // the parent @ethereumjs/block Block
headerData, // header values for the new block
blockOpts: { calcDifficultyFromHeader: parentBlock.header, freeze: false },
})
const parentBlock = Block.fromBlockData(
{ header: { number: 1n } },
{ skipConsensusFormatValidation: true }
)
const headerData = {
number: 2n,
}
const blockBuilder = await vm.buildBlock({
parentBlock, // the parent @ethereumjs/block Block
headerData, // header values for the new block
blockOpts: {
calcDifficultyFromHeader: parentBlock.header,
freeze: false,
skipConsensusFormatValidation: true,
putBlockIntoBlockchain: false,
},
})
const tx = LegacyTransaction.fromTxData()
await blockBuilder.addTransaction(tx)
const pk = hexToBytes('0x26f81cbcffd3d23eace0bb4eac5274bb2f576d310ee85318b5428bf9a71fc89a')
const address = Address.fromPrivateKey(pk)
const account = new Account(0n, 0xfffffffffn)
await vm.stateManager.putAccount(address, account) // create a sending account and give it a big balance
const tx = LegacyTransaction.fromTxData({ gasLimit: 0xffffff, gasPrice: 75n }).sign(pk)
await blockBuilder.addTransaction(tx)
// Add more transactions
// Add more transactions
const block = await blockBuilder.build()
const block = await blockBuilder.build()
console.log(`Built a block with hash ${bytesToHex(block.hash())}`)
}
main()
```
### WASM Crypto Support
This library by default uses JavaScript implementations for the basic standard crypto primitives like hashing or signature verification (for included txs). See `@ethereumjs/common` [README](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/common) for instructions on how to replace with e.g. a more performant WASM implementation by using a shared `common` instance.
## Example

@@ -92,4 +129,4 @@

1. [./examples/run-blockchain](./examples/run-blockchain.cts): Loads tests data, including accounts and blocks, and runs all of them in the VM.
1. [./examples/run-solidity-contract](./examples/run-solidity-contract.cts): Compiles a Solidity contract, and calls constant and non-constant functions.
1. [./examples/run-blockchain](./examples/run-blockchain.ts): Loads tests data, including accounts and blocks, and runs all of them in the VM.
1. [./examples/run-solidity-contract](./examples/run-solidity-contract.ts): Compiles a Solidity contract, and calls constant and non-constant functions.

@@ -116,3 +153,3 @@ All of the examples have their own `README.md` explaining how to run them.

```typescript
```ts
import { EthereumJSClass } from '@ethereumjs/[PACKAGE_NAME]'

@@ -123,3 +160,3 @@ ```

```typescript
```ts
const { EthereumJSClass } = require('@ethereumjs/[PACKAGE_NAME]')

@@ -150,4 +187,4 @@ ```

```typescript
vm.evm.runCode() // or
```ts
vm.evm.runCode()
vm.evm.events.on('step', function (data) {

@@ -180,13 +217,21 @@ console.log(`Opcode: ${data.opcode.name}\tStack: ${data.stack}`)

```typescript
```ts
// ./examples/runGoerliBlock.ts
import { Block } from '@ethereumjs/block'
import { Chain, Common } from '@ethereumjs/common'
import { hexToBytes } from '@ethereumjs/util'
import { VM } from '@ethereumjs/vm'
import { bytesToHex, hexToBytes } from '@ethereumjs/util'
import { VM } from '../src/vm.js'
import goerliBlock2 from './testData/goerliBlock2.json'
const common = new Common({ chain: Chain.Goerli })
const vm = await VM.create({ common, setHardfork: true })
const main = async () => {
const common = new Common({ chain: Chain.Goerli, hardfork: 'london' })
const vm = await VM.create({ common, setHardfork: true })
const serialized = hexToBytes('0xf901f7a06bfee7294bf4457...')
const block = Block.fromRLPSerializedBlock(serialized, { setHardfork: true })
const result = await vm.runBlock(block)
const block = Block.fromRPC(goerliBlock2, undefined, { common })
const result = await vm.runBlock({ block, generate: true, skipHeaderValidation: true }) // we skip header validaiton since we are running a block without the full Ethereum history available
console.log(`The state root for Goerli block 2 is ${bytesToHex(result.stateRoot)}`)
}
main()
```

@@ -200,8 +245,13 @@

```typescript
```ts
// ./examples/runTx.ts#L1-L8
import { Address } from '@ethereumjs/util'
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { LegacyTransaction } from '@ethereumjs/tx'
import { VM } from '@ethereumjs/vm'
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin })
const vm = await VM.create({ common })
const main = async () => {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai })
const vm = await VM.create({ common })
```

@@ -219,12 +269,26 @@

```typescript
```ts
// ./examples/vmWithGenesisState.ts
import { Blockchain } from '@ethereumjs/blockchain'
import { Chain, Common } from '@ethereumjs/common'
import { Chain } from '@ethereumjs/common'
import { getGenesis } from '@ethereumjs/genesis'
import { Address } from '@ethereumjs/util'
import { VM } from '@ethereumjs/vm'
const genesisState = getGenesis(Chain.Mainnet)
const main = async () => {
const genesisState = getGenesis(Chain.Mainnet)
const blockchain = await Blockchain.create({ genesisState })
const vm = await VM.create({ blockchain, genesisState })
const blockchain = await Blockchain.create({ genesisState })
const vm = await VM.create({ blockchain, genesisState })
const account = await vm.stateManager.getAccount(
Address.fromString('0x000d836201318ec6899a67540690382780743280')
)
console.log(
`This balance for account 0x000d836201318ec6899a67540690382780743280 in this chain's genesis state is ${Number(
account?.balance
)}`
)
}
main()
```

@@ -245,8 +309,14 @@

```typescript
```ts
// ./examples/vmWithEIPs.ts
import { Chain, Common } from '@ethereumjs/common'
import { VM } from '@ethereumjs/vm'
const common = new Common({ chain: Chain.Mainnet, eips: [2537] })
const vm = await VM.create({ common })
const main = async () => {
const common = new Common({ chain: Chain.Mainnet, eips: [3074] })
const vm = await VM.create({ common })
console.log(`EIP 3074 is active in the VM - ${vm.common.isActivatedEIP(3074)}`)
}
main()
```

@@ -262,11 +332,20 @@

To run VM/EVM related EIP-4844 functionality you have to active the EIP in the associated `@ethereumjs/common` library:
To run VM/EVM related EIP-4844 functionality you have to activate the EIP in the associated `@ethereumjs/common` library:
```typescript
```ts
// ./examples/vmWith4844.ts
import { Common, Chain, Hardfork } from '@ethereumjs/common'
import { VM } from '../src/vm.js'
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] })
const main = async () => {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] })
const vm = await VM.create({ common })
console.log(`4844 is active in the VM - ${vm.common.isActivatedEIP(4844)}`)
}
main()
```
EIP-4844 comes with a new opcode `DATAHASH` and adds a new point evaluation precompile at address `0x14` in the underlying `@ethereumjs/evm` package.
EIP-4844 comes with a new opcode `BLOBHASH` and adds a new point evaluation precompile at address `0x14` in the underlying `@ethereumjs/evm` package.

@@ -337,3 +416,3 @@ **Note:** Usage of the point evaluation precompile needs a manual KZG library installation and global initialization, see [KZG Setup](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx/README.md#kzg-setup) for instructions.

```shell
DEBUG=ethjs,vm:tx ts-node test.ts
DEBUG=ethjs,vm:tx tsx test.ts
```

@@ -344,3 +423,3 @@

```shell
DEBUG=ethjs,vm:*,vm:*:* ts-node test.ts
DEBUG=ethjs,vm:*,vm:*:* tsx test.ts
```

@@ -351,3 +430,3 @@

```shell
DEBUG=ethjs,vm:*:gas ts-node test.ts
DEBUG=ethjs,vm:*:gas tsx test.ts
```

@@ -358,3 +437,3 @@

```shell
DEBUG=ethjs,vm:*,vm:*:*,-vm:state ts-node test.ts
DEBUG=ethjs,vm:*,vm:*:*,-vm:state tsx test.ts
```

@@ -365,3 +444,3 @@

```shell
DEBUG=ethjs,vm:tx,vm:evm,vm:ops:sstore,vm:*:gas ts-node test.ts
DEBUG=ethjs,vm:tx,vm:evm,vm:ops:sstore,vm:*:gas tsx test.ts
```

@@ -368,0 +447,0 @@

import { zeros } from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import type { Common } from '@ethereumjs/common'
const BYTE_SIZE = 256

@@ -8,2 +10,3 @@

bitvector: Uint8Array
keccakFunction: (msg: Uint8Array) => Uint8Array

@@ -13,3 +16,8 @@ /**

*/
constructor(bitvector?: Uint8Array) {
constructor(bitvector?: Uint8Array, common?: Common) {
if (common?.customCrypto.keccak256 !== undefined) {
this.keccakFunction = common.customCrypto.keccak256
} else {
this.keccakFunction = keccak256
}
if (!bitvector) {

@@ -28,3 +36,3 @@ this.bitvector = zeros(BYTE_SIZE)

add(e: Uint8Array) {
e = keccak256(e)
e = this.keccakFunction(e)
const mask = 2047 // binary 11111111111

@@ -46,3 +54,3 @@

check(e: Uint8Array): boolean {
e = keccak256(e)
e = this.keccakFunction(e)
const mask = 2047 // binary 11111111111

@@ -49,0 +57,0 @@ let match = true

@@ -135,3 +135,3 @@ import { Block } from '@ethereumjs/block'

public async transactionsTrie() {
return Block.genTransactionsTrieRoot(this.transactions)
return Block.genTransactionsTrieRoot(this.transactions, new Trie({ common: this.vm.common }))
}

@@ -143,3 +143,3 @@

public logsBloom() {
const bloom = new Bloom()
const bloom = new Bloom(undefined, this.vm.common)
for (const txResult of this.transactionResults) {

@@ -159,3 +159,3 @@ // Combine blooms via bitwise OR

}
const receiptTrie = new Trie()
const receiptTrie = new Trie({ common: this.vm.common })
for (const [i, txResult] of this.transactionResults.entries()) {

@@ -179,3 +179,3 @@ const tx = this.transactions[i]

: Address.zero()
await rewardAccount(this.vm.evm, coinbase, reward)
await rewardAccount(this.vm.evm, coinbase, reward, this.vm.common)
}

@@ -196,3 +196,3 @@

// converted to wei
await rewardAccount(this.vm.evm, address, amount * GWEI_TO_WEI)
await rewardAccount(this.vm.evm, address, amount * GWEI_TO_WEI, this.vm.common)
}

@@ -310,3 +310,3 @@ }

const withdrawalsRoot = this.withdrawals
? await Block.genWithdrawalsTrieRoot(this.withdrawals)
? await Block.genWithdrawalsTrieRoot(this.withdrawals, new Trie({ common: this.vm.common }))
: undefined

@@ -313,0 +313,0 @@ const receiptTrie = await this.receiptTrie()

import { Block } from '@ethereumjs/block'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import { Trie } from '@ethereumjs/trie'

@@ -36,2 +37,3 @@ import { TransactionType } from '@ethereumjs/tx'

import type { VM } from './vm.js'
import type { Common } from '@ethereumjs/common'
import type { EVM, EVMInterface } from '@ethereumjs/evm'

@@ -64,2 +66,3 @@

const state = this.stateManager
const { root } = opts

@@ -123,2 +126,18 @@ const clearCache = opts.clearCache ?? true

if (this.common.isActivatedEIP(6800)) {
if (!(state instanceof StatelessVerkleStateManager)) {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`)
}
if (this.DEBUG) {
debug(`Initializing StatelessVerkleStateManager executionWitness`)
}
;(this._opts.stateManager as StatelessVerkleStateManager).initVerkleExecutionWitness(
block.executionWitness
)
} else {
if (state instanceof StatelessVerkleStateManager) {
throw Error(`StatelessVerkleStateManager can't execute merkle blocks`)
}
}
// check for DAO support and if we should apply the DAO fork

@@ -132,2 +151,3 @@ if (

}
await this.evm.journal.checkpoint()

@@ -144,3 +164,4 @@ await _applyDAOHardfork(this.evm)

let result
let result: Awaited<ReturnType<typeof applyBlock>>
try {

@@ -191,3 +212,4 @@ result = await applyBlock.bind(this)(block, opts)

block = Block.fromBlockData(blockData, { common: this.common })
} else {
} else if (this.common.isActivatedEIP(6800) === false) {
// Only validate the following headers if verkle blocks aren't activated
if (equalsBytes(result.receiptsRoot, block.header.receiptTrie) === false) {

@@ -230,5 +252,17 @@ if (this.DEBUG) {

}
const msg = _errorMsg('invalid block stateRoot', this, block)
const msg = _errorMsg(
`invalid block stateRoot, got: ${bytesToHex(stateRoot)}, want: ${bytesToHex(
block.header.stateRoot
)}`,
this,
block
)
throw new Error(msg)
}
} else if (this.common.isActivatedEIP(6800) === true) {
// If verkle is activated, only validate the post-state
if ((this._opts.stateManager as StatelessVerkleStateManager).verifyPostState() === false) {
throw new Error(`Verkle post state verification failed on block ${block.header.number}`)
}
debug(`Verkle post state verification succeeded`)
}

@@ -370,3 +404,3 @@

if ((await this.stateManager.getAccount(parentBeaconBlockRootAddress)) === undefined) {
await this.stateManager.putAccount(parentBeaconBlockRootAddress, new Account())
await this.evm.journal.putAccount(parentBeaconBlockRootAddress, new Account())
}

@@ -399,3 +433,3 @@

const bloom = new Bloom()
const bloom = new Bloom(undefined, this.common)
// the total amount of gas used processing these transactions

@@ -406,3 +440,3 @@ let gasUsed = BIGINT_0

if (block.transactions.length !== 0) {
receiptTrie = new Trie()
receiptTrie = new Trie({ common: this.common })
}

@@ -486,3 +520,3 @@

// such that the account is touched and marked for cleanup if it is empty
await rewardAccount(this.evm, address, amount * GWEI_TO_WEI)
await rewardAccount(this.evm, address, amount * GWEI_TO_WEI, this.common)
}

@@ -504,3 +538,3 @@ }

const reward = calculateOmmerReward(ommer.number, block.header.number, minerReward)
const account = await rewardAccount(this.evm, ommer.coinbase, reward)
const account = await rewardAccount(this.evm, ommer.coinbase, reward, this.common)
if (this.DEBUG) {

@@ -512,3 +546,3 @@ debug(`Add uncle reward ${reward} to account ${ommer.coinbase} (-> ${account.balance})`)

const reward = calculateMinerReward(minerReward, ommers.length)
const account = await rewardAccount(this.evm, block.header.coinbase, reward)
const account = await rewardAccount(this.evm, block.header.coinbase, reward, this.common)
if (this.DEBUG) {

@@ -543,6 +577,12 @@ debug(`Add miner reward ${reward} to account ${block.header.coinbase} (-> ${account.balance})`)

address: Address,
reward: bigint
reward: bigint,
common?: Common
): Promise<Account> {
let account = await evm.stateManager.getAccount(address)
if (account === undefined) {
if (common?.isActivatedEIP(6800) === true) {
;(
evm.stateManager as StatelessVerkleStateManager
).accessWitness!.touchAndChargeProofOfAbsence(address)
}
account = new Account()

@@ -552,2 +592,10 @@ }

await evm.journal.putAccount(address, account)
if (common?.isActivatedEIP(6800) === true) {
// use this utility to build access but the computed gas is not charged and hence free
;(evm.stateManager as StatelessVerkleStateManager).accessWitness!.touchTxExistingAndComputeGas(
address,
{ sendsValue: true }
)
}
return account

@@ -617,3 +665,3 @@ }

}
const trie = new Trie()
const trie = new Trie({ common: block.common })
for (const [i, tx] of block.transactions.entries()) {

@@ -620,0 +668,0 @@ await trie.put(RLP.encode(i), tx.serialize())

import { Block } from '@ethereumjs/block'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import { BlobEIP4844Transaction, Capability, isBlobEIP4844Tx } from '@ethereumjs/tx'

@@ -9,5 +10,7 @@ import {

KECCAK256_NULL,
bigIntToBytes,
bytesToHex,
bytesToUnprefixedHex,
equalsBytes,
generateAddress,
hexToBytes,

@@ -31,3 +34,3 @@ short,

import type { VM } from './vm.js'
import type { AccessList, AccessListItem } from '@ethereumjs/common'
import type { AccessList, AccessListItem, Common } from '@ethereumjs/common'
import type { EVM } from '@ethereumjs/evm'

@@ -48,4 +51,8 @@ import type {

const balanceNonceLabel = 'Balance/Nonce checks and update'
const executionLabel = 'Execution'
const logsGasBalanceLabel = 'Logs, gas usage, account/miner balances'
const cleanupAndReceiptsLabel = 'Accounts clean up, access list, journal/cache cleanup, receipts'
const accountsCleanUpLabel = 'Accounts clean up'
const accessListLabel = 'Access list label'
const journalCacheCleanUpLabel = 'Journal/cache cleanup'
const receiptsLabel = 'Receipts'
const entireTxLabel = 'Entire tx'

@@ -209,2 +216,11 @@

let stateAccesses
if (this.common.isActivatedEIP(6800)) {
if (!(this.stateManager instanceof StatelessVerkleStateManager)) {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`)
}
stateAccesses = (this.stateManager as StatelessVerkleStateManager).accessWitness
}
let txAccesses = stateAccesses?.shallowCopy()
const { tx, block } = opts

@@ -277,3 +293,5 @@

const msg = _errorMsg(
`Transaction's maxFeePerGas (${maxFeePerGas}) is less than the block's baseFeePerGas (${baseFeePerGas})`,
`Transaction's ${
'maxFeePerGas' in tx ? 'maxFeePerGas' : 'gasPrice'
} (${maxFeePerGas}) is less than the block's baseFeePerGas (${baseFeePerGas})`,
this,

@@ -311,4 +329,25 @@ block,

let upfrontAwGas = BIGINT_0
if (this.common.isActivatedEIP(6800)) {
upfrontAwGas += txAccesses!.touchTxOriginAndComputeGas(caller)
const sendsValue = tx.value !== BIGINT_0
if (tx.to !== undefined) {
upfrontAwGas += txAccesses!.touchTxExistingAndComputeGas(tx.to, { sendsValue })
debug(`Sender upfront awGas requirement for non contract creation tx is ${upfrontAwGas}`)
} else {
const contractTo = new Address(generateAddress(caller.bytes, bigIntToBytes(nonce)))
upfrontAwGas += txAccesses!.touchAndChargeContractCreateInit(contractTo, { sendsValue })
debug(
`Sender upfront awGas requirement is contract creation at=${short(
contractTo.bytes
)} is ${upfrontAwGas}`
)
}
// reset txAccesses to remove the caches so that access gas can be correctly consumed inside the evm run
txAccesses = stateAccesses?.shallowCopy()
}
// Check balance against upfront tx cost
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas)
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas) + upfrontAwGas
if (balance < upFrontCost) {

@@ -444,7 +483,7 @@ if (opts.skipBalance === true && fromAccount.balance < upFrontCost) {

}
let executionTimerPrecise: number
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(balanceNonceLabel)
// eslint-disable-next-line no-console
console.log('[ For execution see detailed table output ]')
executionTimerPrecise = performance.now()
}

@@ -476,6 +515,15 @@

blobVersionedHashes,
accessWitness: txAccesses,
})) as RunTxResult
if (this.common.isActivatedEIP(6800)) {
stateAccesses?.merge(txAccesses!)
}
if (enableProfiler) {
// eslint-disable-next-line no-console
console.log(`${executionLabel}: ${performance.now() - executionTimerPrecise!}ms`)
// eslint-disable-next-line no-console
console.log('[ For execution details see table output ]')
// eslint-disable-next-line no-console
console.time(logsGasBalanceLabel)

@@ -502,3 +550,3 @@ }

// Generate the bloom for the tx
results.bloom = txLogsBloom(results.execResult.logs)
results.bloom = txLogsBloom(results.execResult.logs, this.common)
if (this.DEBUG) {

@@ -562,2 +610,5 @@ debug(`Generated tx bloom with logs=${results.execResult.logs?.length}`)

if (minerAccount === undefined) {
if (this.common.isActivatedEIP(6800)) {
;(state as StatelessVerkleStateManager).accessWitness!.touchAndChargeProofOfAbsence(miner)
}
minerAccount = new Account()

@@ -572,2 +623,9 @@ }

if (this.common.isActivatedEIP(6800)) {
// use this utility to build access but the computed gas is not charged and hence free
;(state as StatelessVerkleStateManager).accessWitness!.touchTxExistingAndComputeGas(miner, {
sendsValue: true,
})
}
// Put the miner account into the state. If the balance of the miner account remains zero, note that

@@ -585,3 +643,3 @@ // the state.putAccount function puts this into the "touched" accounts. This will thus be removed when

// eslint-disable-next-line no-console
console.time(cleanupAndReceiptsLabel)
console.time(accountsCleanUpLabel)
}

@@ -608,2 +666,9 @@

if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(accountsCleanUpLabel)
// eslint-disable-next-line no-console
console.time(accessListLabel)
}
if (opts.reportAccessList === true && this.common.isActivatedEIP(2930)) {

@@ -628,5 +693,19 @@ // Convert the Map to the desired type

if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(accessListLabel)
// eslint-disable-next-line no-console
console.time(journalCacheCleanUpLabel)
}
await this.evm.journal.cleanup()
state.originalStorageCache.clear()
if (enableProfiler) {
// eslint-disable-next-line no-console
console.timeEnd(journalCacheCleanUpLabel)
// eslint-disable-next-line no-console
console.time(receiptsLabel)
}
// Generate the tx receipt

@@ -645,3 +724,3 @@ const gasUsed = opts.blockGasUsed !== undefined ? opts.blockGasUsed : block.header.gasUsed

// eslint-disable-next-line no-console
console.timeEnd(cleanupAndReceiptsLabel)
console.timeEnd(receiptsLabel)
}

@@ -673,4 +752,4 @@

*/
function txLogsBloom(logs?: any[]): Bloom {
const bloom = new Bloom()
function txLogsBloom(logs?: any[], common?: Common): Bloom {
const bloom = new Bloom(undefined, common)
if (logs) {

@@ -677,0 +756,0 @@ for (let i = 0; i < logs.length; i++) {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc