geth debug tracing boilerplate
This commit is contained in:
parent
7344dd5eb3
commit
3a1abdab0f
@ -874,6 +874,11 @@ type FullNode interface {
|
||||
// Replays all transactions in a block returning the requested traces for each transaction
|
||||
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) //perm:read
|
||||
|
||||
// go-ethereum "debug" trace endpoints
|
||||
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
|
||||
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
|
||||
// CreateBackup creates node backup onder the specified file name. The
|
||||
// method requires that the lotus daemon is running with the
|
||||
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
||||
|
@ -129,4 +129,7 @@ type Gateway interface {
|
||||
Web3ClientVersion(ctx context.Context) (string, error)
|
||||
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
|
||||
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
|
||||
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
|
||||
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
}
|
||||
|
@ -43,6 +43,10 @@ func CreateEthRPCAliases(as apitypes.Aliaser) {
|
||||
as.AliasMethod("trace_block", "Filecoin.EthTraceBlock")
|
||||
as.AliasMethod("trace_replayBlockTransactions", "Filecoin.EthTraceReplayBlockTransactions")
|
||||
|
||||
as.AliasMethod("debug_traceCall", "Filecoin.EthDebugTraceCall")
|
||||
as.AliasMethod("debug_traceBlockByHash", "Filecoin.EthDebugTraceBlockByHash")
|
||||
as.AliasMethod("debug_traceBlockByNumber", "Filecoin.EthDebugTraceBlockByNumber")
|
||||
|
||||
as.AliasMethod("net_version", "Filecoin.NetVersion")
|
||||
as.AliasMethod("net_listening", "Filecoin.NetListening")
|
||||
|
||||
|
@ -1500,12 +1500,57 @@ func (m *MockFullNode) EthTraceBlock(arg0 context.Context, arg1 string) ([]*etht
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthDebugTraceCall mocks base method.
|
||||
func (m *MockFullNode) EthDebugTraceCall(ctx context.Context, arg0 ethtypes.EthTxArgs, arg1 ethtypes.EthBlockNumberOrHash, arg2 *ethtypes.TraceCallConfig) (interface{}, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthDebugTraceCall", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(interface{})
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthDebugTraceBlockByNumber mocks base method.
|
||||
func (m *MockFullNode) EthDebugTraceBlockByNumber(ctx context.Context, arg0 string, arg1 *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthDebugTraceBlockByNumber", arg0, arg1)
|
||||
ret0, _ := ret[0].([]*ethtypes.TxTraceResult)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthDebugTraceBlockByHash mocks base method.
|
||||
func (m *MockFullNode) EthDebugTraceBlockByHash(ctx context.Context, arg0 ethtypes.EthHash, arg1 *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthDebugTraceBlockByHash", arg0, arg1)
|
||||
ret0, _ := ret[0].([]*ethtypes.TxTraceResult)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthTraceBlock indicates an expected call of EthTraceBlock.
|
||||
func (mr *MockFullNodeMockRecorder) EthTraceBlock(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthTraceBlock", reflect.TypeOf((*MockFullNode)(nil).EthTraceBlock), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthDebugTraceCall indicates an expected of EthDebugTraceCall
|
||||
func (mr *MockFullNodeMockRecorder) EthDebugTraceCall(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthDebugTraceCall", reflect.TypeOf((*MockFullNode)(nil).EthDebugTraceCall), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthDebugTraceBlockByHash indicates an expected of EthDebugTraceBlockByHash
|
||||
func (mr *MockFullNodeMockRecorder) EthDebugTraceBlockByHash(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthDebugTraceBlockByHash", reflect.TypeOf((*MockFullNode)(nil).EthDebugTraceBlockByHash), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthDebugTraceBlockByNumber indicates an expected of EthDebugTraceBlockByHash
|
||||
func (mr *MockFullNodeMockRecorder) EthDebugTraceBlockByNumber(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthDebugTraceBlockByNumber", reflect.TypeOf((*MockFullNode)(nil).EthDebugTraceBlockByNumber), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthTraceReplayBlockTransactions mocks base method.
|
||||
func (m *MockFullNode) EthTraceReplayBlockTransactions(arg0 context.Context, arg1 string, arg2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -102,6 +102,10 @@ func (e EthBigInt) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(e.String())
|
||||
}
|
||||
|
||||
func (e EthBigInt) ToInt() big.Int {
|
||||
return (big.Int)(e)
|
||||
}
|
||||
|
||||
func (e *EthBigInt) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
|
120
chain/types/ethtypes/tracing.go
Normal file
120
chain/types/ethtypes/tracing.go
Normal file
@ -0,0 +1,120 @@
|
||||
package ethtypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
|
||||
logger "github.com/ipfs/go-log/v2"
|
||||
)
|
||||
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
type TraceConfig struct {
|
||||
*logger.Config
|
||||
Tracer *string
|
||||
Timeout *string
|
||||
Reexec *uint64
|
||||
// Config specific to given tracer. Note struct logger
|
||||
// config are historically embedded in main object.
|
||||
TracerConfig json.RawMessage
|
||||
}
|
||||
|
||||
// TraceCallConfig is the config for traceCall API. It holds one more
|
||||
// field to override the state for tracing.
|
||||
type TraceCallConfig struct {
|
||||
TraceConfig
|
||||
StateOverrides *StateOverride
|
||||
BlockOverrides *BlockOverrides
|
||||
}
|
||||
|
||||
// OverrideAccount indicates the overriding fields of account during the execution
|
||||
// of a message call.
|
||||
// Note, state and stateDiff can't be specified at the same time. If state is
|
||||
// set, message execution will only use the data in the given state. Otherwise
|
||||
// if statDiff is set, all diff will be applied first and then execute the call
|
||||
// message.
|
||||
type OverrideAccount struct {
|
||||
Nonce *EthUint64 `json:"nonce"`
|
||||
Code *EthBytes `json:"code"`
|
||||
Balance **EthBigInt `json:"balance"`
|
||||
State *map[EthHash]EthHash `json:"state"`
|
||||
StateDiff *map[EthHash]EthHash `json:"stateDiff"`
|
||||
}
|
||||
|
||||
// StateOverride is the collection of overridden accounts.
|
||||
type StateOverride map[EthHash]OverrideAccount
|
||||
|
||||
// BlockOverrides is a set of header fields to override.
|
||||
type BlockOverrides struct {
|
||||
Number *EthBigInt
|
||||
Difficulty *EthBigInt
|
||||
Time *EthUint64
|
||||
GasLimit *EthUint64
|
||||
Coinbase *EthAddress
|
||||
Random *EthHash
|
||||
BaseFee *EthUint64
|
||||
}
|
||||
|
||||
// Apply overrides the given header fields into the given block context.
|
||||
func (diff *BlockOverrides) Apply(blockCtx *BlockContext) {
|
||||
if diff == nil {
|
||||
return
|
||||
}
|
||||
if diff.Number != nil {
|
||||
blockCtx.BlockNumber = diff.Number.Int
|
||||
}
|
||||
if diff.Difficulty != nil {
|
||||
blockCtx.Difficulty = diff.Difficulty.Int
|
||||
}
|
||||
if diff.Time != nil {
|
||||
blockCtx.Time = uint64(*diff.Time)
|
||||
}
|
||||
if diff.GasLimit != nil {
|
||||
blockCtx.GasLimit = uint64(*diff.GasLimit)
|
||||
}
|
||||
if diff.Coinbase != nil {
|
||||
blockCtx.Coinbase = *diff.Coinbase
|
||||
}
|
||||
if diff.Random != nil {
|
||||
blockCtx.Random = diff.Random
|
||||
}
|
||||
if diff.BaseFee != nil {
|
||||
blockCtx.BaseFee = new(big.Int).SetUint64((uint64)(*diff.BaseFee))
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// CanTransferFunc is the signature of a transfer guard function
|
||||
CanTransferFunc func(StateDB, EthAddress, *big.Int) bool
|
||||
// TransferFunc is the signature of a transfer function
|
||||
TransferFunc func(StateDB, EthAddress, EthAddress, *big.Int)
|
||||
// GetHashFunc returns the n'th block hash in the blockchain
|
||||
// and is used by the BLOCKHASH EVM op code.
|
||||
GetHashFunc func(uint64) EthAddress
|
||||
)
|
||||
|
||||
// BlockContext provides the EVM with auxiliary information. Once provided
|
||||
// it shouldn't be modified.
|
||||
type BlockContext struct {
|
||||
// CanTransfer returns whether the account contains
|
||||
// sufficient ether to transfer the value
|
||||
CanTransfer CanTransferFunc
|
||||
// Transfer transfers ether from one account to the other
|
||||
Transfer TransferFunc
|
||||
// GetHash returns the hash corresponding to n
|
||||
GetHash GetHashFunc
|
||||
|
||||
// Block information
|
||||
Coinbase EthAddress // Provides information for COINBASE
|
||||
GasLimit uint64 // Provides information for GASLIMIT
|
||||
BlockNumber *big.Int // Provides information for NUMBER
|
||||
Time uint64 // Provides information for TIME
|
||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||
BaseFee *big.Int // Provides information for BASEFEE
|
||||
Random *EthHash // Provides information for PREVRANDAO
|
||||
}
|
||||
|
||||
// TxTraceResult is the result of a single transaction trace.
|
||||
type TxTraceResult struct {
|
||||
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
|
||||
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
|
||||
}
|
@ -146,6 +146,9 @@ type TargetAPI interface {
|
||||
Web3ClientVersion(ctx context.Context) (string, error)
|
||||
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
|
||||
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
|
||||
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
|
||||
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
}
|
||||
|
||||
var _ TargetAPI = *new(api.FullNode) // gateway depends on latest
|
||||
|
@ -606,6 +606,42 @@ func (gw *Node) EthTraceReplayBlockTransactions(ctx context.Context, blkNum stri
|
||||
return gw.target.EthTraceReplayBlockTransactions(ctx, blkNum, traceTypes)
|
||||
}
|
||||
|
||||
func (gw *Node) EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := gw.checkEthBlockParam(ctx, blockNrOrHash, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gw.target.EthDebugTraceCall(ctx, args, blockNrOrHash, config)
|
||||
}
|
||||
|
||||
func (gw *Node) EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := gw.checkBlkHash(ctx, hash); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gw.target.EthDebugTraceBlockByHash(ctx, hash, config)
|
||||
}
|
||||
|
||||
func (gw *Node) EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := gw.checkBlkParam(ctx, number, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gw.target.EthDebugTraceBlockByNumber(ctx, number, config)
|
||||
}
|
||||
|
||||
var EthMaxFiltersPerConn = 16 // todo make this configurable
|
||||
|
||||
func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, error)) (ethtypes.EthFilterID, error) {
|
||||
|
@ -186,5 +186,17 @@ func (e *EthModuleDummy) EthTraceReplayBlockTransactions(ctx context.Context, bl
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
func (e *EthModuleDummy) EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error) {
|
||||
return nil, ErrModuleDisabled
|
||||
}
|
||||
|
||||
var _ EthModuleAPI = &EthModuleDummy{}
|
||||
var _ EthEventAPI = &EthModuleDummy{}
|
||||
|
@ -73,6 +73,9 @@ type EthModuleAPI interface {
|
||||
Web3ClientVersion(ctx context.Context) (string, error)
|
||||
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
|
||||
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
|
||||
EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error)
|
||||
EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error)
|
||||
}
|
||||
|
||||
type EthEventAPI interface {
|
||||
@ -969,6 +972,18 @@ func (a *EthModule) EthTraceReplayBlockTransactions(ctx context.Context, blkNum
|
||||
return allTraces, nil
|
||||
}
|
||||
|
||||
func (a *EthModule) EthDebugTraceCall(ctx context.Context, args ethtypes.EthTxArgs, blockNrOrHash ethtypes.EthBlockNumberOrHash, config *ethtypes.TraceCallConfig) (interface{}, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a *EthModule) EthDebugTraceBlockByNumber(ctx context.Context, number string, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a *EthModule) EthDebugTraceBlockByHash(ctx context.Context, hash ethtypes.EthHash, config *ethtypes.TraceConfig) ([]*ethtypes.TxTraceResult, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (res *api.InvocResult, err error) {
|
||||
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user