Skip to content

Commit

Permalink
Merge branch 'master' into add-block-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
holgerd77 authored Mar 31, 2021
2 parents a1c936f + 486b992 commit 088122c
Show file tree
Hide file tree
Showing 17 changed files with 486 additions and 92 deletions.
37 changes: 12 additions & 25 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,18 @@ jobs:
strategy:
matrix:
node-version: [15]
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- uses: actions/checkout@v2
with:
submodules: recursive
# steps:
# - name: Use Node.js ${{ matrix.node-version }}
# uses: actions/setup-node@v1
# with:
# node-version: ${{ matrix.node-version }}
# - uses: actions/checkout@v2
# with:
# submodules: recursive

# Installs all dependencies, bootstrapping everything.
- run: npm install
# - run: npm install

# Publishes all packages to a virtual npm registry after giving each a minor version bump
- name: Publish to virtual registry
run: npm run e2e:publish

# This project is simple / does not require resolutions injection
- name: E2E Target - NoahZinsmeister/as-you-permit
run: |
git clone https://github.com/NoahZinsmeister/as-you-permit.git
cd as-you-permit
yarn
rm -rf dist
yarn remove @ethereumjs/vm
yarn add @ethereumjs/vm@e2e
yarn test --verbose
env:
URL_MAINNET: ${{ secrets.URL_MAINNET }}
# # Publishes all packages to a virtual npm registry after giving each a minor version bump
# - name: Publish to virtual registry
# run: npm run e2e:publish
8 changes: 5 additions & 3 deletions packages/tx/src/eip2930Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import {
N_DIV_2,
} from './types'

const emptyAccessList: AccessList = []
const emptyBuffer = Buffer.from([])

/**
* Typed transaction with optional access lists
*
Expand Down Expand Up @@ -109,8 +112,6 @@ export default class AccessListEIP2930Transaction extends BaseTransaction<Access

const [chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, v, r, s] = values

const emptyBuffer = Buffer.from([])

return new AccessListEIP2930Transaction(
{
chainId: new BN(chainId),
Expand All @@ -120,7 +121,7 @@ export default class AccessListEIP2930Transaction extends BaseTransaction<Access
to: to && to.length > 0 ? new Address(to) : undefined,
value: new BN(value),
data: data ?? emptyBuffer,
accessList: accessList ?? emptyBuffer,
accessList: accessList ?? emptyAccessList,
v: v !== undefined ? new BN(v) : undefined, // EIP2930 supports v's with value 0 (empty Buffer)
r: r !== undefined && !r.equals(emptyBuffer) ? new BN(r) : undefined,
s: s !== undefined && !s.equals(emptyBuffer) ? new BN(s) : undefined,
Expand All @@ -137,6 +138,7 @@ export default class AccessListEIP2930Transaction extends BaseTransaction<Access
* varying data types.
*/
public constructor(txData: AccessListEIP2930TxData, opts: TxOptions = {}) {
// Have to split up the const/let part to make eslint happy
const { chainId, accessList } = txData

super(txData, opts)
Expand Down
6 changes: 3 additions & 3 deletions packages/tx/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BN, AddressLike, BNLike, BufferLike } from 'ethereumjs-util'
import { BN, AddressLike, BNLike, BufferLike, PrefixedHexString } from 'ethereumjs-util'
import Common from '@ethereumjs/common'
import { default as Transaction } from './legacyTransaction'
import { default as AccessListEIP2930Transaction } from './eip2930Transaction'
Expand Down Expand Up @@ -36,8 +36,8 @@ export interface TxOptions {
*/

export type AccessListItem = {
address: string
storageKeys: string[]
address: PrefixedHexString
storageKeys: PrefixedHexString[]
}

/*
Expand Down
10 changes: 10 additions & 0 deletions packages/tx/test/eip2930.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,14 @@ tape('[AccessListEIP2930Transaction]', function (t) {

t.end()
})

t.test('should create and sign transactions without passing access list value', (st) => {
const tx = AccessListEIP2930Transaction.fromTxData({}, { common })
const signed = tx.sign(pKey)

st.deepEqual(tx.accessList, [])
st.deepEqual(signed.accessList, [])

st.end()
})
})
6 changes: 5 additions & 1 deletion packages/util/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
(modification: no type change headlines) and this project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [7.1.0] - TBD

- Return false (instead of throwing) for non-hex-string values in account `isValidAddress`, `isValidChecksumAddress`, `isZeroAddress` methods, PR [#1173](https://github.com/ethereumjs/ethereumjs-monorepo/pull/1173)

## [7.0.9] - 2021-03-04

This release adds support for very high `chainId` numbers exceeding `MAX_SAFE_INTEGER` (an example is the chain ID `34180983699157880` used for the ephemeral Yolov3 testnet preparing for the `berlin` hardfork, but high chain IDs might be used for things like private test networks and the like as well), see PR [#290](https://github.com/ethereumjs/ethereumjs-util/pull/290).
Expand Down Expand Up @@ -401,7 +405,7 @@ see PR [#170](https://github.com/ethereumjs/ethereumjs-util/pull/170).
## [6.0.0] - 2018-10-08

- Support for `EIP-155` replay protection by adding an optional `chainId` parameter
to `ecsign()`, `ecrecover()`, `toRpcSig()` and `isValidSignature()`, if present the
to `ecsign()`, `ecrecover()`, `toRpcSig()` and `isValidSignature()`, if present the
new signature format relying on the `chainId` is used, see PR [#143](https://github.com/ethereumjs/ethereumjs-util/pull/143)
- New `generateAddress2()` for `CREATE2` opcode (`EIP-1014`) address creation
(Constantinople HF), see PR [#146](https://github.com/ethereumjs/ethereumjs-util/pull/146)
Expand Down
16 changes: 13 additions & 3 deletions packages/util/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { stripHexPrefix } from 'ethjs-util'
import { KECCAK256_RLP, KECCAK256_NULL } from './constants'
import { zeros, bufferToHex, toBuffer } from './bytes'
import { keccak, keccak256, keccakFromString, rlphash } from './hash'
import { assertIsHexString, assertIsBuffer } from './helpers'
import { assertIsString, assertIsHexString, assertIsBuffer } from './helpers'
import { BNLike, BufferLike, bnToRlp, toType, TypeOutput } from './types'

export interface AccountData {
Expand Down Expand Up @@ -122,7 +122,12 @@ export class Account {
* Checks if the address is a valid. Accepts checksummed addresses too.
*/
export const isValidAddress = function (hexAddress: string): boolean {
assertIsHexString(hexAddress)
try {
assertIsString(hexAddress)
} catch (e) {
return false
}

return /^0x[0-9a-fA-F]{40}$/.test(hexAddress)
}

Expand Down Expand Up @@ -299,7 +304,12 @@ export const zeroAddress = function (): string {
* Checks if a given address is the zero address.
*/
export const isZeroAddress = function (hexAddress: string): boolean {
assertIsHexString(hexAddress)
try {
assertIsString(hexAddress)
} catch (e) {
return false
}

const zeroAddr = zeroAddress()
return zeroAddr === hexAddress
}
12 changes: 12 additions & 0 deletions packages/util/src/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ export class Address {
return this.equals(Address.zero())
}

/**
* True if address is in the address range defined
* by EIP-1352
*/
isPrecompileOrSystemAddress(): boolean {
const addressBN = new BN(this.buf)
const rangeMin = new BN(0)
const rangeMax = new BN('ffff', 'hex')

return addressBN.gte(rangeMin) && addressBN.lte(rangeMax)
}

/**
* Returns hex encoding of address.
*/
Expand Down
3 changes: 2 additions & 1 deletion packages/util/src/bytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export type ToBufferInputTypes =

/**
* Attempts to turn a value into a `Buffer`.
* Inputs supported: `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` or `toBuffer()` method.
* Inputs supported: `Buffer`, `String` (hex-prefixed), `Number`, null/undefined, `BN` and other objects
* with a `toArray()` or `toBuffer()` method.
* @param v the value
*/
export const toBuffer = function (v: ToBufferInputTypes): Buffer {
Expand Down
31 changes: 5 additions & 26 deletions packages/util/test/account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,10 +633,8 @@ tape('Utility Functions', function (t) {
st.end()
})

st.test('input format', function (st) {
st.throws(() => {
isValidChecksumAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
}, 'Should throw when the address is not hex-prefixed')
st.test('Should return false if input is not hex-prefixed', function (st) {
st.notOk(isValidChecksumAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a'))
st.end()
})

Expand All @@ -653,28 +651,9 @@ tape('Utility Functions', function (t) {
st.test('should return false', function (st) {
st.notOk(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6'))
st.notOk(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6aa'))
st.end()
})
st.test('should throw when input is not hex prefixed', function (st) {
st.throws(function () {
isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
})
st.throws(function () {
isValidAddress('x2f015c60e0be116b1f0cd534704db9c92118fb6a')
})
st.throws(function () {
isValidAddress('0X52908400098527886E0F7030069857D2E4169EE7')
})
st.end()
})
st.test('error message should have correct format', function (st) {
const input = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
try {
isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
} catch (err) {
st.ok(err.message.includes('only supports 0x-prefixed hex strings'))
st.ok(err.message.includes(input))
}
st.notOk(isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a'))
st.notOk(isValidAddress('x2f015c60e0be116b1f0cd534704db9c92118fb6a'))
st.notOk(isValidAddress('0X52908400098527886E0F7030069857D2E4169EE7'))
st.end()
})
})
Expand Down
8 changes: 8 additions & 0 deletions packages/util/test/address.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ tape('Address', (t) => {
st.end()
})

t.test('should provide correct precompile check', (st) => {
const precompile = Address.fromString('0x0000000000000000000000000000000000000009')
st.true(precompile.isPrecompileOrSystemAddress(), 'should detect precompile address')
const nonPrecompile = Address.fromString('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39')
st.false(nonPrecompile.isPrecompileOrSystemAddress(), 'should detect non-precompile address')
st.end()
})

t.test('should generate address for CREATE2', (st) => {
for (const testdata of eip1014Testdata) {
const { address, salt, initCode, result } = testdata
Expand Down
6 changes: 2 additions & 4 deletions packages/util/test/bytes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@ tape('is zero address', function (t) {
st.end()
})

t.test('should throw when address is not hex-prefixed', function (st) {
st.throws(function () {
isZeroAddress('0000000000000000000000000000000000000000')
})
t.test('should return false when address is not hex-prefixed', function (st) {
st.equal(isZeroAddress('0000000000000000000000000000000000000000'), false)
st.end()
})
})
Expand Down
9 changes: 4 additions & 5 deletions packages/vm/examples/run-transactions-complete/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Account, BN, toBuffer, pubToAddress, bufferToHex } from 'ethereumjs-util'
import { Address, Account, BN, toBuffer, pubToAddress } from 'ethereumjs-util'
import { Transaction, TxData } from '@ethereumjs/tx'
import VM from '../..'

Expand All @@ -9,12 +9,11 @@ async function main() {
// used to sign transactions and generate addresses
const keyPair = require('./key-pair')
const privateKey = toBuffer(keyPair.secretKey)

const publicKeyBuf = toBuffer(keyPair.publicKey)
const address = pubToAddress(publicKeyBuf, true)
const address = new Address(pubToAddress(publicKeyBuf, true))

console.log('---------------------')
console.log('Sender address: ', bufferToHex(address))
console.log('Sender address: ', address.toString())

// Create a new account
const acctData = {
Expand Down Expand Up @@ -61,7 +60,7 @@ async function runTx(vm: VM, txData: TxData, privateKey: Buffer) {
const createdAddress = results.createdAddress

if (createdAddress) {
console.log('address created: 0x' + createdAddress.toString('hex'))
console.log('address created: ' + createdAddress.toString())
return createdAddress
}
}
Expand Down
41 changes: 37 additions & 4 deletions packages/vm/lib/runTx.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { debug as createDebugLogger } from 'debug'
import { Address, BN } from 'ethereumjs-util'
import { Address, BN, toBuffer } from 'ethereumjs-util'
import { Block } from '@ethereumjs/block'
import { AccessListItem, AccessListEIP2930Transaction, TypedTransaction } from '@ethereumjs/tx'
import {
AccessListItem,
AccessListEIP2930Transaction,
TypedTransaction,
AccessList,
} from '@ethereumjs/tx'
import VM from './index'
import Bloom from './bloom'
import { default as EVM, EVMResult } from './evm/evm'
Expand Down Expand Up @@ -40,6 +45,18 @@ export interface RunTxOpts {
* agains the block's gas limit.
*/
skipBlockGasLimitValidation?: boolean

/**
* If true, adds a generated EIP-2930 access list
* to the `RunTxResult` returned.
*
* Option works with all tx types. EIP-2929 needs to
* be activated (included in `berlin` HF).
*
* Note: if this option is used with a custom `StateManager` implementation
* the `generateAccessList()` method must be implemented.
*/
reportAccessList?: boolean
}

/**
Expand All @@ -58,6 +75,11 @@ export interface RunTxResult extends EVMResult {
* The amount of gas as that was refunded during the transaction (i.e. `gasUsed = totalGasConsumed - gasRefund`)
*/
gasRefund?: BN

/**
* EIP-2930 access list generated for the tx (see `reportAccessList` option)
*/
accessList?: AccessList
}

export interface AfterTxEvent extends RunTxResult {
Expand Down Expand Up @@ -105,16 +127,23 @@ export default async function runTx(this: VM, opts: RunTxOpts): Promise<RunTxRes
this._common.isActivatedEIP(2929)
) {
if (!this._common.isActivatedEIP(2930)) {
await state.revert()
throw new Error('Cannot run transaction: EIP 2930 is not activated.')
}
if (opts.reportAccessList && !('generateAccessList' in state)) {
await state.revert()
throw new Error(
'StateManager needs to implement generateAccessList() when running with reportAccessList option'
)
}

const castedTx = <AccessListEIP2930Transaction>opts.tx

castedTx.AccessListJSON.forEach((accessListItem: AccessListItem) => {
const address = Buffer.from(accessListItem.address.slice(2), 'hex')
const address = toBuffer(accessListItem.address)
state.addWarmedAddress(address)
accessListItem.storageKeys.forEach((storageKey: string) => {
state.addWarmedStorage(address, Buffer.from(storageKey.slice(2), 'hex'))
state.addWarmedStorage(address, toBuffer(storageKey))
})
})
}
Expand All @@ -123,6 +152,10 @@ export default async function runTx(this: VM, opts: RunTxOpts): Promise<RunTxRes
const result = await _runTx.bind(this)(opts)
await state.commit()
debug(`tx checkpoint committed`)
if (this._common.isActivatedEIP(2929) && opts.reportAccessList) {
// @ts-ignore method is not yet part of the interface for backwards-compatibility reasons
result.accessList = state.generateAccessList()
}
return result
} catch (e) {
await state.revert()
Expand Down
Loading

0 comments on commit 088122c

Please sign in to comment.