From 415d9da47002f8bb393dc28ed5fbe7e191478953 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Fri, 18 Jul 2025 13:00:28 +0800 Subject: [PATCH 1/6] cmd/workload, eth/tracers/native: introduce state proof tests --- cmd/workload/main.go | 1 + cmd/workload/prooftest.go | 105 ++++++++ cmd/workload/prooftestgen.go | 326 +++++++++++++++++++++++++ cmd/workload/testsuite.go | 4 + eth/tracers/native/gen_account_json.go | 28 +-- eth/tracers/native/prestate.go | 18 +- ethclient/gethclient/gethclient.go | 7 +- 7 files changed, 464 insertions(+), 25 deletions(-) create mode 100644 cmd/workload/prooftest.go create mode 100644 cmd/workload/prooftestgen.go diff --git a/cmd/workload/main.go b/cmd/workload/main.go index 32618d6a79b..0b890594648 100644 --- a/cmd/workload/main.go +++ b/cmd/workload/main.go @@ -48,6 +48,7 @@ func init() { historyGenerateCommand, filterGenerateCommand, traceGenerateCommand, + proofGenerateCommand, filterPerfCommand, } } diff --git a/cmd/workload/prooftest.go b/cmd/workload/prooftest.go new file mode 100644 index 00000000000..dcc063d30e5 --- /dev/null +++ b/cmd/workload/prooftest.go @@ -0,0 +1,105 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package main + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "os" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/internal/utesting" + "github.com/urfave/cli/v2" +) + +// proofTest is the content of a state-proof test. +type proofTest struct { + BlockNumbers []uint64 `json:"blockNumbers"` + Addresses [][]common.Address `json:"addresses"` + StorageKeys [][][]string `json:"storageKeys"` + Results [][]common.Hash `json:"results"` +} + +type proofTestSuite struct { + cfg testConfig + tests proofTest + invalidDir string +} + +func newProofTestSuite(cfg testConfig, ctx *cli.Context) *proofTestSuite { + s := &proofTestSuite{ + cfg: cfg, + invalidDir: ctx.String(proofTestInvalidOutputFlag.Name), + } + if err := s.loadTests(); err != nil { + exit(err) + } + return s +} + +func (s *proofTestSuite) loadTests() error { + file, err := s.cfg.fsys.Open(s.cfg.proofTestFile) + if err != nil { + // If not found in embedded FS, try to load it from disk + if !os.IsNotExist(err) { + return err + } + file, err = os.OpenFile(s.cfg.proofTestFile, os.O_RDONLY, 0666) + if err != nil { + return fmt.Errorf("can't open proofTestFile: %v", err) + } + } + defer file.Close() + if err := json.NewDecoder(file).Decode(&s.tests); err != nil { + return fmt.Errorf("invalid JSON in %s: %v", s.cfg.proofTestFile, err) + } + if len(s.tests.BlockNumbers) == 0 { + return fmt.Errorf("proofTestFile %s has no test data", s.cfg.proofTestFile) + } + return nil +} + +func (s *proofTestSuite) allTests() []workloadTest { + return []workloadTest{ + newArchiveWorkloadTest("Proof/GetProof", s.getProof), + } +} + +func (s *proofTestSuite) getProof(t *utesting.T) { + ctx := context.Background() + for i, blockNumber := range s.tests.BlockNumbers { + for j := 0; j < len(s.tests.Addresses[i]); j++ { + res, err := s.cfg.client.Geth.GetProof(ctx, s.tests.Addresses[i][j], s.tests.StorageKeys[i][j], big.NewInt(int64(blockNumber))) + if err != nil { + t.Errorf("State proving fails, blockNumber: %d, address: %x, keys: %v, err: %v\n", blockNumber, s.tests.Addresses[i][j], strings.Join(s.tests.StorageKeys[i][j], " "), err) + continue + } + blob, err := json.Marshal(res) + if err != nil { + t.Fatalf("State proving fails: error %v", err) + continue + } + if crypto.Keccak256Hash(blob) != s.tests.Results[i][j] { + t.Errorf("State proof mismatch, %d, number: %d, address: %x, keys: %v: invalid result", i, blockNumber, s.tests.Addresses[i][j], strings.Join(s.tests.StorageKeys[i][j], " ")) + } + } + } +} diff --git a/cmd/workload/prooftestgen.go b/cmd/workload/prooftestgen.go new file mode 100644 index 00000000000..becd7da965e --- /dev/null +++ b/cmd/workload/prooftestgen.go @@ -0,0 +1,326 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see + +package main + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "math/rand" + "os" + "path/filepath" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/eth/tracers/native" + "github.com/ethereum/go-ethereum/internal/flags" + "github.com/ethereum/go-ethereum/internal/testrand" + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +var ( + proofGenerateCommand = &cli.Command{ + Name: "proofgen", + Usage: "Generates tests for state proof verification", + ArgsUsage: "", + Action: generateProofTests, + Flags: []cli.Flag{ + proofTestFileFlag, + proofTestResultOutputFlag, + proofTestStatesFlag, + }, + } + + proofTestFileFlag = &cli.StringFlag{ + Name: "proof-tests", + Usage: "JSON file containing proof test queries", + Value: "proof_tests.json", + Category: flags.TestingCategory, + } + proofTestResultOutputFlag = &cli.StringFlag{ + Name: "proof-output", + Usage: "Folder containing detailed trace output files", + Value: "", + Category: flags.TestingCategory, + } + proofTestStatesFlag = &cli.Int64Flag{ + Name: "proof-states", + Usage: "Number of states to generate proof against", + Value: 10000, + Category: flags.TestingCategory, + } + proofTestInvalidOutputFlag = &cli.StringFlag{ + Name: "proof-invalid", + Usage: "Folder containing the mismatched state proof output files", + Value: "", + Category: flags.TestingCategory, + } +) + +type proofGenerator func(cli *client, head uint64, number int) ([]uint64, [][]common.Address, [][][]string, error) + +func genAccountProof(cli *client, head uint64, number int) ([]uint64, [][]common.Address, [][][]string, error) { + var ( + blockNumbers []uint64 + accountAddresses [][]common.Address + storageKeys [][][]string + nAccounts int + ctx = context.Background() + start = time.Now() + ) + chainID, err := cli.Eth.ChainID(ctx) + if err != nil { + return nil, nil, nil, err + } + signer := types.LatestSignerForChainID(chainID) + + for { + if nAccounts >= number { + break + } + blockNumber := rand.Intn(int(head)) + 1 + + block, err := cli.Eth.BlockByNumber(context.Background(), big.NewInt(int64(blockNumber))) + if err != nil { + continue + } + var ( + addresses []common.Address + keys [][]string + gather = func(address common.Address) { + addresses = append(addresses, address) + keys = append(keys, nil) + nAccounts++ + } + ) + for _, tx := range block.Transactions() { + if nAccounts >= number { + break + } + sender, err := signer.Sender(tx) + if err != nil { + log.Error("Failed to resolve the sender address", "hash", tx.Hash(), "err", err) + continue + } + gather(sender) + + if tx.To() != nil { + gather(*tx.To()) + } + } + blockNumbers = append(blockNumbers, uint64(blockNumber)) + accountAddresses = append(accountAddresses, addresses) + storageKeys = append(storageKeys, keys) + } + log.Info("Generated tests for account proof", "blocks", len(blockNumbers), "accounts", nAccounts, "elapsed", common.PrettyDuration(time.Since(start))) + return blockNumbers, accountAddresses, storageKeys, nil +} + +func genNonExistentAccountProof(cli *client, head uint64, number int) ([]uint64, [][]common.Address, [][][]string, error) { + var ( + blockNumbers []uint64 + accountAddresses [][]common.Address + storageKeys [][][]string + total int + ) + for i := 0; i < number/5; i++ { + var ( + addresses []common.Address + keys [][]string + blockNumber = uint64(rand.Intn(int(head))) + 1 + ) + for j := 0; j < 5; j++ { + addresses = append(addresses, testrand.Address()) + keys = append(keys, nil) + } + total += len(addresses) + blockNumbers = append(blockNumbers, blockNumber) + accountAddresses = append(accountAddresses, addresses) + storageKeys = append(storageKeys, keys) + } + log.Info("Generated tests for non-existing account proof", "blocks", len(blockNumbers), "accounts", total) + return blockNumbers, accountAddresses, storageKeys, nil +} + +func genStorageProof(cli *client, head uint64, number int) ([]uint64, [][]common.Address, [][][]string, error) { + var ( + blockNumbers []uint64 + accountAddresses [][]common.Address + storageKeys [][][]string + + nAccounts int + nStorages int + start = time.Now() + ) + for { + if nAccounts+nStorages >= number { + break + } + blockNumber := rand.Intn(int(head)) + 1 + + block, err := cli.Eth.BlockByNumber(context.Background(), big.NewInt(int64(blockNumber))) + if err != nil { + continue + } + var ( + addresses []common.Address + slots [][]string + tracer = "prestateTracer" + configBlob, _ = json.Marshal(native.PrestateTracerConfig{ + DiffMode: false, + DisableCode: true, + DisableStorage: false, + }) + ) + for _, tx := range block.Transactions() { + if nAccounts+nStorages >= number { + break + } + if tx.To() == nil { + continue + } + blob, err := cli.Geth.TraceTransaction(context.Background(), tx.Hash(), &tracers.TraceConfig{ + Tracer: &tracer, + TracerConfig: configBlob, + }) + if err != nil { + log.Error("Failed to trace the transaction", "blockNumber", blockNumber, "hash", tx.Hash(), "err", err) + continue + } + var accounts map[common.Address]*native.PrestateAccount + if err := json.Unmarshal(blob.(json.RawMessage), &accounts); err != nil { + log.Error("Failed to decode trace result", "blockNumber", blockNumber, "hash", tx.Hash(), "err", err) + continue + } + for addr, account := range accounts { + if len(account.Storage) == 0 { + continue + } + addresses = append(addresses, addr) + nAccounts += 1 + + var keys []string + for k := range account.Storage { + keys = append(keys, k.Hex()) + } + nStorages += len(keys) + + var emptyKeys []string + for i := 0; i < 3; i++ { + emptyKeys = append(emptyKeys, testrand.Hash().Hex()) + } + nStorages += len(emptyKeys) + + slots = append(slots, append(keys, emptyKeys...)) + } + } + blockNumbers = append(blockNumbers, uint64(blockNumber)) + accountAddresses = append(accountAddresses, addresses) + storageKeys = append(storageKeys, slots) + } + log.Info("Generated tests for account proof", "blocks", len(blockNumbers), "accounts", nAccounts, "storages", nStorages, "elapsed", common.PrettyDuration(time.Since(start))) + return blockNumbers, accountAddresses, storageKeys, nil +} + +func genProofRequests(cli *client, head uint64, states int) (*proofTest, error) { + var ( + blockNumbers []uint64 + accountAddresses [][]common.Address + storageKeys [][][]string + ) + for _, fn := range []proofGenerator{genAccountProof, genNonExistentAccountProof, genStorageProof} { + numbers, addresses, keys, err := fn(cli, head, states/3) + if err != nil { + return nil, err + } + blockNumbers = append(blockNumbers, numbers...) + accountAddresses = append(accountAddresses, addresses...) + storageKeys = append(storageKeys, keys...) + } + return &proofTest{ + BlockNumbers: blockNumbers, + Addresses: accountAddresses, + StorageKeys: storageKeys, + }, nil +} + +func generateProofTests(clictx *cli.Context) error { + var ( + client = makeClient(clictx) + ctx = context.Background() + states = clictx.Int(proofTestStatesFlag.Name) + outputFile = clictx.String(proofTestFileFlag.Name) + outputDir = clictx.String(traceTestResultOutputFlag.Name) + ) + head, err := client.Eth.BlockNumber(ctx) + if err != nil { + exit(err) + } + test, err := genProofRequests(client, head, states) + if err != nil { + exit(err) + } + for i, blockNumber := range test.BlockNumbers { + var hashes []common.Hash + for j := 0; j < len(test.Addresses[i]); j++ { + res, err := client.Geth.GetProof(ctx, test.Addresses[i][j], test.StorageKeys[i][j], big.NewInt(int64(blockNumber))) + if err != nil { + log.Error("Failed to prove the state", "number", blockNumber, "address", test.Addresses[i][j], "slots", len(test.StorageKeys[i][j]), "err", err) + continue + } + blob, err := json.Marshal(res) + if err != nil { + return err + } + hashes = append(hashes, crypto.Keccak256Hash(blob)) + writeStateProof(outputDir, blockNumber, test.Addresses[i][j], blob) + } + test.Results = append(test.Results, hashes) + } + writeJSON(outputFile, test) + return nil +} + +func writeStateProof(dir string, blockNumber uint64, address common.Address, result any) { + if dir == "" { + return + } + // Ensure the directory exists + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + exit(fmt.Errorf("failed to create directories: %w", err)) + } + fname := fmt.Sprintf("%d-%x", blockNumber, address) + name := filepath.Join(dir, fname) + file, err := os.Create(name) + if err != nil { + exit(fmt.Errorf("error creating %s: %v", name, err)) + return + } + defer file.Close() + + data, _ := json.MarshalIndent(result, "", " ") + _, err = file.Write(data) + if err != nil { + exit(fmt.Errorf("error writing %s: %v", name, err)) + return + } +} diff --git a/cmd/workload/testsuite.go b/cmd/workload/testsuite.go index 39eeb8e3c20..418b4c976bf 100644 --- a/cmd/workload/testsuite.go +++ b/cmd/workload/testsuite.go @@ -51,6 +51,7 @@ var ( historyTestFileFlag, traceTestFileFlag, traceTestInvalidOutputFlag, + proofTestInvalidOutputFlag, }, } testPatternFlag = &cli.StringFlag{ @@ -95,6 +96,7 @@ type testConfig struct { historyTestFile string historyPruneBlock *uint64 traceTestFile string + proofTestFile string } var errPrunedHistory = fmt.Errorf("attempt to access pruned history") @@ -222,11 +224,13 @@ func runTestCmd(ctx *cli.Context) error { filterSuite := newFilterTestSuite(cfg) historySuite := newHistoryTestSuite(cfg) traceSuite := newTraceTestSuite(cfg, ctx) + proofSuite := newProofTestSuite(cfg, ctx) // Filter test cases. tests := filterSuite.allTests() tests = append(tests, historySuite.allTests()...) tests = append(tests, traceSuite.allTests()...) + tests = append(tests, proofSuite.allTests()...) utests := filterTests(tests, ctx.String(testPatternFlag.Name), func(t workloadTest) bool { if t.Slow && !ctx.Bool(testSlowFlag.Name) { diff --git a/eth/tracers/native/gen_account_json.go b/eth/tracers/native/gen_account_json.go index 4c39cbc38cd..911456c5d59 100644 --- a/eth/tracers/native/gen_account_json.go +++ b/eth/tracers/native/gen_account_json.go @@ -13,44 +13,44 @@ import ( var _ = (*accountMarshaling)(nil) // MarshalJSON marshals as JSON. -func (a account) MarshalJSON() ([]byte, error) { - type account struct { +func (p PrestateAccount) MarshalJSON() ([]byte, error) { + type PrestateAccount struct { Balance *hexutil.Big `json:"balance,omitempty"` Code hexutil.Bytes `json:"code,omitempty"` Nonce uint64 `json:"nonce,omitempty"` Storage map[common.Hash]common.Hash `json:"storage,omitempty"` } - var enc account - enc.Balance = (*hexutil.Big)(a.Balance) - enc.Code = a.Code - enc.Nonce = a.Nonce - enc.Storage = a.Storage + var enc PrestateAccount + enc.Balance = (*hexutil.Big)(p.Balance) + enc.Code = p.Code + enc.Nonce = p.Nonce + enc.Storage = p.Storage return json.Marshal(&enc) } // UnmarshalJSON unmarshals from JSON. -func (a *account) UnmarshalJSON(input []byte) error { - type account struct { +func (p *PrestateAccount) UnmarshalJSON(input []byte) error { + type PrestateAccount struct { Balance *hexutil.Big `json:"balance,omitempty"` Code *hexutil.Bytes `json:"code,omitempty"` Nonce *uint64 `json:"nonce,omitempty"` Storage map[common.Hash]common.Hash `json:"storage,omitempty"` } - var dec account + var dec PrestateAccount if err := json.Unmarshal(input, &dec); err != nil { return err } if dec.Balance != nil { - a.Balance = (*big.Int)(dec.Balance) + p.Balance = (*big.Int)(dec.Balance) } if dec.Code != nil { - a.Code = *dec.Code + p.Code = *dec.Code } if dec.Nonce != nil { - a.Nonce = *dec.Nonce + p.Nonce = *dec.Nonce } if dec.Storage != nil { - a.Storage = dec.Storage + p.Storage = dec.Storage } return nil } diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index 57c66ae3272..765d8df464b 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -35,15 +35,15 @@ import ( "github.com/ethereum/go-ethereum/params" ) -//go:generate go run github.com/fjl/gencodec -type account -field-override accountMarshaling -out gen_account_json.go +//go:generate go run github.com/fjl/gencodec -type PrestateAccount -field-override accountMarshaling -out gen_account_json.go func init() { tracers.DefaultDirectory.Register("prestateTracer", newPrestateTracer, false) } -type stateMap = map[common.Address]*account +type stateMap = map[common.Address]*PrestateAccount -type account struct { +type PrestateAccount struct { Balance *big.Int `json:"balance,omitempty"` Code []byte `json:"code,omitempty"` Nonce uint64 `json:"nonce,omitempty"` @@ -51,7 +51,7 @@ type account struct { empty bool } -func (a *account) exists() bool { +func (a *PrestateAccount) exists() bool { return a.Nonce > 0 || len(a.Code) > 0 || len(a.Storage) > 0 || (a.Balance != nil && a.Balance.Sign() != 0) } @@ -65,7 +65,7 @@ type prestateTracer struct { pre stateMap post stateMap to common.Address - config prestateTracerConfig + config PrestateTracerConfig chainConfig *params.ChainConfig interrupt atomic.Bool // Atomic flag to signal execution interruption reason error // Textual reason for the interruption @@ -73,7 +73,7 @@ type prestateTracer struct { deleted map[common.Address]bool } -type prestateTracerConfig struct { +type PrestateTracerConfig struct { DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications DisableCode bool `json:"disableCode"` // If true, this tracer will not return the contract code DisableStorage bool `json:"disableStorage"` // If true, this tracer will not return the contract storage @@ -81,7 +81,7 @@ type prestateTracerConfig struct { } func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) { - var config prestateTracerConfig + var config PrestateTracerConfig if err := json.Unmarshal(cfg, &config); err != nil { return nil, err } @@ -244,7 +244,7 @@ func (t *prestateTracer) processDiffState() { continue } modified := false - postAccount := &account{Storage: make(map[common.Hash]common.Hash)} + postAccount := &PrestateAccount{Storage: make(map[common.Hash]common.Hash)} newBalance := t.env.StateDB.GetBalance(addr).ToBig() newNonce := t.env.StateDB.GetNonce(addr) @@ -300,7 +300,7 @@ func (t *prestateTracer) lookupAccount(addr common.Address) { return } - acc := &account{ + acc := &PrestateAccount{ Balance: t.env.StateDB.GetBalance(addr).ToBig(), Nonce: t.env.StateDB.GetNonce(addr), Code: t.env.StateDB.GetCode(addr), diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index d030878e546..a55fe4f777f 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -105,7 +105,10 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s var res accountResult err := ec.c.CallContext(ctx, &res, "eth_getProof", account, keys, toBlockNumArg(blockNumber)) - // Turn hexutils back to normal datatypes + if err != nil { + return nil, err + } + // Turn hexutils back to normal data types storageResults := make([]StorageResult, 0, len(res.StorageProof)) for _, st := range res.StorageProof { storageResults = append(storageResults, StorageResult{ @@ -123,7 +126,7 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s StorageHash: res.StorageHash, StorageProof: storageResults, } - return &result, err + return &result, nil } // CallContract executes a message call transaction, which is directly executed in the VM From 7dea55a70ea06128460dd73221d282c12b0a8f92 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Mon, 21 Jul 2025 15:40:15 +0800 Subject: [PATCH 2/6] cmd/workload: fix --- cmd/workload/prooftestgen.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/workload/prooftestgen.go b/cmd/workload/prooftestgen.go index becd7da965e..38a55c75194 100644 --- a/cmd/workload/prooftestgen.go +++ b/cmd/workload/prooftestgen.go @@ -198,7 +198,7 @@ func genStorageProof(cli *client, head uint64, number int) ([]uint64, [][]common if tx.To() == nil { continue } - blob, err := cli.Geth.TraceTransaction(context.Background(), tx.Hash(), &tracers.TraceConfig{ + ret, err := cli.Geth.TraceTransaction(context.Background(), tx.Hash(), &tracers.TraceConfig{ Tracer: &tracer, TracerConfig: configBlob, }) @@ -206,8 +206,13 @@ func genStorageProof(cli *client, head uint64, number int) ([]uint64, [][]common log.Error("Failed to trace the transaction", "blockNumber", blockNumber, "hash", tx.Hash(), "err", err) continue } + blob, err := json.Marshal(ret) + if err != nil { + log.Error("Failed to marshal data", "err", err) + continue + } var accounts map[common.Address]*native.PrestateAccount - if err := json.Unmarshal(blob.(json.RawMessage), &accounts); err != nil { + if err := json.Unmarshal(blob, &accounts); err != nil { log.Error("Failed to decode trace result", "blockNumber", blockNumber, "hash", tx.Hash(), "err", err) continue } From d612de26ee84cb57e4b556e89d14c4a741fa64a9 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 22 Jul 2025 09:01:08 +0800 Subject: [PATCH 3/6] cmd/workload: fix flags --- cmd/workload/README.md | 1 + cmd/workload/prooftestgen.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/workload/README.md b/cmd/workload/README.md index 1b84dd05db9..ee1d6acbc96 100644 --- a/cmd/workload/README.md +++ b/cmd/workload/README.md @@ -34,4 +34,5 @@ the following commands (in this directory) against a synced mainnet node: > go run . filtergen --queries queries/filter_queries_mainnet.json http://host:8545 > go run . historygen --history-tests queries/history_mainnet.json http://host:8545 > go run . tracegen --trace-tests queries/trace_mainnet.json --trace-start 4000000 --trace-end 4000100 http://host:8545 +> go run . proofgen --proof-tests queries/proof_mainnet.json --proof-states 3000 http://host:8545 ``` diff --git a/cmd/workload/prooftestgen.go b/cmd/workload/prooftestgen.go index 38a55c75194..da65d1feb85 100644 --- a/cmd/workload/prooftestgen.go +++ b/cmd/workload/prooftestgen.go @@ -274,7 +274,7 @@ func generateProofTests(clictx *cli.Context) error { ctx = context.Background() states = clictx.Int(proofTestStatesFlag.Name) outputFile = clictx.String(proofTestFileFlag.Name) - outputDir = clictx.String(traceTestResultOutputFlag.Name) + outputDir = clictx.String(proofTestResultOutputFlag.Name) ) head, err := client.Eth.BlockNumber(ctx) if err != nil { From 698cc5ed4cd904e46e81404352cd3083ddff61d5 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 22 Jul 2025 09:21:14 +0800 Subject: [PATCH 4/6] cmd/workload: fix result --- cmd/workload/prooftestgen.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/workload/prooftestgen.go b/cmd/workload/prooftestgen.go index da65d1feb85..5efb02a08e5 100644 --- a/cmd/workload/prooftestgen.go +++ b/cmd/workload/prooftestgen.go @@ -297,7 +297,8 @@ func generateProofTests(clictx *cli.Context) error { return err } hashes = append(hashes, crypto.Keccak256Hash(blob)) - writeStateProof(outputDir, blockNumber, test.Addresses[i][j], blob) + + writeStateProof(outputDir, blockNumber, test.Addresses[i][j], res) } test.Results = append(test.Results, hashes) } From f2a21cb72cf07a51a37a2cf301bf26dce2f8bb03 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 22 Jul 2025 09:31:06 +0800 Subject: [PATCH 5/6] cmd/workload: fix --- cmd/workload/prooftestgen.go | 5 +++-- cmd/workload/testsuite.go | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/workload/prooftestgen.go b/cmd/workload/prooftestgen.go index 5efb02a08e5..a22da4df859 100644 --- a/cmd/workload/prooftestgen.go +++ b/cmd/workload/prooftestgen.go @@ -252,8 +252,9 @@ func genProofRequests(cli *client, head uint64, states int) (*proofTest, error) accountAddresses [][]common.Address storageKeys [][][]string ) - for _, fn := range []proofGenerator{genAccountProof, genNonExistentAccountProof, genStorageProof} { - numbers, addresses, keys, err := fn(cli, head, states/3) + ratio := []float64{0.2, 0.1, 0.7} + for i, fn := range []proofGenerator{genAccountProof, genNonExistentAccountProof, genStorageProof} { + numbers, addresses, keys, err := fn(cli, head, int(float64(states)*ratio[i])) if err != nil { return nil, err } diff --git a/cmd/workload/testsuite.go b/cmd/workload/testsuite.go index 418b4c976bf..b997eddf401 100644 --- a/cmd/workload/testsuite.go +++ b/cmd/workload/testsuite.go @@ -50,6 +50,7 @@ var ( filterQueryFileFlag, historyTestFileFlag, traceTestFileFlag, + proofTestFileFlag, traceTestInvalidOutputFlag, proofTestInvalidOutputFlag, }, From 52253246172ccfb777e5ba098553b0c37d9c4c4f Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 22 Jul 2025 10:08:17 +0800 Subject: [PATCH 6/6] cmd/workload: fix flag resolve --- cmd/workload/testsuite.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmd/workload/testsuite.go b/cmd/workload/testsuite.go index b997eddf401..e9477ceb4eb 100644 --- a/cmd/workload/testsuite.go +++ b/cmd/workload/testsuite.go @@ -148,6 +148,12 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) { } else { cfg.traceTestFile = "queries/trace_mainnet.json" } + if ctx.IsSet(proofTestFileFlag.Name) { + cfg.proofTestFile = ctx.String(proofTestFileFlag.Name) + } else { + cfg.proofTestFile = "queries/proof_mainnet.json" + } + cfg.historyPruneBlock = new(uint64) *cfg.historyPruneBlock = history.PrunePoints[params.MainnetGenesisHash].BlockNumber case ctx.Bool(testSepoliaFlag.Name): @@ -167,6 +173,12 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) { } else { cfg.traceTestFile = "queries/trace_sepolia.json" } + if ctx.IsSet(proofTestFileFlag.Name) { + cfg.proofTestFile = ctx.String(proofTestFileFlag.Name) + } else { + cfg.proofTestFile = "queries/proof_sepolia.json" + } + cfg.historyPruneBlock = new(uint64) *cfg.historyPruneBlock = history.PrunePoints[params.SepoliaGenesisHash].BlockNumber default: @@ -174,6 +186,7 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) { cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name) cfg.historyTestFile = ctx.String(historyTestFileFlag.Name) cfg.traceTestFile = ctx.String(traceTestFileFlag.Name) + cfg.proofTestFile = ctx.String(proofTestFileFlag.Name) } return cfg }