|
|
|
@ -22,6 +22,7 @@ import ( |
|
|
|
|
"io/ioutil" |
|
|
|
|
"math/big" |
|
|
|
|
"os" |
|
|
|
|
"path" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/core" |
|
|
|
@ -75,11 +76,22 @@ func Main(ctx *cli.Context) error { |
|
|
|
|
log.Root().SetHandler(glogger) |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
err error |
|
|
|
|
tracer vm.Tracer |
|
|
|
|
err error |
|
|
|
|
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) { |
|
|
|
|
// Configure the EVM logger
|
|
|
|
|
logConfig := &vm.LogConfig{ |
|
|
|
@ -95,11 +107,11 @@ func Main(ctx *cli.Context) error { |
|
|
|
|
prevFile.Close() |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
getTracer = func(txIndex int) (vm.Tracer, error) { |
|
|
|
|
getTracer = func(txIndex int, txHash common.Hash) (vm.Tracer, error) { |
|
|
|
|
if prevFile != nil { |
|
|
|
|
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 { |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
} 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 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -197,7 +209,7 @@ func Main(ctx *cli.Context) error { |
|
|
|
|
//postAlloc := state.DumpGenesisFormat(false, false, false)
|
|
|
|
|
collector := make(Alloc) |
|
|
|
|
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
|
|
|
|
|
func saveFile(filename string, data interface{}) error { |
|
|
|
|
func saveFile(baseDir, filename string, data interface{}) error { |
|
|
|
|
b, err := json.MarshalIndent(data, "", " ") |
|
|
|
|
if err != nil { |
|
|
|
|
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 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
|
|
|
|
|
// 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{}) |
|
|
|
|
stdErrObject := make(map[string]interface{}) |
|
|
|
|
dispatch := func(fName, name string, obj interface{}) error { |
|
|
|
|
dispatch := func(baseDir, fName, name string, obj interface{}) error { |
|
|
|
|
switch fName { |
|
|
|
|
case "stdout": |
|
|
|
|
stdOutObject[name] = obj |
|
|
|
|
case "stderr": |
|
|
|
|
stdErrObject[name] = obj |
|
|
|
|
default: // save to file
|
|
|
|
|
if err := saveFile(fName, obj); err != nil { |
|
|
|
|
if err := saveFile(baseDir, fName, obj); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
if len(stdOutObject) > 0 { |
|
|
|
|