Skip to content

cmd/evm/internal/t8ntool: support for verkle-at-genesis in evm t8n (verkle transition part 3) #31730

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

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
77 changes: 77 additions & 0 deletions .github/workflows/stable-spec-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Execution Spec Tests - Consume (stable)

on:
push:
branches: [master]
pull_request:
branches: [master, kaustinen-with-shapella]
workflow_dispatch:

env:
FIXTURES_TAG: "[email protected]"

jobs:
setup:
runs-on: ubuntu-latest
steps:
- name: Checkout go-ethereum
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12.4"

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.22.4

- name: Build geth evm
run: |
go build -v ./cmd/evm
mkdir -p ${{ github.workspace }}/bin
mv evm ${{ github.workspace }}/bin/evm
chmod +x ${{ github.workspace }}/bin/evm

- name: Archive built evm
uses: actions/upload-artifact@v4
with:
name: evm
path: ${{ github.workspace }}/bin/evm

consume:
runs-on: ubuntu-latest
needs: setup
strategy:
matrix:
filename:
[
fixtures_verkle-genesis.tar.gz,
]
steps:
- name: Download geth evm
uses: actions/download-artifact@v4
with:
name: evm
path: ./bin

- name: Make evm binary executable and add to PATH
run: |
chmod +x ./bin/evm
echo "${{ github.workspace }}/bin" >> $GITHUB_PATH

- name: Download fixtures
uses: robinraju/release-downloader@v1
with:
repository: "ethereum/execution-spec-tests"
tag: "${{ env.FIXTURES_TAG }}"
fileName: "${{ matrix.filename }}"
extract: true
- name: Clone execution-spec-tests and consume tests
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
git clone https://github.com/ethereum/execution-spec-tests -b ${{ env.FIXTURES_TAG }} --depth 1
cd execution-spec-tests
uv run consume direct --evm-bin="${{ github.workspace }}/bin/evm" --input=../fixtures -n auto
shell: bash
2 changes: 1 addition & 1 deletion cmd/evm/blockrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
continue
}
result := &testResult{Name: name, Pass: true}
if err := tests[name].Run(false, rawdb.HashScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
if err := tests[name].Run(false, rawdb.PathScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
if ctx.Bool(DumpFlag.Name) {
if s, _ := chain.State(); s != nil {
result.State = dump(s)
Expand Down
90 changes: 72 additions & 18 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/triedb"
"github.com/ethereum/go-verkle"
"github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)

type Prestate struct {
Env stEnv `json:"env"`
Pre types.GenesisAlloc `json:"pre"`
Env stEnv `json:"env"`
Pre types.GenesisAlloc `json:"pre"`
VKT map[common.Hash]hexutil.Bytes `json:"vkt,omitempty"`
}

//go:generate go run github.com/fjl/gencodec -type ExecutionResult -field-override executionResultMarshaling -out gen_execresult.go
Expand All @@ -68,6 +70,11 @@ type ExecutionResult struct {
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
Requests [][]byte `json:"requests"`

// Verkle witness
VerkleProof *verkle.VerkleProof `json:"verkleProof,omitempty"`
StateDiff verkle.StateDiff `json:"stateDiff,omitempty"`
ParentRoot common.Hash `json:"parentStateRoot,omitempty"`
}

type executionResultMarshaling struct {
Expand Down Expand Up @@ -101,6 +108,7 @@ type stEnv struct {
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
ParentHash *common.Hash `json:"parentHash,omitempty"`
}

type stEnvMarshaling struct {
Expand Down Expand Up @@ -143,16 +151,17 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return h
}
var (
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
gaspool = new(core.GasPool)
blockHash = common.Hash{0x13, 0x37}
rejectedTxs []*rejectedTx
includedTxs types.Transactions
gasUsed = uint64(0)
blobGasUsed = uint64(0)
receipts = make(types.Receipts, 0)
txIndex = 0
parentStateRoot, statedb = MakePreState(rawdb.NewMemoryDatabase(), chainConfig, pre, chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp))
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
gaspool = new(core.GasPool)
blockHash = common.Hash{0x13, 0x37}
rejectedTxs []*rejectedTx
includedTxs types.Transactions
gasUsed = uint64(0)
blobGasUsed = uint64(0)
receipts = make(types.Receipts, 0)
txIndex = 0
vtrpre *trie.VerkleTrie
)
gaspool.AddGas(pre.Env.GasLimit)
vmContext := vm.BlockContext{
Expand All @@ -165,6 +174,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
GasLimit: pre.Env.GasLimit,
GetHash: getHash,
}

// We save the current state of the Verkle Tree before applying the transactions.
// Note that if the Verkle fork isn't active, this will be a noop.
switch tr := statedb.GetTrie().(type) {
case *trie.VerkleTrie:
vtrpre = tr.Copy()
}

// If currentBaseFee is defined, add it to the vmContext.
if pre.Env.BaseFee != nil {
vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee)
Expand Down Expand Up @@ -251,6 +268,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}
}
statedb.SetTxContext(tx.Hash(), txIndex)
evm.AccessEvents = state.NewAccessEvents(evm.StateDB.PointCache())
var (
snapshot = statedb.Snapshot()
prevGas = gaspool.Gas()
Expand Down Expand Up @@ -315,7 +333,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
evm.Config.Tracer.OnTxEnd(receipt, nil)
}
}

statedb.AccessEvents().Merge(evm.AccessEvents)
txIndex++
}
statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber))
Expand Down Expand Up @@ -348,6 +366,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
// Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)

statedb.AccessEvents().AddAccount(w.Address, true)
}

// Gather the execution-layer triggered requests.
Expand All @@ -373,6 +393,25 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
}
// Add the witness to the execution result
var vktProof *verkle.VerkleProof
var vktStateDiff verkle.StateDiff
if chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) {
keys := statedb.AccessEvents().Keys()
if len(keys) > 0 && vtrpre != nil {
var proofTrie *trie.VerkleTrie
switch tr := statedb.GetTrie().(type) {
case *trie.VerkleTrie:
proofTrie = tr
default:
return nil, nil, nil, fmt.Errorf("invalid tree type in proof generation: %v", tr)
}
vktProof, vktStateDiff, err = vtrpre.Proof(proofTrie, keys)
if err != nil {
return nil, nil, nil, fmt.Errorf("error generating verkle proof for block %d: %w", pre.Env.Number, err)
}
}
}
execRs := &ExecutionResult{
StateRoot: root,
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
Expand All @@ -384,6 +423,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
GasUsed: (math.HexOrDecimal64)(gasUsed),
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
VerkleProof: vktProof,
StateDiff: vktStateDiff,
ParentRoot: parentStateRoot,
}
if pre.Env.Withdrawals != nil {
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
Expand Down Expand Up @@ -414,11 +456,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return statedb, execRs, body, nil
}

func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
// XXX peut-etre pas besoin de changer les parametres tant qu'on n'a pas la conversion
func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prestate, verkle bool) (common.Hash, *state.StateDB) {
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
sdb := state.NewDatabase(tdb, nil)

statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts {
for addr, a := range pre.Pre {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance)
Expand All @@ -427,9 +471,19 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
}
}
// Commit and re-open to start with a clean state.
root, _ := statedb.Commit(0, false, false)
statedb, _ = state.New(root, sdb)
return statedb
mptRoot, err := statedb.Commit(0, false, false)
if err != nil {
panic(err)
}
parentRoot := mptRoot
// If verkle mode started, establish the conversion
if verkle {
if _, ok := statedb.GetTrie().(*trie.VerkleTrie); ok {
return parentRoot, statedb
}
}
statedb, _ = state.New(mptRoot, sdb)
return parentRoot, statedb
}

func rlpHash(x interface{}) (h common.Hash) {
Expand Down
20 changes: 20 additions & 0 deletions cmd/evm/internal/t8ntool/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ var (
"\t<file> - into the file <file> ",
Value: "block.json",
}
OutputVKTFlag = &cli.StringFlag{
Name: "output.vkt",
Usage: "Determines where to put the `VKT` of the post-state.\n" +
"\t`stdout` - into the stdout output\n" +
"\t`stderr` - into the stderr output\n" +
"\t<file> - into the file <file> ",
Value: "vkt.json",
}
OutputWitnessFlag = &cli.StringFlag{
Name: "output.witness",
Usage: "Determines where to put the `witness` of the post-state.\n" +
"\t`stdout` - into the stdout output\n" +
"\t`stderr` - into the stderr output\n" +
"\t<file> - into the file <file> ",
Value: "witness.json",
}
InputAllocFlag = &cli.StringFlag{
Name: "input.alloc",
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
Expand Down Expand Up @@ -123,6 +139,10 @@ var (
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
Value: "txs.rlp",
}
InputVKTFlag = &cli.StringFlag{
Name: "input.vkt",
Usage: "`stdin` or file name of where to find the prestate VKT.",
}
SealCliqueFlag = &cli.StringFlag{
Name: "seal.clique",
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",
Expand Down
6 changes: 6 additions & 0 deletions cmd/evm/internal/t8ntool/gen_stenv.go

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

Loading
Loading