Skip to content

Commit 8cb93e9

Browse files
gballetjsign
andcommitted
cmd/evm/internal/t8ntool: support for verkle-at-genesis testnets
Co-authored-by: Ignacio Hagopian <[email protected]>
1 parent 1591d16 commit 8cb93e9

File tree

9 files changed

+344
-31
lines changed

9 files changed

+344
-31
lines changed
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Execution Spec Tests - Consume (stable)
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master, kaustinen-with-shapella]
8+
workflow_dispatch:
9+
10+
env:
11+
FIXTURES_TAG: "[email protected]"
12+
13+
jobs:
14+
setup:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout go-ethereum
18+
uses: actions/checkout@v4
19+
20+
- name: Setup Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.12.4"
24+
25+
- name: Set up Go
26+
uses: actions/setup-go@v5
27+
with:
28+
go-version: 1.22.4
29+
30+
- name: Build geth evm
31+
run: |
32+
go build -v ./cmd/evm
33+
mkdir -p ${{ github.workspace }}/bin
34+
mv evm ${{ github.workspace }}/bin/evm
35+
chmod +x ${{ github.workspace }}/bin/evm
36+
37+
- name: Archive built evm
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: evm
41+
path: ${{ github.workspace }}/bin/evm
42+
43+
consume:
44+
runs-on: ubuntu-latest
45+
needs: setup
46+
strategy:
47+
matrix:
48+
filename:
49+
[
50+
fixtures_verkle-genesis.tar.gz,
51+
]
52+
steps:
53+
- name: Download geth evm
54+
uses: actions/download-artifact@v4
55+
with:
56+
name: evm
57+
path: ./bin
58+
59+
- name: Make evm binary executable and add to PATH
60+
run: |
61+
chmod +x ./bin/evm
62+
echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
63+
64+
- name: Download fixtures
65+
uses: robinraju/release-downloader@v1
66+
with:
67+
repository: "ethereum/execution-spec-tests"
68+
tag: "${{ env.FIXTURES_TAG }}"
69+
fileName: "${{ matrix.filename }}"
70+
extract: true
71+
- name: Clone execution-spec-tests and consume tests
72+
run: |
73+
curl -LsSf https://astral.sh/uv/install.sh | sh
74+
git clone https://github.com/ethereum/execution-spec-tests -b ${{ env.FIXTURES_TAG }} --depth 1
75+
cd execution-spec-tests
76+
uv run consume direct --evm-bin="${{ github.workspace }}/bin/evm" --input=../fixtures -n auto
77+
shell: bash

cmd/evm/internal/t8ntool/execution.go

+72-18
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ import (
3939
"github.com/ethereum/go-ethereum/rlp"
4040
"github.com/ethereum/go-ethereum/trie"
4141
"github.com/ethereum/go-ethereum/triedb"
42+
"github.com/ethereum/go-verkle"
4243
"github.com/holiman/uint256"
4344
"golang.org/x/crypto/sha3"
4445
)
4546

4647
type Prestate struct {
47-
Env stEnv `json:"env"`
48-
Pre types.GenesisAlloc `json:"pre"`
48+
Env stEnv `json:"env"`
49+
Pre types.GenesisAlloc `json:"pre"`
50+
VKT map[common.Hash]hexutil.Bytes `json:"vkt,omitempty"`
4951
}
5052

5153
//go:generate go run github.com/fjl/gencodec -type ExecutionResult -field-override executionResultMarshaling -out gen_execresult.go
@@ -68,6 +70,11 @@ type ExecutionResult struct {
6870
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
6971
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
7072
Requests [][]byte `json:"requests"`
73+
74+
// Verkle witness
75+
VerkleProof *verkle.VerkleProof `json:"verkleProof,omitempty"`
76+
StateDiff verkle.StateDiff `json:"stateDiff,omitempty"`
77+
ParentRoot common.Hash `json:"parentStateRoot,omitempty"`
7178
}
7279

7380
type executionResultMarshaling struct {
@@ -101,6 +108,7 @@ type stEnv struct {
101108
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
102109
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
103110
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
111+
ParentHash *common.Hash `json:"parentHash,omitempty"`
104112
}
105113

106114
type stEnvMarshaling struct {
@@ -143,16 +151,17 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
143151
return h
144152
}
145153
var (
146-
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
147-
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
148-
gaspool = new(core.GasPool)
149-
blockHash = common.Hash{0x13, 0x37}
150-
rejectedTxs []*rejectedTx
151-
includedTxs types.Transactions
152-
gasUsed = uint64(0)
153-
blobGasUsed = uint64(0)
154-
receipts = make(types.Receipts, 0)
155-
txIndex = 0
154+
parentStateRoot, statedb = MakePreState(rawdb.NewMemoryDatabase(), chainConfig, pre, chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp))
155+
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
156+
gaspool = new(core.GasPool)
157+
blockHash = common.Hash{0x13, 0x37}
158+
rejectedTxs []*rejectedTx
159+
includedTxs types.Transactions
160+
gasUsed = uint64(0)
161+
blobGasUsed = uint64(0)
162+
receipts = make(types.Receipts, 0)
163+
txIndex = 0
164+
vtrpre *trie.VerkleTrie
156165
)
157166
gaspool.AddGas(pre.Env.GasLimit)
158167
vmContext := vm.BlockContext{
@@ -165,6 +174,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
165174
GasLimit: pre.Env.GasLimit,
166175
GetHash: getHash,
167176
}
177+
178+
// We save the current state of the Verkle Tree before applying the transactions.
179+
// Note that if the Verkle fork isn't active, this will be a noop.
180+
switch tr := statedb.GetTrie().(type) {
181+
case *trie.VerkleTrie:
182+
vtrpre = tr.Copy()
183+
}
184+
168185
// If currentBaseFee is defined, add it to the vmContext.
169186
if pre.Env.BaseFee != nil {
170187
vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee)
@@ -251,6 +268,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
251268
}
252269
}
253270
statedb.SetTxContext(tx.Hash(), txIndex)
271+
evm.AccessEvents = state.NewAccessEvents(evm.StateDB.PointCache())
254272
var (
255273
snapshot = statedb.Snapshot()
256274
prevGas = gaspool.Gas()
@@ -315,7 +333,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
315333
evm.Config.Tracer.OnTxEnd(receipt, nil)
316334
}
317335
}
318-
336+
statedb.AccessEvents().Merge(evm.AccessEvents)
319337
txIndex++
320338
}
321339
statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber))
@@ -348,6 +366,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
348366
// Amount is in gwei, turn into wei
349367
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
350368
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
369+
370+
statedb.AccessEvents().AddAccount(w.Address, true)
351371
}
352372

353373
// Gather the execution-layer triggered requests.
@@ -377,6 +397,25 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
377397
if err != nil {
378398
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
379399
}
400+
// Add the witness to the execution result
401+
var vktProof *verkle.VerkleProof
402+
var vktStateDiff verkle.StateDiff
403+
if chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) {
404+
keys := statedb.AccessEvents().Keys()
405+
if len(keys) > 0 && vtrpre != nil {
406+
var proofTrie *trie.VerkleTrie
407+
switch tr := statedb.GetTrie().(type) {
408+
case *trie.VerkleTrie:
409+
proofTrie = tr
410+
default:
411+
return nil, nil, nil, fmt.Errorf("invalid tree type in proof generation: %v", tr)
412+
}
413+
vktProof, vktStateDiff, err = vtrpre.Proof(proofTrie, keys)
414+
if err != nil {
415+
return nil, nil, nil, fmt.Errorf("error generating verkle proof for block %d: %w", pre.Env.Number, err)
416+
}
417+
}
418+
}
380419
execRs := &ExecutionResult{
381420
StateRoot: root,
382421
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
@@ -388,6 +427,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
388427
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
389428
GasUsed: (math.HexOrDecimal64)(gasUsed),
390429
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
430+
VerkleProof: vktProof,
431+
StateDiff: vktStateDiff,
432+
ParentRoot: parentStateRoot,
391433
}
392434
if pre.Env.Withdrawals != nil {
393435
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
@@ -418,11 +460,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
418460
return statedb, execRs, body, nil
419461
}
420462

421-
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
463+
// XXX peut-etre pas besoin de changer les parametres tant qu'on n'a pas la conversion
464+
func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prestate, verkle bool) (common.Hash, *state.StateDB) {
422465
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
423466
sdb := state.NewDatabase(tdb, nil)
467+
424468
statedb, _ := state.New(types.EmptyRootHash, sdb)
425-
for addr, a := range accounts {
469+
for addr, a := range pre.Pre {
426470
statedb.SetCode(addr, a.Code)
427471
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)
428472
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance)
@@ -431,9 +475,19 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
431475
}
432476
}
433477
// Commit and re-open to start with a clean state.
434-
root, _ := statedb.Commit(0, false, false)
435-
statedb, _ = state.New(root, sdb)
436-
return statedb
478+
mptRoot, err := statedb.Commit(0, false, false)
479+
if err != nil {
480+
panic(err)
481+
}
482+
parentRoot := mptRoot
483+
// If verkle mode started, establish the conversion
484+
if verkle {
485+
if _, ok := statedb.GetTrie().(*trie.VerkleTrie); ok {
486+
return parentRoot, statedb
487+
}
488+
}
489+
statedb, _ = state.New(mptRoot, sdb)
490+
return parentRoot, statedb
437491
}
438492

439493
func rlpHash(x interface{}) (h common.Hash) {

cmd/evm/internal/t8ntool/flags.go

+20
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ var (
8888
"\t<file> - into the file <file> ",
8989
Value: "block.json",
9090
}
91+
OutputVKTFlag = &cli.StringFlag{
92+
Name: "output.vkt",
93+
Usage: "Determines where to put the `VKT` of the post-state.\n" +
94+
"\t`stdout` - into the stdout output\n" +
95+
"\t`stderr` - into the stderr output\n" +
96+
"\t<file> - into the file <file> ",
97+
Value: "vkt.json",
98+
}
99+
OutputWitnessFlag = &cli.StringFlag{
100+
Name: "output.witness",
101+
Usage: "Determines where to put the `witness` of the post-state.\n" +
102+
"\t`stdout` - into the stdout output\n" +
103+
"\t`stderr` - into the stderr output\n" +
104+
"\t<file> - into the file <file> ",
105+
Value: "witness.json",
106+
}
91107
InputAllocFlag = &cli.StringFlag{
92108
Name: "input.alloc",
93109
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
@@ -123,6 +139,10 @@ var (
123139
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
124140
Value: "txs.rlp",
125141
}
142+
InputVKTFlag = &cli.StringFlag{
143+
Name: "input.vkt",
144+
Usage: "`stdin` or file name of where to find the prestate VKT.",
145+
}
126146
SealCliqueFlag = &cli.StringFlag{
127147
Name: "seal.clique",
128148
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",

cmd/evm/internal/t8ntool/gen_stenv.go

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)