feature: trace_many return trace list (#27)

* implement `TraceMany`

* upgrade etherlib
This commit is contained in:
Zhang Guyu 2022-07-05 22:41:58 +08:00 committed by GitHub
parent 90d00963b0
commit d8f4c595d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 58 deletions

View file

@ -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
}

2
go.mod
View file

@ -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

6
go.sum
View file

@ -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=