Skip to content

Commit

Permalink
Merge pull request #783 from ethereumjs/group-precompiles-hardfork
Browse files Browse the repository at this point in the history
VM: return precompile functions based on hardfork
  • Loading branch information
holgerd77 authored Jun 19, 2020
2 parents d2b172c + 89d0c8e commit fb82f40
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 9 deletions.
2 changes: 1 addition & 1 deletion packages/vm/lib/evm/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export default class EVM {
* if no such precompile exists.
*/
getPrecompile(address: Buffer): PrecompileFunc {
return getPrecompile(address.toString('hex'))
return getPrecompile(address.toString('hex'), this._vm._common)
}

/**
Expand Down
27 changes: 25 additions & 2 deletions packages/vm/lib/evm/precompiles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ import { default as p6 } from './06-ecadd'
import { default as p7 } from './07-ecmul'
import { default as p8 } from './08-ecpairing'
import { default as p9 } from './09-blake2f'
import Common from '@ethereumjs/common'

interface Precompiles {
[key: string]: PrecompileFunc
}

interface PrecompileAvailability {
[key: string]: string
}

const ripemdPrecompileAddress = '0000000000000000000000000000000000000003'
const precompiles: Precompiles = {
'0000000000000000000000000000000000000001': p1,
Expand All @@ -26,8 +31,26 @@ const precompiles: Precompiles = {
'0000000000000000000000000000000000000009': p9,
}

function getPrecompile(address: string): PrecompileFunc {
return precompiles[address]
const precompileAvailability: PrecompileAvailability = {
'0000000000000000000000000000000000000001': 'homestead',
'0000000000000000000000000000000000000002': 'homestead',
[ripemdPrecompileAddress]: 'homestead',
'0000000000000000000000000000000000000004': 'homestead',
'0000000000000000000000000000000000000005': 'byzantium',
'0000000000000000000000000000000000000006': 'byzantium',
'0000000000000000000000000000000000000007': 'byzantium',
'0000000000000000000000000000000000000008': 'byzantium',
'0000000000000000000000000000000000000009': 'istanbul',
}

function getPrecompile(address: string, common: Common): PrecompileFunc {
if (precompiles[address]) {
const availability = precompileAvailability[address]
if (common.gteHardfork(availability)) {
return precompiles[address]
}
}
return precompiles['']
}

export { precompiles, getPrecompile, PrecompileFunc, PrecompileInput, ripemdPrecompileAddress }
2 changes: 1 addition & 1 deletion packages/vm/tests/api/evm/precompiles/06-ecadd.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tape('Precompiles: ECADD', (t) => {
t.test('ECADD', (st) => {
const common = new Common('mainnet', 'petersburg')
let vm = new VM({ common: common })
let ECADD = getPrecompile('0000000000000000000000000000000000000006')
let ECADD = getPrecompile('0000000000000000000000000000000000000006', common)

let result = ECADD({
data: Buffer.alloc(0),
Expand Down
2 changes: 1 addition & 1 deletion packages/vm/tests/api/evm/precompiles/07-ecmul.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tape('Precompiles: ECMUL', (t) => {
t.test('ECMUL', (st) => {
const common = new Common('mainnet', 'petersburg')
let vm = new VM({ common: common })
let ECMUL = getPrecompile('0000000000000000000000000000000000000007')
let ECMUL = getPrecompile('0000000000000000000000000000000000000007', common)

let result = ECMUL({
data: Buffer.alloc(0),
Expand Down
2 changes: 1 addition & 1 deletion packages/vm/tests/api/evm/precompiles/08-ecpairing.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tape('Precompiles: ECPAIRING', (t) => {
t.test('ECPAIRING', (st) => {
const common = new Common('mainnet', 'petersburg')
let vm = new VM({ common: common })
let ECPAIRING = getPrecompile('0000000000000000000000000000000000000008')
let ECPAIRING = getPrecompile('0000000000000000000000000000000000000008', common)

let result = ECPAIRING({
data: Buffer.from('00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa', 'hex'),
Expand Down
73 changes: 73 additions & 0 deletions packages/vm/tests/api/evm/precompiles/hardfork-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const BN = require('bn.js')
const tape = require('tape')
const Common = require('@ethereumjs/common').default
const util = require('ethereumjs-util')
const VM = require('../../../../dist/index').default
const { getPrecompile } = require('../../../../dist/evm/precompiles')

tape('Precompiles: hardfork availability', (t) => {
t.test('Test ECPAIRING availability', async (st) => {
const ECPAIR_Address = "0000000000000000000000000000000000000008"

// ECPAIR was introduced in Byzantium; check if available from Byzantium.
const commonByzantium = new Common('mainnet', 'byzantium')
let ECPAIRING = getPrecompile(ECPAIR_Address, commonByzantium)

if (!ECPAIRING) {
st.fail("ECPAIRING is not available in petersburg while it should be available")
} else {
st.pass("ECPAIRING available in petersburg")
}

let vm = new VM({ common: commonByzantium })
let result = await vm.runCall({
caller: Buffer.from('0000000000000000000000000000000000000000', 'hex'),
gasLimit: new BN(0xffffffffff),
to: Buffer.from(ECPAIR_Address, 'hex'),
value: new BN(0)
})
st.assert(result.gasUsed.toNumber() == 100000) // check that we are using gas (if address would contain no code we use 0 gas)


// Check if ECPAIR is available in future hard forks.
const commonPetersburg = new Common('mainnet', 'petersburg')
ECPAIRING = getPrecompile(ECPAIR_Address, commonPetersburg)

if (!ECPAIRING) {
st.fail("ECPAIRING is not available in petersburg while it should be available")
} else {
st.pass("ECPAIRING available in petersburg")
}

vm = new VM({ common: commonPetersburg })
result = await vm.runCall({
caller: Buffer.from('0000000000000000000000000000000000000000', 'hex'),
gasLimit: new BN(0xffffffffff),
to: Buffer.from(ECPAIR_Address, 'hex'),
value: new BN(0)
})
st.assert(result.gasUsed.toNumber() == 100000)


// Check if ECPAIR is not available in Homestead.
const commonHomestead = new Common('mainnet', 'homestead')
ECPAIRING = getPrecompile(ECPAIR_Address, commonHomestead)

if (ECPAIRING) {
st.fail("ECPAIRING is available in homestead while it should not be available")
} else {
st.pass("ECPAIRING not available in homestead")
}

vm = new VM({ common: commonHomestead })
result = await vm.runCall({
caller: Buffer.from('0000000000000000000000000000000000000000', 'hex'),
gasLimit: new BN(0xffffffffff),
to: Buffer.from(ECPAIR_Address, 'hex'),
value: new BN(0)
})
st.assert(result.gasUsed.toNumber() == 0) // check that we use no gas, because we are calling into an address without code.

st.end()
})
})
6 changes: 3 additions & 3 deletions packages/vm/tests/api/istanbul/eip-1108.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tape('Istanbul: EIP-1108 tests', (t) => {
t.test('ECADD', (st) => {
const common = new Common('mainnet', 'istanbul')
let vm = new VM({ common: common })
let ECADD = getPrecompile('0000000000000000000000000000000000000006')
let ECADD = getPrecompile('0000000000000000000000000000000000000006', common)

let result = ECADD({
data: Buffer.alloc(0),
Expand All @@ -23,7 +23,7 @@ tape('Istanbul: EIP-1108 tests', (t) => {
t.test('ECMUL', (st) => {
const common = new Common('mainnet', 'istanbul')
let vm = new VM({ common: common })
let ECMUL = getPrecompile('0000000000000000000000000000000000000007')
let ECMUL = getPrecompile('0000000000000000000000000000000000000007', common)

let result = ECMUL({
data: Buffer.alloc(0),
Expand All @@ -37,7 +37,7 @@ tape('Istanbul: EIP-1108 tests', (t) => {
t.test('ECPAIRING', (st) => {
const common = new Common('mainnet', 'istanbul')
let vm = new VM({ common: common })
let ECPAIRING = getPrecompile('0000000000000000000000000000000000000008')
let ECPAIRING = getPrecompile('0000000000000000000000000000000000000008', common)

let result = ECPAIRING({
data: Buffer.from('00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa', 'hex'),
Expand Down

0 comments on commit fb82f40

Please sign in to comment.