Skip to content

Commit 7ebc6c4

Browse files
authored
cmd/evm: statet8n output folder + tx hashes on trace filenames (#21406)
* t8ntool: add output basedir * t8ntool: add txhash to trace filename * t8ntool: don't default to '.' basedir, allow absolute paths
1 parent 560d444 commit 7ebc6c4

File tree

6 files changed

+46
-26
lines changed

6 files changed

+46
-26
lines changed

cmd/evm/README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Command line params that has to be supported are
2929
--trace Output full trace logs to files <txhash>.jsonl
3030
--trace.nomemory Disable full memory dump in traces
3131
--trace.nostack Disable stack output in traces
32+
--trace.noreturndata Disable return data output in traces
33+
--output.basedir value Specifies where output files are placed. Will be created if it does not exist. (default: ".")
3234
--output.alloc alloc Determines where to put the alloc of the post-state.
3335
`stdout` - into the stdout output
3436
`stderr` - into the stderr output
@@ -232,13 +234,13 @@ Example where blockhashes are provided:
232234
./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace
233235
```
234236
```
235-
cat trace-0.jsonl | grep BLOCKHASH -C2
237+
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
236238
```
237239
```
238-
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"depth":1,"refund":0,"opName":"PUSH1","error":""}
239-
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
240-
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"depth":1,"refund":0,"opName":"STOP","error":""}
241-
{"output":"","gasUsed":"0x17","time":155861}
240+
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
241+
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
242+
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"STOP","error":""}
243+
{"output":"","gasUsed":"0x17","time":112885}
242244
```
243245

244246
In this example, the caller has not provided the required blockhash:
@@ -254,9 +256,9 @@ Error code: 4
254256
Another thing that can be done, is to chain invocations:
255257
```
256258
./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json
257-
INFO [06-29|11:52:04.934] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
258-
INFO [06-29|11:52:04.936] rejected tx index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
259-
INFO [06-29|11:52:04.936] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
259+
INFO [08-03|15:25:15.168] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
260+
INFO [08-03|15:25:15.169] rejected tx index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
261+
INFO [08-03|15:25:15.169] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
260262
261263
```
262264
What happened here, is that we first applied two identical transactions, so the second one was rejected.

cmd/evm/internal/t8ntool/execution.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ type stEnvMarshaling struct {
8181
// Apply applies a set of transactions to a pre-state
8282
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
8383
txs types.Transactions, miningReward int64,
84-
getTracerFn func(txIndex int) (tracer vm.Tracer, err error)) (*state.StateDB, *ExecutionResult, error) {
84+
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.Tracer, err error)) (*state.StateDB, *ExecutionResult, error) {
8585

8686
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
8787
// required blockhashes
@@ -135,7 +135,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
135135
rejectedTxs = append(rejectedTxs, i)
136136
continue
137137
}
138-
tracer, err := getTracerFn(txIndex)
138+
tracer, err := getTracerFn(txIndex, tx.Hash())
139139
if err != nil {
140140
return nil, nil, err
141141
}

cmd/evm/internal/t8ntool/flags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ var (
4242
Name: "trace.noreturndata",
4343
Usage: "Disable return data output in traces",
4444
}
45+
OutputBasedir = cli.StringFlag{
46+
Name: "output.basedir",
47+
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
48+
Value: "",
49+
}
4550
OutputAllocFlag = cli.StringFlag{
4651
Name: "output.alloc",
4752
Usage: "Determines where to put the `alloc` of the post-state.\n" +

cmd/evm/internal/t8ntool/transition.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"io/ioutil"
2323
"math/big"
2424
"os"
25+
"path"
2526

2627
"github.com/ethereum/go-ethereum/common"
2728
"github.com/ethereum/go-ethereum/core"
@@ -75,11 +76,22 @@ func Main(ctx *cli.Context) error {
7576
log.Root().SetHandler(glogger)
7677

7778
var (
78-
err error
79-
tracer vm.Tracer
79+
err error
80+
tracer vm.Tracer
81+
baseDir = ""
8082
)
81-
var getTracer func(txIndex int) (vm.Tracer, error)
83+
var getTracer func(txIndex int, txHash common.Hash) (vm.Tracer, error)
8284

85+
// If user specified a basedir, make sure it exists
86+
if ctx.IsSet(OutputBasedir.Name) {
87+
if base := ctx.String(OutputBasedir.Name); len(base) > 0 {
88+
err := os.MkdirAll(base, 0755) // //rw-r--r--
89+
if err != nil {
90+
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
91+
}
92+
baseDir = base
93+
}
94+
}
8395
if ctx.Bool(TraceFlag.Name) {
8496
// Configure the EVM logger
8597
logConfig := &vm.LogConfig{
@@ -95,19 +107,19 @@ func Main(ctx *cli.Context) error {
95107
prevFile.Close()
96108
}
97109
}()
98-
getTracer = func(txIndex int) (vm.Tracer, error) {
110+
getTracer = func(txIndex int, txHash common.Hash) (vm.Tracer, error) {
99111
if prevFile != nil {
100112
prevFile.Close()
101113
}
102-
traceFile, err := os.Create(fmt.Sprintf("trace-%d.jsonl", txIndex))
114+
traceFile, err := os.Create(path.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
103115
if err != nil {
104116
return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
105117
}
106118
prevFile = traceFile
107119
return vm.NewJSONLogger(logConfig, traceFile), nil
108120
}
109121
} else {
110-
getTracer = func(txIndex int) (tracer vm.Tracer, err error) {
122+
getTracer = func(txIndex int, txHash common.Hash) (tracer vm.Tracer, err error) {
111123
return nil, nil
112124
}
113125
}
@@ -197,7 +209,7 @@ func Main(ctx *cli.Context) error {
197209
//postAlloc := state.DumpGenesisFormat(false, false, false)
198210
collector := make(Alloc)
199211
state.DumpToCollector(collector, false, false, false, nil, -1)
200-
return dispatchOutput(ctx, result, collector)
212+
return dispatchOutput(ctx, baseDir, result, collector)
201213

202214
}
203215

@@ -224,39 +236,39 @@ func (g Alloc) OnAccount(addr common.Address, dumpAccount state.DumpAccount) {
224236
}
225237

226238
// saveFile marshalls the object to the given file
227-
func saveFile(filename string, data interface{}) error {
239+
func saveFile(baseDir, filename string, data interface{}) error {
228240
b, err := json.MarshalIndent(data, "", " ")
229241
if err != nil {
230242
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
231243
}
232-
if err = ioutil.WriteFile(filename, b, 0644); err != nil {
244+
if err = ioutil.WriteFile(path.Join(baseDir, filename), b, 0644); err != nil {
233245
return NewError(ErrorIO, fmt.Errorf("failed writing output: %v", err))
234246
}
235247
return nil
236248
}
237249

238250
// dispatchOutput writes the output data to either stderr or stdout, or to the specified
239251
// files
240-
func dispatchOutput(ctx *cli.Context, result *ExecutionResult, alloc Alloc) error {
252+
func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc) error {
241253
stdOutObject := make(map[string]interface{})
242254
stdErrObject := make(map[string]interface{})
243-
dispatch := func(fName, name string, obj interface{}) error {
255+
dispatch := func(baseDir, fName, name string, obj interface{}) error {
244256
switch fName {
245257
case "stdout":
246258
stdOutObject[name] = obj
247259
case "stderr":
248260
stdErrObject[name] = obj
249261
default: // save to file
250-
if err := saveFile(fName, obj); err != nil {
262+
if err := saveFile(baseDir, fName, obj); err != nil {
251263
return err
252264
}
253265
}
254266
return nil
255267
}
256-
if err := dispatch(ctx.String(OutputAllocFlag.Name), "alloc", alloc); err != nil {
268+
if err := dispatch(baseDir, ctx.String(OutputAllocFlag.Name), "alloc", alloc); err != nil {
257269
return err
258270
}
259-
if err := dispatch(ctx.String(OutputResultFlag.Name), "result", result); err != nil {
271+
if err := dispatch(baseDir, ctx.String(OutputResultFlag.Name), "result", result); err != nil {
260272
return err
261273
}
262274
if len(stdOutObject) > 0 {

cmd/evm/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ var stateTransitionCommand = cli.Command{
146146
t8ntool.TraceDisableMemoryFlag,
147147
t8ntool.TraceDisableStackFlag,
148148
t8ntool.TraceDisableReturnDataFlag,
149+
t8ntool.OutputBasedir,
149150
t8ntool.OutputAllocFlag,
150151
t8ntool.OutputResultFlag,
151152
t8ntool.InputAllocFlag,

cmd/evm/transition-test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ echo "Example where blockhashes are provided: "
155155
cmd="./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace"
156156
tick && echo $cmd && tick
157157
$cmd 2>&1 >/dev/null
158-
cmd="cat trace-0.jsonl | grep BLOCKHASH -C2"
158+
cmd="cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2"
159159
tick && echo $cmd && tick
160160
echo "$ticks"
161-
cat trace-0.jsonl | grep BLOCKHASH -C2
161+
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
162162
echo "$ticks"
163163
echo ""
164164

0 commit comments

Comments
 (0)