From ee83dceef0574f4cc1a1f605522e68bf069df3b6 Mon Sep 17 00:00:00 2001 From: raulk Date: Thu, 29 Sep 2022 23:55:13 +0100 Subject: [PATCH] Eth JSON-RPC API: implement eth_getCode and eth_getStorageAt (#9397) --- api/api_full.go | 54 ++--- api/docgen/docgen.go | 5 +- api/eth_transactions.go | 18 +- api/eth_types.go | 40 ++-- api/eth_types_test.go | 16 +- api/mocks/mock_full.go | 40 ++-- api/proxy_gen.go | 104 +++++---- api/v0api/full.go | 16 +- documentation/en/api-v1-unstable-methods.md | 6 +- go.sum | 2 + node/impl/full/eth.go | 224 ++++++++++++++++---- 11 files changed, 328 insertions(+), 197 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 9cd75ff13..82bd44f19 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -150,7 +150,7 @@ type FullNode interface { // ChainGetPath returns a set of revert/apply operations needed to get from // one tipset to another, for example: - //``` + // ``` // to // ^ // from tAA @@ -159,7 +159,7 @@ type FullNode interface { // ^---*--^ // ^ // tRR - //``` + // ``` // Would return `[revert(tBA), apply(tAB), apply(tAA)]` ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) //perm:read @@ -387,12 +387,12 @@ type FullNode interface { ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error //perm:write // ClientUnimport removes references to the specified file from filestore - //ClientUnimport(path string) + // ClientUnimport(path string) // ClientListImports lists imported files and their root CIDs ClientListImports(ctx context.Context) ([]Import, error) //perm:write - //ClientListAsks() []Ask + // ClientListAsks() []Ask // MethodGroup: State // The State methods are used to query, inspect, and interact with chain state. @@ -639,14 +639,14 @@ type FullNode interface { // It takes the following params: , , MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) //perm:read - //MsigGetPending returns pending transactions for the given multisig - //wallet. Once pending transactions are fully approved, they will no longer - //appear here. + // MsigGetPending returns pending transactions for the given multisig + // wallet. Once pending transactions are fully approved, they will no longer + // appear here. MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error) //perm:read // MsigCreate creates a multisig wallet // It takes the following params: , , - //, , + // , , MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (*MessagePrototype, error) //perm:sign // MsigPropose proposes a multisig message @@ -764,31 +764,31 @@ type FullNode interface { // EthAccounts will always return [] since we don't expect Lotus to manage private keys EthAccounts(ctx context.Context) ([]EthAddress, error) //perm:read // EthBlockNumber returns the height of the latest (heaviest) TipSet - EthBlockNumber(ctx context.Context) (EthInt, error) //perm:read + EthBlockNumber(ctx context.Context) (EthUint64, error) //perm:read // EthGetBlockTransactionCountByNumber returns the number of messages in the TipSet - EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum EthInt) (EthInt, error) //perm:read + EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum EthUint64) (EthUint64, error) //perm:read // EthGetBlockTransactionCountByHash returns the number of messages in the TipSet - EthGetBlockTransactionCountByHash(ctx context.Context, blkHash EthHash) (EthInt, error) //perm:read + EthGetBlockTransactionCountByHash(ctx context.Context, blkHash EthHash) (EthUint64, error) //perm:read - EthGetBlockByHash(ctx context.Context, blkHash EthHash, fullTxInfo bool) (EthBlock, error) //perm:read - EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (EthBlock, error) //perm:read - EthGetTransactionByHash(ctx context.Context, txHash *EthHash) (*EthTx, error) //perm:read - EthGetTransactionCount(ctx context.Context, sender EthAddress, blkOpt string) (EthInt, error) //perm:read - EthGetTransactionReceipt(ctx context.Context, txHash EthHash) (*EthTxReceipt, error) //perm:read - EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash EthHash, txIndex EthInt) (EthTx, error) //perm:read - EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum EthInt, txIndex EthInt) (EthTx, error) //perm:read + EthGetBlockByHash(ctx context.Context, blkHash EthHash, fullTxInfo bool) (EthBlock, error) //perm:read + EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (EthBlock, error) //perm:read + EthGetTransactionByHash(ctx context.Context, txHash *EthHash) (*EthTx, error) //perm:read + EthGetTransactionCount(ctx context.Context, sender EthAddress, blkOpt string) (EthUint64, error) //perm:read + EthGetTransactionReceipt(ctx context.Context, txHash EthHash) (*EthTxReceipt, error) //perm:read + EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash EthHash, txIndex EthUint64) (EthTx, error) //perm:read + EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum EthUint64, txIndex EthUint64) (EthTx, error) //perm:read - EthGetCode(ctx context.Context, address EthAddress) (string, error) //perm:read - EthGetStorageAt(ctx context.Context, address EthAddress, position EthInt, blkParam string) (string, error) //perm:read - EthGetBalance(ctx context.Context, address EthAddress, blkParam string) (EthBigInt, error) //perm:read - EthChainId(ctx context.Context) (EthInt, error) //perm:read - NetVersion(ctx context.Context) (string, error) //perm:read - NetListening(ctx context.Context) (bool, error) //perm:read - EthProtocolVersion(ctx context.Context) (EthInt, error) //perm:read - EthGasPrice(ctx context.Context) (EthBigInt, error) //perm:read + EthGetCode(ctx context.Context, address EthAddress) (EthBytes, error) //perm:read + EthGetStorageAt(ctx context.Context, address EthAddress, position EthBytes, blkParam string) (EthBytes, error) //perm:read + EthGetBalance(ctx context.Context, address EthAddress, blkParam string) (EthBigInt, error) //perm:read + EthChainId(ctx context.Context) (EthUint64, error) //perm:read + NetVersion(ctx context.Context) (string, error) //perm:read + NetListening(ctx context.Context) (bool, error) //perm:read + EthProtocolVersion(ctx context.Context) (EthUint64, error) //perm:read + EthGasPrice(ctx context.Context) (EthBigInt, error) //perm:read EthMaxPriorityFeePerGas(ctx context.Context) (EthBigInt, error) //perm:read - EthEstimateGas(ctx context.Context, tx EthCall) (EthInt, error) //perm:read + EthEstimateGas(ctx context.Context, tx EthCall) (EthUint64, error) //perm:read EthCall(ctx context.Context, tx EthCall, blkParam string) (EthBytes, error) //perm:read EthSendRawTransaction(ctx context.Context, rawTx EthBytes) (EthHash, error) //perm:read diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index a6fc278da..afd9dbc8f 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -363,7 +363,8 @@ func init() { }, }) - ethint := api.EthInt(5) + ethint := api.EthUint64(5) + addExample(ethint) addExample(ðint) ethaddr, _ := api.EthAddressFromHex("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031") @@ -444,7 +445,7 @@ func ExampleValue(method string, t, parent reflect.Type) interface{} { case reflect.Ptr: if t.Elem().Kind() == reflect.Struct { es := exampleStruct(method, t.Elem(), t) - //ExampleValues[t] = es + // ExampleValues[t] = es return es } case reflect.Interface: diff --git a/api/eth_transactions.go b/api/eth_transactions.go index 333f12692..5dc630af6 100644 --- a/api/eth_transactions.go +++ b/api/eth_transactions.go @@ -7,7 +7,7 @@ import ( mathbig "math/big" "golang.org/x/crypto/sha3" - xerrors "golang.org/x/xerrors" + "golang.org/x/xerrors" "github.com/filecoin-project/go-address" gocrypto "github.com/filecoin-project/go-crypto" @@ -23,19 +23,19 @@ import ( ) type EthTx struct { - ChainID EthInt `json:"chainId"` - Nonce EthInt `json:"nonce"` + ChainID EthUint64 `json:"chainId"` + Nonce EthUint64 `json:"nonce"` Hash EthHash `json:"hash"` BlockHash EthHash `json:"blockHash"` - BlockNumber EthInt `json:"blockNumber"` - TransactionIndex EthInt `json:"transacionIndex"` + BlockNumber EthUint64 `json:"blockNumber"` + TransactionIndex EthUint64 `json:"transacionIndex"` From EthAddress `json:"from"` To *EthAddress `json:"to"` Value EthBigInt `json:"value"` - Type EthInt `json:"type"` + Type EthUint64 `json:"type"` Input EthBytes `json:"input"` - Gas EthInt `json:"gas"` - GasLimit *EthInt `json:"gasLimit,omitempty"` + Gas EthUint64 `json:"gas"` + GasLimit *EthUint64 `json:"gasLimit,omitempty"` MaxFeePerGas EthBigInt `json:"maxFeePerGas"` MaxPriorityFeePerGas EthBigInt `json:"maxPriorityFeePerGas"` V EthBytes `json:"v"` @@ -436,7 +436,7 @@ func parseInt(v interface{}) (int, error) { var value int64 r := bytes.NewReader(append(make([]byte, 8-len(data)), data...)) if err := binary.Read(r, binary.BigEndian, &value); err != nil { - return 0, xerrors.Errorf("cannot parse interface to EthInt: %w", err) + return 0, xerrors.Errorf("cannot parse interface to EthUint64: %w", err) } return int(value), nil } diff --git a/api/eth_types.go b/api/eth_types.go index 2099e2344..f476f60a0 100644 --- a/api/eth_types.go +++ b/api/eth_types.go @@ -21,25 +21,25 @@ import ( "github.com/filecoin-project/lotus/build" ) -type EthInt int64 +type EthUint64 uint64 -func (e EthInt) MarshalJSON() ([]byte, error) { +func (e EthUint64) MarshalJSON() ([]byte, error) { if e == 0 { return json.Marshal("0x0") } return json.Marshal(fmt.Sprintf("0x%x", e)) } -func (e *EthInt) UnmarshalJSON(b []byte) error { +func (e *EthUint64) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } - parsedInt, err := strconv.ParseInt(strings.Replace(s, "0x", "", -1), 16, 64) + parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), 16, 64) if err != nil { return err } - eint := EthInt(parsedInt) + eint := EthUint64(parsedInt) *e = eint return nil } @@ -116,16 +116,16 @@ type EthBlock struct { TransactionsRoot EthHash `json:"transactionsRoot"` ReceiptsRoot EthHash `json:"receiptsRoot"` // TODO: include LogsBloom - Difficulty EthInt `json:"difficulty"` - Number EthInt `json:"number"` - GasLimit EthInt `json:"gasLimit"` - GasUsed EthInt `json:"gasUsed"` - Timestamp EthInt `json:"timestamp"` + Difficulty EthUint64 `json:"difficulty"` + Number EthUint64 `json:"number"` + GasLimit EthUint64 `json:"gasLimit"` + GasUsed EthUint64 `json:"gasUsed"` + Timestamp EthUint64 `json:"timestamp"` Extradata []byte `json:"extraData"` MixHash EthHash `json:"mixHash"` Nonce EthNonce `json:"nonce"` BaseFeePerGas EthBigInt `json:"baseFeePerGas"` - Size EthInt `json:"size"` + Size EthUint64 `json:"size"` // can be []EthTx or []string depending on query params Transactions []interface{} `json:"transactions"` Uncles []EthHash `json:"uncles"` @@ -133,7 +133,7 @@ type EthBlock struct { var ( EmptyEthHash = EthHash{} - EmptyEthInt = EthInt(0) + EmptyEthInt = EthUint64(0) EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0} ) @@ -147,7 +147,7 @@ func NewEthBlock() EthBlock { Extradata: []byte{}, MixHash: EmptyEthHash, Nonce: EmptyEthNonce, - GasLimit: EthInt(build.BlockGasLimit), // TODO we map Ethereum blocks to Filecoin tipsets; this is inconsistent. + GasLimit: EthUint64(build.BlockGasLimit), // TODO we map Ethereum blocks to Filecoin tipsets; this is inconsistent. Uncles: []EthHash{}, Transactions: []interface{}{}, } @@ -156,7 +156,7 @@ func NewEthBlock() EthBlock { type EthCall struct { From EthAddress `json:"from"` To *EthAddress `json:"to"` - Gas EthInt `json:"gas"` + Gas EthUint64 `json:"gas"` GasPrice EthBigInt `json:"gasPrice"` Value EthBigInt `json:"value"` Data EthBytes `json:"data"` @@ -175,18 +175,18 @@ func (c *EthCall) UnmarshalJSON(b []byte) error { type EthTxReceipt struct { TransactionHash EthHash `json:"transactionHash"` - TransactionIndex EthInt `json:"transactionIndex"` + TransactionIndex EthUint64 `json:"transactionIndex"` BlockHash EthHash `json:"blockHash"` - BlockNumber EthInt `json:"blockNumber"` + BlockNumber EthUint64 `json:"blockNumber"` From EthAddress `json:"from"` To *EthAddress `json:"to"` // Logs // LogsBloom StateRoot EthHash `json:"root"` - Status EthInt `json:"status"` + Status EthUint64 `json:"status"` ContractAddress *EthAddress `json:"contractAddress"` - CumulativeGasUsed EthInt `json:"cumulativeGasUsed"` - GasUsed EthInt `json:"gasUsed"` + CumulativeGasUsed EthUint64 `json:"cumulativeGasUsed"` + GasUsed EthUint64 `json:"gasUsed"` EffectiveGasPrice EthBigInt `json:"effectiveGasPrice"` LogsBloom EthBytes `json:"logsBloom"` Logs []string `json:"logs"` @@ -218,7 +218,7 @@ func NewEthTxReceipt(tx EthTx, lookup *MsgLookup, replay *InvocResult) (EthTxRec receipt.Status = 0 } - receipt.GasUsed = EthInt(lookup.Receipt.GasUsed) + receipt.GasUsed = EthUint64(lookup.Receipt.GasUsed) // TODO: handle CumulativeGasUsed receipt.CumulativeGasUsed = EmptyEthInt diff --git a/api/eth_types_test.go b/api/eth_types_test.go index 9e9759dd6..2a5a8b867 100644 --- a/api/eth_types_test.go +++ b/api/eth_types_test.go @@ -19,26 +19,26 @@ type TestCase struct { func TestEthIntMarshalJSON(t *testing.T) { // https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding testcases := []TestCase{ - {EthInt(0), []byte("\"0x0\"")}, - {EthInt(65), []byte("\"0x41\"")}, - {EthInt(1024), []byte("\"0x400\"")}, + {EthUint64(0), []byte("\"0x0\"")}, + {EthUint64(65), []byte("\"0x41\"")}, + {EthUint64(1024), []byte("\"0x400\"")}, } for _, tc := range testcases { - j, err := tc.Input.(EthInt).MarshalJSON() + j, err := tc.Input.(EthUint64).MarshalJSON() require.Nil(t, err) require.Equal(t, j, tc.Output) } } func TestEthIntUnmarshalJSON(t *testing.T) { testcases := []TestCase{ - {[]byte("\"0x0\""), EthInt(0)}, - {[]byte("\"0x41\""), EthInt(65)}, - {[]byte("\"0x400\""), EthInt(1024)}, + {[]byte("\"0x0\""), EthUint64(0)}, + {[]byte("\"0x41\""), EthUint64(65)}, + {[]byte("\"0x400\""), EthUint64(1024)}, } for _, tc := range testcases { - var i EthInt + var i EthUint64 err := i.UnmarshalJSON(tc.Input.([]byte)) require.Nil(t, err) require.Equal(t, i, tc.Output) diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 2483b1ff8..4a48d4681 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -937,10 +937,10 @@ func (mr *MockFullNodeMockRecorder) EthAccounts(arg0 interface{}) *gomock.Call { } // EthBlockNumber mocks base method. -func (m *MockFullNode) EthBlockNumber(arg0 context.Context) (api.EthInt, error) { +func (m *MockFullNode) EthBlockNumber(arg0 context.Context) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthBlockNumber", arg0) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -967,10 +967,10 @@ func (mr *MockFullNodeMockRecorder) EthCall(arg0, arg1, arg2 interface{}) *gomoc } // EthChainId mocks base method. -func (m *MockFullNode) EthChainId(arg0 context.Context) (api.EthInt, error) { +func (m *MockFullNode) EthChainId(arg0 context.Context) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthChainId", arg0) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -982,10 +982,10 @@ func (mr *MockFullNodeMockRecorder) EthChainId(arg0 interface{}) *gomock.Call { } // EthEstimateGas mocks base method. -func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 api.EthCall) (api.EthInt, error) { +func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 api.EthCall) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1057,10 +1057,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockByNumber(arg0, arg1, arg2 interfa } // EthGetBlockTransactionCountByHash mocks base method. -func (m *MockFullNode) EthGetBlockTransactionCountByHash(arg0 context.Context, arg1 api.EthHash) (api.EthInt, error) { +func (m *MockFullNode) EthGetBlockTransactionCountByHash(arg0 context.Context, arg1 api.EthHash) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBlockTransactionCountByHash", arg0, arg1) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1072,10 +1072,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockTransactionCountByHash(arg0, arg1 } // EthGetBlockTransactionCountByNumber mocks base method. -func (m *MockFullNode) EthGetBlockTransactionCountByNumber(arg0 context.Context, arg1 api.EthInt) (api.EthInt, error) { +func (m *MockFullNode) EthGetBlockTransactionCountByNumber(arg0 context.Context, arg1 api.EthUint64) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetBlockTransactionCountByNumber", arg0, arg1) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1087,10 +1087,10 @@ func (mr *MockFullNodeMockRecorder) EthGetBlockTransactionCountByNumber(arg0, ar } // EthGetCode mocks base method. -func (m *MockFullNode) EthGetCode(arg0 context.Context, arg1 api.EthAddress) (string, error) { +func (m *MockFullNode) EthGetCode(arg0 context.Context, arg1 api.EthAddress) (api.EthBytes, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetCode", arg0, arg1) - ret0, _ := ret[0].(string) + ret0, _ := ret[0].(api.EthBytes) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1102,10 +1102,10 @@ func (mr *MockFullNodeMockRecorder) EthGetCode(arg0, arg1 interface{}) *gomock.C } // EthGetStorageAt mocks base method. -func (m *MockFullNode) EthGetStorageAt(arg0 context.Context, arg1 api.EthAddress, arg2 api.EthInt, arg3 string) (string, error) { +func (m *MockFullNode) EthGetStorageAt(arg0 context.Context, arg1 api.EthAddress, arg2 api.EthBytes, arg3 string) (api.EthBytes, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetStorageAt", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(string) + ret0, _ := ret[0].(api.EthBytes) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1117,7 +1117,7 @@ func (mr *MockFullNodeMockRecorder) EthGetStorageAt(arg0, arg1, arg2, arg3 inter } // EthGetTransactionByBlockHashAndIndex mocks base method. -func (m *MockFullNode) EthGetTransactionByBlockHashAndIndex(arg0 context.Context, arg1 api.EthHash, arg2 api.EthInt) (api.EthTx, error) { +func (m *MockFullNode) EthGetTransactionByBlockHashAndIndex(arg0 context.Context, arg1 api.EthHash, arg2 api.EthUint64) (api.EthTx, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionByBlockHashAndIndex", arg0, arg1, arg2) ret0, _ := ret[0].(api.EthTx) @@ -1132,7 +1132,7 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionByBlockHashAndIndex(arg0, a } // EthGetTransactionByBlockNumberAndIndex mocks base method. -func (m *MockFullNode) EthGetTransactionByBlockNumberAndIndex(arg0 context.Context, arg1, arg2 api.EthInt) (api.EthTx, error) { +func (m *MockFullNode) EthGetTransactionByBlockNumberAndIndex(arg0 context.Context, arg1, arg2 api.EthUint64) (api.EthTx, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionByBlockNumberAndIndex", arg0, arg1, arg2) ret0, _ := ret[0].(api.EthTx) @@ -1162,10 +1162,10 @@ func (mr *MockFullNodeMockRecorder) EthGetTransactionByHash(arg0, arg1 interface } // EthGetTransactionCount mocks base method. -func (m *MockFullNode) EthGetTransactionCount(arg0 context.Context, arg1 api.EthAddress, arg2 string) (api.EthInt, error) { +func (m *MockFullNode) EthGetTransactionCount(arg0 context.Context, arg1 api.EthAddress, arg2 string) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthGetTransactionCount", arg0, arg1, arg2) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1207,10 +1207,10 @@ func (mr *MockFullNodeMockRecorder) EthMaxPriorityFeePerGas(arg0 interface{}) *g } // EthProtocolVersion mocks base method. -func (m *MockFullNode) EthProtocolVersion(arg0 context.Context) (api.EthInt, error) { +func (m *MockFullNode) EthProtocolVersion(arg0 context.Context) (api.EthUint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EthProtocolVersion", arg0) - ret0, _ := ret[0].(api.EthInt) + ret0, _ := ret[0].(api.EthUint64) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 20fcf92ff..d8d0d224d 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -17,8 +17,6 @@ import ( "github.com/libp2p/go-libp2p/core/protocol" "golang.org/x/xerrors" - "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -224,13 +222,13 @@ type FullNodeStruct struct { EthAccounts func(p0 context.Context) ([]EthAddress, error) `perm:"read"` - EthBlockNumber func(p0 context.Context) (EthInt, error) `perm:"read"` + EthBlockNumber func(p0 context.Context) (EthUint64, error) `perm:"read"` EthCall func(p0 context.Context, p1 EthCall, p2 string) (EthBytes, error) `perm:"read"` - EthChainId func(p0 context.Context) (EthInt, error) `perm:"read"` + EthChainId func(p0 context.Context) (EthUint64, error) `perm:"read"` - EthEstimateGas func(p0 context.Context, p1 EthCall) (EthInt, error) `perm:"read"` + EthEstimateGas func(p0 context.Context, p1 EthCall) (EthUint64, error) `perm:"read"` EthGasPrice func(p0 context.Context) (EthBigInt, error) `perm:"read"` @@ -240,27 +238,27 @@ type FullNodeStruct struct { EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (EthBlock, error) `perm:"read"` - EthGetBlockTransactionCountByHash func(p0 context.Context, p1 EthHash) (EthInt, error) `perm:"read"` + EthGetBlockTransactionCountByHash func(p0 context.Context, p1 EthHash) (EthUint64, error) `perm:"read"` - EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 EthInt) (EthInt, error) `perm:"read"` + EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 EthUint64) (EthUint64, error) `perm:"read"` - EthGetCode func(p0 context.Context, p1 EthAddress) (string, error) `perm:"read"` + EthGetCode func(p0 context.Context, p1 EthAddress) (EthBytes, error) `perm:"read"` - EthGetStorageAt func(p0 context.Context, p1 EthAddress, p2 EthInt, p3 string) (string, error) `perm:"read"` + EthGetStorageAt func(p0 context.Context, p1 EthAddress, p2 EthBytes, p3 string) (EthBytes, error) `perm:"read"` - EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 EthHash, p2 EthInt) (EthTx, error) `perm:"read"` + EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 EthHash, p2 EthUint64) (EthTx, error) `perm:"read"` - EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 EthInt, p2 EthInt) (EthTx, error) `perm:"read"` + EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 EthUint64, p2 EthUint64) (EthTx, error) `perm:"read"` EthGetTransactionByHash func(p0 context.Context, p1 *EthHash) (*EthTx, error) `perm:"read"` - EthGetTransactionCount func(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) `perm:"read"` + EthGetTransactionCount func(p0 context.Context, p1 EthAddress, p2 string) (EthUint64, error) `perm:"read"` EthGetTransactionReceipt func(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) `perm:"read"` EthMaxPriorityFeePerGas func(p0 context.Context) (EthBigInt, error) `perm:"read"` - EthProtocolVersion func(p0 context.Context) (EthInt, error) `perm:"read"` + EthProtocolVersion func(p0 context.Context) (EthUint64, error) `perm:"read"` EthSendRawTransaction func(p0 context.Context, p1 EthBytes) (EthHash, error) `perm:"read"` @@ -1852,15 +1850,15 @@ func (s *FullNodeStub) EthAccounts(p0 context.Context) ([]EthAddress, error) { return *new([]EthAddress), ErrNotSupported } -func (s *FullNodeStruct) EthBlockNumber(p0 context.Context) (EthInt, error) { +func (s *FullNodeStruct) EthBlockNumber(p0 context.Context) (EthUint64, error) { if s.Internal.EthBlockNumber == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthBlockNumber(p0) } -func (s *FullNodeStub) EthBlockNumber(p0 context.Context) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthBlockNumber(p0 context.Context) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } func (s *FullNodeStruct) EthCall(p0 context.Context, p1 EthCall, p2 string) (EthBytes, error) { @@ -1874,26 +1872,26 @@ func (s *FullNodeStub) EthCall(p0 context.Context, p1 EthCall, p2 string) (EthBy return *new(EthBytes), ErrNotSupported } -func (s *FullNodeStruct) EthChainId(p0 context.Context) (EthInt, error) { +func (s *FullNodeStruct) EthChainId(p0 context.Context) (EthUint64, error) { if s.Internal.EthChainId == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthChainId(p0) } -func (s *FullNodeStub) EthChainId(p0 context.Context) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthChainId(p0 context.Context) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 EthCall) (EthInt, error) { +func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 EthCall) (EthUint64, error) { if s.Internal.EthEstimateGas == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthEstimateGas(p0, p1) } -func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 EthCall) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 EthCall) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } func (s *FullNodeStruct) EthGasPrice(p0 context.Context) (EthBigInt, error) { @@ -1940,69 +1938,69 @@ func (s *FullNodeStub) EthGetBlockByNumber(p0 context.Context, p1 string, p2 boo return *new(EthBlock), ErrNotSupported } -func (s *FullNodeStruct) EthGetBlockTransactionCountByHash(p0 context.Context, p1 EthHash) (EthInt, error) { +func (s *FullNodeStruct) EthGetBlockTransactionCountByHash(p0 context.Context, p1 EthHash) (EthUint64, error) { if s.Internal.EthGetBlockTransactionCountByHash == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthGetBlockTransactionCountByHash(p0, p1) } -func (s *FullNodeStub) EthGetBlockTransactionCountByHash(p0 context.Context, p1 EthHash) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthGetBlockTransactionCountByHash(p0 context.Context, p1 EthHash) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 EthInt) (EthInt, error) { +func (s *FullNodeStruct) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 EthUint64) (EthUint64, error) { if s.Internal.EthGetBlockTransactionCountByNumber == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthGetBlockTransactionCountByNumber(p0, p1) } -func (s *FullNodeStub) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 EthInt) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 EthUint64) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } -func (s *FullNodeStruct) EthGetCode(p0 context.Context, p1 EthAddress) (string, error) { +func (s *FullNodeStruct) EthGetCode(p0 context.Context, p1 EthAddress) (EthBytes, error) { if s.Internal.EthGetCode == nil { - return "", ErrNotSupported + return *new(EthBytes), ErrNotSupported } return s.Internal.EthGetCode(p0, p1) } -func (s *FullNodeStub) EthGetCode(p0 context.Context, p1 EthAddress) (string, error) { - return "", ErrNotSupported +func (s *FullNodeStub) EthGetCode(p0 context.Context, p1 EthAddress) (EthBytes, error) { + return *new(EthBytes), ErrNotSupported } -func (s *FullNodeStruct) EthGetStorageAt(p0 context.Context, p1 EthAddress, p2 EthInt, p3 string) (string, error) { +func (s *FullNodeStruct) EthGetStorageAt(p0 context.Context, p1 EthAddress, p2 EthBytes, p3 string) (EthBytes, error) { if s.Internal.EthGetStorageAt == nil { - return "", ErrNotSupported + return *new(EthBytes), ErrNotSupported } return s.Internal.EthGetStorageAt(p0, p1, p2, p3) } -func (s *FullNodeStub) EthGetStorageAt(p0 context.Context, p1 EthAddress, p2 EthInt, p3 string) (string, error) { - return "", ErrNotSupported +func (s *FullNodeStub) EthGetStorageAt(p0 context.Context, p1 EthAddress, p2 EthBytes, p3 string) (EthBytes, error) { + return *new(EthBytes), ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 EthHash, p2 EthInt) (EthTx, error) { +func (s *FullNodeStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 EthHash, p2 EthUint64) (EthTx, error) { if s.Internal.EthGetTransactionByBlockHashAndIndex == nil { return *new(EthTx), ErrNotSupported } return s.Internal.EthGetTransactionByBlockHashAndIndex(p0, p1, p2) } -func (s *FullNodeStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 EthHash, p2 EthInt) (EthTx, error) { +func (s *FullNodeStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 EthHash, p2 EthUint64) (EthTx, error) { return *new(EthTx), ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 EthInt, p2 EthInt) (EthTx, error) { +func (s *FullNodeStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 EthUint64, p2 EthUint64) (EthTx, error) { if s.Internal.EthGetTransactionByBlockNumberAndIndex == nil { return *new(EthTx), ErrNotSupported } return s.Internal.EthGetTransactionByBlockNumberAndIndex(p0, p1, p2) } -func (s *FullNodeStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 EthInt, p2 EthInt) (EthTx, error) { +func (s *FullNodeStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 EthUint64, p2 EthUint64) (EthTx, error) { return *new(EthTx), ErrNotSupported } @@ -2017,15 +2015,15 @@ func (s *FullNodeStub) EthGetTransactionByHash(p0 context.Context, p1 *EthHash) return nil, ErrNotSupported } -func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) { +func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthUint64, error) { if s.Internal.EthGetTransactionCount == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthGetTransactionCount(p0, p1, p2) } -func (s *FullNodeStub) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthGetTransactionCount(p0 context.Context, p1 EthAddress, p2 string) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } func (s *FullNodeStruct) EthGetTransactionReceipt(p0 context.Context, p1 EthHash) (*EthTxReceipt, error) { @@ -2050,15 +2048,15 @@ func (s *FullNodeStub) EthMaxPriorityFeePerGas(p0 context.Context) (EthBigInt, e return *new(EthBigInt), ErrNotSupported } -func (s *FullNodeStruct) EthProtocolVersion(p0 context.Context) (EthInt, error) { +func (s *FullNodeStruct) EthProtocolVersion(p0 context.Context) (EthUint64, error) { if s.Internal.EthProtocolVersion == nil { - return *new(EthInt), ErrNotSupported + return *new(EthUint64), ErrNotSupported } return s.Internal.EthProtocolVersion(p0) } -func (s *FullNodeStub) EthProtocolVersion(p0 context.Context) (EthInt, error) { - return *new(EthInt), ErrNotSupported +func (s *FullNodeStub) EthProtocolVersion(p0 context.Context) (EthUint64, error) { + return *new(EthUint64), ErrNotSupported } func (s *FullNodeStruct) EthSendRawTransaction(p0 context.Context, p1 EthBytes) (EthHash, error) { diff --git a/api/v0api/full.go b/api/v0api/full.go index ca1371794..87d5cba4e 100644 --- a/api/v0api/full.go +++ b/api/v0api/full.go @@ -141,7 +141,7 @@ type FullNode interface { // ChainGetPath returns a set of revert/apply operations needed to get from // one tipset to another, for example: - //``` + // ``` // to // ^ // from tAA @@ -150,7 +150,7 @@ type FullNode interface { // ^---*--^ // ^ // tRR - //``` + // ``` // Would return `[revert(tBA), apply(tAB), apply(tAA)]` ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*api.HeadChange, error) //perm:read @@ -367,12 +367,12 @@ type FullNode interface { ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error //perm:write // ClientUnimport removes references to the specified file from filestore - //ClientUnimport(path string) + // ClientUnimport(path string) // ClientListImports lists imported files and their root CIDs ClientListImports(ctx context.Context) ([]api.Import, error) //perm:write - //ClientListAsks() []Ask + // ClientListAsks() []Ask // MethodGroup: State // The State methods are used to query, inspect, and interact with chain state. @@ -641,14 +641,14 @@ type FullNode interface { // It takes the following params: , , MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) //perm:read - //MsigGetPending returns pending transactions for the given multisig - //wallet. Once pending transactions are fully approved, they will no longer - //appear here. + // MsigGetPending returns pending transactions for the given multisig + // wallet. Once pending transactions are fully approved, they will no longer + // appear here. MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error) //perm:read // MsigCreate creates a multisig wallet // It takes the following params: , , - //, , + // , , MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) //perm:sign // MsigPropose proposes a multisig message // It takes the following params: , , , diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 126b61e1f..7c585d008 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -2376,7 +2376,7 @@ Inputs: ] ``` -Response: `"string value"` +Response: `"0x07"` ### EthGetStorageAt @@ -2387,12 +2387,12 @@ Inputs: ```json [ "0x0707070707070707070707070707070707070707", - "0x5", + "0x07", "string value" ] ``` -Response: `"string value"` +Response: `"0x07"` ### EthGetTransactionByBlockHashAndIndex diff --git a/go.sum b/go.sum index d4d20669f..7ec086403 100644 --- a/go.sum +++ b/go.sum @@ -347,6 +347,8 @@ github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27 github.com/filecoin-project/go-state-types v0.9.10-0.20221109071515-5536f160fe27/go.mod h1:7ty480tvttEAqWKywhAaDCElk7ksTqEXtXWAzTSdEKo= github.com/filecoin-project/go-state-types v0.1.11-0.20220923222823-af1291888ee8 h1:iu/6jTVXyZDN/RBh2M2+K0i1ML+4DxydDJ/Bm7BjhjA= github.com/filecoin-project/go-state-types v0.1.11-0.20220923222823-af1291888ee8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= +github.com/filecoin-project/go-state-types v0.1.11-0.20220929211033-a2339f216f21 h1:9asw8iXwZES+/kULEPCmbcmE95QVfE/5BIuYsbFMQZc= +github.com/filecoin-project/go-state-types v0.1.11-0.20220929211033-a2339f216f21/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index d54536606..6a5f0ff76 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -1,10 +1,13 @@ package full import ( + "bytes" "context" "fmt" "strconv" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "go.uber.org/fx" "golang.org/x/xerrors" @@ -14,7 +17,6 @@ import ( builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin/v8/evm" init8 "github.com/filecoin-project/go-state-types/builtin/v8/init" - "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/lotus/api" @@ -29,26 +31,26 @@ import ( ) type EthModuleAPI interface { - EthBlockNumber(ctx context.Context) (api.EthInt, error) + EthBlockNumber(ctx context.Context) (api.EthUint64, error) EthAccounts(ctx context.Context) ([]api.EthAddress, error) - EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthInt) (api.EthInt, error) - EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthInt, error) + EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) + EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) EthGetTransactionByHash(ctx context.Context, txHash *api.EthHash) (*api.EthTx, error) - EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthInt, error) + EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkOpt string) (api.EthUint64, error) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) - EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthInt) (api.EthTx, error) - EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthInt, txIndex api.EthInt) (api.EthTx, error) - EthGetCode(ctx context.Context, address api.EthAddress) (string, error) - EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthInt, blkParam string) (string, error) + EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) + EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) + EthGetCode(ctx context.Context, address api.EthAddress) (api.EthBytes, error) + EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) - EthChainId(ctx context.Context) (api.EthInt, error) + EthChainId(ctx context.Context) (api.EthUint64, error) NetVersion(ctx context.Context) (string, error) NetListening(ctx context.Context) (bool, error) - EthProtocolVersion(ctx context.Context) (api.EthInt, error) + EthProtocolVersion(ctx context.Context) (api.EthUint64, error) EthGasPrice(ctx context.Context) (api.EthBigInt, error) - EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthInt, error) + EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) EthSendRawTransaction(ctx context.Context, rawTx api.EthBytes) (api.EthHash, error) @@ -85,9 +87,9 @@ func (a *EthModule) StateNetworkName(ctx context.Context) (dtypes.NetworkName, e return stmgr.GetNetworkName(ctx, a.StateManager, a.Chain.GetHeaviestTipSet().ParentState()) } -func (a *EthModule) EthBlockNumber(context.Context) (api.EthInt, error) { +func (a *EthModule) EthBlockNumber(context.Context) (api.EthUint64, error) { height := a.Chain.GetHeaviestTipSet().Height() - return api.EthInt(height), nil + return api.EthUint64(height), nil } func (a *EthModule) EthAccounts(context.Context) ([]api.EthAddress, error) { @@ -109,23 +111,23 @@ func (a *EthModule) countTipsetMsgs(ctx context.Context, ts *types.TipSet) (int, return count, nil } -func (a *EthModule) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthInt) (api.EthInt, error) { +func (a *EthModule) EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum api.EthUint64) (api.EthUint64, error) { ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(blkNum), nil, false) if err != nil { - return api.EthInt(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) + return api.EthUint64(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) } count, err := a.countTipsetMsgs(ctx, ts) - return api.EthInt(count), err + return api.EthUint64(count), err } -func (a *EthModule) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthInt, error) { +func (a *EthModule) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash api.EthHash) (api.EthUint64, error) { ts, err := a.Chain.GetTipSetByCid(ctx, blkHash.ToCid()) if err != nil { - return api.EthInt(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) + return api.EthUint64(0), xerrors.Errorf("error loading tipset %s: %w", ts, err) } count, err := a.countTipsetMsgs(ctx, ts) - return api.EthInt(count), err + return api.EthUint64(count), err } func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, fullTxInfo bool) (api.EthBlock, error) { @@ -137,10 +139,10 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash api.EthHash, } func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (api.EthBlock, error) { - var num api.EthInt + var num api.EthUint64 err := num.UnmarshalJSON([]byte(`"` + blkNum + `"`)) if err != nil { - num = api.EthInt(a.Chain.GetHeaviestTipSet().Height()) + num = api.EthUint64(a.Chain.GetHeaviestTipSet().Height()) } ts, err := a.Chain.GetTipsetByHeight(ctx, abi.ChainEpoch(num), nil, false) @@ -170,16 +172,16 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *api.Eth return &tx, nil } -func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkParam string) (api.EthInt, error) { +func (a *EthModule) EthGetTransactionCount(ctx context.Context, sender api.EthAddress, blkParam string) (api.EthUint64, error) { addr, err := sender.ToFilecoinAddress() if err != nil { - return api.EthInt(0), err + return api.EthUint64(0), err } nonce, err := a.Mpool.GetNonce(ctx, addr, types.EmptyTSK) if err != nil { - return api.EthInt(0), err + return api.EthUint64(0), err } - return api.EthInt(nonce), nil + return api.EthUint64(nonce), nil } func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.EthHash) (*api.EthTxReceipt, error) { @@ -207,21 +209,149 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash api.Eth return &receipt, nil } -func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthInt) (api.EthTx, error) { +func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash api.EthHash, txIndex api.EthUint64) (api.EthTx, error) { return api.EthTx{}, nil } -func (a *EthModule) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthInt, txIndex api.EthInt) (api.EthTx, error) { +func (a *EthModule) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum api.EthUint64, txIndex api.EthUint64) (api.EthTx, error) { return api.EthTx{}, nil } // EthGetCode returns string value of the compiled bytecode -func (a *EthModule) EthGetCode(ctx context.Context, address api.EthAddress) (string, error) { - return "", nil +func (a *EthModule) EthGetCode(ctx context.Context, ethAddr api.EthAddress) (api.EthBytes, error) { + to, err := ethAddr.ToFilecoinAddress() + if err != nil { + return nil, xerrors.Errorf("cannot get Filecoin address: %w", err) + } + + // use the system actor as the caller + from, err := address.NewIDAddress(0) + if err != nil { + return nil, fmt.Errorf("failed to construct system sender address: %w", err) + } + msg := &types.Message{ + From: from, + To: to, + Value: big.Zero(), + Method: abi.MethodNum(3), // GetBytecode + Params: nil, + GasLimit: build.BlockGasLimit, + GasFeeCap: big.Zero(), + GasPremium: big.Zero(), + } + + ts := a.Chain.GetHeaviestTipSet() + + // Try calling until we find a height with no migration. + var res *api.InvocResult + for { + res, err = a.StateManager.Call(ctx, msg, ts) + if err != stmgr.ErrExpensiveFork { + break + } + ts, err = a.Chain.GetTipSetFromKey(ctx, ts.Parents()) + if err != nil { + return nil, xerrors.Errorf("getting parent tipset: %w", err) + } + } + + if err != nil { + return nil, xerrors.Errorf("Call failed: %w", err) + } + + if res.MsgRct == nil { + return nil, fmt.Errorf("no message receipt") + } + + if res.MsgRct.ExitCode.IsError() { + return nil, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error) + } + + var bytecodeCid cbg.CborCid + if err := bytecodeCid.UnmarshalCBOR(bytes.NewReader(res.MsgRct.Return)); err != nil { + return nil, fmt.Errorf("failed to decode EVM bytecode CID: %w", err) + } + + blk, err := a.Chain.StateBlockstore().Get(ctx, cid.Cid(bytecodeCid)) + if err != nil { + return nil, fmt.Errorf("failed to get EVM bytecode: %w", err) + } + + return blk.RawData(), nil } -func (a *EthModule) EthGetStorageAt(ctx context.Context, address api.EthAddress, position api.EthInt, blkParam string) (string, error) { - return "", nil +func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr api.EthAddress, position api.EthBytes, blkParam string) (api.EthBytes, error) { + l := len(position) + if l > 32 { + return nil, fmt.Errorf("supplied storage key is too long") + } + + // pad with zero bytes if smaller than 32 bytes + position = append(make([]byte, 32-l, 32-l), position...) + + to, err := ethAddr.ToFilecoinAddress() + if err != nil { + return nil, xerrors.Errorf("cannot get Filecoin address: %w", err) + } + + // use the system actor as the caller + from, err := address.NewIDAddress(0) + if err != nil { + return nil, fmt.Errorf("failed to construct system sender address: %w", err) + } + + // TODO super duper hack (raulk). The EVM runtime actor uses the U256 parameter type in + // GetStorageAtParams, which serializes as a hex-encoded string. It should serialize + // as bytes. We didn't get to fix in time for Iron, so for now we just pass + // through the hex-encoded value passed through the Eth JSON-RPC API, by remarshalling it. + // We don't fix this at origin (builtin-actors) because we are not updating the bundle + // for Iron. + tmp, err := position.MarshalJSON() + if err != nil { + panic(err) + } + params, err := actors.SerializeParams(&evm.GetStorageAtParams{ + StorageKey: tmp[1 : len(tmp)-1], // TODO strip the JSON-encoding quotes -- yuck + }) + if err != nil { + return nil, fmt.Errorf("failed to serialize parameters: %w", err) + } + + msg := &types.Message{ + From: from, + To: to, + Value: big.Zero(), + Method: abi.MethodNum(4), // GetStorageAt + Params: params, + GasLimit: build.BlockGasLimit, + GasFeeCap: big.Zero(), + GasPremium: big.Zero(), + } + + ts := a.Chain.GetHeaviestTipSet() + + // Try calling until we find a height with no migration. + var res *api.InvocResult + for { + res, err = a.StateManager.Call(ctx, msg, ts) + if err != stmgr.ErrExpensiveFork { + break + } + ts, err = a.Chain.GetTipSetFromKey(ctx, ts.Parents()) + if err != nil { + return nil, xerrors.Errorf("getting parent tipset: %w", err) + } + } + + if err != nil { + return nil, xerrors.Errorf("Call failed: %w", err) + } + + if res.MsgRct == nil { + return nil, fmt.Errorf("no message receipt") + } + + return res.MsgRct.Return, nil } func (a *EthModule) EthGetBalance(ctx context.Context, address api.EthAddress, blkParam string) (api.EthBigInt, error) { @@ -238,8 +368,8 @@ func (a *EthModule) EthGetBalance(ctx context.Context, address api.EthAddress, b return api.EthBigInt{Int: actor.Balance.Int}, nil } -func (a *EthModule) EthChainId(ctx context.Context) (api.EthInt, error) { - return api.EthInt(build.Eip155ChainId), nil +func (a *EthModule) EthChainId(ctx context.Context) (api.EthUint64, error) { + return api.EthUint64(build.Eip155ChainId), nil } func (a *EthModule) NetVersion(ctx context.Context) (string, error) { @@ -255,9 +385,9 @@ func (a *EthModule) NetListening(ctx context.Context) (bool, error) { return true, nil } -func (a *EthModule) EthProtocolVersion(ctx context.Context) (api.EthInt, error) { +func (a *EthModule) EthProtocolVersion(ctx context.Context) (api.EthUint64, error) { height := a.Chain.GetHeaviestTipSet().Height() - return api.EthInt(a.StateManager.GetNetworkVersion(ctx, height)), nil + return api.EthUint64(a.StateManager.GetNetworkVersion(ctx, height)), nil } func (a *EthModule) EthMaxPriorityFeePerGas(ctx context.Context) (api.EthBigInt, error) { @@ -393,19 +523,19 @@ func (a *EthModule) applyEvmMsg(ctx context.Context, tx api.EthCall) (*api.Invoc if err != nil { return nil, xerrors.Errorf("CallWithGas failed: %w", err) } - if res.MsgRct.ExitCode != exitcode.Ok { + if res.MsgRct.ExitCode.IsError() { return nil, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error) } return res, nil } -func (a *EthModule) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthInt, error) { +func (a *EthModule) EthEstimateGas(ctx context.Context, tx api.EthCall) (api.EthUint64, error) { invokeResult, err := a.applyEvmMsg(ctx, tx) if err != nil { - return api.EthInt(0), err + return api.EthUint64(0), err } ret := invokeResult.MsgRct.GasUsed - return api.EthInt(ret), nil + return api.EthUint64(ret), nil } func (a *EthModule) EthCall(ctx context.Context, tx api.EthCall, blkParam string) (api.EthBytes, error) { @@ -466,11 +596,11 @@ func (a *EthModule) ethBlockFromFilecoinTipSet(ctx context.Context, ts *types.Ti } } - block.Number = api.EthInt(ts.Height()) + block.Number = api.EthUint64(ts.Height()) block.ParentHash = parentBlkHash - block.Timestamp = api.EthInt(ts.Blocks()[0].Timestamp) + block.Timestamp = api.EthUint64(ts.Blocks()[0].Timestamp) block.BaseFeePerGas = api.EthBigInt{Int: ts.Blocks()[0].ParentBaseFee.Int} - block.GasUsed = api.EthInt(gasUsed) + block.GasUsed = api.EthUint64(gasUsed) return block, nil } @@ -526,15 +656,15 @@ func (a *EthModule) ethTxFromFilecoinMessageLookup(ctx context.Context, msgLooku } tx := api.EthTx{ - ChainID: api.EthInt(build.Eip155ChainId), + ChainID: api.EthUint64(build.Eip155ChainId), Hash: txHash, BlockHash: blkHash, - BlockNumber: api.EthInt(msgLookup.Height), + BlockNumber: api.EthUint64(msgLookup.Height), From: fromEthAddr, To: toAddr, Value: api.EthBigInt(msg.Value), - Type: api.EthInt(2), - Gas: api.EthInt(msg.GasLimit), + Type: api.EthUint64(2), + Gas: api.EthUint64(msg.GasLimit), MaxFeePerGas: api.EthBigInt(msg.GasFeeCap), MaxPriorityFeePerGas: api.EthBigInt(msg.GasPremium), V: api.EthBytes{},