From e0fe6b8881db9227e55dce5effe30ef99d644ef8 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 17 May 2023 09:45:01 +0200 Subject: [PATCH 1/6] Common: remove deprecated nextHardforkBlock() and isNextHardforkBlock() methods --- packages/common/src/common.ts | 52 -------------------------- packages/common/test/hardforks.spec.ts | 22 ----------- 2 files changed, 74 deletions(-) diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index aa977ba2da..59d797ad5a 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -777,58 +777,6 @@ export class Common extends EventEmitter { return BigInt(nextHfBlock) } - /** - * Returns the change block for the next hardfork after the hardfork provided or set - * @param hardfork Hardfork name, optional if HF set - * @returns Block number or null if not available - * @deprecated - */ - nextHardforkBlock(hardfork?: string | Hardfork): bigint | null { - hardfork = hardfork ?? this._hardfork - let hfBlock = this.hardforkBlock(hardfork) - // If this is a merge hardfork with block not set, then we fallback to previous hardfork - // to find the nextHardforkBlock - if (hfBlock === null && hardfork === Hardfork.Paris) { - const hfs = this.hardforks() - const mergeIndex = hfs.findIndex((hf) => hf.ttd !== null && hf.ttd !== undefined) - if (mergeIndex < 0) { - throw Error(`Paris (Merge) hardfork should have been found`) - } - hfBlock = this.hardforkBlock(hfs[mergeIndex - 1].name) - } - if (hfBlock === null) { - return null - } - // Next fork block number or null if none available - // Logic: if accumulator is still null and on the first occurrence of - // a block greater than the current hfBlock set the accumulator, - // pass on the accumulator as the final result from this time on - const nextHfBlock = this.hardforks().reduce((acc: bigint | null, hf: HardforkConfig) => { - // We need to ignore the merge block in our next hardfork calc - const block = BigInt( - hf.block === null || (hf.ttd !== undefined && hf.ttd !== null) ? 0 : hf.block - ) - // Typescript can't seem to follow that the hfBlock is not null at this point - return block > hfBlock! && acc === null ? block : acc - }, null) - return nextHfBlock - } - - /** - * True if block number provided is the hardfork change block following the hardfork given or set - * @param blockNumber Number of the block to check - * @param hardfork Hardfork name, optional if HF set - * @returns True if blockNumber is HF block - * @deprecated - */ - isNextHardforkBlock(blockNumber: BigIntLike, hardfork?: string | Hardfork): boolean { - blockNumber = toType(blockNumber, TypeOutput.BigInt) - hardfork = hardfork ?? this._hardfork - const nextHardforkBlock = this.nextHardforkBlock(hardfork) - - return nextHardforkBlock === null ? false : nextHardforkBlock === blockNumber - } - /** * Internal helper function to calculate a fork hash * @param hardfork Hardfork name diff --git a/packages/common/test/hardforks.spec.ts b/packages/common/test/hardforks.spec.ts index b9ae47b33a..156a5da95b 100644 --- a/packages/common/test/hardforks.spec.ts +++ b/packages/common/test/hardforks.spec.ts @@ -166,28 +166,6 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { st.end() }) - t.test('isNextHardforkBlock()', function (st: tape.Test) { - const c = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) - let msg = - 'should work with HF set / return true for correct next HF block for chainstart (rinkeby: chainstart -> homestead)' - st.equal(c.isNextHardforkBlock(1), true, msg) - - msg = - 'should correctly skip a HF where block is set to null (rinkeby: homestead -> (dao) -> tangerineWhistle)' - st.equal(c.isNextHardforkBlock(2, 'homestead'), true, msg) - - msg = 'should return true for correct next HF (rinkeby: byzantium -> constantinople)' - st.equal(c.isNextHardforkBlock(3660663, Hardfork.Byzantium), true, msg) - - msg = 'should return false for a block number too low (rinkeby: byzantium -> constantinople)' - st.equal(c.isNextHardforkBlock(124, Hardfork.Byzantium), false, msg) - - msg = 'should return false for a block number too high (rinkeby: byzantium -> constantinople)' - st.equal(c.isNextHardforkBlock(605948938, Hardfork.Byzantium), false, msg) - - st.end() - }) - t.test('hardforkIsActiveOnBlock() / activeOnBlock()', function (st: tape.Test) { let c = new Common({ chain: Chain.Ropsten }) let msg = 'Ropsten, byzantium (provided), 1700000 -> true' From 0761997eedcd9419c2128cf36f1bb3316f592824 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 17 May 2023 09:47:17 +0200 Subject: [PATCH 2/6] Common: remove deprecated isHardforkBlock() method --- packages/common/src/common.ts | 14 -------------- packages/common/test/hardforks.spec.ts | 18 ------------------ 2 files changed, 32 deletions(-) diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index 59d797ad5a..8344061c5a 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -714,20 +714,6 @@ export class Common extends EventEmitter { return BigInt(ttd) } - /** - * True if block number provided is the hardfork (given or set) change block - * @param blockNumber Number of the block to check - * @param hardfork Hardfork name, optional if HF set - * @returns True if blockNumber is HF block - * @deprecated - */ - isHardforkBlock(blockNumber: BigIntLike, hardfork?: string | Hardfork): boolean { - blockNumber = toType(blockNumber, TypeOutput.BigInt) - hardfork = hardfork ?? this._hardfork - const block = this.hardforkBlock(hardfork) - return typeof block === 'bigint' && block !== BigInt(0) ? block === blockNumber : false - } - /** * Returns the change block for the next hardfork after the hardfork provided or set * @param hardfork Hardfork name, optional if HF set diff --git a/packages/common/test/hardforks.spec.ts b/packages/common/test/hardforks.spec.ts index 156a5da95b..d936b67686 100644 --- a/packages/common/test/hardforks.spec.ts +++ b/packages/common/test/hardforks.spec.ts @@ -124,24 +124,6 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) { st.end() }) - t.test('isHardforkBlock()', function (st: tape.Test) { - let c = new Common({ chain: Chain.Ropsten }) - let msg = 'should return true for HF change block for byzantium (provided)' - st.equal(c.isHardforkBlock(1700000, Hardfork.Byzantium), true, msg) - - msg = 'should return false for another block for byzantium (provided)' - st.equal(c.isHardforkBlock(1700001, Hardfork.Byzantium), false, msg) - - c = new Common({ chain: Chain.Ropsten, hardfork: Hardfork.Byzantium }) - msg = 'should return true for HF change block for byzantium (set)' - st.equal(c.isHardforkBlock(1700000), true, msg) - - msg = 'should return false for another block for byzantium (set)' - st.equal(c.isHardforkBlock(1700001), false, msg) - - st.end() - }) - t.test('nextHardforkBlockOrTimestamp()', function (st: tape.Test) { let c = new Common({ chain: Chain.Rinkeby, hardfork: Hardfork.Chainstart }) let msg = From 8def11540f29e1480f5cdb6bddc8790cdb8edfe4 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 17 May 2023 10:39:56 +0200 Subject: [PATCH 3/6] Blockchain: remove deprecated getHead() method --- packages/blockchain/src/blockchain.ts | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index f495cd2516..a97864e325 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -279,7 +279,7 @@ export class Blockchain implements BlockchainInterface { /** * Returns the specified iterator head. * - * This function replaces the old {@link Blockchain.getHead} method. Note that + * This function replaces the old Blockchain.getHead() method. Note that * the function deviates from the old behavior and returns the * genesis hash instead of the current head block if an iterator * has not been run. This matches the behavior of {@link Blockchain.iterator}. @@ -295,27 +295,6 @@ export class Blockchain implements BlockchainInterface { }) } - /** - * Returns the specified iterator head. - * - * @param name - Optional name of the iterator head (default: 'vm') - * - * @deprecated use {@link Blockchain.getIteratorHead} instead. - * Note that {@link Blockchain.getIteratorHead} doesn't return - * the `headHeader` but the genesis hash as an initial iterator - * head value (now matching the behavior of {@link Blockchain.iterator} - * on a first run) - */ - async getHead(name = 'vm'): Promise { - return this.runWithLock(async () => { - // if the head is not found return the headHeader - const hash = this._heads[name] ?? this._headBlockHash - if (hash === undefined) throw new Error('No head found.') - const block = await this.getBlock(hash) - return block - }) - } - /** * Returns the latest header in the canonical chain. */ From 2d71cca14e1a0cf5dccfa57e13ad7181ad5fa14e Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 17 May 2023 11:00:27 +0200 Subject: [PATCH 4/6] EVM: Rename SHA3 opcode -> KECCAK256 --- packages/common/src/hardforks/chainstart.json | 4 ++-- packages/evm/src/opcodes/codes.ts | 2 +- packages/evm/src/opcodes/functions.ts | 2 +- packages/evm/src/opcodes/gas.ts | 6 +++--- packages/vm/test/util.ts | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/common/src/hardforks/chainstart.json b/packages/common/src/hardforks/chainstart.json index 8d04b3647a..16d98a92a6 100644 --- a/packages/common/src/hardforks/chainstart.json +++ b/packages/common/src/hardforks/chainstart.json @@ -34,11 +34,11 @@ "v": 10, "d": "Times ceil(log256(exponent)) for the EXP instruction" }, - "sha3": { + "keccak256": { "v": 30, "d": "Base fee of the SHA3 opcode" }, - "sha3Word": { + "keccak256Word": { "v": 6, "d": "Once per word of the SHA3 operation's data" }, diff --git a/packages/evm/src/opcodes/codes.ts b/packages/evm/src/opcodes/codes.ts index d476eb6018..91ad44ab4b 100644 --- a/packages/evm/src/opcodes/codes.ts +++ b/packages/evm/src/opcodes/codes.ts @@ -79,7 +79,7 @@ const opcodes: OpcodeEntry = { 0x1a: { name: 'BYTE', isAsync: false, dynamicGas: false }, // 0x20 range - crypto - 0x20: { name: 'SHA3', isAsync: false, dynamicGas: true }, + 0x20: { name: 'KECCAK256', isAsync: false, dynamicGas: true }, // 0x30 range - closure state 0x30: { name: 'ADDRESS', isAsync: true, dynamicGas: false }, diff --git a/packages/evm/src/opcodes/functions.ts b/packages/evm/src/opcodes/functions.ts index 5330c86477..f7e95a028d 100644 --- a/packages/evm/src/opcodes/functions.ts +++ b/packages/evm/src/opcodes/functions.ts @@ -365,7 +365,7 @@ export const handlers: Map = new Map([ }, ], // 0x20 range - crypto - // 0x20: SHA3 + // 0x20: KECCAK256 [ 0x20, function (runState) { diff --git a/packages/evm/src/opcodes/gas.ts b/packages/evm/src/opcodes/gas.ts index 9e76de96a3..f3313a98ce 100644 --- a/packages/evm/src/opcodes/gas.ts +++ b/packages/evm/src/opcodes/gas.ts @@ -59,12 +59,12 @@ export const dynamicGasHandlers: Map { const [offset, length] = runState.stack.peek(2) gas += subMemUsage(runState, offset, length, common) - gas += common.param('gasPrices', 'sha3Word') * divCeil(length, BigInt(32)) + gas += common.param('gasPrices', 'keccak256Word') * divCeil(length, BigInt(32)) return gas }, ], @@ -473,7 +473,7 @@ export const dynamicGasHandlers: Map Date: Wed, 17 May 2023 11:36:43 +0200 Subject: [PATCH 5/6] EVM: rename DIFFICULTY opcode to PREVRANDAO post Merge --- packages/evm/src/opcodes/codes.ts | 32 ++++++++++++++++++------------- packages/evm/test/opcodes.spec.ts | 27 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/packages/evm/src/opcodes/codes.ts b/packages/evm/src/opcodes/codes.ts index 91ad44ab4b..d7493d31c9 100644 --- a/packages/evm/src/opcodes/codes.ts +++ b/packages/evm/src/opcodes/codes.ts @@ -212,7 +212,7 @@ const hardforkOpcodes: { hardfork: Hardfork; opcodes: OpcodeEntry }[] = [ { hardfork: Hardfork.Homestead, opcodes: { - 0xf4: { name: 'DELEGATECALL', isAsync: true, dynamicGas: true }, // EIP 7 + 0xf4: { name: 'DELEGATECALL', isAsync: true, dynamicGas: true }, // EIP-7 }, }, { @@ -223,7 +223,7 @@ const hardforkOpcodes: { hardfork: Hardfork; opcodes: OpcodeEntry }[] = [ 0xf2: { name: 'CALLCODE', isAsync: true, dynamicGas: true }, 0x3b: { name: 'EXTCODESIZE', isAsync: true, dynamicGas: true }, 0x3c: { name: 'EXTCODECOPY', isAsync: true, dynamicGas: true }, - 0xf4: { name: 'DELEGATECALL', isAsync: true, dynamicGas: true }, // EIP 7 + 0xf4: { name: 'DELEGATECALL', isAsync: true, dynamicGas: true }, // EIP-7 0xff: { name: 'SELFDESTRUCT', isAsync: true, dynamicGas: true }, 0x31: { name: 'BALANCE', isAsync: true, dynamicGas: true }, }, @@ -231,27 +231,33 @@ const hardforkOpcodes: { hardfork: Hardfork; opcodes: OpcodeEntry }[] = [ { hardfork: Hardfork.Byzantium, opcodes: { - 0xfd: { name: 'REVERT', isAsync: false, dynamicGas: true }, // EIP 140 - 0xfa: { name: 'STATICCALL', isAsync: true, dynamicGas: true }, // EIP 214 - 0x3d: { name: 'RETURNDATASIZE', isAsync: true, dynamicGas: false }, // EIP 211 - 0x3e: { name: 'RETURNDATACOPY', isAsync: true, dynamicGas: true }, // EIP 211 + 0xfd: { name: 'REVERT', isAsync: false, dynamicGas: true }, // EIP-140 + 0xfa: { name: 'STATICCALL', isAsync: true, dynamicGas: true }, // EIP-214 + 0x3d: { name: 'RETURNDATASIZE', isAsync: true, dynamicGas: false }, // EIP-211 + 0x3e: { name: 'RETURNDATACOPY', isAsync: true, dynamicGas: true }, // EIP-211 }, }, { hardfork: Hardfork.Constantinople, opcodes: { - 0x1b: { name: 'SHL', isAsync: false, dynamicGas: false }, // EIP 145 - 0x1c: { name: 'SHR', isAsync: false, dynamicGas: false }, // EIP 145 - 0x1d: { name: 'SAR', isAsync: false, dynamicGas: false }, // EIP 145 - 0x3f: { name: 'EXTCODEHASH', isAsync: true, dynamicGas: true }, // EIP 1052 - 0xf5: { name: 'CREATE2', isAsync: true, dynamicGas: true }, // EIP 1014 + 0x1b: { name: 'SHL', isAsync: false, dynamicGas: false }, // EIP-145 + 0x1c: { name: 'SHR', isAsync: false, dynamicGas: false }, // EIP-145 + 0x1d: { name: 'SAR', isAsync: false, dynamicGas: false }, // EIP-145 + 0x3f: { name: 'EXTCODEHASH', isAsync: true, dynamicGas: true }, // EIP-1052 + 0xf5: { name: 'CREATE2', isAsync: true, dynamicGas: true }, // EIP-1014 }, }, { hardfork: Hardfork.Istanbul, opcodes: { - 0x46: { name: 'CHAINID', isAsync: false, dynamicGas: false }, // EIP 1344 - 0x47: { name: 'SELFBALANCE', isAsync: false, dynamicGas: false }, // EIP 1884 + 0x46: { name: 'CHAINID', isAsync: false, dynamicGas: false }, // EIP-1344 + 0x47: { name: 'SELFBALANCE', isAsync: false, dynamicGas: false }, // EIP-1884 + }, + }, + { + hardfork: Hardfork.Paris, + opcodes: { + 0x44: { name: 'PREVRANDAO', isAsync: true, dynamicGas: false }, // EIP-4399 }, }, ] diff --git a/packages/evm/test/opcodes.spec.ts b/packages/evm/test/opcodes.spec.ts index 24fa67c6bc..f481a448ab 100644 --- a/packages/evm/test/opcodes.spec.ts +++ b/packages/evm/test/opcodes.spec.ts @@ -5,6 +5,7 @@ import * as tape from 'tape' import { EVM } from '../src' tape('EVM -> getActiveOpcodes()', (t) => { + const DIFFICULTY_PREVRANDAO = 0x44 const CHAINID = 0x46 //istanbul opcode const BEGINSUB = 0x5c // EIP-2315 opcode @@ -48,6 +49,32 @@ tape('EVM -> getActiveOpcodes()', (t) => { st.end() }) + t.test('should switch DIFFICULTY opcode name to PREVRANDAO when >= Merge HF', async (st) => { + let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul }) + let evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) + st.equal( + evm.getActiveOpcodes().get(DIFFICULTY_PREVRANDAO)!.name, + 'DIFFICULTY', + 'Opcode x44 named DIFFICULTY pre-Merge' + ) + + common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Paris }) + evm = await EVM.create({ + common, + stateManager: new DefaultStateManager(), + }) + st.equal( + evm.getActiveOpcodes().get(DIFFICULTY_PREVRANDAO)!.name, + 'PREVRANDAO', + 'Opcode x44 named PREVRANDAO post-Merge' + ) + + st.end() + }) + t.test('should expose opcodes when EIP is active', async (st) => { let common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul, eips: [2315] }) let evm = await EVM.create({ From 9ad718b3f1d529a3e232ab5612f820a0c3e55906 Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 17 May 2023 13:58:42 +0200 Subject: [PATCH 6/6] Common: add prevrandaio gas price to EIP-4399 definition file --- packages/common/src/eips/4399.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/common/src/eips/4399.json b/packages/common/src/eips/4399.json index 95109b2710..9e514f4ae4 100644 --- a/packages/common/src/eips/4399.json +++ b/packages/common/src/eips/4399.json @@ -7,7 +7,12 @@ "minimumHardfork": "london", "requiredEIPs": [], "gasConfig": {}, - "gasPrices": {}, + "gasPrices": { + "prevrandao": { + "v": 2, + "d": "Base fee of the PREVRANDAO opcode (previously DIFFICULTY)" + } + }, "vm": {}, "pow": {} }