@nomicfoundation/ethereumjs-evm
Advanced tools
Comparing version 1.3.1 to 1.3.2
@@ -17,3 +17,2 @@ export declare const FORMAT = 239; | ||
export declare const validOpcodes: (code: Buffer) => boolean; | ||
export declare const getEOFCode: (code: Buffer) => Buffer; | ||
export declare const EOF: { | ||
@@ -20,0 +19,0 @@ FORMAT: number; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EOF = exports.getEOFCode = exports.validOpcodes = exports.codeAnalysis = exports.VERSION = exports.MAGIC = exports.FORMAT = void 0; | ||
exports.EOF = exports.validOpcodes = exports.codeAnalysis = exports.VERSION = exports.MAGIC = exports.FORMAT = void 0; | ||
const opcodes_1 = require("./opcodes"); | ||
@@ -25,3 +25,3 @@ exports.FORMAT = 0xef; | ||
}; | ||
if (container[0] !== exports.FORMAT || container[1] !== exports.MAGIC || container[2] !== exports.VERSION) | ||
if (container[1] !== exports.MAGIC || container[2] !== exports.VERSION) | ||
// Bytecode does not contain EOF1 "magic" or version number in expected positions | ||
@@ -96,14 +96,3 @@ return; | ||
exports.validOpcodes = validOpcodes; | ||
const getEOFCode = (code) => { | ||
const sectionSizes = (0, exports.codeAnalysis)(code); | ||
if (sectionSizes === undefined) { | ||
return code; | ||
} | ||
else { | ||
const codeStart = sectionSizes.data > 0 ? 10 : 7; | ||
return code.slice(codeStart, codeStart + sectionSizes.code); | ||
} | ||
}; | ||
exports.getEOFCode = getEOFCode; | ||
exports.EOF = { FORMAT: exports.FORMAT, MAGIC: exports.MAGIC, VERSION: exports.VERSION, codeAnalysis: exports.codeAnalysis, validOpcodes: exports.validOpcodes }; | ||
//# sourceMappingURL=eof.js.map |
/// <reference types="node" /> | ||
import { Common } from '@nomicfoundation/ethereumjs-common'; | ||
import { Address, AsyncEventEmitter } from '@nomicfoundation/ethereumjs-util'; | ||
import { Address } from '@nomicfoundation/ethereumjs-util'; | ||
import AsyncEventEmitter = require('async-eventemitter'); | ||
import { EvmError } from './exceptions'; | ||
@@ -37,7 +38,5 @@ import { Message } from './message'; | ||
* - [EIP-3670](https://eips.ethereum.org/EIPS/eip-3670) - EOF - Code Validation (`experimental`) | ||
* - [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction | ||
* - [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) - Limit and meter initcode | ||
* - [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) - Supplant DIFFICULTY opcode with PREVRANDAO (Merge) | ||
* - [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) - Shard Blob Transactions (`experimental`) | ||
* - [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) - Beacon chain push withdrawals as operations | ||
* - [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction (`experimental`) | ||
* - [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) - Limit and meter initcode (`experimental`) | ||
* - [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) - Supplant DIFFICULTY opcode with PREVRANDAO (Merge) (`experimental`) | ||
* - [EIP-5133](https://eips.ethereum.org/EIPS/eip-5133) - Delaying Difficulty Bomb to mid-September 2022 | ||
@@ -88,3 +87,2 @@ * | ||
export declare class EVM implements EVMInterface { | ||
private static supportedHardforks; | ||
protected _tx?: { | ||
@@ -121,2 +119,8 @@ gasPrice: bigint; | ||
/** | ||
* Cached emit() function, not for public usage | ||
* set to public due to implementation internals | ||
* @hidden | ||
*/ | ||
readonly _emit: (topic: string, data: any) => Promise<void>; | ||
/** | ||
* Pointer to the mcl package, not for public usage | ||
@@ -136,3 +140,2 @@ * set to public due to implementation internals | ||
readonly DEBUG: boolean; | ||
readonly _emit: (topic: string, data: any) => Promise<void>; | ||
/** | ||
@@ -187,3 +190,3 @@ * EVM async constructor. Creates engine instance and initializes it. | ||
private postMessageCleanup; | ||
copy(): EVMInterface; | ||
copy(): EVM; | ||
} | ||
@@ -190,0 +193,0 @@ /** |
@@ -6,2 +6,3 @@ "use strict"; | ||
const ethereumjs_util_1 = require("@nomicfoundation/ethereumjs-util"); | ||
const AsyncEventEmitter = require("async-eventemitter"); | ||
const debug_1 = require("debug"); | ||
@@ -44,3 +45,3 @@ const util_1 = require("util"); | ||
this.DEBUG = false; | ||
this.events = new ethereumjs_util_1.AsyncEventEmitter(); | ||
this.events = new AsyncEventEmitter(); | ||
this._optsCached = opts; | ||
@@ -59,3 +60,3 @@ this.eei = opts.eei; | ||
1153, 1559, 2315, 2537, 2565, 2718, 2929, 2930, 3074, 3198, 3529, 3540, 3541, 3607, 3651, | ||
3670, 3855, 3860, 4399, 4895, 4844, 5133, | ||
3670, 3855, 3860, 4399, 5133, | ||
]; | ||
@@ -67,3 +68,21 @@ for (const eip of this._common.eips()) { | ||
} | ||
if (!EVM.supportedHardforks.includes(this._common.hardfork())) { | ||
const supportedHardforks = [ | ||
ethereumjs_common_1.Hardfork.Chainstart, | ||
ethereumjs_common_1.Hardfork.Homestead, | ||
ethereumjs_common_1.Hardfork.Dao, | ||
ethereumjs_common_1.Hardfork.TangerineWhistle, | ||
ethereumjs_common_1.Hardfork.SpuriousDragon, | ||
ethereumjs_common_1.Hardfork.Byzantium, | ||
ethereumjs_common_1.Hardfork.Constantinople, | ||
ethereumjs_common_1.Hardfork.Petersburg, | ||
ethereumjs_common_1.Hardfork.Istanbul, | ||
ethereumjs_common_1.Hardfork.MuirGlacier, | ||
ethereumjs_common_1.Hardfork.Berlin, | ||
ethereumjs_common_1.Hardfork.London, | ||
ethereumjs_common_1.Hardfork.ArrowGlacier, | ||
ethereumjs_common_1.Hardfork.GrayGlacier, | ||
ethereumjs_common_1.Hardfork.MergeForkIdTransition, | ||
ethereumjs_common_1.Hardfork.Merge, | ||
]; | ||
if (!supportedHardforks.includes(this._common.hardfork())) { | ||
throw new Error(`Hardfork ${this._common.hardfork()} not set as supported in supportedHardforks`); | ||
@@ -89,7 +108,9 @@ } | ||
} | ||
// Safeguard if "process" is not available (browser) | ||
if (typeof process?.env.DEBUG !== 'undefined') { | ||
this.DEBUG = true; | ||
} | ||
// We cache this promisified function as it's called from the main execution loop, and | ||
// promisifying each time has a huge performance impact. | ||
this._emit = ((0, util_1.promisify)(this.events.emit.bind(this.events))); | ||
// Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables | ||
this.DEBUG = process?.env?.DEBUG?.includes('ethjs') ?? false; | ||
} | ||
@@ -214,3 +235,3 @@ get precompiles() { | ||
await this._reduceSenderBalance(account, message); | ||
if (this._common.isActivatedEIP(3860) && !this._allowUnlimitedContractSize) { | ||
if (this._common.isActivatedEIP(3860)) { | ||
if (message.data.length > Number(this._common.param('vm', 'maxInitCodeSize'))) { | ||
@@ -387,3 +408,3 @@ return { | ||
// This contract would be considered "DEAD" in later hard forks. | ||
// It is thus an unnecessary default item, which we have to save to dik | ||
// It is thus an unecessary default item, which we have to save to dik | ||
// It does change the state root, but it only wastes storage. | ||
@@ -419,4 +440,2 @@ //await this._state.putContractCode(message.to, result.returnValue) | ||
gasRefund: message.gasRefund, | ||
containerCode: message.containerCode, | ||
versionedHashes: message.versionedHashes ?? [], | ||
}; | ||
@@ -463,3 +482,2 @@ const interpreter = new interpreter_1.Interpreter(this, this.eei, env, message.gasLimit); | ||
let message = opts.message; | ||
let callerAccount; | ||
if (!message) { | ||
@@ -474,3 +492,3 @@ this._block = opts.block ?? defaultBlock(); | ||
if (opts.skipBalance === true) { | ||
callerAccount = await this.eei.getAccount(caller); | ||
const callerAccount = await this.eei.getAccount(caller); | ||
if (callerAccount.balance < value) { | ||
@@ -495,15 +513,4 @@ // if skipBalance and balance less than value, set caller balance to `value` to ensure sufficient funds | ||
delegatecall: opts.delegatecall, | ||
versionedHashes: opts.versionedHashes, | ||
}); | ||
} | ||
if (message.depth === 0) { | ||
if (!callerAccount) { | ||
callerAccount = await this.eei.getAccount(message.caller); | ||
} | ||
callerAccount.nonce++; | ||
await this.eei.putAccount(message.caller, callerAccount); | ||
if (this.DEBUG) { | ||
debug(`Update fromAccount (caller) nonce (-> ${callerAccount.nonce}))`); | ||
} | ||
} | ||
await this._emit('beforeMessage', message); | ||
@@ -544,6 +551,3 @@ if (!message.to && this._common.isActivatedEIP(2929) === true) { | ||
// If that is the case, then all refunds are forfeited | ||
// There is one exception: if the CODESTORE_OUT_OF_GAS error is thrown | ||
// (this only happens the Frontier/Chainstart fork) | ||
// then the error is dismissed | ||
if (err && err.error !== exceptions_1.ERROR.CODESTORE_OUT_OF_GAS) { | ||
if (err) { | ||
result.execResult.selfdestruct = {}; | ||
@@ -602,3 +606,2 @@ result.execResult.gasRefund = BigInt(0); | ||
isStatic: opts.isStatic, | ||
versionedHashes: opts.versionedHashes, | ||
}); | ||
@@ -637,10 +640,4 @@ return this.runInterpreter(message, { pc: opts.pc }); | ||
else { | ||
message.containerCode = await this.eei.getContractCode(message.codeAddress); | ||
message.code = await this.eei.getContractCode(message.codeAddress); | ||
message.isCompiled = false; | ||
if (this._common.isActivatedEIP(3540)) { | ||
message.code = (0, eof_1.getEOFCode)(message.containerCode); | ||
} | ||
else { | ||
message.code = message.containerCode; | ||
} | ||
} | ||
@@ -656,3 +653,6 @@ } | ||
const acc = await this.eei.getAccount(message.caller); | ||
const newNonce = acc.nonce - BigInt(1); | ||
let newNonce = acc.nonce; | ||
if (message.depth > 0) { | ||
newNonce--; | ||
} | ||
addr = (0, ethereumjs_util_1.generateAddress)(message.caller.buf, (0, ethereumjs_util_1.bigIntToBuffer)(newNonce)); | ||
@@ -698,10 +698,7 @@ } | ||
copy() { | ||
const common = this._common.copy(); | ||
common.setHardfork(this._common.hardfork()); | ||
const opts = { | ||
...this._optsCached, | ||
common, | ||
common: this._common.copy(), | ||
eei: this.eei.copy(), | ||
}; | ||
opts.eei._common = common; | ||
return new EVM(opts); | ||
@@ -711,22 +708,2 @@ } | ||
exports.EVM = EVM; | ||
EVM.supportedHardforks = [ | ||
ethereumjs_common_1.Hardfork.Chainstart, | ||
ethereumjs_common_1.Hardfork.Homestead, | ||
ethereumjs_common_1.Hardfork.Dao, | ||
ethereumjs_common_1.Hardfork.TangerineWhistle, | ||
ethereumjs_common_1.Hardfork.SpuriousDragon, | ||
ethereumjs_common_1.Hardfork.Byzantium, | ||
ethereumjs_common_1.Hardfork.Constantinople, | ||
ethereumjs_common_1.Hardfork.Petersburg, | ||
ethereumjs_common_1.Hardfork.Istanbul, | ||
ethereumjs_common_1.Hardfork.MuirGlacier, | ||
ethereumjs_common_1.Hardfork.Berlin, | ||
ethereumjs_common_1.Hardfork.London, | ||
ethereumjs_common_1.Hardfork.ArrowGlacier, | ||
ethereumjs_common_1.Hardfork.GrayGlacier, | ||
ethereumjs_common_1.Hardfork.MergeForkIdTransition, | ||
ethereumjs_common_1.Hardfork.Merge, | ||
ethereumjs_common_1.Hardfork.Shanghai, | ||
ethereumjs_common_1.Hardfork.ShardingForkDev, | ||
]; | ||
function OOGResult(gasLimit) { | ||
@@ -733,0 +710,0 @@ return { |
@@ -30,5 +30,3 @@ export declare enum ERROR { | ||
BLS_12_381_INPUT_EMPTY = "input is empty", | ||
BLS_12_381_FP_NOT_IN_FIELD = "fp point not in field", | ||
POINT_GREATER_THAN_BLS_MODULUS = "point greater than BLS modulus", | ||
INVALID_COMMITMENT = "kzg commitment does not match versioned hash" | ||
BLS_12_381_FP_NOT_IN_FIELD = "fp point not in field" | ||
} | ||
@@ -35,0 +33,0 @@ export declare class EvmError { |
@@ -36,5 +36,2 @@ "use strict"; | ||
ERROR["BLS_12_381_FP_NOT_IN_FIELD"] = "fp point not in field"; | ||
// Point Evaluation Errors | ||
ERROR["POINT_GREATER_THAN_BLS_MODULUS"] = "point greater than BLS modulus"; | ||
ERROR["INVALID_COMMITMENT"] = "kzg commitment does not match versioned hash"; | ||
})(ERROR = exports.ERROR || (exports.ERROR = {})); | ||
@@ -41,0 +38,0 @@ class EvmError { |
@@ -41,4 +41,2 @@ /// <reference types="node" /> | ||
gasRefund: bigint; | ||
containerCode?: Buffer; /** Full container code for EOF1 contracts */ | ||
versionedHashes: Buffer[]; /** Versioned hashes for blob transactions */ | ||
} | ||
@@ -45,0 +43,0 @@ export interface RunState { |
@@ -243,3 +243,3 @@ "use strict"; | ||
*/ | ||
await this._evm._emit('step', eventObj); | ||
return this._evm._emit('step', eventObj); | ||
} | ||
@@ -428,3 +428,3 @@ // Returns all valid jump and jumpsub destinations. | ||
getCodeSize() { | ||
return BigInt(this._env.containerCode ? this._env.containerCode.length : this._env.code.length); | ||
return BigInt(this._env.code.length); | ||
} | ||
@@ -435,3 +435,3 @@ /** | ||
getCode() { | ||
return this._env.containerCode ?? this._env.code; | ||
return this._env.code; | ||
} | ||
@@ -675,3 +675,3 @@ /** | ||
await this._eei.putAccount(this._env.address, this._env.contract); | ||
if (this._common.isActivatedEIP(3860) && !this._evm._allowUnlimitedContractSize) { | ||
if (this._common.isActivatedEIP(3860)) { | ||
if (data.length > Number(this._common.param('vm', 'maxInitCodeSize'))) { | ||
@@ -678,0 +678,0 @@ return BigInt(0); |
@@ -13,3 +13,2 @@ "use strict"; | ||
}; | ||
const CONTAINER_SIZE = 8192; | ||
/** | ||
@@ -34,6 +33,3 @@ * Memory implements a simple memory model | ||
if (sizeDiff > 0) { | ||
this._store = Buffer.concat([ | ||
this._store, | ||
Buffer.alloc(Math.ceil(sizeDiff / CONTAINER_SIZE) * CONTAINER_SIZE), | ||
]); | ||
this._store = Buffer.concat([this._store, Buffer.alloc(sizeDiff)]); | ||
} | ||
@@ -56,3 +52,5 @@ } | ||
throw new Error('Value exceeds memory capacity'); | ||
value.copy(this._store, offset); | ||
for (let i = 0; i < size; i++) { | ||
this._store[offset + i] = value[i]; | ||
} | ||
} | ||
@@ -59,0 +57,0 @@ /** |
@@ -27,3 +27,2 @@ /// <reference types="node" /> | ||
gasRefund?: bigint; | ||
versionedHashes?: Buffer[]; | ||
} | ||
@@ -42,3 +41,2 @@ export declare class Message { | ||
salt?: Buffer; | ||
containerCode?: Buffer; /** container code for EOF1 contracts - used by CODECOPY/CODESIZE */ | ||
/** | ||
@@ -60,6 +58,2 @@ * Map of addresses to selfdestruct. Key is the unprefixed address. | ||
gasRefund: bigint; | ||
/** | ||
* List of versioned hashes if message is a blob transaction in the outer VM | ||
*/ | ||
versionedHashes?: Buffer[]; | ||
constructor(opts: MessageOpts); | ||
@@ -66,0 +60,0 @@ /** |
@@ -32,3 +32,2 @@ "use strict"; | ||
this.gasRefund = opts.gasRefund ?? defaults.gasRefund; | ||
this.versionedHashes = opts.versionedHashes; | ||
if (this.value < 0) { | ||
@@ -35,0 +34,0 @@ throw new Error(`value field cannot be negative, received ${this.value}`); |
@@ -16,3 +16,3 @@ "use strict"; | ||
this.dynamicGas = dynamicGas; | ||
// Opcode isn't subject to change, thus all further modifications are prevented. | ||
// Opcode isn't subject to change, thus all futher modifications are prevented. | ||
Object.freeze(this); | ||
@@ -252,11 +252,5 @@ } | ||
}, | ||
{ | ||
eip: 4844, | ||
opcodes: { | ||
0x49: { name: 'DATAHASH', isAsync: false, dynamicGas: false }, | ||
}, | ||
}, | ||
]; | ||
/** | ||
* Convert basic opcode info dictionary into complete OpcodeList instance. | ||
* Convert basic opcode info dictonary into complete OpcodeList instance. | ||
* | ||
@@ -263,0 +257,0 @@ * @param opcodes {Object} Receive basic opcodes info dictionary. |
@@ -148,3 +148,3 @@ "use strict"; | ||
} | ||
const r = (0, util_1.exponentiation)(base, exponent); | ||
const r = (0, util_1.exponentation)(base, exponent); | ||
runState.stack.push(r); | ||
@@ -422,2 +422,3 @@ }, | ||
const dataLengthNum = Number(dataLength); | ||
runState.memory.extend(memOffsetNum, dataLengthNum); | ||
runState.memory.write(memOffsetNum, dataLengthNum, data); | ||
@@ -443,2 +444,3 @@ } | ||
const lengthNum = Number(dataLength); | ||
runState.memory.extend(memOffsetNum, lengthNum); | ||
runState.memory.write(memOffsetNum, lengthNum, data); | ||
@@ -467,2 +469,3 @@ } | ||
const lengthNum = Number(dataLength); | ||
runState.memory.extend(memOffsetNum, lengthNum); | ||
runState.memory.write(memOffsetNum, lengthNum, data); | ||
@@ -478,8 +481,10 @@ } | ||
const address = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(addressBigInt)); | ||
const account = await runState.eei.getAccount(address); | ||
if (account.isEmpty()) { | ||
const empty = (await runState.eei.getAccount(address)).isEmpty(); | ||
if (empty) { | ||
runState.stack.push(BigInt(0)); | ||
return; | ||
} | ||
runState.stack.push(BigInt('0x' + account.codeHash.toString('hex'))); | ||
const codeHash = (await runState.eei.getAccount(new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(addressBigInt)))) | ||
.codeHash; | ||
runState.stack.push(BigInt('0x' + codeHash.toString('hex'))); | ||
}, | ||
@@ -503,2 +508,3 @@ ], | ||
const lengthNum = Number(dataLength); | ||
runState.memory.extend(memOffsetNum, lengthNum); | ||
runState.memory.write(memOffsetNum, lengthNum, data); | ||
@@ -592,15 +598,2 @@ } | ||
], | ||
// 0x49: DATAHASH | ||
[ | ||
0x49, | ||
function (runState) { | ||
const index = runState.stack.pop(); | ||
if (runState.env.versionedHashes.length > Number(index)) { | ||
runState.stack.push((0, ethereumjs_util_1.bufferToBigInt)(runState.env.versionedHashes[Number(index)])); | ||
} | ||
else { | ||
runState.stack.push(BigInt(0)); | ||
} | ||
}, | ||
], | ||
// 0x50 range - 'storage' and execution | ||
@@ -630,2 +623,3 @@ // 0x50: POP | ||
const offsetNum = Number(offset); | ||
runState.memory.extend(offsetNum, 32); | ||
runState.memory.write(offsetNum, 32, buf); | ||
@@ -641,2 +635,3 @@ }, | ||
const offsetNum = Number(offset); | ||
runState.memory.extend(offsetNum, 1); | ||
runState.memory.write(offsetNum, 1, buf); | ||
@@ -778,3 +773,5 @@ }, | ||
} | ||
const loaded = (0, ethereumjs_util_1.bufferToBigInt)(runState.code.slice(runState.programCounter, runState.programCounter + numToPush)); | ||
const loaded = (0, ethereumjs_util_1.bufferToBigInt)(runState.interpreter | ||
.getCode() | ||
.slice(runState.programCounter, runState.programCounter + numToPush)); | ||
runState.programCounter += numToPush; | ||
@@ -781,0 +778,0 @@ runState.stack.push(loaded); |
@@ -239,6 +239,2 @@ "use strict"; | ||
} | ||
if (common.isActivatedEIP(3860) === true) { | ||
gas += | ||
((length + BigInt(31)) / BigInt(32)) * common.param('gasPrices', 'initCodeWordCost'); | ||
} | ||
gas += (0, util_1.subMemUsage)(runState, offset, length, common); | ||
@@ -369,6 +365,2 @@ let gasLimit = BigInt(runState.interpreter.getGasLeft()) - gas; | ||
} | ||
if (common.isActivatedEIP(3860) === true) { | ||
gas += | ||
((length + BigInt(31)) / BigInt(32)) * common.param('gasPrices', 'initCodeWordCost'); | ||
} | ||
gas += common.param('gasPrices', 'sha3Word') * (0, util_1.divCeil)(length, BigInt(32)); | ||
@@ -375,0 +367,0 @@ let gasLimit = runState.interpreter.getGasLeft() - gas; |
@@ -76,3 +76,3 @@ /// <reference types="node" /> | ||
export declare function abs(a: bigint): bigint; | ||
export declare function exponentiation(bas: bigint, exp: bigint): bigint; | ||
export declare function exponentation(bas: bigint, exp: bigint): bigint; | ||
//# sourceMappingURL=util.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.exponentiation = exports.abs = exports.toTwos = exports.fromTwos = exports.mod = exports.updateSstoreGas = exports.writeCallOutput = exports.subMemUsage = exports.maxCallGas = exports.jumpSubIsValid = exports.jumpIsValid = exports.getFullname = exports.getDataSlice = exports.divCeil = exports.describeLocation = exports.addressToBuffer = exports.trap = exports.setLengthLeftStorage = void 0; | ||
exports.exponentation = exports.abs = exports.toTwos = exports.fromTwos = exports.mod = exports.updateSstoreGas = exports.writeCallOutput = exports.subMemUsage = exports.maxCallGas = exports.jumpSubIsValid = exports.jumpIsValid = exports.getFullname = exports.getDataSlice = exports.divCeil = exports.describeLocation = exports.addressToBuffer = exports.trap = exports.setLengthLeftStorage = void 0; | ||
const ethereumjs_common_1 = require("@nomicfoundation/ethereumjs-common"); | ||
@@ -235,3 +235,3 @@ const ethereumjs_util_1 = require("@nomicfoundation/ethereumjs-util"); | ||
const N = BigInt(115792089237316195423570985008687907853269984665640564039457584007913129639936); | ||
function exponentiation(bas, exp) { | ||
function exponentation(bas, exp) { | ||
let t = BigInt(1); | ||
@@ -247,3 +247,3 @@ while (exp > BigInt(0)) { | ||
} | ||
exports.exponentiation = exponentiation; | ||
exports.exponentation = exponentation; | ||
//# sourceMappingURL=util.js.map |
import { Address } from '@nomicfoundation/ethereumjs-util'; | ||
import type { PrecompileFunc, PrecompileInput } from './types'; | ||
import { PrecompileFunc, PrecompileInput } from './types'; | ||
import type { Common } from '@nomicfoundation/ethereumjs-common'; | ||
@@ -18,4 +18,3 @@ interface Precompiles { | ||
declare function getActivePrecompiles(common: Common, customPrecompiles?: CustomPrecompile[]): Map<string, PrecompileFunc>; | ||
export { getActivePrecompiles, precompiles, ripemdPrecompileAddress }; | ||
export type { AddPrecompile, CustomPrecompile, DeletePrecompile, PrecompileFunc, PrecompileInput }; | ||
export { AddPrecompile, CustomPrecompile, DeletePrecompile, getActivePrecompiles, PrecompileFunc, PrecompileInput, precompiles, ripemdPrecompileAddress, }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -125,6 +125,2 @@ "use strict"; | ||
}, | ||
'0000000000000000000000000000000000000014': { | ||
type: PrecompileAvailabilityCheck.EIP, | ||
param: 4844, | ||
}, | ||
}; | ||
@@ -138,3 +134,3 @@ function getPrecompile(address, common) { | ||
(availability.type === PrecompileAvailabilityCheck.EIP && | ||
common.isActivatedEIP(availability.param))) { | ||
common.eips().includes(availability.param))) { | ||
return precompiles[addr]; | ||
@@ -141,0 +137,0 @@ } |
@@ -5,5 +5,6 @@ /// <reference types="node" /> | ||
import type { Message } from './message'; | ||
import type { OpHandler, OpcodeList } from './opcodes'; | ||
import type { OpHandler } from './opcodes'; | ||
import type { AsyncDynamicGasHandler, SyncDynamicGasHandler } from './opcodes/gas'; | ||
import type { Account, Address, AsyncEventEmitter, PrefixedHexString } from '@nomicfoundation/ethereumjs-util'; | ||
import type { Account, Address, PrefixedHexString } from '@nomicfoundation/ethereumjs-util'; | ||
import type AsyncEventEmitter from 'async-eventemitter'; | ||
/** | ||
@@ -15,3 +16,2 @@ * API of the EVM | ||
runCode?(opts: EVMRunCodeOpts): Promise<ExecResult>; | ||
getActiveOpcodes?(): OpcodeList; | ||
precompiles: Map<string, any>; | ||
@@ -144,6 +144,2 @@ copy(): EVMInterface; | ||
message?: Message; | ||
/** | ||
* Versioned hashes for each blob in a blob transaction | ||
*/ | ||
versionedHashes?: Buffer[]; | ||
} | ||
@@ -212,6 +208,2 @@ /** | ||
pc?: number; | ||
/** | ||
* Versioned hashes for each blob in a blob transaction | ||
*/ | ||
versionedHashes?: Buffer[]; | ||
} | ||
@@ -218,0 +210,0 @@ interface NewContractEvent { |
{ | ||
"name": "@nomicfoundation/ethereumjs-evm", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "JavaScript Ethereum Virtual Machine (EVM) implementation", | ||
@@ -33,4 +33,4 @@ "keywords": [ | ||
"clean": "../../config/cli/clean-package.sh", | ||
"coverage": "c8 --all --reporter=lcov --reporter=text npm run coverage:test", | ||
"coverage:test": "npm run test && cd ../vm && npm run tester -- --state", | ||
"coverage": "c8 --all --reporter=lcov --reporter=text --reporter=text-lcov npm run coverage:test", | ||
"coverage:test": "npm run test; cd ../vm; npm run tester -- --state", | ||
"docs:build": "typedoc --options typedoc.js", | ||
@@ -44,3 +44,3 @@ "examples": "ts-node ../../scripts/examples-runner.ts -- evm", | ||
"tape": "tape -r ts-node/register --stack-size=1500", | ||
"test": "npm run tape -- './test/**/*.spec.ts'", | ||
"test": "npm run tape -- './tests/**/*.spec.ts'", | ||
"test:browser": "karma start karma.conf.js", | ||
@@ -50,6 +50,6 @@ "tsc": "../../config/cli/ts-compile.sh" | ||
"dependencies": { | ||
"@nomicfoundation/ethereumjs-common": "3.1.1", | ||
"@nomicfoundation/ethereumjs-tx": "4.1.1", | ||
"@nomicfoundation/ethereumjs-util": "8.0.5", | ||
"@ethersproject/providers": "^5.7.1", | ||
"@nomicfoundation/ethereumjs-common": "3.1.2", | ||
"@nomicfoundation/ethereumjs-util": "8.0.6", | ||
"@types/async-eventemitter": "^0.2.1", | ||
"async-eventemitter": "^0.2.4", | ||
"debug": "^4.3.3", | ||
@@ -61,3 +61,3 @@ "ethereum-cryptography": "0.1.3", | ||
"devDependencies": { | ||
"@nomicfoundation/ethereumjs-statemanager": "1.0.4", | ||
"@nomicfoundation/ethereumjs-statemanager": "1.0.5", | ||
"@ethersproject/abi": "^5.0.12", | ||
@@ -70,3 +70,2 @@ "@types/benchmark": "^1.0.33", | ||
"benchmark": "^2.1.4", | ||
"c-kzg": "^1.0.8", | ||
"level": "^8.0.0", | ||
@@ -73,0 +72,0 @@ "memory-level": "^1.0.0", |
@@ -24,4 +24,2 @@ # @ethereumjs/evm | ||
**Note:** If you want to work with `EIP-4844` related functionality, you will have additional manual installation steps for the **KZG setup**, see related section below. | ||
## Usage | ||
@@ -81,3 +79,3 @@ | ||
1. [./examples/decode-opcodes](./examples/decode-opcodes.ts): Decodes a binary EVM program into its opcodes. | ||
1. [./examples/runCode](./examples/runCode.ts): Show how to use this library in a browser. | ||
1. [./examples/run-code-browser](./examples/run-code-browser.js): Show how to use this library in a browser. | ||
@@ -161,3 +159,2 @@ All of the examples have their own `README.md` explaining how to run them. | ||
- [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) - Transient Storage Opcodes (`experimental`) | ||
- [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) - Fee Market (`london` EIP) | ||
@@ -175,27 +172,6 @@ - [EIP-2315](https://eips.ethereum.org/EIPS/eip-2315) - Simple subroutines (`experimental`) | ||
- [EIP-3670](https://eips.ethereum.org/EIPS/eip-3670) - EOF - Code Validation (`experimental`) | ||
- [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction | ||
- [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) - Limit and meter initcode | ||
- [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) - Supplant DIFFICULTY opcode with PREVRANDAO (Merge) | ||
- [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) - Shard Blob Transactions (`experimental`) | ||
- [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) - Beacon chain push withdrawals as operations | ||
- [EIP-5133](https://eips.ethereum.org/EIPS/eip-5133) - Delaying Difficulty Bomb to mid-September 2022 | ||
- [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction (`experimental`) | ||
- [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) - Limit and meter initcode (`experimental`) | ||
- [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) - Supplant DIFFICULTY opcode with PREVRANDAO (Merge) (`experimental`) | ||
### EIP-4844 Shard Blob Transactions Support (experimental) | ||
This library supports an experimental version of the blob transaction type introduced with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) as being specified in the [01d3209](https://github.com/ethereum/EIPs/commit/01d320998d1d53d95f347b5f43feaf606f230703) EIP version from February 8, 2023 and deployed along `eip4844-devnet-4` (January 2023) starting with `v1.3.0`. | ||
#### Initialization | ||
To run EVM related EIP-4844 functionality you have to active the EIP in the associated `@ethereumjs/common` library: | ||
```typescript | ||
import { Common, Chain, Hardfork } from '@ethereumjs/common' | ||
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Shanghai, eips: [4844] }) | ||
``` | ||
EIP-4844 comes with a new opcode `DATAHASH` and adds a new point evaluation precompile at address `0x14`. | ||
**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. | ||
### Tracing Events | ||
@@ -236,5 +212,5 @@ | ||
If an exception is thrown from within the handler or a function called | ||
If an exception is thrown from withing the handler or a function called | ||
by it, the exception will bubble into the EVM and interrupt it, possibly | ||
corrupting its state. It's strongly recommended not to throw from within | ||
corrupting its state. It's strongly recommended not to throw from withing | ||
event handlers. | ||
@@ -244,3 +220,3 @@ | ||
If you want to understand your EVM runs we have added a hierarchically structured list of debug loggers for your convenience which can be activated in arbitrary combinations. We also use these loggers internally for development and testing. These loggers use the [debug](https://github.com/visionmedia/debug) library and can be activated on the CL with `DEBUG=ethjs,[Logger Selection] node [Your Script to Run].js` and produce output like the following: | ||
If you want to understand your EVM runs we have added a hierarchically structured list of debug loggers for your convenience which can be activated in arbitrary combinations. We also use these loggers internally for development and testing. These loggers use the [debug](https://github.com/visionmedia/debug) library and can be activated on the CL with `DEBUG=[Logger Selection] node [Your Script to Run].js` and produce output like the following: | ||
@@ -264,3 +240,3 @@ ![EthereumJS EVM Debug Logger](./debug.png?raw=true) | ||
```shell | ||
DEBUG=ethjs,evm ts-node test.ts | ||
DEBUG=evm ts-node test.ts | ||
``` | ||
@@ -271,3 +247,3 @@ | ||
```shell | ||
DEBUG=ethjs,evm:*,evm:*:* ts-node test.ts | ||
DEBUG=evm:*,evm:*:* ts-node test.ts | ||
``` | ||
@@ -278,3 +254,3 @@ | ||
```shell | ||
DEBUG=ethjs,evm:*:gas ts-node test.ts | ||
DEBUG=evm:*:gas ts-node test.ts | ||
``` | ||
@@ -285,3 +261,3 @@ | ||
```shell | ||
DEBUG=ethjs,evm:*,evm:*:*,-evm:ops ts-node test.ts | ||
DEBUG=evm:*,evm:*:*,-evm:ops ts-node test.ts | ||
``` | ||
@@ -292,3 +268,3 @@ | ||
```shell | ||
DEBUG=ethjs,evm,evm:ops:sstore,evm:*:gas ts-node test.ts | ||
DEBUG=evm,evm:ops:sstore,evm:*:gas ts-node test.ts | ||
``` | ||
@@ -295,0 +271,0 @@ |
@@ -24,3 +24,3 @@ import { handlers } from './opcodes' | ||
} | ||
if (container[0] !== FORMAT || container[1] !== MAGIC || container[2] !== VERSION) | ||
if (container[1] !== MAGIC || container[2] !== VERSION) | ||
// Bytecode does not contain EOF1 "magic" or version number in expected positions | ||
@@ -96,12 +96,2 @@ return | ||
export const getEOFCode = (code: Buffer) => { | ||
const sectionSizes = codeAnalysis(code) | ||
if (sectionSizes === undefined) { | ||
return code | ||
} else { | ||
const codeStart = sectionSizes.data > 0 ? 10 : 7 | ||
return code.slice(codeStart, codeStart + sectionSizes.code) | ||
} | ||
} | ||
export const EOF = { FORMAT, MAGIC, VERSION, codeAnalysis, validOpcodes } |
121
src/evm.ts
import { Chain, Common, Hardfork } from '@nomicfoundation/ethereumjs-common' | ||
import { | ||
Address, | ||
AsyncEventEmitter, | ||
KECCAK256_NULL, | ||
@@ -13,6 +12,7 @@ MAX_INTEGER, | ||
} from '@nomicfoundation/ethereumjs-util' | ||
import AsyncEventEmitter = require('async-eventemitter') | ||
import { debug as createDebugLogger } from 'debug' | ||
import { promisify } from 'util' | ||
import { EOF, getEOFCode } from './eof' | ||
import { EOF } from './eof' | ||
import { ERROR, EvmError } from './exceptions' | ||
@@ -80,7 +80,5 @@ import { Interpreter } from './interpreter' | ||
* - [EIP-3670](https://eips.ethereum.org/EIPS/eip-3670) - EOF - Code Validation (`experimental`) | ||
* - [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction | ||
* - [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) - Limit and meter initcode | ||
* - [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) - Supplant DIFFICULTY opcode with PREVRANDAO (Merge) | ||
* - [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) - Shard Blob Transactions (`experimental`) | ||
* - [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) - Beacon chain push withdrawals as operations | ||
* - [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction (`experimental`) | ||
* - [EIP-3860](https://eips.ethereum.org/EIPS/eip-3860) - Limit and meter initcode (`experimental`) | ||
* - [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) - Supplant DIFFICULTY opcode with PREVRANDAO (Merge) (`experimental`) | ||
* - [EIP-5133](https://eips.ethereum.org/EIPS/eip-5133) - Delaying Difficulty Bomb to mid-September 2022 | ||
@@ -145,22 +143,2 @@ * | ||
export class EVM implements EVMInterface { | ||
private static supportedHardforks = [ | ||
Hardfork.Chainstart, | ||
Hardfork.Homestead, | ||
Hardfork.Dao, | ||
Hardfork.TangerineWhistle, | ||
Hardfork.SpuriousDragon, | ||
Hardfork.Byzantium, | ||
Hardfork.Constantinople, | ||
Hardfork.Petersburg, | ||
Hardfork.Istanbul, | ||
Hardfork.MuirGlacier, | ||
Hardfork.Berlin, | ||
Hardfork.London, | ||
Hardfork.ArrowGlacier, | ||
Hardfork.GrayGlacier, | ||
Hardfork.MergeForkIdTransition, | ||
Hardfork.Merge, | ||
Hardfork.Shanghai, | ||
Hardfork.ShardingForkDev, | ||
] | ||
protected _tx?: { | ||
@@ -216,2 +194,9 @@ gasPrice: bigint | ||
/** | ||
* Cached emit() function, not for public usage | ||
* set to public due to implementation internals | ||
* @hidden | ||
*/ | ||
public readonly _emit: (topic: string, data: any) => Promise<void> | ||
/** | ||
* Pointer to the mcl package, not for public usage | ||
@@ -233,4 +218,2 @@ * set to public due to implementation internals | ||
public readonly _emit: (topic: string, data: any) => Promise<void> | ||
/** | ||
@@ -248,3 +231,3 @@ * EVM async constructor. Creates engine instance and initializes it. | ||
constructor(opts: EVMOpts) { | ||
this.events = new AsyncEventEmitter() | ||
this.events = new AsyncEventEmitter<EVMEvents>() | ||
@@ -267,3 +250,3 @@ this._optsCached = opts | ||
1153, 1559, 2315, 2537, 2565, 2718, 2929, 2930, 3074, 3198, 3529, 3540, 3541, 3607, 3651, | ||
3670, 3855, 3860, 4399, 4895, 4844, 5133, | ||
3670, 3855, 3860, 4399, 5133, | ||
] | ||
@@ -277,3 +260,21 @@ | ||
if (!EVM.supportedHardforks.includes(this._common.hardfork() as Hardfork)) { | ||
const supportedHardforks = [ | ||
Hardfork.Chainstart, | ||
Hardfork.Homestead, | ||
Hardfork.Dao, | ||
Hardfork.TangerineWhistle, | ||
Hardfork.SpuriousDragon, | ||
Hardfork.Byzantium, | ||
Hardfork.Constantinople, | ||
Hardfork.Petersburg, | ||
Hardfork.Istanbul, | ||
Hardfork.MuirGlacier, | ||
Hardfork.Berlin, | ||
Hardfork.London, | ||
Hardfork.ArrowGlacier, | ||
Hardfork.GrayGlacier, | ||
Hardfork.MergeForkIdTransition, | ||
Hardfork.Merge, | ||
] | ||
if (!supportedHardforks.includes(this._common.hardfork() as Hardfork)) { | ||
throw new Error( | ||
@@ -305,2 +306,7 @@ `Hardfork ${this._common.hardfork()} not set as supported in supportedHardforks` | ||
// Safeguard if "process" is not available (browser) | ||
if (typeof process?.env.DEBUG !== 'undefined') { | ||
this.DEBUG = true | ||
} | ||
// We cache this promisified function as it's called from the main execution loop, and | ||
@@ -311,5 +317,2 @@ // promisifying each time has a huge performance impact. | ||
) | ||
// Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables | ||
this.DEBUG = process?.env?.DEBUG?.includes('ethjs') ?? false | ||
} | ||
@@ -429,3 +432,3 @@ | ||
if (this._common.isActivatedEIP(3860) && !this._allowUnlimitedContractSize) { | ||
if (this._common.isActivatedEIP(3860)) { | ||
if (message.data.length > Number(this._common.param('vm', 'maxInitCodeSize'))) { | ||
@@ -617,3 +620,3 @@ return { | ||
// This contract would be considered "DEAD" in later hard forks. | ||
// It is thus an unnecessary default item, which we have to save to dik | ||
// It is thus an unecessary default item, which we have to save to dik | ||
// It does change the state root, but it only wastes storage. | ||
@@ -654,4 +657,2 @@ //await this._state.putContractCode(message.to, result.returnValue) | ||
gasRefund: message.gasRefund, | ||
containerCode: message.containerCode, | ||
versionedHashes: message.versionedHashes ?? [], | ||
} | ||
@@ -706,3 +707,2 @@ | ||
let message = opts.message | ||
let callerAccount | ||
if (!message) { | ||
@@ -714,2 +714,3 @@ this._block = opts.block ?? defaultBlock() | ||
} | ||
const caller = opts.caller ?? Address.zero() | ||
@@ -719,3 +720,3 @@ | ||
if (opts.skipBalance === true) { | ||
callerAccount = await this.eei.getAccount(caller) | ||
const callerAccount = await this.eei.getAccount(caller) | ||
if (callerAccount.balance < value) { | ||
@@ -741,17 +742,5 @@ // if skipBalance and balance less than value, set caller balance to `value` to ensure sufficient funds | ||
delegatecall: opts.delegatecall, | ||
versionedHashes: opts.versionedHashes, | ||
}) | ||
} | ||
if (message.depth === 0) { | ||
if (!callerAccount) { | ||
callerAccount = await this.eei.getAccount(message.caller) | ||
} | ||
callerAccount.nonce++ | ||
await this.eei.putAccount(message.caller, callerAccount) | ||
if (this.DEBUG) { | ||
debug(`Update fromAccount (caller) nonce (-> ${callerAccount.nonce}))`) | ||
} | ||
} | ||
await this._emit('beforeMessage', message) | ||
@@ -802,6 +791,3 @@ | ||
// If that is the case, then all refunds are forfeited | ||
// There is one exception: if the CODESTORE_OUT_OF_GAS error is thrown | ||
// (this only happens the Frontier/Chainstart fork) | ||
// then the error is dismissed | ||
if (err && err.error !== ERROR.CODESTORE_OUT_OF_GAS) { | ||
if (err) { | ||
result.execResult.selfdestruct = {} | ||
@@ -864,3 +850,2 @@ result.execResult.gasRefund = BigInt(0) | ||
isStatic: opts.isStatic, | ||
versionedHashes: opts.versionedHashes, | ||
}) | ||
@@ -908,9 +893,4 @@ | ||
} else { | ||
message.containerCode = await this.eei.getContractCode(message.codeAddress) | ||
message.code = await this.eei.getContractCode(message.codeAddress) | ||
message.isCompiled = false | ||
if (this._common.isActivatedEIP(3540)) { | ||
message.code = getEOFCode(message.containerCode) | ||
} else { | ||
message.code = message.containerCode | ||
} | ||
} | ||
@@ -926,3 +906,6 @@ } | ||
const acc = await this.eei.getAccount(message.caller) | ||
const newNonce = acc.nonce - BigInt(1) | ||
let newNonce = acc.nonce | ||
if (message.depth > 0) { | ||
newNonce-- | ||
} | ||
addr = generateAddress(message.caller.buf, bigIntToBuffer(newNonce)) | ||
@@ -971,12 +954,8 @@ } | ||
public copy(): EVMInterface { | ||
const common = this._common.copy() | ||
common.setHardfork(this._common.hardfork()) | ||
public copy() { | ||
const opts = { | ||
...this._optsCached, | ||
common, | ||
common: this._common.copy(), | ||
eei: this.eei.copy(), | ||
} | ||
;(opts.eei as any)._common = common | ||
return new EVM(opts) | ||
@@ -983,0 +962,0 @@ } |
@@ -34,6 +34,2 @@ export enum ERROR { | ||
BLS_12_381_FP_NOT_IN_FIELD = 'fp point not in field', | ||
// Point Evaluation Errors | ||
POINT_GREATER_THAN_BLS_MODULUS = 'point greater than BLS modulus', | ||
INVALID_COMMITMENT = 'kzg commitment does not match versioned hash', | ||
} | ||
@@ -40,0 +36,0 @@ |
@@ -50,4 +50,2 @@ import { ConsensusAlgorithm } from '@nomicfoundation/ethereumjs-common' | ||
gasRefund: bigint /* Current value (at begin of the frame) of the gas refund */ | ||
containerCode?: Buffer /** Full container code for EOF1 contracts */ | ||
versionedHashes: Buffer[] /** Versioned hashes for blob transactions */ | ||
} | ||
@@ -362,3 +360,3 @@ | ||
*/ | ||
await this._evm._emit('step', eventObj) | ||
return this._evm._emit('step', eventObj) | ||
} | ||
@@ -579,3 +577,3 @@ | ||
getCodeSize(): bigint { | ||
return BigInt(this._env.containerCode ? this._env.containerCode.length : this._env.code.length) | ||
return BigInt(this._env.code.length) | ||
} | ||
@@ -587,3 +585,3 @@ | ||
getCode(): Buffer { | ||
return this._env.containerCode ?? this._env.code | ||
return this._env.code | ||
} | ||
@@ -881,3 +879,3 @@ | ||
if (this._common.isActivatedEIP(3860) && !this._evm._allowUnlimitedContractSize) { | ||
if (this._common.isActivatedEIP(3860)) { | ||
if (data.length > Number(this._common.param('vm', 'maxInitCodeSize'))) { | ||
@@ -884,0 +882,0 @@ return BigInt(0) |
@@ -10,4 +10,2 @@ const ceil = (value: number, ceiling: number): number => { | ||
const CONTAINER_SIZE = 8192 | ||
/** | ||
@@ -36,6 +34,3 @@ * Memory implements a simple memory model | ||
if (sizeDiff > 0) { | ||
this._store = Buffer.concat([ | ||
this._store, | ||
Buffer.alloc(Math.ceil(sizeDiff / CONTAINER_SIZE) * CONTAINER_SIZE), | ||
]) | ||
this._store = Buffer.concat([this._store, Buffer.alloc(sizeDiff)]) | ||
} | ||
@@ -60,3 +55,5 @@ } | ||
value.copy(this._store, offset) | ||
for (let i = 0; i < size; i++) { | ||
this._store[offset + i] = value[i] | ||
} | ||
} | ||
@@ -63,0 +60,0 @@ |
@@ -35,3 +35,2 @@ import { Address } from '@nomicfoundation/ethereumjs-util' | ||
gasRefund?: bigint | ||
versionedHashes?: Buffer[] | ||
} | ||
@@ -51,3 +50,2 @@ | ||
salt?: Buffer | ||
containerCode?: Buffer /** container code for EOF1 contracts - used by CODECOPY/CODESIZE */ | ||
/** | ||
@@ -65,6 +63,2 @@ * Map of addresses to selfdestruct. Key is the unprefixed address. | ||
gasRefund: bigint // Keeps track of the gasRefund at the start of the frame (used for journaling purposes) | ||
/** | ||
* List of versioned hashes if message is a blob transaction in the outer VM | ||
*/ | ||
versionedHashes?: Buffer[] | ||
@@ -87,3 +81,3 @@ constructor(opts: MessageOpts) { | ||
this.gasRefund = opts.gasRefund ?? defaults.gasRefund | ||
this.versionedHashes = opts.versionedHashes | ||
if (this.value < 0) { | ||
@@ -90,0 +84,0 @@ throw new Error(`value field cannot be negative, received ${this.value}`) |
@@ -42,3 +42,3 @@ import { Hardfork } from '@nomicfoundation/ethereumjs-common' | ||
// Opcode isn't subject to change, thus all further modifications are prevented. | ||
// Opcode isn't subject to change, thus all futher modifications are prevented. | ||
Object.freeze(this) | ||
@@ -295,12 +295,6 @@ } | ||
}, | ||
{ | ||
eip: 4844, | ||
opcodes: { | ||
0x49: { name: 'DATAHASH', isAsync: false, dynamicGas: false }, | ||
}, | ||
}, | ||
] | ||
/** | ||
* Convert basic opcode info dictionary into complete OpcodeList instance. | ||
* Convert basic opcode info dictonary into complete OpcodeList instance. | ||
* | ||
@@ -307,0 +301,0 @@ * @param opcodes {Object} Receive basic opcodes info dictionary. |
@@ -20,3 +20,3 @@ import { | ||
describeLocation, | ||
exponentiation, | ||
exponentation, | ||
fromTwos, | ||
@@ -181,3 +181,3 @@ getDataSlice, | ||
} | ||
const r = exponentiation(base, exponent) | ||
const r = exponentation(base, exponent) | ||
runState.stack.push(r) | ||
@@ -459,2 +459,3 @@ }, | ||
const dataLengthNum = Number(dataLength) | ||
runState.memory.extend(memOffsetNum, dataLengthNum) | ||
runState.memory.write(memOffsetNum, dataLengthNum, data) | ||
@@ -481,2 +482,3 @@ } | ||
const lengthNum = Number(dataLength) | ||
runState.memory.extend(memOffsetNum, lengthNum) | ||
runState.memory.write(memOffsetNum, lengthNum, data) | ||
@@ -509,2 +511,3 @@ } | ||
const lengthNum = Number(dataLength) | ||
runState.memory.extend(memOffsetNum, lengthNum) | ||
runState.memory.write(memOffsetNum, lengthNum, data) | ||
@@ -520,4 +523,4 @@ } | ||
const address = new Address(addressToBuffer(addressBigInt)) | ||
const account = await runState.eei.getAccount(address) | ||
if (account.isEmpty()) { | ||
const empty = (await runState.eei.getAccount(address)).isEmpty() | ||
if (empty) { | ||
runState.stack.push(BigInt(0)) | ||
@@ -527,3 +530,5 @@ return | ||
runState.stack.push(BigInt('0x' + account.codeHash.toString('hex'))) | ||
const codeHash = (await runState.eei.getAccount(new Address(addressToBuffer(addressBigInt)))) | ||
.codeHash | ||
runState.stack.push(BigInt('0x' + codeHash.toString('hex'))) | ||
}, | ||
@@ -552,2 +557,3 @@ ], | ||
const lengthNum = Number(dataLength) | ||
runState.memory.extend(memOffsetNum, lengthNum) | ||
runState.memory.write(memOffsetNum, lengthNum, data) | ||
@@ -642,14 +648,2 @@ } | ||
], | ||
// 0x49: DATAHASH | ||
[ | ||
0x49, | ||
function (runState) { | ||
const index = runState.stack.pop() | ||
if (runState.env.versionedHashes.length > Number(index)) { | ||
runState.stack.push(bufferToBigInt(runState.env.versionedHashes[Number(index)])) | ||
} else { | ||
runState.stack.push(BigInt(0)) | ||
} | ||
}, | ||
], | ||
// 0x50 range - 'storage' and execution | ||
@@ -679,2 +673,3 @@ // 0x50: POP | ||
const offsetNum = Number(offset) | ||
runState.memory.extend(offsetNum, 32) | ||
runState.memory.write(offsetNum, 32, buf) | ||
@@ -691,2 +686,3 @@ }, | ||
const offsetNum = Number(offset) | ||
runState.memory.extend(offsetNum, 1) | ||
runState.memory.write(offsetNum, 1, buf) | ||
@@ -842,5 +838,6 @@ }, | ||
} | ||
const loaded = bufferToBigInt( | ||
runState.code.slice(runState.programCounter, runState.programCounter + numToPush) | ||
runState.interpreter | ||
.getCode() | ||
.slice(runState.programCounter, runState.programCounter + numToPush) | ||
) | ||
@@ -847,0 +844,0 @@ runState.programCounter += numToPush |
@@ -298,7 +298,2 @@ import { Hardfork } from '@nomicfoundation/ethereumjs-common' | ||
if (common.isActivatedEIP(3860) === true) { | ||
gas += | ||
((length + BigInt(31)) / BigInt(32)) * common.param('gasPrices', 'initCodeWordCost') | ||
} | ||
gas += subMemUsage(runState, offset, length, common) | ||
@@ -467,7 +462,2 @@ | ||
if (common.isActivatedEIP(3860) === true) { | ||
gas += | ||
((length + BigInt(31)) / BigInt(32)) * common.param('gasPrices', 'initCodeWordCost') | ||
} | ||
gas += common.param('gasPrices', 'sha3Word') * divCeil(length, BigInt(32)) | ||
@@ -474,0 +464,0 @@ let gasLimit = runState.interpreter.getGasLeft() - gas |
@@ -253,3 +253,3 @@ import { Hardfork } from '@nomicfoundation/ethereumjs-common' | ||
const N = BigInt(115792089237316195423570985008687907853269984665640564039457584007913129639936) | ||
export function exponentiation(bas: bigint, exp: bigint) { | ||
export function exponentation(bas: bigint, exp: bigint) { | ||
let t = BigInt(1) | ||
@@ -256,0 +256,0 @@ while (exp > BigInt(0)) { |
@@ -22,4 +22,4 @@ import { Hardfork } from '@nomicfoundation/ethereumjs-common' | ||
import { precompile12 } from './12-bls12-map-fp2-to-g2' | ||
import { PrecompileFunc, PrecompileInput } from './types' | ||
import type { PrecompileFunc, PrecompileInput } from './types' | ||
import type { Common } from '@nomicfoundation/ethereumjs-common' | ||
@@ -149,6 +149,2 @@ | ||
}, | ||
'0000000000000000000000000000000000000014': { | ||
type: PrecompileAvailabilityCheck.EIP, | ||
param: 4844, | ||
}, | ||
} | ||
@@ -164,3 +160,3 @@ | ||
(availability.type === PrecompileAvailabilityCheck.EIP && | ||
common.isActivatedEIP(availability.param)) | ||
common.eips().includes(availability.param)) | ||
) { | ||
@@ -210,4 +206,11 @@ return precompiles[addr] | ||
export { getActivePrecompiles, precompiles, ripemdPrecompileAddress } | ||
export type { AddPrecompile, CustomPrecompile, DeletePrecompile, PrecompileFunc, PrecompileInput } | ||
export { | ||
AddPrecompile, | ||
CustomPrecompile, | ||
DeletePrecompile, | ||
getActivePrecompiles, | ||
PrecompileFunc, | ||
PrecompileInput, | ||
precompiles, | ||
ripemdPrecompileAddress, | ||
} |
import type { EVM, EVMResult, ExecResult } from './evm' | ||
import type { InterpreterStep } from './interpreter' | ||
import type { Message } from './message' | ||
import type { OpHandler, OpcodeList } from './opcodes' | ||
import type { OpHandler } from './opcodes' | ||
import type { AsyncDynamicGasHandler, SyncDynamicGasHandler } from './opcodes/gas' | ||
import type { | ||
Account, | ||
Address, | ||
AsyncEventEmitter, | ||
PrefixedHexString, | ||
} from '@nomicfoundation/ethereumjs-util' | ||
import type { Account, Address, PrefixedHexString } from '@nomicfoundation/ethereumjs-util' | ||
import type AsyncEventEmitter from 'async-eventemitter' | ||
@@ -19,3 +15,2 @@ /** | ||
runCode?(opts: EVMRunCodeOpts): Promise<ExecResult> | ||
getActiveOpcodes?(): OpcodeList | ||
precompiles: Map<string, any> // Note: the `any` type is used because EVM only needs to have the addresses of the precompiles (not their functions) | ||
@@ -152,6 +147,2 @@ copy(): EVMInterface | ||
message?: Message | ||
/** | ||
* Versioned hashes for each blob in a blob transaction | ||
*/ | ||
versionedHashes?: Buffer[] | ||
} | ||
@@ -219,6 +210,2 @@ | ||
pc?: number | ||
/** | ||
* Versioned hashes for each blob in a blob transaction | ||
*/ | ||
versionedHashes?: Buffer[] | ||
} | ||
@@ -225,0 +212,0 @@ |
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
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
13
759663
13848
308
+ Addedasync-eventemitter@^0.2.4
+ Added@nomicfoundation/ethereumjs-common@3.1.2(transitive)
+ Added@nomicfoundation/ethereumjs-rlp@4.0.3(transitive)
+ Added@nomicfoundation/ethereumjs-util@8.0.6(transitive)
+ Added@types/async-eventemitter@0.2.4(transitive)
+ Added@types/events@3.0.3(transitive)
+ Addedasync@2.6.4(transitive)
+ Addedasync-eventemitter@0.2.4(transitive)
+ Addedelliptic@6.5.7(transitive)
+ Addedlodash@4.17.21(transitive)
- Removed@ethersproject/providers@^5.7.1
- Removed@nomicfoundation/ethereumjs-tx@4.1.1
- Removed@chainsafe/as-sha256@0.3.1(transitive)
- Removed@chainsafe/persistent-merkle-tree@0.4.20.5.0(transitive)
- Removed@chainsafe/ssz@0.10.20.9.4(transitive)
- Removed@ethersproject/abstract-provider@5.7.0(transitive)
- Removed@ethersproject/abstract-signer@5.7.0(transitive)
- Removed@ethersproject/address@5.7.0(transitive)
- Removed@ethersproject/base64@5.7.0(transitive)
- Removed@ethersproject/basex@5.7.0(transitive)
- Removed@ethersproject/bignumber@5.7.0(transitive)
- Removed@ethersproject/bytes@5.7.0(transitive)
- Removed@ethersproject/constants@5.7.0(transitive)
- Removed@ethersproject/hash@5.7.0(transitive)
- Removed@ethersproject/keccak256@5.7.0(transitive)
- Removed@ethersproject/logger@5.7.0(transitive)
- Removed@ethersproject/networks@5.7.1(transitive)
- Removed@ethersproject/properties@5.7.0(transitive)
- Removed@ethersproject/providers@5.7.2(transitive)
- Removed@ethersproject/random@5.7.0(transitive)
- Removed@ethersproject/rlp@5.7.0(transitive)
- Removed@ethersproject/sha2@5.7.0(transitive)
- Removed@ethersproject/signing-key@5.7.0(transitive)
- Removed@ethersproject/strings@5.7.0(transitive)
- Removed@ethersproject/transactions@5.7.0(transitive)
- Removed@ethersproject/web@5.7.1(transitive)
- Removed@nomicfoundation/ethereumjs-common@3.1.1(transitive)
- Removed@nomicfoundation/ethereumjs-rlp@4.0.2(transitive)
- Removed@nomicfoundation/ethereumjs-tx@4.1.1(transitive)
- Removed@nomicfoundation/ethereumjs-util@8.0.5(transitive)
- Removedbech32@1.1.4(transitive)
- Removedbn.js@5.2.1(transitive)
- Removedcase@1.6.3(transitive)
- Removedelliptic@6.5.4(transitive)
- Removedjs-sha3@0.8.0(transitive)
- Removedws@7.4.6(transitive)