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

Implement t8ntool to use for execution-spec-tests / VM Block Builder Adjustments #3603

Merged
merged 120 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from 108 commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
2f26e9d
tx: implement strict 7702 validation
jochem-brouwer Aug 12, 2024
f59b5a0
vm: update 7702 tx validation
jochem-brouwer Aug 12, 2024
5d8ba39
evm: update 7702 [no ci]
jochem-brouwer Aug 12, 2024
4a20346
tx: add / fix 7702 tests
jochem-brouwer Aug 12, 2024
5e8e756
Merge branch 'master' into 7702-update
jochem-brouwer Aug 12, 2024
ad3effb
vm: fix test encoding of authorization lists [no ci]
jochem-brouwer Aug 12, 2024
f6da2c4
Merge branch 'master' into 7702-update
jochem-brouwer Aug 13, 2024
f8950b8
vm: correctly put authority nonce
jochem-brouwer Aug 14, 2024
842db9d
vm: add test 7702 extcodehash/extcodesize
jochem-brouwer Aug 16, 2024
0b6692f
vm: expand extcode* tests 7702 [no ci]
jochem-brouwer Aug 16, 2024
6136308
Merge branch 'master' into 7702-update
jochem-brouwer Aug 17, 2024
7a01e81
tx/vm: update tests [no ci]
jochem-brouwer Aug 17, 2024
0310175
evm/vm: update opcodes and fix tests 7702
jochem-brouwer Aug 17, 2024
81d2da2
Merge branch 'master' into 7702-update
jochem-brouwer Aug 17, 2024
d773d2b
fix cspell [no ci]
jochem-brouwer Aug 17, 2024
ddea27e
Implement t8n
jochem-brouwer Aug 18, 2024
db42d5e
cleanup
jochem-brouwer Aug 18, 2024
b9e7995
make start.sh executable
jochem-brouwer Aug 18, 2024
1afdf1b
remove console.log [no ci]
jochem-brouwer Aug 18, 2024
68d70b3
change readme [no ci]
jochem-brouwer Aug 18, 2024
7dc01c6
update t8n [no ci]
jochem-brouwer Aug 18, 2024
b30536d
add sample (delete me later)
jochem-brouwer Aug 18, 2024
4cf4547
update t8n [no ci]
jochem-brouwer Aug 18, 2024
c4b702e
update t8n to correctly output alloc [no ci]
jochem-brouwer Aug 18, 2024
7f4dc6a
remove console.logs [no ci]
jochem-brouwer Aug 18, 2024
e556de9
fix certain values for expected output [no ci]
jochem-brouwer Aug 19, 2024
e83e414
some t8n fixes regarding output
jochem-brouwer Aug 19, 2024
121ed0b
lint [no ci]
jochem-brouwer Aug 19, 2024
528612b
t8n fixes for paris format [no ci]
jochem-brouwer Aug 19, 2024
d4d3100
vm: get params from tx for 7702 [no ci]
jochem-brouwer Aug 19, 2024
b06a54c
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 19, 2024
d0a4dfb
t8n console.log dumps [no ci]
jochem-brouwer Aug 19, 2024
0fa00d3
vm: 7702 correctly apply the refund [no ci]
jochem-brouwer Aug 19, 2024
280b25f
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 19, 2024
1a21f86
vm: 7702: correctly handle self-sponsored txs [no ci]
jochem-brouwer Aug 19, 2024
3c94331
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 19, 2024
6162957
tx: throw if authorization list is empty
jochem-brouwer Aug 19, 2024
2043d1e
vm: requests do not throw if code is non-existant
jochem-brouwer Aug 19, 2024
01dafa1
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 19, 2024
9bd46ad
evm: ensure correct extcodehash reporting if account is delegated to …
jochem-brouwer Aug 19, 2024
41c4845
Merge branch 'master' into 7702-update
jochem-brouwer Aug 19, 2024
29de15f
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 19, 2024
1623bc7
update t8n to generate logs [no ci]
jochem-brouwer Aug 19, 2024
a617c3b
Merge branch 'master' into 7702-update
jochem-brouwer Aug 19, 2024
629cdbc
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 19, 2024
b28ff84
t8n correctly output log format [no ci]
jochem-brouwer Aug 19, 2024
d5ece8b
change t8ntool start script name [no ci]
jochem-brouwer Aug 19, 2024
0da8108
putcode log
jochem-brouwer Aug 20, 2024
d4f9c60
vm: 7702 ensure delegated accounts are not deleted [no ci]
jochem-brouwer Aug 20, 2024
8612a29
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 20, 2024
678c7cf
t8n: output CLrequests [no ci]
jochem-brouwer Aug 20, 2024
d26ddb3
Merge branch 'master' into 7702-update
jochem-brouwer Aug 20, 2024
fe0351d
Merge branch '7702-update' into t8ntool [no ci]
jochem-brouwer Aug 20, 2024
ae01bca
t8n: add initKzg / blob tx support
jochem-brouwer Aug 20, 2024
8f9eddb
t8n: add blockhash support
jochem-brouwer Aug 21, 2024
4edea49
t8n: produce allocation for system contracts
jochem-brouwer Aug 21, 2024
57a98cc
vm/buildBlock: take parentHash from headerData if present
jochem-brouwer Aug 21, 2024
3685ab4
t8n: lint [no ci]
jochem-brouwer Aug 21, 2024
db3d243
vm: exit early if system contract has no code [no ci]
jochem-brouwer Aug 21, 2024
d95e598
t8n: use mcl instead of noble for bls [no ci]
jochem-brouwer Aug 21, 2024
993684d
remove console.logs
jochem-brouwer Aug 23, 2024
a41ef16
evm: 7702 correctly check for gas on delegated code
jochem-brouwer Aug 23, 2024
30072e2
evm: add verkle gas logic for 7702
jochem-brouwer Aug 23, 2024
eb5a79f
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 23, 2024
79d3833
t8n: delete unwanted files [no ci]
jochem-brouwer Aug 25, 2024
33b8523
vm/tx: fix 7702 tests
jochem-brouwer Aug 25, 2024
964b97a
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 25, 2024
5b4313a
tx: throw if 7702-tx has no `to` field
jochem-brouwer Aug 25, 2024
07793c7
vm/tx: fix 7702 tests
jochem-brouwer Aug 25, 2024
e65100f
t8n: first cleanup
jochem-brouwer Aug 25, 2024
820c3c3
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 25, 2024
757395b
t8ntool: WIP [no ci]
jochem-brouwer Aug 26, 2024
f68fa9c
VM: exit early on non-existing system contracts
jochem-brouwer Aug 26, 2024
2f0d1ab
VM: exit early on non-existing system contracts
jochem-brouwer Aug 26, 2024
70acda7
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 26, 2024
4ed53d4
backup [no ci]
jochem-brouwer Aug 26, 2024
93b1d13
t8ntool: do not delete coinbase
jochem-brouwer Aug 27, 2024
eb3063c
correctly exit early on requests
jochem-brouwer Aug 27, 2024
d133f9d
backup
jochem-brouwer Aug 27, 2024
80788a1
7702: add delegated account to warm address
jochem-brouwer Aug 27, 2024
ec85a45
7702: add delegated account to warm address
jochem-brouwer Aug 27, 2024
f89d04b
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 27, 2024
2ba2b34
increase memory limit
jochem-brouwer Aug 27, 2024
332799a
export node options
jochem-brouwer Aug 27, 2024
fc16513
vm: requests do restore system account
jochem-brouwer Aug 28, 2024
8b0cc5c
vm: requests do restore system account
jochem-brouwer Aug 28, 2024
edc695f
Merge branch '7702-update' into t8ntool
jochem-brouwer Aug 28, 2024
097f7be
t8ntool: convert edge cases to correct values
jochem-brouwer Aug 28, 2024
e710e78
7702: continue processing once auth ecrecover is invalid
jochem-brouwer Aug 28, 2024
e7fa82f
Merge branch '7702-update' into t8ntool [no ci]
jochem-brouwer Aug 28, 2024
8cc5755
evm/vm: add 7702 delegation constant
jochem-brouwer Sep 2, 2024
21f1de1
Merge branch 'master' into 7702-update
jochem-brouwer Sep 2, 2024
6325bc3
vm: fix requests
jochem-brouwer Sep 2, 2024
cb131ee
Merge branch '7702-update' into t8ntool
jochem-brouwer Sep 2, 2024
0d77c3f
Merge branch 'master' into 7702-update
jochem-brouwer Sep 2, 2024
4287e95
vm: unduplify 3607 error msg
jochem-brouwer Sep 2, 2024
bb346da
Merge branch '7702-update' into t8ntool [no ci]
jochem-brouwer Sep 2, 2024
d0e5105
update wip t8n cleanup [no ci]
jochem-brouwer Sep 2, 2024
1b7dfbf
add TODO to buildblock
jochem-brouwer Sep 2, 2024
e98cf8c
update t8ntool to use createVM [no ci]
jochem-brouwer Sep 3, 2024
aceb8ef
update clean version as well [no ci]
jochem-brouwer Sep 3, 2024
aed93cd
Merge remote-tracking branch 'origin/master' into 7702-update
acolytec3 Sep 11, 2024
ea9f88d
Merge branch 'master' into 7702-update
acolytec3 Sep 11, 2024
88dfdd0
fix example
acolytec3 Sep 11, 2024
e3d843e
Merge branch '7702-update' into t8ntool
jochem-brouwer Sep 12, 2024
06c958e
Merge branch 'master' into t8ntool
jochem-brouwer Sep 12, 2024
aad5ce6
t8ntool attempt to cleanup
jochem-brouwer Sep 12, 2024
f97d56b
t8ntool: cleanup
jochem-brouwer Sep 12, 2024
632ee30
t8ntool fix import
jochem-brouwer Sep 13, 2024
f75624c
remove old files
jochem-brouwer Sep 13, 2024
cc2abf7
use noble bls t8ntool
jochem-brouwer Sep 13, 2024
7a26e26
add loggers to t8n args
jochem-brouwer Sep 13, 2024
6d913ec
add readme [no ci]
jochem-brouwer Sep 13, 2024
df2d0b9
add t8ntool test
jochem-brouwer Sep 13, 2024
40638cc
fix cspell
jochem-brouwer Sep 13, 2024
bd9ebe1
Merge branch 'master' into t8ntool
jochem-brouwer Sep 13, 2024
552b9ed
add deprecated output.body
jochem-brouwer Sep 13, 2024
fb67671
make tsc happy
jochem-brouwer Sep 13, 2024
f272184
vm: fix 2935 test
jochem-brouwer Sep 13, 2024
335967a
Skip t8n tests in browser
acolytec3 Sep 14, 2024
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
13 changes: 10 additions & 3 deletions packages/vm/src/buildBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class BlockBuilder {

this.headerData = {
...opts.headerData,
parentHash: opts.parentBlock.hash(),
parentHash: opts.headerData?.parentHash ?? opts.parentBlock.hash(),
number: opts.headerData?.number ?? opts.parentBlock.header.number + BIGINT_1,
gasLimit: opts.headerData?.gasLimit ?? opts.parentBlock.header.gasLimit,
timestamp: opts.headerData?.timestamp ?? Math.round(Date.now() / 1000),
Expand Down Expand Up @@ -213,7 +213,10 @@ export class BlockBuilder {
*/
async addTransaction(
tx: TypedTransaction,
{ skipHardForkValidation }: { skipHardForkValidation?: boolean } = {},
{
skipHardForkValidation,
allowNoBlobs,
}: { skipHardForkValidation?: boolean; allowNoBlobs?: boolean } = {},
) {
this.checkStatus()

Expand Down Expand Up @@ -242,7 +245,11 @@ export class BlockBuilder {

// Guard against the case if a tx came into the pool without blobs i.e. network wrapper payload
if (blobTx.blobs === undefined) {
throw new Error('blobs missing for 4844 transaction')
// TODO: verify if we want this, do we want to allow the block builder to accept blob txs without the actual blobs?
// (these must have at least one `blobVersionedHashes`, this is verified at tx-level)
acolytec3 marked this conversation as resolved.
Show resolved Hide resolved
if (allowNoBlobs !== true) {
throw new Error('blobs missing for 4844 transaction')
}
}

if (this.blobGasUsed + BigInt(blobTx.numBlobs()) * blobGasPerBlob > blobGasLimit) {
Expand Down
33 changes: 12 additions & 21 deletions packages/vm/src/runBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,14 +494,12 @@ export async function accumulateParentBlockHash(

// getAccount with historyAddress will throw error as witnesses are not bundled
// but we need to put account so as to query later for slot
try {
if ((await vm.stateManager.getAccount(historyAddress)) === undefined) {
const emptyHistoryAcc = new Account(BigInt(1))
await vm.evm.journal.putAccount(historyAddress, emptyHistoryAcc)
}
} catch (_e) {
const emptyHistoryAcc = new Account(BigInt(1))
await vm.evm.journal.putAccount(historyAddress, emptyHistoryAcc)
const code = await vm.stateManager.getCode(historyAddress)

if (code.length === 0) {
// Exit early, system contract has no code so no storage is written
// TODO: verify with Gabriel that this is fine regarding verkle (should we put an empty account?)
return
}

async function putBlockHash(vm: VM, hash: Uint8Array, number: bigint) {
Expand Down Expand Up @@ -536,24 +534,17 @@ export async function accumulateParentBeaconBlockRoot(vm: VM, root: Uint8Array,
const timestampIndex = timestamp % historicalRootsLength
const timestampExtended = timestampIndex + historicalRootsLength

/**
* Note: (by Jochem)
* If we don't do vm (put account if undefined / non-existent), block runner crashes because the beacon root address does not exist
* vm is hence (for me) again a reason why it should /not/ throw if the address does not exist
* All ethereum accounts have empty storage by default
*/

/**
* Note: (by Gabriel)
* Get account will throw an error in stateless execution b/c witnesses are not bundled
* But we do need an account so we are able to put the storage
*/
try {
if ((await vm.stateManager.getAccount(parentBeaconBlockRootAddress)) === undefined) {
await vm.evm.journal.putAccount(parentBeaconBlockRootAddress, new Account())
}
} catch (_) {
await vm.evm.journal.putAccount(parentBeaconBlockRootAddress, new Account())
const code = await vm.stateManager.getCode(parentBeaconBlockRootAddress)

if (code.length === 0) {
// Exit early, system contract has no code so no storage is written
// TODO: verify with Gabriel that this is fine regarding verkle (should we put an empty account?)
return
}

await vm.stateManager.putStorage(
Expand Down
1 change: 1 addition & 0 deletions packages/vm/test/t8n/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO write instructions
8 changes: 8 additions & 0 deletions packages/vm/test/t8n/ethereumjs-t8ntool.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
if [[ "$1" == "--version" ]]; then
echo "ethereumjs t8n v1"
exit 0
fi
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
export NODE_OPTIONS="--max-old-space-size=4096"
tsx "$SCRIPT_DIR/launchT8N.ts" "$@"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
tsx "$SCRIPT_DIR/launchT8N.ts" "$@"
npx tsx "$SCRIPT_DIR/launchT8N.ts" "$@"

This way it will run even if I only have tsx installed locally within ethjs and not globally.

122 changes: 122 additions & 0 deletions packages/vm/test/t8n/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import yargs from 'yargs'
import { hideBin } from 'yargs/helpers'

import type { T8NOptions } from './types.js'

export function getArguments() {
const argsParsed = yargs(hideBin(process.argv))
.parserConfiguration({
'dot-notation': false,
})
.option('state.fork', {
describe: 'Fork to use',
type: 'string',
demandOption: true,
})
.option('state.chainid', {
describe: 'ChainID to use',
type: 'string',
default: '1',
})
.option('state.reward', {
describe:
'Coinbase reward after running txs. If 0: coinbase account is touched and rewarded 0 wei. If -1, the coinbase account is not touched (default)',
type: 'string',
default: '-1',
})
.option('input.alloc', {
describe: 'Initial state allocation',
type: 'string',
demandOption: true,
})
.option('input.txs', {
describe: 'JSON input of txs to run on top of the initial state allocation',
type: 'string',
demandOption: true,
})
.option('input.env', {
describe: 'Input environment (coinbase, difficulty, etc.)',
type: 'string',
demandOption: true,
})
.option('output.basedir', {
describe: 'Base directory to write output to',
type: 'string',
demandOption: true,
})
.option('output.result', {
describe: 'File to write output results to (relative to `output.basedir`)',
type: 'string',
demandOption: true,
})
.option('output.alloc', {
describe: 'File to write output allocation to (after running the transactions)',
type: 'string',
demandOption: true,
})
.option('output.body', {
describe: 'File to write the txs RLP to',
type: 'string',
default: 'txs.rlp',
})
.strict()
.help().argv

const args = argsParsed as any as T8NOptions

args.input = {
alloc: (<any>args)['input.alloc'],
txs: (<any>args)['input.txs'],
env: (<any>args)['input.env'],
}
args.output = {
basedir: (<any>args)['output.basedir'],
result: (<any>args)['output.result'],
alloc: (<any>args)['output.alloc'],
body: (<any>args)['output.body'],
}
args.state = {
fork: (<any>args)['state.fork'],
reward: BigInt((<any>args)['state.reward']),
chainid: BigInt((<any>args)['state.chainid']),
}

return args
}

/**
* This function accepts an `inputs.env` which converts non-hex-prefixed numbers
* to a BigInt value, to avoid errors when converting non-prefixed hex strings to
* numbers
* @param input
* @returns converted input
*/
export function normalizeNumbers(input: any) {
const keys = [
'currentGasLimit',
'currentNumber',
'currentTimestamp',
'currentRandom',
'currentDifficulty',
'currentBaseFee',
'currentBlobGasUsed',
'currentExcessBlobGas',
'parentDifficulty',
'parentTimestamp',
'parentBaseFee',
'parentGasUsed',
'parentGasLimit',
'parentBlobGasUsed',
'parentExcessBlobGas',
]

for (const key of keys) {
const value = input[key]
if (value !== undefined) {
if (value.substring(0, 2) !== '0x') {
input[key] = BigInt(value)
}
}
}
return input
}
6 changes: 6 additions & 0 deletions packages/vm/test/t8n/launchT8N.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { getArguments } from './helpers.js'
import { TransitionTool } from './t8ntool.js'

const args = getArguments()

await TransitionTool.run(args)
110 changes: 110 additions & 0 deletions packages/vm/test/t8n/stateTracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
bigIntToHex,
bytesToHex,
createAddressFromString,
hexToBytes,
setLengthLeft,
unpadBytes,
} from '@ethereumjs/util'

import type { VM } from '../../src/vm.js'
import type { T8NAlloc } from './types.js'
import type { Account, Address, PrefixedHexString } from '@ethereumjs/util'

export class StateTracker {
private allocTracker: {
// TODO these are all PrefixexHexString
[address: string]: {
storage: string[]
}
} = {}

private alloc: T8NAlloc

private vm: VM

constructor(vm: VM, alloc: T8NAlloc) {
this.alloc = alloc
const originalPutAccount = vm.stateManager.putAccount
const originalPutCode = vm.stateManager.putCode
const originalPutStorage = vm.stateManager.putStorage

this.vm = vm

const self = this

vm.stateManager.putAccount = async function (...args: [Address, Account?]) {
const address = args[0]
self.addAddress(address.toString())
await originalPutAccount.apply(this, args)
}

vm.stateManager.putCode = async function (...args: [Address, Uint8Array]) {
const address = args[0]
self.addAddress(address.toString())
return originalPutCode.apply(this, args)
}

vm.stateManager.putStorage = async function (...args: [Address, Uint8Array, Uint8Array]) {
const address = args[0]
const key = args[1]
self.addStorage(address.toString(), <PrefixedHexString>bytesToHex(key))
return originalPutStorage.apply(this, args)
}
}

private addAddress(address: PrefixedHexString) {
if (this.allocTracker[address] === undefined) {
this.allocTracker[address] = { storage: [] }
}
return this.allocTracker[address]
}

private addStorage(address: PrefixedHexString, storage: PrefixedHexString) {
const storageList = this.addAddress(address).storage
if (!storageList.includes(storage)) {
storageList.push(storage)
}
}

public async dumpAlloc() {
// Build output alloc
const outputAlloc = this.alloc
for (const addressString in this.allocTracker) {
const address = createAddressFromString(addressString)
const account = await this.vm.stateManager.getAccount(address)
if (account === undefined) {
delete outputAlloc[addressString]
continue
}
if (outputAlloc[addressString] === undefined) {
outputAlloc[addressString] = {
balance: '0x0',
}
}
outputAlloc[addressString].nonce = bigIntToHex(account.nonce)
outputAlloc[addressString].balance = bigIntToHex(account.balance)
outputAlloc[addressString].code = bytesToHex(await this.vm.stateManager.getCode(address))

const storage = this.allocTracker[addressString].storage
outputAlloc[addressString].storage = outputAlloc[addressString].storage ?? {}

for (const key of storage) {
const keyBytes = hexToBytes(<PrefixedHexString>key)
let storageKeyTrimmed = bytesToHex(unpadBytes(keyBytes))
if (storageKeyTrimmed === '0x') {
storageKeyTrimmed = '0x00'
}
const value = await this.vm.stateManager.getStorage(address, setLengthLeft(keyBytes, 32))
if (value.length === 0) {
delete outputAlloc[addressString].storage[storageKeyTrimmed]
// To be sure, also delete any keys which are left-padded to 32 bytes
delete outputAlloc[addressString].storage[key]
continue
}
outputAlloc[addressString].storage[storageKeyTrimmed] = bytesToHex(value)
}
}
return outputAlloc
}
}
Loading
Loading