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: verkle testing extraction #3817

Merged
merged 7 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/common/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,8 @@ export class Common {
for (const hfChanges of this.HARDFORK_CHANGES) {
// EIP-referencing HF config (e.g. for berlin)
if ('eips' in hfChanges[1]) {
const hfEIPs = hfChanges[1]['eips']
for (const eip of hfEIPs!) {
const hfEIPs = hfChanges[1]['eips'] ?? []
for (const eip of hfEIPs) {
this._mergeWithParamsCache(this._params[eip] ?? {})
}
}
Expand All @@ -337,7 +337,7 @@ export class Common {

for (const [name, hf] of this.HARDFORK_CHANGES) {
if (this.gteHardfork(name) && 'eips' in hf) {
this._activatedEIPsCache = this._activatedEIPsCache.concat(hf['eips'] as number[])
this._activatedEIPsCache = this._activatedEIPsCache.concat(hf.eips ?? [])
}
}
this._activatedEIPsCache = this._activatedEIPsCache.concat(this._eips)
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/hardforks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,6 @@ export const hardforksDict: HardforksDict = {
* Status : Final
*/
verkle: {
eips: [4762, 6800],
eips: [2935, 4762, 6800],
},
}
13 changes: 10 additions & 3 deletions packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,20 @@ export type VerkleAccessedStateWithAddress = VerkleAccessedState & {
export interface VerkleAccessWitnessInterface {
accesses(): Generator<VerkleAccessedStateWithAddress>
rawAccesses(): Generator<RawVerkleAccessedState>
debugWitnessCost(): void
touchAndChargeProofOfAbsence(address: Address): bigint
touchAndChargeMessageCall(address: Address): bigint
touchAndChargeValueTransfer(target: Address): bigint
touchAndChargeContractCreateInit(address: Address): bigint
touchAndChargeContractCreateCompleted(address: Address): bigint
touchTxOriginAndComputeGas(origin: Address): bigint
touchTxTargetAndComputeGas(target: Address, { sendsValue }: { sendsValue?: boolean }): bigint
touchCodeChunksRangeOnReadAndChargeGas(contact: Address, startPc: number, endPc: number): bigint
touchCodeChunksRangeOnWriteAndChargeGas(contact: Address, startPc: number, endPc: number): bigint
touchCodeChunksRangeOnReadAndComputeGas(contract: Address, startPc: number, endPc: number): bigint
touchCodeChunksRangeOnWriteAndComputeGas(
contract: Address,
startPc: number,
endPc: number,
): bigint
touchAddressOnWriteAndComputeGas(
address: Address,
treeIndex: number | bigint,
Expand All @@ -120,7 +125,7 @@ export interface VerkleAccessWitnessInterface {
treeIndex: number | bigint,
subIndex: number | Uint8Array,
): bigint
touchAddressAndChargeGas(
touchAddressAndComputeGas(
address: Address,
treeIndex: number | bigint,
subIndex: number | Uint8Array,
Expand All @@ -133,6 +138,8 @@ export interface VerkleAccessWitnessInterface {
{ isWrite }: { isWrite?: boolean },
): AccessEventFlags
merge(accessWitness: VerkleAccessWitnessInterface): void
commit(): void
revert(): void
}

/*
Expand Down
35 changes: 35 additions & 0 deletions packages/evm/src/chunkCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { ChunkAccessEvent } from './verkleAccessWitness.js'
import type { PrefixedHexString } from '@ethereumjs/util'
export class ChunkCache {
cache: Map<PrefixedHexString, ChunkAccessEvent>

constructor() {
this.cache = new Map<PrefixedHexString, ChunkAccessEvent>()
}

set(stemKey: PrefixedHexString, accessedStem: ChunkAccessEvent) {
this.cache.set(stemKey, accessedStem)
}

get(stemHex: PrefixedHexString): ChunkAccessEvent | undefined {
return this.cache.get(stemHex)
}

del(stemHex: PrefixedHexString): void {
this.cache.delete(stemHex)
}

Check warning on line 20 in packages/evm/src/chunkCache.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/chunkCache.ts#L19-L20

Added lines #L19 - L20 were not covered by tests

commit(): [PrefixedHexString, ChunkAccessEvent][] {
const items: [PrefixedHexString, ChunkAccessEvent][] = Array.from(this.cache.entries())
this.clear()
return items
}

clear(): void {
this.cache.clear()
}

size() {
return this.cache.size
}

Check warning on line 34 in packages/evm/src/chunkCache.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/chunkCache.ts#L33-L34

Added lines #L33 - L34 were not covered by tests
}
32 changes: 25 additions & 7 deletions packages/evm/src/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,13 @@
if (this.DEBUG) {
debugGas(`callAccessGas charged(${callAccessGas}) caused OOG (-> ${gasLimit})`)
}
message.accessWitness.revert()

Check warning on line 290 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L290

Added line #L290 was not covered by tests
return { execResult: OOGResult(message.gasLimit) }
} else {
if (this.DEBUG) {
debugGas(`callAccessGas used (${callAccessGas} gas (-> ${gasLimit}))`)
}
message.accessWitness.commit()
}
}

Expand Down Expand Up @@ -323,11 +325,13 @@
`Proof of absence access charged(${absenceProofAccessGas}) caused OOG (-> ${gasLimit})`,
)
}
message.accessWitness?.revert()

Check warning on line 328 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L328

Added line #L328 was not covered by tests
return { execResult: OOGResult(message.gasLimit) }
} else {
if (this.DEBUG) {
debugGas(`Proof of absence access used (${absenceProofAccessGas} gas (-> ${gasLimit}))`)
}
message.accessWitness?.commit()

Check warning on line 334 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L334

Added line #L334 was not covered by tests
}
}
toAccount = new Account()
Expand Down Expand Up @@ -469,12 +473,14 @@
debugGas(
`ContractCreateInit charge(${contractCreateAccessGas}) caused OOG (-> ${gasLimit})`,
)
message.accessWitness?.revert()

Check warning on line 476 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L476

Added line #L476 was not covered by tests
}
return { execResult: OOGResult(message.gasLimit) }
} else {
if (this.DEBUG) {
debugGas(`ContractCreateInit charged (${contractCreateAccessGas} gas (-> ${gasLimit}))`)
}
message.accessWitness?.commit()

Check warning on line 483 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L483

Added line #L483 was not covered by tests
}
}

Expand Down Expand Up @@ -553,11 +559,15 @@
`ContractCreateComplete access gas (${createCompleteAccessGas}) caused OOG (-> ${gasLimit})`,
)
}
message.accessWitness?.revert()

Check warning on line 562 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L562

Added line #L562 was not covered by tests
return { execResult: OOGResult(message.gasLimit) }
} else {
debug(
`ContractCreateComplete access used (${createCompleteAccessGas}) gas (-> ${gasLimit})`,
)
if (this.DEBUG) {
debug(
`ContractCreateComplete access used (${createCompleteAccessGas}) gas (-> ${gasLimit})`,
)
}
message.accessWitness?.commit()

Check warning on line 570 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L565-L570

Added lines #L565 - L570 were not covered by tests
}
}

Expand Down Expand Up @@ -635,6 +645,7 @@
if (this.DEBUG) {
debug(`Contract creation: out of gas`)
}
message.accessWitness?.revert()

Check warning on line 648 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L648

Added line #L648 was not covered by tests
result = { ...result, ...OOGResult(message.gasLimit) }
}
} else {
Expand All @@ -644,12 +655,14 @@
if (this.DEBUG) {
debug(`Not enough gas to pay the code deposit fee (Frontier)`)
}
message.accessWitness?.revert()
result = { ...result, ...COOGResult(totalGas - returnFee) }
CodestoreOOG = true
} else {
if (this.DEBUG) {
debug(`Contract creation: out of gas`)
}
message.accessWitness?.revert()

Check warning on line 665 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L665

Added line #L665 was not covered by tests
result = { ...result, ...OOGResult(message.gasLimit) }
}
}
Expand All @@ -668,6 +681,7 @@
`ContractCreateComplete access gas (${createCompleteAccessGas}) caused OOG (-> ${gasLimit})`,
)
}
message.accessWitness?.revert()

Check warning on line 684 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L684

Added line #L684 was not covered by tests
result = { ...result, ...OOGResult(message.gasLimit) }
} else {
debug(
Expand All @@ -686,7 +700,7 @@
// Add access charges for writing this code to the state
if (this.common.isActivatedEIP(6800)) {
const byteCodeWriteAccessfee =
message.accessWitness!.touchCodeChunksRangeOnWriteAndChargeGas(
message.accessWitness!.touchCodeChunksRangeOnWriteAndComputeGas(

Check warning on line 703 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L703

Added line #L703 was not covered by tests
message.to,
0,
result.returnValue.length - 1,
Expand All @@ -698,9 +712,11 @@
`byteCodeWrite access gas (${byteCodeWriteAccessfee}) caused OOG (-> ${gasLimit})`,
)
}
message.accessWitness?.revert()

Check warning on line 715 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L715

Added line #L715 was not covered by tests
result = { ...result, ...OOGResult(message.gasLimit) }
} else {
debug(`byteCodeWrite access used (${byteCodeWriteAccessfee}) gas (-> ${gasLimit})`)
message.accessWitness?.commit()

Check warning on line 719 in packages/evm/src/evm.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/evm.ts#L719

Added line #L719 was not covered by tests
result.executionGasUsed += byteCodeWriteAccessfee
}
}
Expand Down Expand Up @@ -802,6 +818,7 @@
}
}

message.accessWitness?.commit()
return {
...result,
runState: {
Expand Down Expand Up @@ -834,11 +851,11 @@
let callerAccount
if (!message) {
this._block = opts.block ?? defaultBlock()
const caller = opts.caller ?? createZeroAddress()
this._tx = {
gasPrice: opts.gasPrice ?? BIGINT_0,
origin: opts.origin ?? opts.caller ?? createZeroAddress(),
origin: opts.origin ?? caller,
}
const caller = opts.caller ?? createZeroAddress()

const value = opts.value ?? BIGINT_0
if (opts.skipBalance === true) {
Expand Down Expand Up @@ -916,7 +933,7 @@
result = await this._executeCall(message as MessageWithTo)
} else {
if (this.DEBUG) {
debug(`Message CREATE execution (to undefined)`)
debug(`Message CREATE execution (to: undefined)`)
}
result = await this._executeCreate(message)
}
Expand Down Expand Up @@ -962,6 +979,7 @@
this.performanceLogger.stopTimer(timer!, 0)
}

message.accessWitness?.commit()
return result
}

Expand Down
18 changes: 11 additions & 7 deletions packages/evm/src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@
this.performanceLogger.unpauseTimer(overheadTimer)
}
} catch (e: any) {
// Revert access witness changes if we revert - per EIP-4762
this._runState.env.accessWitness?.revert()
if (overheadTimer !== undefined) {
this.performanceLogger.unpauseTimer(overheadTimer)
}
Expand Down Expand Up @@ -375,10 +377,17 @@
// It needs the base fee, for correct gas limit calculation for the CALL opcodes
gas = await opEntry.gasHandler(this._runState, gas, this.common)
}

if (this._evm.events.listenerCount('step') > 0 || this._evm.DEBUG) {
// Only run this stepHook function if there is an event listener (e.g. test runner)
// or if the vm is running in debug mode (to display opcode debug logs)
await this._runStepHook(gas, this.getGasLeft())
}

if (this.common.isActivatedEIP(6800) && this._env.chargeCodeAccesses === true) {
const contract = this._runState.interpreter.getAddress()
const statelessGas =
this._runState.env.accessWitness!.touchCodeChunksRangeOnReadAndChargeGas(
this._runState.env.accessWitness!.touchCodeChunksRangeOnReadAndComputeGas(

Check warning on line 390 in packages/evm/src/interpreter.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/interpreter.ts#L390

Added line #L390 was not covered by tests
contract,
this._runState.programCounter,
this._runState.programCounter,
Expand All @@ -387,12 +396,6 @@
debugGas(`codechunk accessed statelessGas=${statelessGas} (-> ${gas})`)
}

if (this._evm.events.listenerCount('step') > 0 || this._evm.DEBUG) {
// Only run this stepHook function if there is an event listener (e.g. test runner)
// or if the vm is running in debug mode (to display opcode debug logs)
await this._runStepHook(gas, this.getGasLeft())
}

// Check for invalid opcode
if (opInfo.isInvalid) {
throw new EvmError(ERROR.INVALID_OPCODE)
Expand All @@ -412,6 +415,7 @@
} else {
opFn.apply(null, [this._runState, this.common])
}
this._runState.env.accessWitness?.commit()
} finally {
if (this.profilerOpts?.enabled === true) {
this.performanceLogger.stopTimer(
Expand Down
2 changes: 1 addition & 1 deletion packages/evm/src/opcodes/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@
const contract = runState.interpreter.getAddress()
const startOffset = Math.min(runState.code.length, runState.programCounter + 1)
const endOffset = Math.min(runState.code.length, startOffset + numToPush - 1)
const statelessGas = runState.env.accessWitness!.touchCodeChunksRangeOnReadAndChargeGas(
const statelessGas = runState.env.accessWitness!.touchCodeChunksRangeOnReadAndComputeGas(

Check warning on line 962 in packages/evm/src/opcodes/functions.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/opcodes/functions.ts#L962

Added line #L962 was not covered by tests
contract,
startOffset,
endOffset,
Expand Down
4 changes: 2 additions & 2 deletions packages/evm/src/opcodes/gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@
codeEnd = codeSize
}

gas += runState.env.accessWitness!.touchCodeChunksRangeOnReadAndChargeGas(
gas += runState.env.accessWitness!.touchCodeChunksRangeOnReadAndComputeGas(

Check warning on line 157 in packages/evm/src/opcodes/gas.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/opcodes/gas.ts#L157

Added line #L157 was not covered by tests
contract,
Number(_codeOffset),
Number(codeEnd),
Expand Down Expand Up @@ -242,7 +242,7 @@
codeEnd = codeSize
}

gas += runState.env.accessWitness!.touchCodeChunksRangeOnReadAndChargeGas(
gas += runState.env.accessWitness!.touchCodeChunksRangeOnReadAndComputeGas(

Check warning on line 245 in packages/evm/src/opcodes/gas.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/opcodes/gas.ts#L245

Added line #L245 was not covered by tests
address,
Number(_codeOffset),
Number(codeEnd),
Expand Down
1 change: 1 addition & 0 deletions packages/evm/src/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ export const paramsEVM: ParamsDict = {
// evm
historyStorageAddress: '0x0aae40965e6800cd9b1f4b05ff21581047e3f91e', // The address where the historical blockhashes are stored
historyServeWindow: 8192, // The amount of blocks to be served by the historical blockhash contract
systemAddress: '0xfffffffffffffffffffffffffffffffffffffffe', // The system address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to have both of these parameters since they are identical?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will admit that I've been a bit confused with regards to those two addresses. I've played around when troubleshooting so this is a remnant of that. I've adjusted it so that it matches the EIP: https://eips.ethereum.org/EIPS/eip-2935

},
/**
. * BASEFEE opcode
Expand Down
44 changes: 44 additions & 0 deletions packages/evm/src/stemCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { StemAccessEvent, StemMeta } from './verkleAccessWitness.js'
import type { PrefixedHexString } from '@ethereumjs/util'
export class StemCache {
cache: Map<PrefixedHexString, StemAccessEvent & StemMeta>

constructor() {
this.cache = new Map<PrefixedHexString, StemAccessEvent & StemMeta>()
}

set(stemKey: PrefixedHexString, accessedStem: StemAccessEvent & StemMeta) {
this.cache.set(stemKey, accessedStem)
}

get(stemHex: PrefixedHexString): (StemAccessEvent & StemMeta) | undefined {
return this.cache.get(stemHex)
}

del(stemHex: PrefixedHexString): void {
this.cache.delete(stemHex)
}

Check warning on line 20 in packages/evm/src/stemCache.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/stemCache.ts#L19-L20

Added lines #L19 - L20 were not covered by tests

commit(): [PrefixedHexString, StemAccessEvent & StemMeta][] {
const items: [PrefixedHexString, StemAccessEvent & StemMeta][] = Array.from(
this.cache.entries(),
)
this.clear()
return items
}

/**
* Clear cache
*/
clear(): void {
this.cache.clear()
}

/**
* Returns the size of the cache
* @returns
*/
size() {
return this.cache.size
}

Check warning on line 43 in packages/evm/src/stemCache.ts

View check run for this annotation

Codecov / codecov/patch

packages/evm/src/stemCache.ts#L42-L43

Added lines #L42 - L43 were not covered by tests
}
Loading
Loading