Moved tracing types to ethtypes to address circular dependencies

This commit is contained in:
Fridrik Asmundsson 2023-08-22 16:15:14 +00:00
parent ef7bcfec06
commit 8d8891a431
12 changed files with 289 additions and 295 deletions

View File

@ -871,9 +871,9 @@ type FullNode interface {
// TraceAPI related methods // TraceAPI related methods
// //
// Returns traces created at given block // Returns traces created at given block
TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) //perm:read EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) //perm:read
// Replays all transactions in a block returning the requested traces for each transaction // Replays all transactions in a block returning the requested traces for each transaction
TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) //perm:read EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) //perm:read
// CreateBackup creates node backup onder the specified file name. The // CreateBackup creates node backup onder the specified file name. The
// method requires that the lotus daemon is running with the // method requires that the lotus daemon is running with the

View File

@ -127,6 +127,6 @@ type Gateway interface {
EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error)
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error)
Web3ClientVersion(ctx context.Context) (string, error) Web3ClientVersion(ctx context.Context) (string, error)
TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
} }

View File

@ -40,8 +40,8 @@ func CreateEthRPCAliases(as apitypes.Aliaser) {
as.AliasMethod("eth_subscribe", "Filecoin.EthSubscribe") as.AliasMethod("eth_subscribe", "Filecoin.EthSubscribe")
as.AliasMethod("eth_unsubscribe", "Filecoin.EthUnsubscribe") as.AliasMethod("eth_unsubscribe", "Filecoin.EthUnsubscribe")
as.AliasMethod("trace_block", "Filecoin.TraceBlock") as.AliasMethod("trace_block", "Filecoin.EthTraceBlock")
as.AliasMethod("trace_replayBlockTransactions", "Filecoin.TraceReplayBlockTransactions") as.AliasMethod("trace_replayBlockTransactions", "Filecoin.EthTraceReplayBlockTransactions")
as.AliasMethod("net_version", "Filecoin.NetVersion") as.AliasMethod("net_version", "Filecoin.NetVersion")
as.AliasMethod("net_listening", "Filecoin.NetListening") as.AliasMethod("net_listening", "Filecoin.NetListening")

View File

@ -1491,6 +1491,36 @@ func (mr *MockFullNodeMockRecorder) EthSyncing(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSyncing", reflect.TypeOf((*MockFullNode)(nil).EthSyncing), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSyncing", reflect.TypeOf((*MockFullNode)(nil).EthSyncing), arg0)
} }
// EthTraceBlock mocks base method.
func (m *MockFullNode) EthTraceBlock(arg0 context.Context, arg1 string) ([]*ethtypes.EthTraceBlock, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthTraceBlock", arg0, arg1)
ret0, _ := ret[0].([]*ethtypes.EthTraceBlock)
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)
}
// EthTraceReplayBlockTransactions mocks base method.
func (m *MockFullNode) EthTraceReplayBlockTransactions(arg0 context.Context, arg1 string, arg2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EthTraceReplayBlockTransactions", arg0, arg1, arg2)
ret0, _ := ret[0].([]*ethtypes.EthTraceReplayBlockTransaction)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// EthTraceReplayBlockTransactions indicates an expected call of EthTraceReplayBlockTransactions.
func (mr *MockFullNodeMockRecorder) EthTraceReplayBlockTransactions(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthTraceReplayBlockTransactions", reflect.TypeOf((*MockFullNode)(nil).EthTraceReplayBlockTransactions), arg0, arg1, arg2)
}
// EthUninstallFilter mocks base method. // EthUninstallFilter mocks base method.
func (m *MockFullNode) EthUninstallFilter(arg0 context.Context, arg1 ethtypes.EthFilterID) (bool, error) { func (m *MockFullNode) EthUninstallFilter(arg0 context.Context, arg1 ethtypes.EthFilterID) (bool, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -4023,36 +4053,6 @@ func (mr *MockFullNodeMockRecorder) SyncValidateTipset(arg0, arg1 interface{}) *
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncValidateTipset", reflect.TypeOf((*MockFullNode)(nil).SyncValidateTipset), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncValidateTipset", reflect.TypeOf((*MockFullNode)(nil).SyncValidateTipset), arg0, arg1)
} }
// TraceBlock mocks base method.
func (m *MockFullNode) TraceBlock(arg0 context.Context, arg1 string) ([]*ethtypes.TraceBlock, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TraceBlock", arg0, arg1)
ret0, _ := ret[0].([]*ethtypes.TraceBlock)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// TraceBlock indicates an expected call of TraceBlock.
func (mr *MockFullNodeMockRecorder) TraceBlock(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TraceBlock", reflect.TypeOf((*MockFullNode)(nil).TraceBlock), arg0, arg1)
}
// TraceReplayBlockTransactions mocks base method.
func (m *MockFullNode) TraceReplayBlockTransactions(arg0 context.Context, arg1 string, arg2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TraceReplayBlockTransactions", arg0, arg1, arg2)
ret0, _ := ret[0].([]*ethtypes.TraceReplayBlockTransaction)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// TraceReplayBlockTransactions indicates an expected call of TraceReplayBlockTransactions.
func (mr *MockFullNodeMockRecorder) TraceReplayBlockTransactions(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TraceReplayBlockTransactions", reflect.TypeOf((*MockFullNode)(nil).TraceReplayBlockTransactions), arg0, arg1, arg2)
}
// Version mocks base method. // Version mocks base method.
func (m *MockFullNode) Version(arg0 context.Context) (api.APIVersion, error) { func (m *MockFullNode) Version(arg0 context.Context) (api.APIVersion, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -316,6 +316,10 @@ type FullNodeMethods struct {
EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) `perm:"read"` EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) `perm:"read"`
EthTraceBlock func(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) `perm:"read"`
EthTraceReplayBlockTransactions func(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) `perm:"read"`
EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"read"` EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"read"`
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"read"` EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"read"`
@ -596,10 +600,6 @@ type FullNodeMethods struct {
SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"`
TraceBlock func(p0 context.Context, p1 string) ([]*ethtypes.TraceBlock, error) `perm:"read"`
TraceReplayBlockTransactions func(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) `perm:"read"`
WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"`
WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"`
@ -736,6 +736,10 @@ type GatewayMethods struct {
EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) `` EthSyncing func(p0 context.Context) (ethtypes.EthSyncingResult, error) ``
EthTraceBlock func(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) ``
EthTraceReplayBlockTransactions func(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) ``
EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) ``
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) ``
@ -818,10 +822,6 @@ type GatewayMethods struct {
StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) ``
TraceBlock func(p0 context.Context, p1 string) ([]*ethtypes.TraceBlock, error) ``
TraceReplayBlockTransactions func(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) ``
Version func(p0 context.Context) (APIVersion, error) `` Version func(p0 context.Context) (APIVersion, error) ``
WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) ``
@ -2465,6 +2465,28 @@ func (s *FullNodeStub) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult
return *new(ethtypes.EthSyncingResult), ErrNotSupported return *new(ethtypes.EthSyncingResult), ErrNotSupported
} }
func (s *FullNodeStruct) EthTraceBlock(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) {
if s.Internal.EthTraceBlock == nil {
return *new([]*ethtypes.EthTraceBlock), ErrNotSupported
}
return s.Internal.EthTraceBlock(p0, p1)
}
func (s *FullNodeStub) EthTraceBlock(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) {
return *new([]*ethtypes.EthTraceBlock), ErrNotSupported
}
func (s *FullNodeStruct) EthTraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
if s.Internal.EthTraceReplayBlockTransactions == nil {
return *new([]*ethtypes.EthTraceReplayBlockTransaction), ErrNotSupported
}
return s.Internal.EthTraceReplayBlockTransactions(p0, p1, p2)
}
func (s *FullNodeStub) EthTraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
return *new([]*ethtypes.EthTraceReplayBlockTransaction), ErrNotSupported
}
func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
if s.Internal.EthUninstallFilter == nil { if s.Internal.EthUninstallFilter == nil {
return false, ErrNotSupported return false, ErrNotSupported
@ -4005,28 +4027,6 @@ func (s *FullNodeStub) SyncValidateTipset(p0 context.Context, p1 types.TipSetKey
return false, ErrNotSupported return false, ErrNotSupported
} }
func (s *FullNodeStruct) TraceBlock(p0 context.Context, p1 string) ([]*ethtypes.TraceBlock, error) {
if s.Internal.TraceBlock == nil {
return *new([]*ethtypes.TraceBlock), ErrNotSupported
}
return s.Internal.TraceBlock(p0, p1)
}
func (s *FullNodeStub) TraceBlock(p0 context.Context, p1 string) ([]*ethtypes.TraceBlock, error) {
return *new([]*ethtypes.TraceBlock), ErrNotSupported
}
func (s *FullNodeStruct) TraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) {
if s.Internal.TraceReplayBlockTransactions == nil {
return *new([]*ethtypes.TraceReplayBlockTransaction), ErrNotSupported
}
return s.Internal.TraceReplayBlockTransactions(p0, p1, p2)
}
func (s *FullNodeStub) TraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) {
return *new([]*ethtypes.TraceReplayBlockTransaction), ErrNotSupported
}
func (s *FullNodeStruct) WalletBalance(p0 context.Context, p1 address.Address) (types.BigInt, error) { func (s *FullNodeStruct) WalletBalance(p0 context.Context, p1 address.Address) (types.BigInt, error) {
if s.Internal.WalletBalance == nil { if s.Internal.WalletBalance == nil {
return *new(types.BigInt), ErrNotSupported return *new(types.BigInt), ErrNotSupported
@ -4709,6 +4709,28 @@ func (s *GatewayStub) EthSyncing(p0 context.Context) (ethtypes.EthSyncingResult,
return *new(ethtypes.EthSyncingResult), ErrNotSupported return *new(ethtypes.EthSyncingResult), ErrNotSupported
} }
func (s *GatewayStruct) EthTraceBlock(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) {
if s.Internal.EthTraceBlock == nil {
return *new([]*ethtypes.EthTraceBlock), ErrNotSupported
}
return s.Internal.EthTraceBlock(p0, p1)
}
func (s *GatewayStub) EthTraceBlock(p0 context.Context, p1 string) ([]*ethtypes.EthTraceBlock, error) {
return *new([]*ethtypes.EthTraceBlock), ErrNotSupported
}
func (s *GatewayStruct) EthTraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
if s.Internal.EthTraceReplayBlockTransactions == nil {
return *new([]*ethtypes.EthTraceReplayBlockTransaction), ErrNotSupported
}
return s.Internal.EthTraceReplayBlockTransactions(p0, p1, p2)
}
func (s *GatewayStub) EthTraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
return *new([]*ethtypes.EthTraceReplayBlockTransaction), ErrNotSupported
}
func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
if s.Internal.EthUninstallFilter == nil { if s.Internal.EthUninstallFilter == nil {
return false, ErrNotSupported return false, ErrNotSupported
@ -5160,28 +5182,6 @@ func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3
return nil, ErrNotSupported return nil, ErrNotSupported
} }
func (s *GatewayStruct) TraceBlock(p0 context.Context, p1 string) ([]*ethtypes.TraceBlock, error) {
if s.Internal.TraceBlock == nil {
return *new([]*ethtypes.TraceBlock), ErrNotSupported
}
return s.Internal.TraceBlock(p0, p1)
}
func (s *GatewayStub) TraceBlock(p0 context.Context, p1 string) ([]*ethtypes.TraceBlock, error) {
return *new([]*ethtypes.TraceBlock), ErrNotSupported
}
func (s *GatewayStruct) TraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) {
if s.Internal.TraceReplayBlockTransactions == nil {
return *new([]*ethtypes.TraceReplayBlockTransaction), ErrNotSupported
}
return s.Internal.TraceReplayBlockTransactions(p0, p1, p2)
}
func (s *GatewayStub) TraceReplayBlockTransactions(p0 context.Context, p1 string, p2 []string) ([]*ethtypes.TraceReplayBlockTransaction, error) {
return *new([]*ethtypes.TraceReplayBlockTransaction), ErrNotSupported
}
func (s *GatewayStruct) Version(p0 context.Context) (APIVersion, error) { func (s *GatewayStruct) Version(p0 context.Context) (APIVersion, error) {
if s.Internal.Version == nil { if s.Internal.Version == nil {
return *new(APIVersion), ErrNotSupported return *new(APIVersion), ErrNotSupported

View File

@ -18,6 +18,7 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
builtintypes "github.com/filecoin-project/go-state-types/builtin" builtintypes "github.com/filecoin-project/go-state-types/builtin"
@ -929,3 +930,51 @@ func (e *EthBlockNumberOrHash) UnmarshalJSON(b []byte) error {
return errors.New("invalid block param") return errors.New("invalid block param")
} }
type EthTrace struct {
Action EthTraceAction `json:"action"`
Result EthTraceResult `json:"result"`
Subtraces int `json:"subtraces"`
TraceAddress []int `json:"traceAddress"`
Type string `json:"Type"`
Parent *EthTrace `json:"-"`
}
func (t *EthTrace) SetCallType(callType string) {
t.Action.CallType = callType
t.Type = callType
}
type EthTraceBlock struct {
*EthTrace
BlockHash EthHash `json:"blockHash"`
BlockNumber int64 `json:"blockNumber"`
TransactionHash EthHash `json:"transactionHash"`
TransactionPosition int `json:"transactionPosition"`
}
type EthTraceReplayBlockTransaction struct {
Output string `json:"output"`
StateDiff *string `json:"stateDiff"`
Trace []*EthTrace `json:"trace"`
TransactionHash EthHash `json:"transactionHash"`
VmTrace *string `json:"vmTrace"`
}
type EthTraceAction struct {
CallType string `json:"callType"`
From string `json:"from"`
To string `json:"to"`
Gas EthUint64 `json:"gas"`
Input string `json:"input"`
Value EthBigInt `json:"value"`
Method abi.MethodNum `json:"-"`
CodeCid cid.Cid `json:"-"`
}
type EthTraceResult struct {
GasUsed EthUint64 `json:"gasUsed"`
Output string `json:"output"`
}

View File

@ -104,6 +104,8 @@
* [EthSendRawTransaction](#EthSendRawTransaction) * [EthSendRawTransaction](#EthSendRawTransaction)
* [EthSubscribe](#EthSubscribe) * [EthSubscribe](#EthSubscribe)
* [EthSyncing](#EthSyncing) * [EthSyncing](#EthSyncing)
* [EthTraceBlock](#EthTraceBlock)
* [EthTraceReplayBlockTransactions](#EthTraceReplayBlockTransactions)
* [EthUninstallFilter](#EthUninstallFilter) * [EthUninstallFilter](#EthUninstallFilter)
* [EthUnsubscribe](#EthUnsubscribe) * [EthUnsubscribe](#EthUnsubscribe)
* [Filecoin](#Filecoin) * [Filecoin](#Filecoin)
@ -287,9 +289,6 @@
* [SyncUnmarkAllBad](#SyncUnmarkAllBad) * [SyncUnmarkAllBad](#SyncUnmarkAllBad)
* [SyncUnmarkBad](#SyncUnmarkBad) * [SyncUnmarkBad](#SyncUnmarkBad)
* [SyncValidateTipset](#SyncValidateTipset) * [SyncValidateTipset](#SyncValidateTipset)
* [Trace](#Trace)
* [TraceBlock](#TraceBlock)
* [TraceReplayBlockTransactions](#TraceReplayBlockTransactions)
* [Wallet](#Wallet) * [Wallet](#Wallet)
* [WalletBalance](#WalletBalance) * [WalletBalance](#WalletBalance)
* [WalletDefaultAddress](#WalletDefaultAddress) * [WalletDefaultAddress](#WalletDefaultAddress)
@ -3086,6 +3085,99 @@ Inputs: `null`
Response: `false` Response: `false`
### EthTraceBlock
TraceAPI related methods
Returns traces created at given block
Perms: read
Inputs:
```json
[
"string value"
]
```
Response:
```json
[
{
"action": {
"callType": "string value",
"from": "string value",
"to": "string value",
"gas": "0x5",
"input": "string value",
"value": "0x0"
},
"result": {
"gasUsed": "0x5",
"output": "string value"
},
"subtraces": 123,
"traceAddress": [
123
],
"Type": "string value",
"blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
"blockNumber": 9,
"transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
"transactionPosition": 123
}
]
```
### EthTraceReplayBlockTransactions
Replays all transactions in a block returning the requested traces for each transaction
Perms: read
Inputs:
```json
[
"string value",
[
"string value"
]
]
```
Response:
```json
[
{
"output": "string value",
"stateDiff": "string value",
"trace": [
{
"action": {
"callType": "string value",
"from": "string value",
"to": "string value",
"gas": "0x5",
"input": "string value",
"value": "0x0"
},
"result": {
"gasUsed": "0x5",
"output": "string value"
},
"subtraces": 123,
"traceAddress": [
123
],
"Type": "string value"
}
],
"transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
"vmTrace": "string value"
}
]
```
### EthUninstallFilter ### EthUninstallFilter
Uninstalls a filter with given id. Uninstalls a filter with given id.
@ -8823,102 +8915,6 @@ Inputs:
Response: `true` Response: `true`
## Trace
### TraceBlock
TraceAPI related methods
Returns traces created at given block
Perms: read
Inputs:
```json
[
"string value"
]
```
Response:
```json
[
{
"action": {
"callType": "string value",
"from": "string value",
"to": "string value",
"gas": "0x5",
"input": "string value",
"value": "0x0"
},
"result": {
"gasUsed": "0x5",
"output": "string value"
},
"subtraces": 123,
"traceAddress": [
123
],
"Type": "string value",
"blockHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
"blockNumber": 9,
"transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
"transactionPosition": 123
}
]
```
### TraceReplayBlockTransactions
Replays all transactions in a block returning the requested traces for each transaction
Perms: read
Inputs:
```json
[
"string value",
[
"string value"
]
]
```
Response:
```json
[
{
"output": "string value",
"stateDiff": "string value",
"trace": [
{
"action": {
"callType": "string value",
"from": "string value",
"to": "string value",
"gas": "0x5",
"input": "string value",
"value": "0x0"
},
"result": {
"gasUsed": "0x5",
"output": "string value"
},
"subtraces": 123,
"traceAddress": [
123
],
"Type": "string value"
}
],
"transactionHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
"vmTrace": "string value"
}
]
```
## Wallet ## Wallet

View File

@ -144,8 +144,8 @@ type TargetAPI interface {
EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error)
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error)
Web3ClientVersion(ctx context.Context) (string, error) Web3ClientVersion(ctx context.Context) (string, error)
TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
} }
var _ TargetAPI = *new(api.FullNode) // gateway depends on latest var _ TargetAPI = *new(api.FullNode) // gateway depends on latest

View File

@ -582,7 +582,7 @@ func (gw *Node) Web3ClientVersion(ctx context.Context) (string, error) {
return gw.target.Web3ClientVersion(ctx) return gw.target.Web3ClientVersion(ctx)
} }
func (gw *Node) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) { func (gw *Node) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
@ -591,10 +591,10 @@ func (gw *Node) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.Trac
return nil, err return nil, err
} }
return gw.target.TraceBlock(ctx, blkNum) return gw.target.EthTraceBlock(ctx, blkNum)
} }
func (gw *Node) TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) { func (gw *Node) EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
if err := gw.limit(ctx, stateRateLimitTokens); err != nil { if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
return nil, err return nil, err
} }
@ -603,7 +603,7 @@ func (gw *Node) TraceReplayBlockTransactions(ctx context.Context, blkNum string,
return nil, err return nil, err
} }
return gw.target.TraceReplayBlockTransactions(ctx, blkNum, traceTypes) return gw.target.EthTraceReplayBlockTransactions(ctx, blkNum, traceTypes)
} }
var EthMaxFiltersPerConn = 16 // todo make this configurable var EthMaxFiltersPerConn = 16 // todo make this configurable

View File

@ -178,11 +178,11 @@ func (e *EthModuleDummy) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubs
return false, ErrModuleDisabled return false, ErrModuleDisabled
} }
func (e *EthModuleDummy) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) { func (e *EthModuleDummy) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) {
return nil, ErrModuleDisabled return nil, ErrModuleDisabled
} }
func (e *EthModuleDummy) TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) { func (e *EthModuleDummy) EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
return nil, ErrModuleDisabled return nil, ErrModuleDisabled
} }

View File

@ -71,8 +71,8 @@ type EthModuleAPI interface {
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error)
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error)
Web3ClientVersion(ctx context.Context) (string, error) Web3ClientVersion(ctx context.Context) (string, error)
TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
} }
type EthEventAPI interface { type EthEventAPI interface {
@ -825,7 +825,7 @@ func (a *EthModule) Web3ClientVersion(ctx context.Context) (string, error) {
return build.UserVersion(), nil return build.UserVersion(), nil
} }
func (a *EthModule) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.TraceBlock, error) { func (a *EthModule) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) {
ts, err := getTipsetByBlockNumber(ctx, a.Chain, blkNum, false) ts, err := getTipsetByBlockNumber(ctx, a.Chain, blkNum, false)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to get tipset: %w", err) return nil, xerrors.Errorf("failed to get tipset: %w", err)
@ -856,7 +856,7 @@ func (a *EthModule) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.
return nil, xerrors.Errorf("failed to parse eth hash from cid: %w", err) return nil, xerrors.Errorf("failed to parse eth hash from cid: %w", err)
} }
allTraces := make([]*ethtypes.TraceBlock, 0, len(trace)) allTraces := make([]*ethtypes.EthTraceBlock, 0, len(trace))
msgIdx := 0 msgIdx := 0
for _, ir := range trace { for _, ir := range trace {
// ignore messages from system actor // ignore messages from system actor
@ -880,16 +880,16 @@ func (a *EthModule) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.
continue continue
} }
traces := []*ethtypes.Trace{} traces := []*ethtypes.EthTrace{}
err = ethtypes.BuildTraces(&traces, nil, []int{}, ir.ExecutionTrace, int64(ts.Height())) err = buildTraces(ctx, &traces, nil, []int{}, ir.ExecutionTrace, int64(ts.Height()), a.StateAPI)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed building traces: %w", err) return nil, xerrors.Errorf("failed building traces: %w", err)
} }
traceBlocks := make([]*ethtypes.TraceBlock, 0, len(traces)) traceBlocks := make([]*ethtypes.EthTraceBlock, 0, len(traces))
for _, trace := range traces { for _, trace := range traces {
traceBlocks = append(traceBlocks, &ethtypes.TraceBlock{ traceBlocks = append(traceBlocks, &ethtypes.EthTraceBlock{
Trace: trace, EthTrace: trace,
BlockHash: blkHash, BlockHash: blkHash,
BlockNumber: int64(ts.Height()), BlockNumber: int64(ts.Height()),
TransactionHash: *txHash, TransactionHash: *txHash,
@ -903,7 +903,7 @@ func (a *EthModule) TraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.
return allTraces, nil return allTraces, nil
} }
func (a *EthModule) TraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.TraceReplayBlockTransaction, error) { func (a *EthModule) EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) {
if len(traceTypes) != 1 || traceTypes[0] != "trace" { if len(traceTypes) != 1 || traceTypes[0] != "trace" {
return nil, fmt.Errorf("only 'trace' is supported") return nil, fmt.Errorf("only 'trace' is supported")
} }
@ -918,7 +918,7 @@ func (a *EthModule) TraceReplayBlockTransactions(ctx context.Context, blkNum str
return nil, xerrors.Errorf("failed when calling ExecutionTrace: %w", err) return nil, xerrors.Errorf("failed when calling ExecutionTrace: %w", err)
} }
allTraces := make([]*ethtypes.TraceReplayBlockTransaction, 0, len(trace)) allTraces := make([]*ethtypes.EthTraceReplayBlockTransaction, 0, len(trace))
for _, ir := range trace { for _, ir := range trace {
// ignore messages from system actor // ignore messages from system actor
if ir.Msg.From == builtinactors.SystemActorAddr { if ir.Msg.From == builtinactors.SystemActorAddr {
@ -934,14 +934,14 @@ func (a *EthModule) TraceReplayBlockTransactions(ctx context.Context, blkNum str
continue continue
} }
t := ethtypes.TraceReplayBlockTransaction{ t := ethtypes.EthTraceReplayBlockTransaction{
Output: hex.EncodeToString(ir.MsgRct.Return), Output: hex.EncodeToString(ir.MsgRct.Return),
TransactionHash: *txHash, TransactionHash: *txHash,
StateDiff: nil, StateDiff: nil,
VmTrace: nil, VmTrace: nil,
} }
err = ethtypes.BuildTraces(&t.Trace, nil, []int{}, ir.ExecutionTrace, int64(ts.Height())) err = buildTraces(ctx, &t.Trace, nil, []int{}, ir.ExecutionTrace, int64(ts.Height()), a.StateAPI)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed building traces: %w", err) return nil, xerrors.Errorf("failed building traces: %w", err)
} }

View File

@ -1,100 +1,49 @@
package ethtypes package full
import ( import (
"bytes" "bytes"
"context"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io" "io"
"github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log/v2"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin" builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/ethtypes"
) )
var log = logging.Logger("traceapi") // buildTraces recursively builds the traces for a given ExecutionTrace by walking the subcalls
func buildTraces(ctx context.Context, traces *[]*ethtypes.EthTrace, parent *ethtypes.EthTrace, addr []int, et types.ExecutionTrace, height int64, sa StateAPI) error {
type Trace struct { trace := &ethtypes.EthTrace{
Action Action `json:"action"` Action: ethtypes.EthTraceAction{
Result Result `json:"result"`
Subtraces int `json:"subtraces"`
TraceAddress []int `json:"traceAddress"`
Type string `json:"Type"`
parent *Trace
}
func (t *Trace) setCallType(callType string) {
t.Action.CallType = callType
t.Type = callType
}
type TraceBlock struct {
*Trace
BlockHash EthHash `json:"blockHash"`
BlockNumber int64 `json:"blockNumber"`
TransactionHash EthHash `json:"transactionHash"`
TransactionPosition int `json:"transactionPosition"`
}
type TraceReplayBlockTransaction struct {
Output string `json:"output"`
StateDiff *string `json:"stateDiff"`
Trace []*Trace `json:"trace"`
TransactionHash EthHash `json:"transactionHash"`
VmTrace *string `json:"vmTrace"`
}
type Action struct {
CallType string `json:"callType"`
From string `json:"from"`
To string `json:"to"`
Gas EthUint64 `json:"gas"`
Input string `json:"input"`
Value EthBigInt `json:"value"`
method abi.MethodNum `json:"-"`
codeCid cid.Cid `json:"-"`
}
type Result struct {
GasUsed EthUint64 `json:"gasUsed"`
Output string `json:"output"`
}
// BuildTraces recursively builds the traces for a given ExecutionTrace by walking the subcalls
func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.ExecutionTrace, height int64) error {
trace := &Trace{
Action: Action{
From: et.Msg.From.String(), From: et.Msg.From.String(),
To: et.Msg.To.String(), To: et.Msg.To.String(),
Gas: EthUint64(et.Msg.GasLimit), Gas: ethtypes.EthUint64(et.Msg.GasLimit),
Input: hex.EncodeToString(et.Msg.Params), Input: hex.EncodeToString(et.Msg.Params),
Value: EthBigInt(et.Msg.Value), Value: ethtypes.EthBigInt(et.Msg.Value),
method: et.Msg.Method, Method: et.Msg.Method,
codeCid: et.Msg.CodeCid, CodeCid: et.Msg.CodeCid,
}, },
Result: Result{ Result: ethtypes.EthTraceResult{
GasUsed: EthUint64(et.SumGas().TotalGas), GasUsed: ethtypes.EthUint64(et.SumGas().TotalGas),
Output: hex.EncodeToString(et.MsgRct.Return), Output: hex.EncodeToString(et.MsgRct.Return),
}, },
Subtraces: len(et.Subcalls), Subtraces: len(et.Subcalls),
TraceAddress: addr, TraceAddress: addr,
parent: parent, Parent: parent,
} }
trace.setCallType("call") trace.SetCallType("call")
// TODO: is it OK to check this here or is this only specific to certain edge case (evm to evm)? // TODO: is it OK to check this here or is this only specific to certain edge case (evm to evm)?
if et.Msg.ReadOnly { if et.Msg.ReadOnly {
trace.setCallType("staticcall") trace.SetCallType("staticcall")
} }
// there are several edge cases thar require special handling when displaying the traces // there are several edge cases thar require special handling when displaying the traces
@ -104,7 +53,7 @@ func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.Execution
// When an EVM actor is invoked with a method number above 1023 that's not frc42(InvokeEVM) // When an EVM actor is invoked with a method number above 1023 that's not frc42(InvokeEVM)
// then we need to format native calls in a way that makes sense to Ethereum tooling (convert // then we need to format native calls in a way that makes sense to Ethereum tooling (convert
// the input & output to solidity ABI format). // the input & output to solidity ABI format).
if builtinactors.IsEvmActor(parent.Action.codeCid) && if builtinactors.IsEvmActor(parent.Action.CodeCid) &&
et.Msg.Method > 1023 && et.Msg.Method > 1023 &&
et.Msg.Method != builtin.MethodsEVM.InvokeContract { et.Msg.Method != builtin.MethodsEVM.InvokeContract {
log.Debugf("found Native call! method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height) log.Debugf("found Native call! method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height)
@ -124,10 +73,10 @@ func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.Execution
// //
// Actor A calls to the init actor on method 2 and The init actor creates the target actor B then calls it on method 1 // Actor A calls to the init actor on method 2 and The init actor creates the target actor B then calls it on method 1
if parent.Action.To == builtin.InitActorAddr.String() && if parent.Action.To == builtin.InitActorAddr.String() &&
parent.Action.method == builtin.MethodsInit.Exec && parent.Action.Method == builtin.MethodsInit.Exec &&
et.Msg.Method == builtin.MethodConstructor { et.Msg.Method == builtin.MethodConstructor {
log.Debugf("Native actor creation! method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height) log.Debugf("Native actor creation! method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height)
parent.setCallType("create") parent.SetCallType("create")
parent.Action.To = et.Msg.To.String() parent.Action.To = et.Msg.To.String()
parent.Action.Input = hex.EncodeToString([]byte{0x0, 0x0, 0x0, 0xFE}) parent.Action.Input = hex.EncodeToString([]byte{0x0, 0x0, 0x0, 0xFE})
parent.Result.Output = "" parent.Result.Output = ""
@ -143,25 +92,25 @@ func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.Execution
// 1) EVM contract A calls the EAM (Ethereum Address Manager) on method 2 (create) or 3 (create2). // 1) EVM contract A calls the EAM (Ethereum Address Manager) on method 2 (create) or 3 (create2).
// 2) The EAM calls the init actor on method 3 (Exec4). // 2) The EAM calls the init actor on method 3 (Exec4).
// 3) The init actor creates the target actor B then calls it on method 1. // 3) The init actor creates the target actor B then calls it on method 1.
if parent.parent != nil { if parent.Parent != nil {
calledCreateOnEAM := parent.parent.Action.To == builtin.EthereumAddressManagerActorAddr.String() && calledCreateOnEAM := parent.Parent.Action.To == builtin.EthereumAddressManagerActorAddr.String() &&
(parent.parent.Action.method == builtin.MethodsEAM.Create || parent.parent.Action.method == builtin.MethodsEAM.Create2) (parent.Parent.Action.Method == builtin.MethodsEAM.Create || parent.Parent.Action.Method == builtin.MethodsEAM.Create2)
eamCalledInitOnExec4 := parent.Action.To == builtin.InitActorAddr.String() && eamCalledInitOnExec4 := parent.Action.To == builtin.InitActorAddr.String() &&
parent.Action.method == builtin.MethodsInit.Exec4 parent.Action.Method == builtin.MethodsInit.Exec4
initCreatedActor := trace.Action.method == builtin.MethodConstructor initCreatedActor := trace.Action.Method == builtin.MethodConstructor
if calledCreateOnEAM && eamCalledInitOnExec4 && initCreatedActor { if calledCreateOnEAM && eamCalledInitOnExec4 && initCreatedActor {
log.Debugf("EVM contract creation method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height) log.Debugf("EVM contract creation method:%d, code:%s, height:%d", et.Msg.Method, et.Msg.CodeCid.String(), height)
if parent.parent.Action.method == builtin.MethodsEAM.Create { if parent.Parent.Action.Method == builtin.MethodsEAM.Create {
parent.parent.setCallType("create") parent.Parent.SetCallType("create")
} else { } else {
parent.parent.setCallType("create2") parent.Parent.SetCallType("create2")
} }
// update the parent.parent to make this // update the parent.parent to make this
parent.parent.Action.To = trace.Action.To parent.Parent.Action.To = trace.Action.To
parent.parent.Subtraces = 0 parent.Parent.Subtraces = 0
// delete the parent (the EAM) and skip the current trace (init) // delete the parent (the EAM) and skip the current trace (init)
*traces = (*traces)[:len(*traces)-1] *traces = (*traces)[:len(*traces)-1]
@ -174,17 +123,17 @@ func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.Execution
// //
// Any outbound call from an EVM actor on methods 1-1023 are side-effects from EVM instructions // Any outbound call from an EVM actor on methods 1-1023 are side-effects from EVM instructions
// and should be dropped from the trace. // and should be dropped from the trace.
if builtinactors.IsEvmActor(parent.Action.codeCid) && if builtinactors.IsEvmActor(parent.Action.CodeCid) &&
et.Msg.Method > 0 && et.Msg.Method > 0 &&
et.Msg.Method <= 1023 { et.Msg.Method <= 1023 {
log.Debugf("found outbound call from an EVM actor on method 1-1023 method:%d, code:%s, height:%d", et.Msg.Method, parent.Action.codeCid.String(), height) log.Debugf("found outbound call from an EVM actor on method 1-1023 method:%d, code:%s, height:%d", et.Msg.Method, parent.Action.CodeCid.String(), height)
// TODO: if I handle this case and drop this call from the trace then I am not able to detect delegate calls // TODO: if I handle this case and drop this call from the trace then I am not able to detect delegate calls
} }
// EVM -> EVM calls // EVM -> EVM calls
// //
// Check for normal EVM to EVM calls and decode the params and return values // Check for normal EVM to EVM calls and decode the params and return values
if builtinactors.IsEvmActor(parent.Action.codeCid) && if builtinactors.IsEvmActor(parent.Action.CodeCid) &&
builtinactors.IsEthAccountActor(et.Msg.CodeCid) && builtinactors.IsEthAccountActor(et.Msg.CodeCid) &&
et.Msg.Method == builtin.MethodsEVM.InvokeContract { et.Msg.Method == builtin.MethodsEVM.InvokeContract {
log.Debugf("found evm to evm call, code:%s, height: %d", et.Msg.CodeCid.String(), height) log.Debugf("found evm to evm call, code:%s, height: %d", et.Msg.CodeCid.String(), height)
@ -206,12 +155,12 @@ func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.Execution
// 2) Check that the previous trace calls another actor on method 3 (GetByteCode) and they are at the same level (same parent) // 2) Check that the previous trace calls another actor on method 3 (GetByteCode) and they are at the same level (same parent)
// 3) Treat this as a delegate call to actor A. // 3) Treat this as a delegate call to actor A.
if trace.Action.From == trace.Action.To && if trace.Action.From == trace.Action.To &&
trace.Action.method == builtin.MethodsEVM.InvokeContractDelegate && trace.Action.Method == builtin.MethodsEVM.InvokeContractDelegate &&
len(*traces) > 0 { len(*traces) > 0 {
log.Debugf("found delegate call, height: %d", height) log.Debugf("found delegate call, height: %d", height)
prev := (*traces)[len(*traces)-1] prev := (*traces)[len(*traces)-1]
if prev.Action.From == trace.Action.From && prev.Action.method == builtin.MethodsEVM.GetBytecode && prev.parent == trace.parent { if prev.Action.From == trace.Action.From && prev.Action.Method == builtin.MethodsEVM.GetBytecode && prev.Parent == trace.Parent {
trace.setCallType("delegatecall") trace.SetCallType("delegatecall")
trace.Action.To = prev.Action.To trace.Action.To = prev.Action.To
} }
} }
@ -220,7 +169,7 @@ func BuildTraces(traces *[]*Trace, parent *Trace, addr []int, et types.Execution
*traces = append(*traces, trace) *traces = append(*traces, trace)
for i, call := range et.Subcalls { for i, call := range et.Subcalls {
err := BuildTraces(traces, trace, append(addr, i), call, height) err := buildTraces(ctx, traces, trace, append(addr, i), call, height, sa)
if err != nil { if err != nil {
return err return err
} }