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
This commit is contained in:
parent
560d44479c
commit
7ebc6c43ff
@ -29,6 +29,8 @@ Command line params that has to be supported are
|
|||||||
--trace Output full trace logs to files <txhash>.jsonl
|
--trace Output full trace logs to files <txhash>.jsonl
|
||||||
--trace.nomemory Disable full memory dump in traces
|
--trace.nomemory Disable full memory dump in traces
|
||||||
--trace.nostack Disable stack output in traces
|
--trace.nostack Disable stack output in traces
|
||||||
|
--trace.noreturndata Disable return data output in traces
|
||||||
|
--output.basedir value Specifies where output files are placed. Will be created if it does not exist. (default: ".")
|
||||||
--output.alloc alloc Determines where to put the alloc of the post-state.
|
--output.alloc alloc Determines where to put the alloc of the post-state.
|
||||||
`stdout` - into the stdout output
|
`stdout` - into the stdout output
|
||||||
`stderr` - into the stderr output
|
`stderr` - into the stderr output
|
||||||
@ -232,13 +234,13 @@ Example where blockhashes are provided:
|
|||||||
./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace
|
./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
cat trace-0.jsonl | grep BLOCKHASH -C2
|
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"depth":1,"refund":0,"opName":"PUSH1","error":""}
|
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
|
||||||
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
|
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
|
||||||
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"depth":1,"refund":0,"opName":"STOP","error":""}
|
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"STOP","error":""}
|
||||||
{"output":"","gasUsed":"0x17","time":155861}
|
{"output":"","gasUsed":"0x17","time":112885}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the caller has not provided the required blockhash:
|
In this example, the caller has not provided the required blockhash:
|
||||||
@ -254,9 +256,9 @@ Error code: 4
|
|||||||
Another thing that can be done, is to chain invocations:
|
Another thing that can be done, is to chain invocations:
|
||||||
```
|
```
|
||||||
./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
|
./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
|
||||||
INFO [06-29|11:52:04.934] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
|
INFO [08-03|15:25:15.168] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
|
||||||
INFO [06-29|11:52:04.936] rejected tx index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
|
INFO [08-03|15:25:15.169] rejected tx index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
|
||||||
INFO [06-29|11:52:04.936] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
|
INFO [08-03|15:25:15.169] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
|
||||||
|
|
||||||
```
|
```
|
||||||
What happened here, is that we first applied two identical transactions, so the second one was rejected.
|
What happened here, is that we first applied two identical transactions, so the second one was rejected.
|
||||||
|
@ -81,7 +81,7 @@ type stEnvMarshaling struct {
|
|||||||
// Apply applies a set of transactions to a pre-state
|
// Apply applies a set of transactions to a pre-state
|
||||||
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
txs types.Transactions, miningReward int64,
|
txs types.Transactions, miningReward int64,
|
||||||
getTracerFn func(txIndex int) (tracer vm.Tracer, err error)) (*state.StateDB, *ExecutionResult, error) {
|
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.Tracer, err error)) (*state.StateDB, *ExecutionResult, error) {
|
||||||
|
|
||||||
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
|
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
|
||||||
// required blockhashes
|
// required blockhashes
|
||||||
@ -135,7 +135,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
rejectedTxs = append(rejectedTxs, i)
|
rejectedTxs = append(rejectedTxs, i)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tracer, err := getTracerFn(txIndex)
|
tracer, err := getTracerFn(txIndex, tx.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,11 @@ var (
|
|||||||
Name: "trace.noreturndata",
|
Name: "trace.noreturndata",
|
||||||
Usage: "Disable return data output in traces",
|
Usage: "Disable return data output in traces",
|
||||||
}
|
}
|
||||||
|
OutputBasedir = cli.StringFlag{
|
||||||
|
Name: "output.basedir",
|
||||||
|
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
|
||||||
|
Value: "",
|
||||||
|
}
|
||||||
OutputAllocFlag = cli.StringFlag{
|
OutputAllocFlag = cli.StringFlag{
|
||||||
Name: "output.alloc",
|
Name: "output.alloc",
|
||||||
Usage: "Determines where to put the `alloc` of the post-state.\n" +
|
Usage: "Determines where to put the `alloc` of the post-state.\n" +
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
@ -77,9 +78,20 @@ func Main(ctx *cli.Context) error {
|
|||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
tracer vm.Tracer
|
tracer vm.Tracer
|
||||||
|
baseDir = ""
|
||||||
)
|
)
|
||||||
var getTracer func(txIndex int) (vm.Tracer, error)
|
var getTracer func(txIndex int, txHash common.Hash) (vm.Tracer, error)
|
||||||
|
|
||||||
|
// If user specified a basedir, make sure it exists
|
||||||
|
if ctx.IsSet(OutputBasedir.Name) {
|
||||||
|
if base := ctx.String(OutputBasedir.Name); len(base) > 0 {
|
||||||
|
err := os.MkdirAll(base, 0755) // //rw-r--r--
|
||||||
|
if err != nil {
|
||||||
|
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
||||||
|
}
|
||||||
|
baseDir = base
|
||||||
|
}
|
||||||
|
}
|
||||||
if ctx.Bool(TraceFlag.Name) {
|
if ctx.Bool(TraceFlag.Name) {
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
logConfig := &vm.LogConfig{
|
logConfig := &vm.LogConfig{
|
||||||
@ -95,11 +107,11 @@ func Main(ctx *cli.Context) error {
|
|||||||
prevFile.Close()
|
prevFile.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
getTracer = func(txIndex int) (vm.Tracer, error) {
|
getTracer = func(txIndex int, txHash common.Hash) (vm.Tracer, error) {
|
||||||
if prevFile != nil {
|
if prevFile != nil {
|
||||||
prevFile.Close()
|
prevFile.Close()
|
||||||
}
|
}
|
||||||
traceFile, err := os.Create(fmt.Sprintf("trace-%d.jsonl", txIndex))
|
traceFile, err := os.Create(path.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
}
|
}
|
||||||
@ -107,7 +119,7 @@ func Main(ctx *cli.Context) error {
|
|||||||
return vm.NewJSONLogger(logConfig, traceFile), nil
|
return vm.NewJSONLogger(logConfig, traceFile), nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getTracer = func(txIndex int) (tracer vm.Tracer, err error) {
|
getTracer = func(txIndex int, txHash common.Hash) (tracer vm.Tracer, err error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +209,7 @@ func Main(ctx *cli.Context) error {
|
|||||||
//postAlloc := state.DumpGenesisFormat(false, false, false)
|
//postAlloc := state.DumpGenesisFormat(false, false, false)
|
||||||
collector := make(Alloc)
|
collector := make(Alloc)
|
||||||
state.DumpToCollector(collector, false, false, false, nil, -1)
|
state.DumpToCollector(collector, false, false, false, nil, -1)
|
||||||
return dispatchOutput(ctx, result, collector)
|
return dispatchOutput(ctx, baseDir, result, collector)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,12 +236,12 @@ func (g Alloc) OnAccount(addr common.Address, dumpAccount state.DumpAccount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// saveFile marshalls the object to the given file
|
// saveFile marshalls the object to the given file
|
||||||
func saveFile(filename string, data interface{}) error {
|
func saveFile(baseDir, filename string, data interface{}) error {
|
||||||
b, err := json.MarshalIndent(data, "", " ")
|
b, err := json.MarshalIndent(data, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
||||||
}
|
}
|
||||||
if err = ioutil.WriteFile(filename, b, 0644); err != nil {
|
if err = ioutil.WriteFile(path.Join(baseDir, filename), b, 0644); err != nil {
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed writing output: %v", err))
|
return NewError(ErrorIO, fmt.Errorf("failed writing output: %v", err))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -237,26 +249,26 @@ func saveFile(filename string, data interface{}) error {
|
|||||||
|
|
||||||
// dispatchOutput writes the output data to either stderr or stdout, or to the specified
|
// dispatchOutput writes the output data to either stderr or stdout, or to the specified
|
||||||
// files
|
// files
|
||||||
func dispatchOutput(ctx *cli.Context, result *ExecutionResult, alloc Alloc) error {
|
func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc) error {
|
||||||
stdOutObject := make(map[string]interface{})
|
stdOutObject := make(map[string]interface{})
|
||||||
stdErrObject := make(map[string]interface{})
|
stdErrObject := make(map[string]interface{})
|
||||||
dispatch := func(fName, name string, obj interface{}) error {
|
dispatch := func(baseDir, fName, name string, obj interface{}) error {
|
||||||
switch fName {
|
switch fName {
|
||||||
case "stdout":
|
case "stdout":
|
||||||
stdOutObject[name] = obj
|
stdOutObject[name] = obj
|
||||||
case "stderr":
|
case "stderr":
|
||||||
stdErrObject[name] = obj
|
stdErrObject[name] = obj
|
||||||
default: // save to file
|
default: // save to file
|
||||||
if err := saveFile(fName, obj); err != nil {
|
if err := saveFile(baseDir, fName, obj); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := dispatch(ctx.String(OutputAllocFlag.Name), "alloc", alloc); err != nil {
|
if err := dispatch(baseDir, ctx.String(OutputAllocFlag.Name), "alloc", alloc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := dispatch(ctx.String(OutputResultFlag.Name), "result", result); err != nil {
|
if err := dispatch(baseDir, ctx.String(OutputResultFlag.Name), "result", result); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(stdOutObject) > 0 {
|
if len(stdOutObject) > 0 {
|
||||||
|
@ -146,6 +146,7 @@ var stateTransitionCommand = cli.Command{
|
|||||||
t8ntool.TraceDisableMemoryFlag,
|
t8ntool.TraceDisableMemoryFlag,
|
||||||
t8ntool.TraceDisableStackFlag,
|
t8ntool.TraceDisableStackFlag,
|
||||||
t8ntool.TraceDisableReturnDataFlag,
|
t8ntool.TraceDisableReturnDataFlag,
|
||||||
|
t8ntool.OutputBasedir,
|
||||||
t8ntool.OutputAllocFlag,
|
t8ntool.OutputAllocFlag,
|
||||||
t8ntool.OutputResultFlag,
|
t8ntool.OutputResultFlag,
|
||||||
t8ntool.InputAllocFlag,
|
t8ntool.InputAllocFlag,
|
||||||
|
@ -155,10 +155,10 @@ echo "Example where blockhashes are provided: "
|
|||||||
cmd="./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace"
|
cmd="./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace"
|
||||||
tick && echo $cmd && tick
|
tick && echo $cmd && tick
|
||||||
$cmd 2>&1 >/dev/null
|
$cmd 2>&1 >/dev/null
|
||||||
cmd="cat trace-0.jsonl | grep BLOCKHASH -C2"
|
cmd="cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2"
|
||||||
tick && echo $cmd && tick
|
tick && echo $cmd && tick
|
||||||
echo "$ticks"
|
echo "$ticks"
|
||||||
cat trace-0.jsonl | grep BLOCKHASH -C2
|
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
|
||||||
echo "$ticks"
|
echo "$ticks"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user