-
Notifications
You must be signed in to change notification settings - Fork 802
/
Copy patht8ntool.spec.ts
149 lines (137 loc) · 6.2 KB
/
t8ntool.spec.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import { readFileSync } from 'fs'
import { assert, describe, expect, it } from 'vitest'
import { TransitionTool } from '../../t8n/t8ntool.ts'
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
import { MerkleStateManager } from '@ethereumjs/statemanager'
import { createTx } from '@ethereumjs/tx'
import { Account, createAddressFromPrivateKey, hexToBytes, randomBytes } from '@ethereumjs/util'
import { createVM, runTx } from '../../../src/index.ts'
import { stepTraceJSON, summaryTraceJSON } from '../../t8n/helpers.ts'
import type { T8NOptions } from '../../t8n/types.ts'
const t8nDir = 'test/t8n/testdata/'
const args: T8NOptions = {
state: {
fork: 'shanghai',
reward: BigInt(0),
chainid: BigInt(1),
},
input: {
alloc: `${t8nDir}input/alloc.json`,
txs: `${t8nDir}input/txs.json`,
env: `${t8nDir}input/env.json`,
},
output: {
basedir: t8nDir,
result: `output/resultTEST.json`,
alloc: `output/allocTEST.json`,
},
log: false,
trace: false,
}
// This test is generated using `execution-spec-tests` commit 88cab2521322191b2ec7ef7d548740c0b0a264fc, running:
// fill -k test_push0_contracts[fork_Shanghai-blockchain_test-key_sstore] --fork Shanghai tests/shanghai/eip3855_push0 --evm-bin=<ETHEREUMJS_T8NTOOL_LAUNCHER.sh>
// The test will run the TransitionTool using the inputs, and then compare if the output matches
describe('test runner config tests', () => {
it('should run t8ntool with inputs and report the expected output', async () => {
await TransitionTool.run(args)
const expectedResult = JSON.parse(readFileSync(`${t8nDir}output/result.json`).toString())
const expectedAlloc = JSON.parse(readFileSync(`${t8nDir}output/alloc.json`).toString())
const reportedResult = JSON.parse(readFileSync(`${t8nDir}output/resultTEST.json`).toString())
const reportedAlloc = JSON.parse(readFileSync(`${t8nDir}output/allocTEST.json`).toString())
assert.deepStrictEqual(reportedResult, expectedResult, 'result matches expected result')
assert.deepStrictEqual(reportedAlloc, expectedAlloc, 'alloc matches expected alloc')
})
})
describe('trace tests', async () => {
it('should produce a valid step trace for a legacy contract', async () => {
const common = new Common({ chain: Mainnet, hardfork: Hardfork.Cancun })
const sm = new MerkleStateManager({ common })
const vm = await createVM({ common, stateManager: sm })
const bytecode = hexToBytes('0x604260005260206000F3') // PUSH1 42 PUSH1 00 MSTORE PUSH1 20 PUSH1 00 RETURN
const contractAddress = createAddressFromPrivateKey(randomBytes(32))
await vm.stateManager.putAccount(contractAddress)
await vm.stateManager.putCode(contractAddress, bytecode)
const trace: string[] = []
vm.evm.events!.on('step', (step) => {
trace.push(JSON.stringify(stepTraceJSON(step, true)))
})
vm.events!.on('afterTx', async (event) => {
trace.push(JSON.stringify(await summaryTraceJSON(event, vm)))
})
const tx = await createTx({
to: contractAddress,
data: bytecode,
gasLimit: 0xffffffff,
gasPrice: 0xf,
}).sign(randomBytes(32))
await runTx(vm, { tx, skipBalance: true, skipBlockGasLimitValidation: true, skipNonce: true })
assert.equal(trace.length, 7, 'trace length is 7')
assert.equal(JSON.parse(trace[6]).gasUsed, 21154)
})
it('should produce a trace of the correct length', async () => {
const common = new Common({
hardfork: Hardfork.Prague,
eips: [663, 3540, 3670, 4200, 4750, 5450, 6206, 7069, 7480, 7620, 7692, 7698],
chain: Mainnet,
})
const sm = new MerkleStateManager({ common })
const vm = await createVM({ common, stateManager: sm })
const code = hexToBytes('0xef000101000402000100030400010000800001305000ef')
const pk = randomBytes(32)
const caller = createAddressFromPrivateKey(pk) // caller address
const contractAddress = createAddressFromPrivateKey(randomBytes(32)) // contract address
await vm.stateManager.putCode(contractAddress, code)
await vm.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x11111111)))
const tx = await createTx({
gasLimit: BigInt(0xffff),
gasPrice: 0x7,
to: contractAddress,
}).sign(pk)
const trace: string[] = []
vm.evm.events!.on('step', (step) => {
trace.push(JSON.stringify(stepTraceJSON(step, true)))
})
vm.events!.on('afterTx', async (event) => {
trace.push(JSON.stringify(await summaryTraceJSON(event, vm)))
})
const result = await runTx(vm, {
tx,
skipBalance: true,
skipNonce: true,
skipBlockGasLimitValidation: true,
})
assert.equal(result.execResult.executionGasUsed, BigInt(4))
assert.equal(trace.length, 4)
})
it('should produce a trace with storage activates', async () => {
const bytecode = hexToBytes('0x604260005560206000f3') // PUSH1 42 PUSH1 00 MSTORE PUSH1 20 PUSH1 00 RETURN
const common = new Common({ chain: Mainnet, hardfork: Hardfork.Cancun })
const sm = new MerkleStateManager({ common })
const vm = await createVM({ common, stateManager: sm })
const contractAddress = createAddressFromPrivateKey(randomBytes(32))
await vm.stateManager.putAccount(contractAddress)
await vm.stateManager.putCode(contractAddress, bytecode)
const trace: string[] = []
vm.evm.events!.on('step', (step) => {
trace.push(JSON.stringify(stepTraceJSON(step, false, true)))
})
vm.events!.on('afterTx', async (event) => {
trace.push(JSON.stringify(await summaryTraceJSON(event, vm)))
})
const tx = await createTx({
to: contractAddress,
gasLimit: 0xffffffff,
gasPrice: 0xf,
}).sign(randomBytes(32))
await runTx(vm, { tx, skipBalance: true, skipBlockGasLimitValidation: true, skipNonce: true })
assert.equal(trace.length, 7, 'trace length is 7')
// First step trace should have empty storage
const traceStepWithoutStorage = JSON.parse(trace[0])
expect(traceStepWithoutStorage.storage.length).toBe(0)
// Last step trace should have storage with actual value
const traceStepWithStorage = JSON.parse(trace[5])
assert.exists(traceStepWithStorage.storage)
expect(traceStepWithStorage.storage).toMatchObject([['0x0', '0x42']])
assert.equal(JSON.parse(trace[6]).gasUsed, 43115)
})
})