From 39e1d4567f75f021bfa61c0d39bb41a80a28f8ae Mon Sep 17 00:00:00 2001 From: cgewecke Date: Mon, 15 Jun 2020 19:56:59 -0700 Subject: [PATCH] Restrict opcodes to berlin hardfork --- packages/vm/lib/evm/opFns.ts | 38 ++++++++++++++++-------- packages/vm/tests/api/berlin/eip-2315.js | 5 +++- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/vm/lib/evm/opFns.ts b/packages/vm/lib/evm/opFns.ts index 734d2be181..20fec58b51 100644 --- a/packages/vm/lib/evm/opFns.ts +++ b/packages/vm/lib/evm/opFns.ts @@ -1,5 +1,5 @@ import BN = require('bn.js') -import { keccak256, setLengthRight, TWO_POW256, MAX_INTEGER, KECCAK256_NULL } from 'ethereumjs-util' +import * as utils from 'ethereumjs-util' import { ERROR, VmError } from '../exceptions' import { RunState } from './interpreter' @@ -38,12 +38,12 @@ export const handlers: { [k: string]: OpHandler } = { }, ADD: function (runState: RunState) { const [a, b] = runState.stack.popN(2) - const r = a.add(b).mod(TWO_POW256) + const r = a.add(b).mod(utils.TWO_POW256) runState.stack.push(r) }, MUL: function (runState: RunState) { const [a, b] = runState.stack.popN(2) - const r = a.mul(b).mod(TWO_POW256) + const r = a.mul(b).mod(utils.TWO_POW256) runState.stack.push(r) }, SUB: function (runState: RunState) { @@ -137,7 +137,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(new BN(0)) return } - const m = BN.red(TWO_POW256) + const m = BN.red(utils.TWO_POW256) const redBase = base.toRed(m) const r = redBase.redPow(exponent) runState.stack.push(r.fromRed()) @@ -229,7 +229,7 @@ export const handlers: { [k: string]: OpHandler } = { return } - const r = b.shln(a.toNumber()).iand(MAX_INTEGER) + const r = b.shln(a.toNumber()).iand(utils.MAX_INTEGER) runState.stack.push(r) }, SHR: function (runState: RunState) { @@ -255,7 +255,7 @@ export const handlers: { [k: string]: OpHandler } = { const isSigned = b.testn(255) if (a.gten(256)) { if (isSigned) { - r = new BN(MAX_INTEGER) + r = new BN(utils.MAX_INTEGER) } else { r = new BN(0) } @@ -266,7 +266,7 @@ export const handlers: { [k: string]: OpHandler } = { const c = b.shrn(a.toNumber()) if (isSigned) { const shiftedOutWidth = 255 - a.toNumber() - const mask = MAX_INTEGER.shrn(shiftedOutWidth).shln(shiftedOutWidth) + const mask = utils.MAX_INTEGER.shrn(shiftedOutWidth).shln(shiftedOutWidth) r = c.ior(mask) } else { r = c @@ -285,7 +285,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.eei.useGas( new BN(runState._common.param('gasPrices', 'sha3Word')).imul(divCeil(length, new BN(32))), ) - const r = new BN(keccak256(data)) + const r = new BN(utils.keccak256(data)) runState.stack.push(r) }, // 0x30 range - closure state @@ -317,7 +317,7 @@ export const handlers: { [k: string]: OpHandler } = { const i = pos.toNumber() let loaded = runState.eei.getCallData().slice(i, i + 32) loaded = loaded.length ? loaded : Buffer.from([0]) - const r = new BN(setLengthRight(loaded, 32)) + const r = new BN(utils.setLengthRight(loaded, 32)) runState.stack.push(r) }, @@ -394,11 +394,11 @@ export const handlers: { [k: string]: OpHandler } = { const code = await runState.eei.getExternalCode(address) if (code.length === 0) { - runState.stack.push(new BN(KECCAK256_NULL)) + runState.stack.push(new BN(utils.KECCAK256_NULL)) return } - runState.stack.push(new BN(keccak256(code))) + runState.stack.push(new BN(utils.keccak256(code))) }, RETURNDATASIZE: function (runState: RunState) { runState.stack.push(runState.eei.getReturnDataSize()) @@ -567,10 +567,18 @@ export const handlers: { [k: string]: OpHandler } = { }, JUMPDEST: function (runState: RunState) {}, BEGINSUB: function (runState: RunState) { + if (!runState._common.gteHardfork('berlin')) { + trap(ERROR.INVALID_OPCODE) + } + trap(ERROR.INVALID_BEGINSUB + ' at ' + describeLocation(runState)) }, JUMPSUB: function (runState: RunState) { const dest = runState.stack.pop() + if (!runState._common.gteHardfork('berlin')) { + trap(ERROR.INVALID_OPCODE) + } + if (dest.gt(runState.eei.getCodeSize())) { trap(ERROR.INVALID_JUMPSUB + ' at ' + describeLocation(runState)) } @@ -585,6 +593,10 @@ export const handlers: { [k: string]: OpHandler } = { runState.programCounter = destNum + 1 }, RETURNSUB: function (runState: RunState) { + if (!runState._common.gteHardfork('berlin')) { + trap(ERROR.INVALID_OPCODE) + } + if (runState.returnStack.length < 1) { trap(ERROR.INVALID_RETURNSUB) } @@ -852,7 +864,7 @@ export const handlers: { [k: string]: OpHandler } = { } function describeLocation(runState: RunState) { - var hash = keccak256(runState.eei.getCode()).toString('hex') + var hash = utils.keccak256(runState.eei.getCode()).toString('hex') var address = runState.eei.getAddress().toString('hex') var pc = runState.programCounter - 1 return hash + '/' + address + ':' + pc @@ -912,7 +924,7 @@ function getDataSlice(data: Buffer, offset: BN, length: BN): Buffer { data = data.slice(offset.toNumber(), end.toNumber()) // Right-pad with zeros to fill dataLength bytes - data = setLengthRight(data, length.toNumber()) + data = utils.setLengthRight(data, length.toNumber()) return data } diff --git a/packages/vm/tests/api/berlin/eip-2315.js b/packages/vm/tests/api/berlin/eip-2315.js index 96f34e35dc..bb33e9ddb4 100644 --- a/packages/vm/tests/api/berlin/eip-2315.js +++ b/packages/vm/tests/api/berlin/eip-2315.js @@ -1,15 +1,18 @@ const tape = require('tape') const BN = require('bn.js') const VM = require('../../../dist/index').default +const Common = require('@ethereumjs/common').default + tape('Berlin: EIP 2315 tests', t => { let callArgs; let stepCounter; let vm; + const common = new Common('mainnet', 'berlin') const runTest = async function(test, st){ let i = 0; - vm = new VM(); + vm = new VM({ common: common }); vm.on('step', function(step){ if (test.steps.length){