mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
cmd/workload, eth/tracers/native: introduce state proof tests (#32247)
This pull request introduces a new workload command, providing the features for `eth_getProof` endpoint test generation and execution.
This commit is contained in:
parent
15f52a2937
commit
6978ab48aa
7 changed files with 488 additions and 5 deletions
|
|
@ -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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ func init() {
|
|||
historyGenerateCommand,
|
||||
filterGenerateCommand,
|
||||
traceGenerateCommand,
|
||||
proofGenerateCommand,
|
||||
filterPerfCommand,
|
||||
filterFuzzCommand,
|
||||
}
|
||||
|
|
|
|||
105
cmd/workload/prooftest.go
Normal file
105
cmd/workload/prooftest.go
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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], " "))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
355
cmd/workload/prooftestgen.go
Normal file
355
cmd/workload/prooftestgen.go
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
// 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 <http://www.gnu.org/licenses/>
|
||||
|
||||
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: "<RPC endpoint URL>",
|
||||
Action: generateProofTests,
|
||||
Flags: []cli.Flag{
|
||||
proofTestFileFlag,
|
||||
proofTestResultOutputFlag,
|
||||
proofTestStatesFlag,
|
||||
proofTestStartBlockFlag,
|
||||
proofTestEndBlockFlag,
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
proofTestStartBlockFlag = &cli.Uint64Flag{
|
||||
Name: "proof-start",
|
||||
Usage: "The number of starting block for proof verification (included)",
|
||||
Category: flags.TestingCategory,
|
||||
}
|
||||
proofTestEndBlockFlag = &cli.Uint64Flag{
|
||||
Name: "proof-end",
|
||||
Usage: "The number of ending block for proof verification (excluded)",
|
||||
Category: flags.TestingCategory,
|
||||
}
|
||||
)
|
||||
|
||||
type proofGenerator func(cli *client, startBlock uint64, endBlock uint64, number int) ([]uint64, [][]common.Address, [][][]string, error)
|
||||
|
||||
func genAccountProof(cli *client, startBlock uint64, endBlock 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 := uint64(rand.Intn(int(endBlock-startBlock))) + startBlock
|
||||
|
||||
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, 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, startBlock uint64, endBlock 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(endBlock-startBlock))) + startBlock
|
||||
)
|
||||
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, startBlock uint64, endBlock 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 := uint64(rand.Intn(int(endBlock-startBlock))) + startBlock
|
||||
|
||||
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
|
||||
}
|
||||
ret, 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
|
||||
}
|
||||
blob, err := json.Marshal(ret)
|
||||
if err != nil {
|
||||
log.Error("Failed to marshal data", "err", err)
|
||||
continue
|
||||
}
|
||||
var accounts map[common.Address]*types.Account
|
||||
if err := json.Unmarshal(blob, &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, blockNumber)
|
||||
accountAddresses = append(accountAddresses, addresses)
|
||||
storageKeys = append(storageKeys, slots)
|
||||
}
|
||||
log.Info("Generated tests for storage proof", "blocks", len(blockNumbers), "accounts", nAccounts, "storages", nStorages, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
return blockNumbers, accountAddresses, storageKeys, nil
|
||||
}
|
||||
|
||||
func genProofRequests(cli *client, startBlock, endBlock uint64, states int) (*proofTest, error) {
|
||||
var (
|
||||
blockNumbers []uint64
|
||||
accountAddresses [][]common.Address
|
||||
storageKeys [][][]string
|
||||
)
|
||||
ratio := []float64{0.2, 0.1, 0.7}
|
||||
for i, fn := range []proofGenerator{genAccountProof, genNonExistentAccountProof, genStorageProof} {
|
||||
numbers, addresses, keys, err := fn(cli, startBlock, endBlock, int(float64(states)*ratio[i]))
|
||||
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(proofTestResultOutputFlag.Name)
|
||||
startBlock = clictx.Uint64(proofTestStartBlockFlag.Name)
|
||||
endBlock = clictx.Uint64(proofTestEndBlockFlag.Name)
|
||||
)
|
||||
head, err := client.Eth.BlockNumber(ctx)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
if startBlock > head || endBlock > head {
|
||||
return fmt.Errorf("chain is out of proof range, head %d, start: %d, limit: %d", head, startBlock, endBlock)
|
||||
}
|
||||
if endBlock == 0 {
|
||||
endBlock = head
|
||||
}
|
||||
log.Info("Generating proof states", "startBlock", startBlock, "endBlock", endBlock, "states", states)
|
||||
|
||||
test, err := genProofRequests(client, startBlock, endBlock, 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], res)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,9 @@ var (
|
|||
filterQueryFileFlag,
|
||||
historyTestFileFlag,
|
||||
traceTestFileFlag,
|
||||
proofTestFileFlag,
|
||||
traceTestInvalidOutputFlag,
|
||||
proofTestInvalidOutputFlag,
|
||||
},
|
||||
}
|
||||
testPatternFlag = &cli.StringFlag{
|
||||
|
|
@ -95,6 +97,7 @@ type testConfig struct {
|
|||
historyTestFile string
|
||||
historyPruneBlock *uint64
|
||||
traceTestFile string
|
||||
proofTestFile string
|
||||
}
|
||||
|
||||
var errPrunedHistory = errors.New("attempt to access pruned history")
|
||||
|
|
@ -145,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):
|
||||
|
|
@ -164,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:
|
||||
|
|
@ -171,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
|
||||
}
|
||||
|
|
@ -222,11 +238,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) {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,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
|
||||
|
|
@ -74,7 +74,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
|
||||
|
|
@ -82,7 +82,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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ 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))
|
||||
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 {
|
||||
|
|
@ -122,7 +125,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
|
||||
|
|
|
|||
Loading…
Reference in a new issue