Skip to content

Commit 51c1bb7

Browse files
authored
cmd/workload: introduce transaction-trace test (#31288)
This pull request introduces a new test suite in workload framework, for transaction tracing. **test generation** `go run . tracegen --trace-tests trace-test.json http://host:8545` and you can choose to store the trace result in a specific folder `go run . tracegen --trace-tests trace-test.json --trace-output ./trace-result http://host:8545` **test run** `./workload test -run Trace/Transaction --trace-invalid ./trace-invalid http://host:8545` The mismatched trace result will be saved in the specific folder for further investigation.
1 parent 7ec493f commit 51c1bb7

File tree

15 files changed

+594
-169
lines changed

15 files changed

+594
-169
lines changed

cmd/workload/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ the following commands (in this directory) against a synced mainnet node:
2626
```shell
2727
> go run . filtergen --queries queries/filter_queries_mainnet.json http://host:8545
2828
> go run . historygen --history-tests queries/history_mainnet.json http://host:8545
29+
> go run . tracegen --trace-tests queries/trace_mainnet.json http://host:8545
2930
```

cmd/workload/client.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2025 The go-ethereum Authors
2+
// This file is part of go-ethereum.
3+
//
4+
// go-ethereum is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// go-ethereum is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
"github.com/ethereum/go-ethereum/common"
24+
"github.com/ethereum/go-ethereum/common/hexutil"
25+
"github.com/ethereum/go-ethereum/core/types"
26+
"github.com/ethereum/go-ethereum/ethclient"
27+
"github.com/ethereum/go-ethereum/ethclient/gethclient"
28+
"github.com/ethereum/go-ethereum/rpc"
29+
"github.com/urfave/cli/v2"
30+
)
31+
32+
type client struct {
33+
Eth *ethclient.Client
34+
Geth *gethclient.Client
35+
RPC *rpc.Client
36+
}
37+
38+
func makeClient(ctx *cli.Context) *client {
39+
if ctx.NArg() < 1 {
40+
exit("missing RPC endpoint URL as command-line argument")
41+
}
42+
url := ctx.Args().First()
43+
cl, err := rpc.Dial(url)
44+
if err != nil {
45+
exit(fmt.Errorf("could not create RPC client at %s: %v", url, err))
46+
}
47+
return &client{
48+
RPC: cl,
49+
Eth: ethclient.NewClient(cl),
50+
Geth: gethclient.New(cl),
51+
}
52+
}
53+
54+
type simpleBlock struct {
55+
Number hexutil.Uint64 `json:"number"`
56+
Hash common.Hash `json:"hash"`
57+
}
58+
59+
type simpleTransaction struct {
60+
Hash common.Hash `json:"hash"`
61+
TransactionIndex hexutil.Uint64 `json:"transactionIndex"`
62+
}
63+
64+
func (c *client) getBlockByHash(ctx context.Context, arg common.Hash, fullTx bool) (*simpleBlock, error) {
65+
var r *simpleBlock
66+
err := c.RPC.CallContext(ctx, &r, "eth_getBlockByHash", arg, fullTx)
67+
return r, err
68+
}
69+
70+
func (c *client) getBlockByNumber(ctx context.Context, arg uint64, fullTx bool) (*simpleBlock, error) {
71+
var r *simpleBlock
72+
err := c.RPC.CallContext(ctx, &r, "eth_getBlockByNumber", hexutil.Uint64(arg), fullTx)
73+
return r, err
74+
}
75+
76+
func (c *client) getTransactionByBlockHashAndIndex(ctx context.Context, block common.Hash, index uint64) (*simpleTransaction, error) {
77+
var r *simpleTransaction
78+
err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index))
79+
return r, err
80+
}
81+
82+
func (c *client) getTransactionByBlockNumberAndIndex(ctx context.Context, block uint64, index uint64) (*simpleTransaction, error) {
83+
var r *simpleTransaction
84+
err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockNumberAndIndex", hexutil.Uint64(block), hexutil.Uint64(index))
85+
return r, err
86+
}
87+
88+
func (c *client) getBlockTransactionCountByHash(ctx context.Context, block common.Hash) (uint64, error) {
89+
var r hexutil.Uint64
90+
err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByHash", block)
91+
return uint64(r), err
92+
}
93+
94+
func (c *client) getBlockTransactionCountByNumber(ctx context.Context, block uint64) (uint64, error) {
95+
var r hexutil.Uint64
96+
err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByNumber", hexutil.Uint64(block))
97+
return uint64(r), err
98+
}
99+
100+
func (c *client) getBlockReceipts(ctx context.Context, arg any) ([]*types.Receipt, error) {
101+
var result []*types.Receipt
102+
err := c.RPC.CallContext(ctx, &result, "eth_getBlockReceipts", arg)
103+
return result, err
104+
}

cmd/workload/filtertest.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ func newFilterTestSuite(cfg testConfig) *filterTestSuite {
4545
return s
4646
}
4747

48-
func (s *filterTestSuite) allTests() []utesting.Test {
49-
return []utesting.Test{
50-
{Name: "Filter/ShortRange", Fn: s.filterShortRange},
51-
{Name: "Filter/LongRange", Fn: s.filterLongRange, Slow: true},
52-
{Name: "Filter/FullRange", Fn: s.filterFullRange, Slow: true},
48+
func (s *filterTestSuite) allTests() []workloadTest {
49+
return []workloadTest{
50+
newWorkLoadTest("Filter/ShortRange", s.filterShortRange),
51+
newSlowWorkloadTest("Filter/LongRange", s.filterLongRange),
52+
newSlowWorkloadTest("Filter/FullRange", s.filterFullRange),
5353
}
5454
}
5555

cmd/workload/historytest.go

Lines changed: 10 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323

2424
"github.com/ethereum/go-ethereum/common"
2525
"github.com/ethereum/go-ethereum/common/hexutil"
26-
"github.com/ethereum/go-ethereum/core/types"
2726
"github.com/ethereum/go-ethereum/internal/utesting"
2827
)
2928

@@ -65,40 +64,16 @@ func (s *historyTestSuite) loadTests() error {
6564
return nil
6665
}
6766

68-
func (s *historyTestSuite) allTests() []utesting.Test {
69-
return []utesting.Test{
70-
{
71-
Name: "History/getBlockByHash",
72-
Fn: s.testGetBlockByHash,
73-
},
74-
{
75-
Name: "History/getBlockByNumber",
76-
Fn: s.testGetBlockByNumber,
77-
},
78-
{
79-
Name: "History/getBlockReceiptsByHash",
80-
Fn: s.testGetBlockReceiptsByHash,
81-
},
82-
{
83-
Name: "History/getBlockReceiptsByNumber",
84-
Fn: s.testGetBlockReceiptsByNumber,
85-
},
86-
{
87-
Name: "History/getBlockTransactionCountByHash",
88-
Fn: s.testGetBlockTransactionCountByHash,
89-
},
90-
{
91-
Name: "History/getBlockTransactionCountByNumber",
92-
Fn: s.testGetBlockTransactionCountByNumber,
93-
},
94-
{
95-
Name: "History/getTransactionByBlockHashAndIndex",
96-
Fn: s.testGetTransactionByBlockHashAndIndex,
97-
},
98-
{
99-
Name: "History/getTransactionByBlockNumberAndIndex",
100-
Fn: s.testGetTransactionByBlockNumberAndIndex,
101-
},
67+
func (s *historyTestSuite) allTests() []workloadTest {
68+
return []workloadTest{
69+
newWorkLoadTest("History/getBlockByHash", s.testGetBlockByHash),
70+
newWorkLoadTest("History/getBlockByNumber", s.testGetBlockByNumber),
71+
newWorkLoadTest("History/getBlockReceiptsByHash", s.testGetBlockReceiptsByHash),
72+
newWorkLoadTest("History/getBlockReceiptsByNumber", s.testGetBlockReceiptsByNumber),
73+
newWorkLoadTest("History/getBlockTransactionCountByHash", s.testGetBlockTransactionCountByHash),
74+
newWorkLoadTest("History/getBlockTransactionCountByNumber", s.testGetBlockTransactionCountByNumber),
75+
newWorkLoadTest("History/getTransactionByBlockHashAndIndex", s.testGetTransactionByBlockHashAndIndex),
76+
newWorkLoadTest("History/getTransactionByBlockNumberAndIndex", s.testGetTransactionByBlockNumberAndIndex),
10277
}
10378
}
10479

@@ -279,55 +254,3 @@ func (s *historyTestSuite) testGetTransactionByBlockNumberAndIndex(t *utesting.T
279254
}
280255
}
281256
}
282-
283-
type simpleBlock struct {
284-
Number hexutil.Uint64 `json:"number"`
285-
Hash common.Hash `json:"hash"`
286-
}
287-
288-
type simpleTransaction struct {
289-
Hash common.Hash `json:"hash"`
290-
TransactionIndex hexutil.Uint64 `json:"transactionIndex"`
291-
}
292-
293-
func (c *client) getBlockByHash(ctx context.Context, arg common.Hash, fullTx bool) (*simpleBlock, error) {
294-
var r *simpleBlock
295-
err := c.RPC.CallContext(ctx, &r, "eth_getBlockByHash", arg, fullTx)
296-
return r, err
297-
}
298-
299-
func (c *client) getBlockByNumber(ctx context.Context, arg uint64, fullTx bool) (*simpleBlock, error) {
300-
var r *simpleBlock
301-
err := c.RPC.CallContext(ctx, &r, "eth_getBlockByNumber", hexutil.Uint64(arg), fullTx)
302-
return r, err
303-
}
304-
305-
func (c *client) getTransactionByBlockHashAndIndex(ctx context.Context, block common.Hash, index uint64) (*simpleTransaction, error) {
306-
var r *simpleTransaction
307-
err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index))
308-
return r, err
309-
}
310-
311-
func (c *client) getTransactionByBlockNumberAndIndex(ctx context.Context, block uint64, index uint64) (*simpleTransaction, error) {
312-
var r *simpleTransaction
313-
err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockNumberAndIndex", hexutil.Uint64(block), hexutil.Uint64(index))
314-
return r, err
315-
}
316-
317-
func (c *client) getBlockTransactionCountByHash(ctx context.Context, block common.Hash) (uint64, error) {
318-
var r hexutil.Uint64
319-
err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByHash", block)
320-
return uint64(r), err
321-
}
322-
323-
func (c *client) getBlockTransactionCountByNumber(ctx context.Context, block uint64) (uint64, error) {
324-
var r hexutil.Uint64
325-
err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByNumber", hexutil.Uint64(block))
326-
return uint64(r), err
327-
}
328-
329-
func (c *client) getBlockReceipts(ctx context.Context, arg any) ([]*types.Receipt, error) {
330-
var result []*types.Receipt
331-
err := c.RPC.CallContext(ctx, &result, "eth_getBlockReceipts", arg)
332-
return result, err
333-
}

cmd/workload/historytestgen.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ var (
5151
}
5252
historyTestEarliestFlag = &cli.IntFlag{
5353
Name: "earliest",
54-
Usage: "JSON file containing filter test queries",
54+
Usage: "The earliest block to test queries",
5555
Value: 0,
5656
Category: flags.TestingCategory,
5757
}
@@ -139,7 +139,7 @@ func calcReceiptsHash(rcpt []*types.Receipt) common.Hash {
139139
func writeJSON(fileName string, value any) {
140140
file, err := os.Create(fileName)
141141
if err != nil {
142-
exit(fmt.Errorf("Error creating %s: %v", fileName, err))
142+
exit(fmt.Errorf("error creating %s: %v", fileName, err))
143143
return
144144
}
145145
defer file.Close()

cmd/workload/main.go

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ import (
2020
"fmt"
2121
"os"
2222

23-
"github.com/ethereum/go-ethereum/ethclient"
2423
"github.com/ethereum/go-ethereum/internal/debug"
2524
"github.com/ethereum/go-ethereum/internal/flags"
26-
"github.com/ethereum/go-ethereum/rpc"
2725
"github.com/urfave/cli/v2"
2826
)
2927

@@ -49,6 +47,7 @@ func init() {
4947
runTestCommand,
5048
historyGenerateCommand,
5149
filterGenerateCommand,
50+
traceGenerateCommand,
5251
filterPerfCommand,
5352
}
5453
}
@@ -57,26 +56,6 @@ func main() {
5756
exit(app.Run(os.Args))
5857
}
5958

60-
type client struct {
61-
Eth *ethclient.Client
62-
RPC *rpc.Client
63-
}
64-
65-
func makeClient(ctx *cli.Context) *client {
66-
if ctx.NArg() < 1 {
67-
exit("missing RPC endpoint URL as command-line argument")
68-
}
69-
url := ctx.Args().First()
70-
cl, err := rpc.Dial(url)
71-
if err != nil {
72-
exit(fmt.Errorf("Could not create RPC client at %s: %v", url, err))
73-
}
74-
return &client{
75-
RPC: cl,
76-
Eth: ethclient.NewClient(cl),
77-
}
78-
}
79-
8059
func exit(err any) {
8160
if err == nil {
8261
os.Exit(0)

cmd/workload/queries/trace_mainnet.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

cmd/workload/queries/trace_sepolia.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)