Skip to content

Commit

Permalink
Add Verkle SM methods as optional methods to interface, replace Verkl…
Browse files Browse the repository at this point in the history
…eSM imports and castings in VM
  • Loading branch information
holgerd77 committed Aug 17, 2024
1 parent 1692654 commit 83db446
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 23 deletions.
10 changes: 9 additions & 1 deletion packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External Interfaces for other EthereumJS libraries
*/

import type { Account, Address, PrefixedHexString } from '@ethereumjs/util'
import type { Account, Address, PrefixedHexString, VerkleExecutionWitness } from '@ethereumjs/util'

export interface StorageDump {
[key: string]: string
Expand Down Expand Up @@ -161,6 +161,14 @@ export interface StateManagerInterface {
}
generateCanonicalGenesis?(initState: any): Promise<void> // TODO make input more typesafe
// only Verkle/EIP-6800 (experimental)
accessWitness?: AccessWitnessInterface
initVerkleExecutionWitness?(
blockNum: bigint,
executionWitness?: VerkleExecutionWitness | null,
accessWitness?: AccessWitnessInterface,
): void
verifyVerkleProof?(stateRoot: Uint8Array): boolean
verifyPostState?(): boolean
checkChunkWitnessPresent?(contract: Address, programCounter: number): Promise<boolean>
getAppliedKey?(address: Uint8Array): Uint8Array // only for preimages

Expand Down
2 changes: 1 addition & 1 deletion packages/statemanager/src/statelessVerkleStateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ export class StatelessVerkleStateManager implements StateManagerInterface {
* @param {Uint8Array} stateRoot - The stateRoot to verify the executionWitness against
* @returns {boolean} - Returns true if the executionWitness matches the provided stateRoot, otherwise false
*/
verifyProof(stateRoot: Uint8Array): boolean {
verifyVerkleProof(stateRoot: Uint8Array): boolean {
if (this._executionWitness === undefined) {
debug('Missing executionWitness')
return false
Expand Down
6 changes: 6 additions & 0 deletions packages/vm/examples/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import { loadVerkleCrypto } from 'verkle-cryptography-wasm'

Check warning on line 2 in packages/vm/examples/test.ts

View check run for this annotation

Codecov / codecov/patch

packages/vm/examples/test.ts#L1-L2

Added lines #L1 - L2 were not covered by tests

const verkleCrypto = await loadVerkleCrypto()
const sm = new StatelessVerkleStateManager({ verkleCrypto })
console.log(sm)

Check warning on line 6 in packages/vm/examples/test.ts

View check run for this annotation

Codecov / codecov/patch

packages/vm/examples/test.ts#L4-L6

Added lines #L4 - L6 were not covered by tests
28 changes: 12 additions & 16 deletions packages/vm/src/runBlock.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createBlock, genRequestsTrieRoot } from '@ethereumjs/block'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import { Trie } from '@ethereumjs/trie'
import { TransactionType } from '@ethereumjs/tx'
import {
Expand Down Expand Up @@ -134,7 +133,7 @@ export async function runBlock(vm: VM, opts: RunBlockOpts): Promise<RunBlockResu
}

if (vm.common.isActivatedEIP(6800)) {
if (!(stateManager instanceof StatelessVerkleStateManager)) {
if (typeof stateManager.initVerkleExecutionWitness !== 'function') {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`)
}

Expand All @@ -153,17 +152,17 @@ export async function runBlock(vm: VM, opts: RunBlockOpts): Promise<RunBlockResu
await stateManager.setStateRoot(block.header.stateRoot)

// Populate the execution witness
stateManager.initVerkleExecutionWitness(block.header.number, block.executionWitness)
stateManager.initVerkleExecutionWitness!(block.header.number, block.executionWitness)

if (stateManager.verifyProof(opts.parentStateRoot) === false) {
if (stateManager.verifyVerkleProof!(opts.parentStateRoot) === false) {
throw Error(`Verkle proof verification failed`)
}

if (vm.DEBUG) {
debug(`Verkle proof verification succeeded`)
}
} else {
if (stateManager instanceof StatelessVerkleStateManager) {
if (typeof stateManager.initVerkleExecutionWitness === 'function') {
throw Error(`StatelessVerkleStateManager can't execute merkle blocks`)
}
}
Expand Down Expand Up @@ -315,7 +314,7 @@ export async function runBlock(vm: VM, opts: RunBlockOpts): Promise<RunBlockResu
}
} else if (vm.common.isActivatedEIP(6800)) {
// If verkle is activated, only validate the post-state
if ((vm['_opts'].stateManager as StatelessVerkleStateManager).verifyPostState() === false) {
if (vm['_opts'].stateManager!.verifyPostState!() === false) {
throw new Error(`Verkle post state verification failed on block ${block.header.number}`)
}
debug(`Verkle post state verification succeeded`)
Expand Down Expand Up @@ -517,9 +516,11 @@ export async function accumulateParentBlockHash(
if (vm.common.isActivatedEIP(6800)) {
const { treeIndex, subIndex } = getVerkleTreeIndexesForStorageSlot(ringKey)
// just create access witnesses without charging for the gas
;(
vm.stateManager as StatelessVerkleStateManager
).accessWitness!.touchAddressOnWriteAndComputeGas(historyAddress, treeIndex, subIndex)
vm.stateManager.accessWitness!.touchAddressOnWriteAndComputeGas(
historyAddress,
treeIndex,
subIndex,
)
}
const key = setLengthLeft(bigIntToBytes(ringKey), 32)
await vm.stateManager.putStorage(historyAddress, key, hash)
Expand Down Expand Up @@ -734,9 +735,7 @@ export async function rewardAccount(
let account = await evm.stateManager.getAccount(address)
if (account === undefined) {
if (common?.isActivatedEIP(6800) === true) {
;(
evm.stateManager as StatelessVerkleStateManager
).accessWitness!.touchAndChargeProofOfAbsence(address)
evm.stateManager.accessWitness!.touchAndChargeProofOfAbsence(address)

Check warning on line 738 in packages/vm/src/runBlock.ts

View check run for this annotation

Codecov / codecov/patch

packages/vm/src/runBlock.ts#L738

Added line #L738 was not covered by tests
}
account = new Account()
}
Expand All @@ -745,10 +744,7 @@ export async function rewardAccount(

if (common?.isActivatedEIP(6800) === true) {
// use vm utility to build access but the computed gas is not charged and hence free
;(evm.stateManager as StatelessVerkleStateManager).accessWitness!.touchTxTargetAndComputeGas(
address,
{ sendsValue: true },
)
evm.stateManager.accessWitness!.touchTxTargetAndComputeGas(address, { sendsValue: true })

Check warning on line 747 in packages/vm/src/runBlock.ts

View check run for this annotation

Codecov / codecov/patch

packages/vm/src/runBlock.ts#L747

Added line #L747 was not covered by tests
}
return account
}
Expand Down
9 changes: 4 additions & 5 deletions packages/vm/src/runTx.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { cliqueSigner, createBlock } from '@ethereumjs/block'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import { Blob4844Tx, Capability, isBlob4844Tx } from '@ethereumjs/tx'
import {
Account,
Expand Down Expand Up @@ -190,10 +189,10 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {

let stateAccesses
if (vm.common.isActivatedEIP(6800)) {
if (!(vm.stateManager instanceof StatelessVerkleStateManager)) {
if (typeof vm.stateManager.initVerkleExecutionWitness !== 'function') {
throw Error(`StatelessVerkleStateManager needed for execution of verkle blocks`)
}
stateAccesses = (vm.stateManager as StatelessVerkleStateManager).accessWitness
stateAccesses = vm.stateManager.accessWitness!
}
const txAccesses = stateAccesses?.shallowCopy()

Expand Down Expand Up @@ -597,7 +596,7 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
let minerAccount = await state.getAccount(miner)
if (minerAccount === undefined) {
if (vm.common.isActivatedEIP(6800)) {
;(state as StatelessVerkleStateManager).accessWitness!.touchAndChargeProofOfAbsence(miner)
state.accessWitness!.touchAndChargeProofOfAbsence(miner)

Check warning on line 599 in packages/vm/src/runTx.ts

View check run for this annotation

Codecov / codecov/patch

packages/vm/src/runTx.ts#L599

Added line #L599 was not covered by tests
}
minerAccount = new Account()
}
Expand All @@ -609,7 +608,7 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {

if (vm.common.isActivatedEIP(6800)) {
// use vm utility to build access but the computed gas is not charged and hence free
;(state as StatelessVerkleStateManager).accessWitness!.touchTxTargetAndComputeGas(miner, {
state.accessWitness!.touchTxTargetAndComputeGas(miner, {
sendsValue: true,
})
}
Expand Down

0 comments on commit 83db446

Please sign in to comment.