From d8f4c595d47b299d7eaed7a4eb3a6ff8c59b39aa Mon Sep 17 00:00:00 2001 From: Zhang Guyu Date: Tue, 5 Jul 2022 22:41:58 +0800 Subject: [PATCH] feature: trace_many return trace list (#27) * implement `TraceMany` * upgrade etherlib --- eth/api_pre_exec.go | 118 ++++++++++++++++++++++++-------------------- go.mod | 2 +- go.sum | 6 +-- 3 files changed, 68 insertions(+), 58 deletions(-) diff --git a/eth/api_pre_exec.go b/eth/api_pre_exec.go index 3f85a6754e..2b480f98c2 100644 --- a/eth/api_pre_exec.go +++ b/eth/api_pre_exec.go @@ -8,6 +8,7 @@ import ( "math/big" txtrace "github.com/DeBankDeFi/etherlib/pkg/txtracev1" + txtrace2 "github.com/DeBankDeFi/etherlib/pkg/txtracev2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" @@ -187,17 +188,34 @@ type PreArgs struct { } type PreResult struct { - Trace *[]txtrace.ActionTrace `json:"trace"` - Logs []*types.Log `json:"logs"` + Trace txtrace2.ActionTraceList `json:"trace"` + Logs []*types.Log `json:"logs"` + StateDiff txtrace2.StateDiff `json:"stateDiff"` + Error string `json:"error,omitempty"` + GasUsed uint64 `json:"gasUsed"` } -func (api *PreExecAPI) TraceMany(ctx context.Context, origins []PreArgs) (*PreResult, error) { +func (api *PreExecAPI) TraceMany(ctx context.Context, origins []PreArgs) ([]PreResult, error) { + preResList := make([]PreResult, 0) state, header, err := api.e.APIBackend.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) if state == nil || err != nil { return nil, err } - for i := 0; i < len(origins)-1; i++ { + for i := 0; i < len(origins); i++ { origin := origins[i] + if origin.Nonce == nil { + preResList = append(preResList, PreResult{ + Error: fmt.Sprintf("invalid nonce, tx index %d, nonce is nil", i), + }) + continue + } + nonce := state.GetNonce(*origin.From) + if (uint64)(*origin.Nonce) != nonce { + preResList = append(preResList, PreResult{ + Error: fmt.Sprintf("invalid nonce, tx index %d, want %d, got %d", i, nonce, *origin.Nonce), + }) + continue + } txArgs := ethapi.TransactionArgs{ ChainID: (*hexutil.Big)(big.NewInt(1)), From: origin.From, @@ -214,64 +232,56 @@ func (api *PreExecAPI) TraceMany(ctx context.Context, origins []PreArgs) (*PreRe // Get a new instance of the EVM. msg, err := txArgs.ToMessage(0, header.BaseFee) if err != nil { - return nil, err + preResList = append(preResList, PreResult{ + Error: fmt.Sprintf("toMessage failed, tx index %d, err %v", i, err), + }) + continue } - evm, vmError, err := api.e.APIBackend.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}) + txHash := common.BigToHash(big.NewInt(int64(i))) + tracer := txtrace2.NewOeTracer(nil, header.Hash(), header.Number, txHash, uint64(i)) + evm, vmError, err := api.e.APIBackend.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true, Debug: true, Tracer: tracer}) if err != nil { - return nil, err + preResList = append(preResList, PreResult{ + Error: fmt.Sprintf("getEvm failed, tx index %d, err %v", i, err), + }) + continue } // Execute the message. gp := new(core.GasPool).AddGas(math.MaxUint64) - _, err = core.ApplyMessage(evm, msg, gp) + state.Prepare(txHash, i) + result, err := core.ApplyMessage(evm, msg, gp) if err := vmError(); err != nil { - return nil, err + preRes := PreResult{ + Error: fmt.Sprintf("evm apply failed, tx index %d, err %v", i, err), + } + if result != nil { + preRes.GasUsed = result.UsedGas + } + preResList = append(preResList, preRes) + continue } if err != nil { - return nil, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) + preRes := PreResult{ + Error: fmt.Sprintf("evm apply failed, tx index %d, err %v", i, err), + } + if result != nil { + preRes.GasUsed = result.UsedGas + } + preResList = append(preResList, preRes) + continue } + preRes := PreResult{ + Trace: tracer.GetTraces(), + Logs: state.GetLogs(txHash, header.Hash()), + StateDiff: tracer.GetStateDiff(), + } + if result != nil { + preRes.GasUsed = result.UsedGas + } + if len(preRes.Trace) > 0 && (preRes.Trace)[0].Error != "" { + preRes.Error = (preRes.Trace)[0].Error + } + preResList = append(preResList, preRes) } - origin := origins[len(origins)-1] - txArgs := ethapi.TransactionArgs{ - ChainID: (*hexutil.Big)(big.NewInt(1)), - From: origin.From, - To: origin.To, - Gas: origin.Gas, - GasPrice: origin.GasPrice, - MaxFeePerGas: origin.MaxFeePerGas, - MaxPriorityFeePerGas: origin.MaxPriorityFeePerGas, - Value: origin.Value, - Nonce: origin.Nonce, - Data: origin.Data, - Input: origin.Input, - } - // Get a new instance of the EVM. - msg, err := txArgs.ToMessage(0, header.BaseFee) - if err != nil { - return nil, err - } - tracer := txtrace.NewOeTracer(nil) - tracer.SetFrom(msg.From()) - tracer.SetTo(msg.To()) - tracer.SetValue(*msg.Value()) - tracer.SetTxIndex(uint(0)) - tracer.SetBlockNumber(header.Number) - tracer.SetBlockHash(header.Hash()) - evm, vmError, err := api.e.APIBackend.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true, Debug: true, Tracer: tracer}) - if err != nil { - return nil, err - } - // Execute the message. - gp := new(core.GasPool).AddGas(math.MaxUint64) - txHash := common.BigToHash(big.NewInt(1)) - state.Prepare(txHash, len(origins)-1) - result, err := core.ApplyMessage(evm, msg, gp) - if err := vmError(); err != nil { - return nil, err - } - if err != nil { - return nil, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) - } - tracer.SetGasUsed(result.UsedGas) - tracer.Finalize() - return &PreResult{Trace: tracer.GetResult(), Logs: state.GetLogs(txHash, header.Hash())}, nil + return preResList, nil } diff --git a/go.mod b/go.mod index 0928d5e37a..f1963e30c1 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 - github.com/DeBankDeFi/etherlib v0.2.3-rc3 + github.com/DeBankDeFi/etherlib v0.2.4 github.com/VictoriaMetrics/fastcache v1.6.0 github.com/aws/aws-sdk-go-v2 v1.2.0 github.com/aws/aws-sdk-go-v2/config v1.1.1 diff --git a/go.sum b/go.sum index 1bff9ee5e4..a22060fe1d 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/DeBankDeFi/etherlib v0.2.3-rc3 h1:CPFf4IV+eZ6m/hpMNvG3ucCHMoxczpGKa+ETH3lrf38= -github.com/DeBankDeFi/etherlib v0.2.3-rc3/go.mod h1:iliUmiV5RH9901m0gLTUAAlAwVtd+y4mlaoyeM2w5ms= +github.com/DeBankDeFi/etherlib v0.2.4 h1:lkpzBlnwvtmyqLncIzHOcDtIwoFTquLleo396JaGXPI= +github.com/DeBankDeFi/etherlib v0.2.4/go.mod h1:Q/pkoKm4oZu9UOhLm07Zg7sxXvnLI3GdOoK4bE2t+xI= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= @@ -118,7 +118,7 @@ github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.10.18/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8= +github.com/ethereum/go-ethereum v1.10.19/go.mod h1:IJBNMtzKcNHPtllYihy6BL2IgK1u+32JriaTbdt4v+w= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0=