Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EVM refactor (old) #1912

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ae950d2
vm: rename vmstate/eei
jochem-brouwer May 25, 2022
29554bc
evm: setup type skeleton
jochem-brouwer May 26, 2022
cd72062
vm/evm: update types
jochem-brouwer May 26, 2022
1539fad
vm/eei: extra types
jochem-brouwer May 26, 2022
ac33941
vm: extract EEI from EVM
jochem-brouwer May 26, 2022
0d49db6
vm: move types to correct place
jochem-brouwer May 26, 2022
f447394
vm: preliminary VmState removal
jochem-brouwer May 26, 2022
0935805
vm: add env to interpreter + extract getAddress from EEI
jochem-brouwer May 26, 2022
88f16bb
vm: extract getSelfBalance from EEI
jochem-brouwer May 26, 2022
77ea28a
vm: extract CallData* from EEI
jochem-brouwer May 26, 2022
1f1989b
vm: remove getCaller, getCodeSize, getCode, isStatic from EEI
jochem-brouwer May 26, 2022
5a41fca
vm: remove Tx-related methods from EEI
jochem-brouwer May 26, 2022
16b0287
vm: remove block-related methods from EEI
jochem-brouwer May 26, 2022
6e27483
vm: remove getChainId from EEI
jochem-brouwer May 26, 2022
4ac4ef2
vm: extract all call/selfdestruct/log-related logic from EEI
jochem-brouwer May 26, 2022
2b14275
vm: extract environment from EEI
jochem-brouwer May 26, 2022
d5dbcc3
vm: remove evm/gasleft from EEI
jochem-brouwer May 26, 2022
d479e9e
vm: remove EIFactory. EVM now has singleton EEI
jochem-brouwer May 26, 2022
95c3e11
vm: add custom EEI/EVM options
jochem-brouwer May 27, 2022
700b228
vm: evm/eei/vm: rename certain properties, remove vmstate dependency
jochem-brouwer May 27, 2022
a0181aa
comment fix
jochem-brouwer May 27, 2022
9f18ecf
vm/evm: ensure exp dynamic gas calculated in gas.ts not functions.ts
jochem-brouwer May 27, 2022
a12481b
vm/evm: remove unnecessary item in Env
jochem-brouwer May 27, 2022
49121e5
vm/interpreter: all state access via eei.state
jochem-brouwer May 27, 2022
6fd6ce9
vm/evm: remove gasRefund property and put this in runState
jochem-brouwer May 31, 2022
55c49ba
vm/evm: move `auth` from `_Env` to `RunState`
jochem-brouwer Jun 6, 2022
0349af6
vm/evm: move return buffer into runstate
jochem-brouwer Jun 6, 2022
22188ef
vm/evm: fix gas refunds
jochem-brouwer Jun 6, 2022
83a9746
vm/evm: move gasLeft as property of Interpreter into RunState
jochem-brouwer Jun 6, 2022
339c581
vm/evm: add AsyncEventEmitter type
jochem-brouwer Jun 9, 2022
df12d50
evm/interpreter: better type safety
jochem-brouwer Jun 9, 2022
adae093
client: fix build
jochem-brouwer Jun 9, 2022
9b8c476
evm: fix build
jochem-brouwer Jun 10, 2022
9c03f3a
eei/evm: define EEI interface
jochem-brouwer Jun 10, 2022
9694db1
evm/vm: use EEI Interface
jochem-brouwer Jun 10, 2022
00e29e4
evm/vm: add EVM interface and use this
jochem-brouwer Jun 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/client/lib/execution/vmexecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class VMExecution extends Execution {
this.hardfork = this.config.execCommon.hardfork()
this.config.logger.info(`Initializing VM execution hardfork=${this.hardfork}`)
if (number === BigInt(0)) {
await this.vm.vmState.generateCanonicalGenesis()
await this.vm.eei.state.generateCanonicalGenesis()
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/miner/miner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export class Miner {

// Set the state root to ensure the resulting state
// is based on the parent block's state
await vmCopy.vmState.setStateRoot(parentBlock.header.stateRoot)
await vmCopy.eei.state.setStateRoot(parentBlock.header.stateRoot)

let difficulty
let cliqueSigner
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/miner/pendingBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class PendingBlock {

// Set the state root to ensure the resulting state
// is based on the parent block's state
await vm.vmState.setStateRoot(parentBlock.header.stateRoot)
await vm.eei.state.setStateRoot(parentBlock.header.stateRoot)

const td = await vm.blockchain.getTotalDifficulty(parentBlock.hash())
vm._common.setHardforkByBlockNumber(parentBlock.header.number, td)
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/service/txpool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ export class TxPool {
.map((obj) => obj.tx)
.sort((a, b) => Number(a.nonce - b.nonce))
// Check if the account nonce matches the lowest known tx nonce
const { nonce } = await this.vm.vmState.getAccount(new Address(Buffer.from(address, 'hex')))
const { nonce } = await this.vm.eei.state.getAccount(new Address(Buffer.from(address, 'hex')))
if (txsSortedByNonce[0].nonce !== nonce) {
// Account nonce does not match the lowest known tx nonce,
// therefore no txs from this address are currently exectuable
Expand Down
1 change: 1 addition & 0 deletions packages/vm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"@types/node": "^16.11.7",
"@types/node-dir": "^0.0.34",
"@types/tape": "^4.13.2",
"@types/async-eventemitter": "^0.2.1",
"benchmark": "^2.1.4",
"eslint": "^6.8.0",
"karma": "^6.3.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/vm/src/buildBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export class BlockBuilder {
const coinbase = this.headerData.coinbase
? new Address(toBuffer(this.headerData.coinbase))
: Address.zero()
await rewardAccount(this.vm.vmState, coinbase, reward)
await rewardAccount(this.vm.eei.state, coinbase, reward)
}

/**
Expand Down
134 changes: 134 additions & 0 deletions packages/vm/src/eei/eei.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Address, bufferToBigInt } from 'ethereumjs-util'
import Common from '@ethereumjs/common'

import { VmState } from './vmState'
import TransientStorage from './transientStorage'
import { addressToBuffer } from '../evm/opcodes'
import { StateManager } from '@ethereumjs/statemanager'
import { EEIInterface } from '../evm/types'

type Block = {
hash(): Buffer
}

type Blockchain = {
getBlock(blockId: number): Promise<Block>
}

/**
* External interface made available to EVM bytecode. Modeled after
* the ewasm EEI [spec](https://github.com/ewasm/design/blob/master/eth_interface.md).
* It includes methods for accessing/modifying state, calling or creating contracts, access
* to environment data among other things.
* The EEI instance also keeps artifacts produced by the bytecode such as logs
* and to-be-selfdestructed addresses.
*/
export default class EEI implements EEIInterface {
readonly state: VmState // TODO this is part of the interface, remove underscore (search .ei._state, replace all)
protected _common: Common
_transientStorage: TransientStorage
protected _blockchain: Blockchain

constructor(stateManager: StateManager, common: Common, blockchain: Blockchain) {
this._common = common
this._transientStorage = new TransientStorage()
this._blockchain = blockchain
this.state = new VmState({ common, stateManager })
}

/**
* Returns balance of the given account.
* @param address - Address of account
*/
async getExternalBalance(address: Address): Promise<bigint> {
const account = await this.state.getAccount(address)
return account.balance
}

/**
* Get size of an account’s code.
* @param address - Address of account
*/
async getExternalCodeSize(address: bigint): Promise<bigint> {
const addr = new Address(addressToBuffer(address))
const code = await this.state.getContractCode(addr)
return BigInt(code.length)
}

/**
* Returns code of an account.
* @param address - Address of account
*/
async getExternalCode(address: bigint): Promise<Buffer> {
const addr = new Address(addressToBuffer(address))
return this.state.getContractCode(addr)
}

/**
* Returns Gets the hash of one of the 256 most recent complete blocks.
* @param num - Number of block
*/
async getBlockHash(num: bigint): Promise<bigint> {
const block = await this._blockchain.getBlock(Number(num))
return bufferToBigInt(block.hash())
}

/**
* Storage 256-bit value into storage of an address
* @param address Address to store into
* @param key Storage key
* @param value Storage value
*/
async storageStore(address: Address, key: Buffer, value: Buffer): Promise<void> {
await this.state.putContractStorage(address, key, value)
}

/**
* Loads a 256-bit value to memory from persistent storage.
* @param address Address to get storage key value from
* @param key Storage key
* @param original If true, return the original storage value (default: false)
*/
async storageLoad(address: Address, key: Buffer, original = false): Promise<Buffer> {
if (original) {
return this.state.getOriginalContractStorage(address, key)
} else {
return this.state.getContractStorage(address, key)
}
}

/**
* Store 256-bit a value in memory to transient storage.
* @param address Address to use
* @param key Storage key
* @param value Storage value
*/
transientStorageStore(address: Address, key: Buffer, value: Buffer): void {
return this._transientStorage.put(address, key, value)
}

/**
* Loads a 256-bit value to memory from transient storage.
* @param address Address to use
* @param key Storage key
*/
transientStorageLoad(address: Address, key: Buffer): Buffer {
return this._transientStorage.get(address, key)
}

/**
* Returns true if account is empty or non-existent (according to EIP-161).
* @param address - Address of account
*/
async isAccountEmpty(address: Address): Promise<boolean> {
return this.state.accountIsEmpty(address)
}

/**
* Returns true if account exists in the state trie (it can be empty). Returns false if the account is `null`.
* @param address - Address of account
*/
async accountExists(address: Address): Promise<boolean> {
return this.state.accountExists(address)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Address } from 'ethereumjs-util'
import { TransientStorageInterface } from '../evm/types'

type TransientStorageCurrent = Map<string, Map<string, Buffer>>

Expand All @@ -10,7 +11,7 @@ interface TransientStorageModification {

type TransientStorageJournal = TransientStorageModification[]

export default class TransientStorage {
export default class TransientStorage implements TransientStorageInterface {
/**
* The current values of the transient storage, keyed by contract address and then slot
*/
Expand Down
18 changes: 3 additions & 15 deletions packages/vm/src/vmState.ts → packages/vm/src/eei/vmState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,14 @@ import { AccessList, AccessListItem } from '@ethereumjs/tx'
import { Account, Address, toBuffer } from 'ethereumjs-util'
const Set = require('core-js-pure/es/set')

import { StateManager, StateAccess, AccountFields } from '@ethereumjs/statemanager'
import { StateManager, AccountFields } from '@ethereumjs/statemanager'

import { ripemdPrecompileAddress } from './evm/precompiles'
import { ripemdPrecompileAddress } from '../evm/precompiles'
import { debug as createDebugLogger, Debugger } from 'debug'
import { VmStateAccess } from '../evm/types'

type AddressHex = string

interface VmStateAccess extends StateAccess {
touchAccount(address: Address): void
addWarmedAddress(address: Buffer): void
isWarmedAddress(address: Buffer): boolean
addWarmedStorage(address: Buffer, slot: Buffer): void
isWarmedStorage(address: Buffer, slot: Buffer): boolean
clearWarmedAccounts(): void
generateAccessList?(addressesRemoved: Address[], addressesOnlyStorage: Address[]): AccessList
getOriginalContractStorage(address: Address, key: Buffer): Promise<Buffer>
clearOriginalStorageCache(): void
cleanupTouchedAccounts(): Promise<void>
}

export class VmState implements VmStateAccess {
_common: Common
_debug: Debugger
Expand Down
Loading