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

vm, client: continuing v6 breaking changes #1815

Merged
merged 3 commits into from
Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions packages/client/lib/execution/receipt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PreByzantiumTxReceipt, PostByzantiumTxReceipt, TxReceipt } from '@ether
import { Log } from '@ethereumjs/vm/dist/evm/types'
import Bloom from '@ethereumjs/vm/dist/bloom'
import { TypedTransaction } from '@ethereumjs/tx'
import { rlp, intToBuffer, bufferToInt } from 'ethereumjs-util'
import { rlp, intToBuffer, bufferToInt, bigIntToBuffer, bufferToBigInt } from 'ethereumjs-util'
import { MetaDBManager, DBKey } from './metaDBManager'
import type { Block } from '@ethereumjs/block'

Expand Down Expand Up @@ -302,7 +302,7 @@ export class ReceiptsManager extends MetaDBManager {
value.map((r) => [
(r as PreByzantiumTxReceipt).stateRoot ??
intToBuffer((r as PostByzantiumTxReceipt).status),
r.gasUsed,
bigIntToBuffer(r.gasUsed),
this.rlp(RlpConvert.Encode, RlpType.Logs, r.logs),
])
)
Expand All @@ -315,14 +315,14 @@ export class ReceiptsManager extends MetaDBManager {
// Pre-Byzantium Receipt
return {
stateRoot: r[0],
gasUsed,
gasUsed: bufferToBigInt(gasUsed),
logs,
} as PreByzantiumTxReceipt
} else {
// Post-Byzantium Receipt
return {
status: bufferToInt(r[0]),
gasUsed,
gasUsed: bufferToBigInt(gasUsed),
logs,
} as PostByzantiumTxReceipt
}
Expand Down
8 changes: 6 additions & 2 deletions packages/client/lib/net/protocol/ethprotocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export class EthProtocol extends Protocol {
let encodedReceipt = rlp.encode([
(receipt as PreByzantiumTxReceipt).stateRoot ??
(receipt as PostByzantiumTxReceipt).status,
receipt.gasUsed,
bigIntToBuffer(receipt.gasUsed),
receipt.bitvector,
receipt.logs,
])
Expand All @@ -252,7 +252,11 @@ export class EthProtocol extends Protocol {
// Legacy receipt if r[0] >= 0xc0, otherwise typed receipt with first byte as TransactionType
const decoded = rlp.decode(r[0] >= 0xc0 ? r : r.slice(1)) as any
const [stateRootOrStatus, cumulativeGasUsed, logsBloom, logs] = decoded
const receipt = { gasUsed: cumulativeGasUsed, bitvector: logsBloom, logs } as TxReceipt
const receipt = {
gasUsed: bufferToBigInt(cumulativeGasUsed),
bitvector: logsBloom,
logs,
} as TxReceipt
if (stateRootOrStatus.length === 32) {
;(receipt as PreByzantiumTxReceipt).stateRoot = stateRootOrStatus
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/client/lib/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ const jsonRpcReceipt = async (
blockNumber: bigIntToHex(block.header.number),
from: tx.getSenderAddress().toString(),
to: tx.to?.toString() ?? null,
cumulativeGasUsed: bufferToHex(receipt.gasUsed),
cumulativeGasUsed: bigIntToHex(receipt.gasUsed),
effectiveGasPrice: bigIntToHex(effectiveGasPrice),
gasUsed: bigIntToHex(gasUsed),
contractAddress: contractAddress?.toString() ?? null,
Expand Down Expand Up @@ -535,7 +535,7 @@ export class Eth {
skipBalance: true,
skipBlockGasLimitValidation: true,
})
return `0x${gasUsed.toString(16)}`
return bigIntToHex(gasUsed)
}

/**
Expand Down
3 changes: 2 additions & 1 deletion packages/client/lib/service/fullethereumservice.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Hardfork } from '@ethereumjs/common'
import { bigIntToBuffer } from 'ethereumjs-util'
import { EthereumService, EthereumServiceOptions } from './ethereumservice'
import { FullSynchronizer } from '../sync/fullsync'
import { EthProtocol } from '../net/protocol/ethprotocol'
Expand All @@ -8,7 +9,6 @@ import { Protocol } from '../net/protocol'
import { Miner } from '../miner'
import { VMExecution } from '../execution'
import { Event } from '../types'

import type { Block } from '@ethereumjs/block'

interface FullEthereumServiceOptions extends EthereumServiceOptions {
Expand Down Expand Up @@ -189,6 +189,7 @@ export class FullEthereumService extends EthereumService {
let receiptsSize = 0
for (const hash of hashes) {
const blockReceipts = await receiptsManager.getReceipts(hash, true, true)
blockReceipts.forEach((r) => (r.gasUsed = bigIntToBuffer(r.gasUsed) as any))
if (!blockReceipts) continue
receipts.push(...blockReceipts)
receiptsSize += Buffer.byteLength(JSON.stringify(blockReceipts))
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/util/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const main = async () => {
const stateManager = new DefaultStateManager({ trie, common })
// Ensure we run on the right root
stateManager.setStateRoot(Buffer.from('${(
await execution.vm.stateManager.getStateRoot(true)
await execution.vm.stateManager.getStateRoot()
).toString('hex')}', 'hex'))
Expand Down
6 changes: 3 additions & 3 deletions packages/client/test/net/protocol/ethprotocol.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx'
import { Chain } from '../../../lib/blockchain/chain'
import { Config } from '../../../lib/config'
import { EthProtocol } from '../../../lib/net/protocol'
import { bigIntToBuffer, bufferToBigInt, intToBuffer } from 'ethereumjs-util'
import { bigIntToBuffer, bufferToBigInt } from 'ethereumjs-util'

tape('[EthProtocol]', (t) => {
t.test('should get properties', (t) => {
Expand Down Expand Up @@ -151,14 +151,14 @@ tape('[EthProtocol]', (t) => {
const receipts = [
{
status: 1 as 0 | 1,
gasUsed: intToBuffer(100),
gasUsed: BigInt(100),
bitvector: Buffer.alloc(256),
logs: [[Buffer.alloc(20), [Buffer.alloc(32), Buffer.alloc(32, 1)], Buffer.alloc(10)]],
txType: 2,
},
{
status: 0 as 0 | 1,
gasUsed: intToBuffer(1000),
gasUsed: BigInt(1000),
bitvector: Buffer.alloc(256, 1),
logs: [[Buffer.alloc(20, 1), [Buffer.alloc(32, 1), Buffer.alloc(32, 1)], Buffer.alloc(10)]],
txType: 0,
Expand Down
5 changes: 2 additions & 3 deletions packages/client/test/service/fullethereumservice.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import tape from 'tape'
import td from 'testdouble'
import { Log } from '@ethereumjs/vm/dist/evm/types'
import { intToBuffer } from 'ethereumjs-util'
import { Config } from '../../lib/config'
import { Event } from '../../lib/types'
import { VMExecution } from '../../lib/execution'
Expand Down Expand Up @@ -132,7 +131,7 @@ tape('[FullEthereumService]', async (t) => {
const receipts = [
{
status: 1 as 0 | 1,
gasUsed: intToBuffer(100),
gasUsed: BigInt(100),
bitvector: Buffer.alloc(256),
logs: [
[Buffer.alloc(20), [Buffer.alloc(32), Buffer.alloc(32, 1)], Buffer.alloc(10)],
Expand All @@ -141,7 +140,7 @@ tape('[FullEthereumService]', async (t) => {
},
{
status: 0 as 0 | 1,
gasUsed: intToBuffer(1000),
gasUsed: BigInt(1000),
bitvector: Buffer.alloc(256, 1),
logs: [
[Buffer.alloc(20, 1), [Buffer.alloc(32, 1), Buffer.alloc(32, 1)], Buffer.alloc(10)],
Expand Down
6 changes: 3 additions & 3 deletions packages/vm/benchmarks/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ export const verifyResult = (block: Block, result: RunBlockResult) => {
// check if there are receipts
const { receipts } = result
if (receipts) {
let cumGasUsed = 0
let cumGasUsed = BigInt(0)
for (let index = 0; index < receipts.length; index++) {
let gasUsedExpected = parseInt(receipts[index].gasUsed.toString('hex'), 16)
let cumGasUsedActual = parseInt(receipts[index].gasUsed.toString('hex'), 16)
let gasUsedExpected = receipts[index].gasUsed
let cumGasUsedActual = receipts[index].gasUsed
let gasUsed = cumGasUsedActual - cumGasUsed
if (gasUsed !== gasUsedExpected) {
console.log(`[DEBUG]
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 @@ -222,7 +222,7 @@ export class BlockBuilder {
await this.rewardMiner()
}

const stateRoot = await this.vm.stateManager.getStateRoot(true)
const stateRoot = await this.vm.stateManager.getStateRoot()
const transactionsTrie = await this.transactionsTrie()
const receiptTrie = await this.receiptTrie()
const logsBloom = this.logsBloom()
Expand Down
12 changes: 3 additions & 9 deletions packages/vm/src/evm/eei.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,7 @@ export default class EEI {
getBlockCoinbase(): bigint {
let coinbase: Address
if (this._common.consensusAlgorithm() === ConsensusAlgorithm.Clique) {
// Backwards-compatibilty check
// TODO: can be removed along VM v5 release
if ('cliqueSigner' in this._env.block.header) {
coinbase = this._env.block.header.cliqueSigner()
} else {
coinbase = Address.zero()
}
coinbase = this._env.block.header.cliqueSigner()
} else {
coinbase = this._env.block.header.coinbase
}
Expand Down Expand Up @@ -554,7 +548,7 @@ export default class EEI {
}

// this should always be safe
this.useGas(results.gasUsed, 'CALL, STATICCALL, DELEGATECALL, CALLCODE')
this.useGas(results.execResult.gasUsed, 'CALL, STATICCALL, DELEGATECALL, CALLCODE')

// Set return value
if (
Expand Down Expand Up @@ -627,7 +621,7 @@ export default class EEI {
}

// this should always be safe
this.useGas(results.gasUsed, 'CREATE')
this.useGas(results.execResult.gasUsed, 'CREATE')

// Set return buffer in case revert happened
if (
Expand Down
46 changes: 19 additions & 27 deletions packages/vm/src/evm/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
MAX_INTEGER,
} from 'ethereumjs-util'
import { Block } from '@ethereumjs/block'
import { Hardfork } from '@ethereumjs/common'
import { ERROR, VmError } from '../exceptions'
import { StateManager } from '../state/index'
import { getPrecompile, PrecompileFunc } from './precompiles'
Expand All @@ -29,17 +30,17 @@ const debugGas = createDebugLogger('vm:evm:gas')
*/
export interface EVMResult {
/**
* Amount of gas used by the transaction
*/
gasUsed: bigint
/**
* Address of created account durint transaction, if any
* Address of created account during transaction, if any
*/
createdAddress?: Address
/**
* Contains the results from running the code, if any, as described in {@link runCode}
*/
execResult: ExecResult
/**
* Total amount of gas to be refunded from all nested calls.
*/
gasRefund?: bigint
}

/**
Expand All @@ -48,15 +49,15 @@ export interface EVMResult {
export interface ExecResult {
runState?: RunState
/**
* Description of the exception, if any occured
* Description of the exception, if any occurred
*/
exceptionError?: VmError
/**
* Amount of gas left
*/
gas?: bigint
/**
* Amount of gas the code used to run
* Amount of gas the transaction used to run
*/
gasUsed: bigint
/**
Expand All @@ -71,10 +72,6 @@ export interface ExecResult {
* A map from the accounts that have self-destructed to the addresses to send their funds to
*/
selfdestruct?: { [k: string]: Buffer }
/**
* Total amount of gas to be refunded from all nested calls.
*/
gasRefund?: bigint
}

export interface NewContractEvent {
Expand Down Expand Up @@ -189,26 +186,27 @@ export default class EVM {
result = await this._executeCreate(message)
}
if (this._vm.DEBUG) {
const { gasUsed, exceptionError, returnValue, gasRefund } = result.execResult
const { gasUsed, exceptionError, returnValue } = result.execResult
debug(
`Received message execResult: [ gasUsed=${gasUsed} exceptionError=${
exceptionError ? `'${exceptionError.error}'` : 'none'
} returnValue=0x${short(returnValue)} gasRefund=${gasRefund ?? 0} ]`
} returnValue=0x${short(returnValue)} gasRefund=${result.gasRefund ?? 0} ]`
)
}
const err = result.execResult.exceptionError
// This clause captures any error which happened during execution
// If that is the case, then set the _refund tracker to the old refund value
if (err) {
// TODO: Move `gasRefund` to a tx-level result object
// instead of `ExecResult`.
this._refund = oldRefund
result.execResult.selfdestruct = {}
}
result.execResult.gasRefund = this._refund
result.gasRefund = this._refund

if (err) {
if (this._vm._common.gteHardfork('homestead') || err.error != ERROR.CODESTORE_OUT_OF_GAS) {
if (
this._vm._common.gteHardfork(Hardfork.Homestead) ||
err.error != ERROR.CODESTORE_OUT_OF_GAS
) {
result.execResult.logs = []
await this._state.revert()
if (this._vm.DEBUG) {
Expand Down Expand Up @@ -269,7 +267,6 @@ export default class EVM {
}
if (exit) {
return {
gasUsed: BigInt(0),
execResult: {
gasUsed: BigInt(0),
exceptionError: errorMessage, // Only defined if addToBalance failed
Expand All @@ -296,7 +293,6 @@ export default class EVM {
}

return {
gasUsed: result.gasUsed,
execResult: result,
}
}
Expand All @@ -309,7 +305,6 @@ export default class EVM {
if (this._vm._common.isActivatedEIP(3860)) {
if (message.data.length > this._vm._common.param('vm', 'maxInitCodeSize')) {
return {
gasUsed: message.gasLimit,
createdAddress: message.to,
execResult: {
returnValue: Buffer.alloc(0),
Expand Down Expand Up @@ -337,7 +332,6 @@ export default class EVM {
debug(`Returning on address collision`)
}
return {
gasUsed: message.gasLimit,
createdAddress: message.to,
execResult: {
returnValue: Buffer.alloc(0),
Expand All @@ -358,7 +352,7 @@ export default class EVM {

toAccount = await this._state.getAccount(message.to)
// EIP-161 on account creation and CREATE execution
if (this._vm._common.gteHardfork('spuriousDragon')) {
if (this._vm._common.gteHardfork(Hardfork.SpuriousDragon)) {
toAccount.nonce += BigInt(1)
}

Expand All @@ -385,7 +379,6 @@ export default class EVM {
}
if (exit) {
return {
gasUsed: BigInt(0),
createdAddress: message.to,
execResult: {
gasUsed: BigInt(0),
Expand Down Expand Up @@ -417,7 +410,7 @@ export default class EVM {
let allowedCodeSize = true
if (
!result.exceptionError &&
this._vm._common.gteHardfork('spuriousDragon') &&
this._vm._common.gteHardfork(Hardfork.SpuriousDragon) &&
result.returnValue.length > this._vm._common.param('vm', 'maxCodeSize')
) {
allowedCodeSize = false
Expand Down Expand Up @@ -461,7 +454,7 @@ export default class EVM {
result.gasUsed = totalGas
}
} else {
if (this._vm._common.gteHardfork('homestead')) {
if (this._vm._common.gteHardfork(Hardfork.Homestead)) {
if (this._vm.DEBUG) {
debug(`Not enough gas or code size not allowed (>= Homestead)`)
}
Expand Down Expand Up @@ -489,7 +482,7 @@ export default class EVM {
}
} else if (CodestoreOOG) {
// This only happens at Frontier. But, let's do a sanity check;
if (!this._vm._common.gteHardfork('homestead')) {
if (!this._vm._common.gteHardfork(Hardfork.Homestead)) {
// Pre-Homestead behavior; put an empty contract.
// This contract would be considered "DEAD" in later hard forks.
// It is thus an unecessary default item, which we have to save to dik
Expand All @@ -501,7 +494,6 @@ export default class EVM {
}

return {
gasUsed: result.gasUsed,
createdAddress: message.to,
execResult: result,
}
Expand Down
Loading