cmd/evm/internal/t8ntool: support for verkle-at-genesis testnets

Co-authored-by: Ignacio Hagopian <jsign.uy@gmail.com>
This commit is contained in:
Guillaume Ballet 2025-04-22 18:17:18 +02:00
parent bb038c64a5
commit 2196aa1158
No known key found for this signature in database
11 changed files with 349 additions and 35 deletions

77
.github/workflows/stable-spec-tests.yml vendored Normal file
View file

@ -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: "verkle@v0.0.9-alpha-1"
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

View file

@ -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)

View file

@ -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
@ -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 {
@ -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 {
@ -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{
@ -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)
@ -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()
@ -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))
@ -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.
@ -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)),
@ -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))
@ -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)
@ -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) {

View file

@ -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.",
@ -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.",

View file

@ -37,6 +37,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
ParentHash *common.Hash `json:"parentHash,omitempty"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
@ -59,6 +60,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
enc.ParentHash = s.ParentHash
return json.Marshal(&enc)
}
@ -85,6 +87,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
ParentHash *common.Hash `json:"parentHash,omitempty"`
}
var dec stEnv
if err := json.Unmarshal(input, &dec); err != nil {
@ -154,5 +157,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.ParentBeaconBlockRoot != nil {
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
}
if dec.ParentHash != nil {
s.ParentHash = dec.ParentHash
}
return nil
}

View file

@ -75,10 +75,11 @@ var (
)
type input struct {
Alloc types.GenesisAlloc `json:"alloc,omitempty"`
Env *stEnv `json:"env,omitempty"`
Txs []*txWithKey `json:"txs,omitempty"`
TxRlp string `json:"txsRlp,omitempty"`
Alloc types.GenesisAlloc `json:"alloc,omitempty"`
Env *stEnv `json:"env,omitempty"`
VKT map[common.Hash]hexutil.Bytes `json:"vkt,omitempty"`
Txs []*txWithKey `json:"txs,omitempty"`
TxRlp string `json:"txsRlp,omitempty"`
}
func Transition(ctx *cli.Context) error {
@ -90,16 +91,16 @@ func Transition(ctx *cli.Context) error {
// stdin input or in files.
// Check if anything needs to be read from stdin
var (
prestate Prestate
txIt txIterator // txs to apply
allocStr = ctx.String(InputAllocFlag.Name)
prestate Prestate
txIt txIterator // txs to apply
allocStr = ctx.String(InputAllocFlag.Name)
vktStr = ctx.String(InputVKTFlag.Name)
envStr = ctx.String(InputEnvFlag.Name)
txStr = ctx.String(InputTxsFlag.Name)
inputData = &input{}
)
// Figure out the prestate alloc
if allocStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector {
if allocStr == stdinSelector || vktStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector {
decoder := json.NewDecoder(os.Stdin)
if err := decoder.Decode(inputData); err != nil {
return NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err))
@ -110,8 +111,18 @@ func Transition(ctx *cli.Context) error {
return err
}
}
if vktStr != stdinSelector {
if err := readFile(vktStr, "VKT", &inputData.Alloc); err != nil {
return err
}
}
prestate.Pre = inputData.Alloc
if vktStr != stdinSelector && vktStr != "" {
if err := readFile(vktStr, "VKT", &inputData.VKT); err != nil {
return err
}
}
prestate.VKT = inputData.VKT
// Set the block environment
if envStr != stdinSelector {
var env stEnv
@ -183,8 +194,14 @@ func Transition(ctx *cli.Context) error {
}
// Dump the execution result
collector := make(Alloc)
s.DumpToCollector(collector, nil)
return dispatchOutput(ctx, baseDir, result, collector, body)
var vktleaves map[common.Hash]hexutil.Bytes
if !chainConfig.IsVerkle(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) {
s.DumpToCollector(collector, nil)
} else {
vktleaves = make(map[common.Hash]hexutil.Bytes)
s.DumpVKTLeaves(vktleaves)
}
return dispatchOutput(ctx, baseDir, result, collector, body, vktleaves)
}
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
@ -306,7 +323,7 @@ func saveFile(baseDir, filename string, data interface{}) error {
// dispatchOutput writes the output data to either stderr or stdout, or to the specified
// files
func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, body hexutil.Bytes) error {
func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, body hexutil.Bytes, vkt map[common.Hash]hexutil.Bytes) error {
stdOutObject := make(map[string]interface{})
stdErrObject := make(map[string]interface{})
dispatch := func(baseDir, fName, name string, obj interface{}) error {
@ -333,6 +350,11 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
if err := dispatch(baseDir, ctx.String(OutputBodyFlag.Name), "body", body); err != nil {
return err
}
if vkt != nil {
if err := dispatch(baseDir, ctx.String(OutputVKTFlag.Name), "vkt", vkt); err != nil {
return err
}
}
if len(stdOutObject) > 0 {
b, err := json.MarshalIndent(stdOutObject, "", " ")
if err != nil {

View file

@ -146,10 +146,13 @@ var (
t8ntool.TraceEnableCallFramesFlag,
t8ntool.OutputBasedir,
t8ntool.OutputAllocFlag,
t8ntool.OutputVKTFlag,
t8ntool.OutputWitnessFlag,
t8ntool.OutputResultFlag,
t8ntool.OutputBodyFlag,
t8ntool.InputAllocFlag,
t8ntool.InputEnvFlag,
t8ntool.InputVKTFlag,
t8ntool.InputTxsFlag,
t8ntool.ForknameFlag,
t8ntool.ChainIDFlag,

View file

@ -98,6 +98,17 @@ data, and verifies that all snapshot storage data has a corresponding account.
Description: `
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
information about the specified address.
`,
},
{
Name: "inspect-garys-account",
Usage: "Check all snapshot layers for the specific account",
ArgsUsage: "<address | hash>",
Action: checkGarysAccounts,
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
information about the specified address.
`,
},
{
@ -692,3 +703,72 @@ func checkAccount(ctx *cli.Context) error {
log.Info("Checked the snapshot journalled storage", "time", common.PrettyDuration(time.Since(start)))
return nil
}
func checkGarysAccounts(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close()
var root common.Hash
if ctx.NArg() == 1 {
rootBytes := common.FromHex(ctx.Args().Get(1))
if len(rootBytes) != common.HashLength {
return fmt.Errorf("invalid hash: %s", ctx.Args().Get(1))
}
root = common.BytesToHash(rootBytes)
} else {
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
return errors.New("no head block")
}
root = headBlock.Root()
}
snapConfig := snapshot.Config{
CacheSize: 256,
Recovery: false,
NoBuild: true,
AsyncBuild: false,
}
snaptree, err := snapshot.New(snapConfig, chaindb, triedb, root)
if err != nil {
return err
}
accIt, err := snaptree.AccountIterator(root, common.Hash{})
if err != nil {
log.Error("Failed to create account iterator", "error", err)
return err
}
defer accIt.Release()
// Open the file in append mode, create it if it doesn't exist
file, err := os.OpenFile("weird_contracts.csv", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
file.WriteString("account hash,nonce,code hash,root hash,balance\n")
var weird int
for accIt.Next() {
acc, err := types.FullAccount(accIt.Account())
if err != nil {
log.Error("Failed to get full account", "error", err)
return err
}
if acc.Nonce == 0 && bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) && acc.Root != types.EmptyRootHash {
weird++
if _, err = file.WriteString(fmt.Sprintf("%x,%d,%x,%x,%s\n", accIt.Hash(), acc.Nonce, acc.CodeHash, acc.Root, acc.Balance.String())); err != nil {
return err
}
}
}
log.Info("sweep completed", "count", weird)
return nil
}

View file

@ -208,6 +208,18 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
return nextKey
}
func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) {
it, err := s.trie.(*trie.VerkleTrie).NodeIterator(nil)
if err != nil {
panic(err)
}
for it.Next(true) {
if it.Leaf() {
collector[common.BytesToHash(it.LeafKey())] = it.LeafBlob()
}
}
}
// RawDump returns the state. If the processing is aborted e.g. due to options
// reaching Max, the `Next` key is set on the returned Dump.
func (s *StateDB) RawDump(opts *DumpConfig) Dump {

View file

@ -117,19 +117,20 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
return UnsupportedForkError{t.json.Network}
}
// import pre accounts & construct test genesis block & state root
// Commit genesis state
gspec := t.genesis(config)
var (
db = rawdb.NewMemoryDatabase()
tconf = &triedb.Config{
Preimages: true,
IsVerkle: gspec.Config.VerkleTime != nil && *gspec.Config.VerkleTime <= gspec.Timestamp,
}
)
if scheme == rawdb.PathScheme {
if scheme == rawdb.PathScheme || tconf.IsVerkle {
tconf.PathDB = pathdb.Defaults
} else {
tconf.HashDB = hashdb.Defaults
}
// Commit genesis state
gspec := t.genesis(config)
// if ttd is not specified, set an arbitrary huge value
if gspec.Config.TerminalTotalDifficulty == nil {

View file

@ -464,6 +464,45 @@ var Forks = map[string]*params.ChainConfig{
Osaka: params.DefaultOsakaBlobConfig,
},
},
"Verkle": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(0),
VerkleTime: u64(0),
},
"ShanghaiToVerkleAtTime32": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(0),
VerkleTime: u64(32),
},
}
// AvailableForks returns the set of defined fork names