diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 335f1f8c..293d5542 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -42,8 +42,8 @@ func NewPublicEthAPI(cliCtx context.CLIContext, nonceLock *AddrLocker, } // ProtocolVersion returns the supported Ethereum protocol version. -func (e *PublicEthAPI) ProtocolVersion() string { - return version.ProtocolVersion +func (e *PublicEthAPI) ProtocolVersion() hexutil.Uint { + return hexutil.Uint(version.ProtocolVersion) } // Syncing returns whether or not the current node is syncing with other peers. Returns false if not, or a struct @@ -95,16 +95,16 @@ func (e *PublicEthAPI) Accounts() ([]common.Address, error) { } // BlockNumber returns the current block number. -func (e *PublicEthAPI) BlockNumber() *big.Int { +func (e *PublicEthAPI) BlockNumber() (hexutil.Uint64, error) { res, _, err := e.cliCtx.QueryWithData(fmt.Sprintf("custom/%s/blockNumber", types.ModuleName), nil) if err != nil { - fmt.Printf("could not resolve: %s\n", err) - return nil + return hexutil.Uint64(0), err } - var out types.QueryResBlockNumber - e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return out.Number + var qRes uint64 + e.cliCtx.Codec.MustUnmarshalJSON(res, &qRes) + + return hexutil.Uint64(qRes), nil } // GetBalance returns the provided account's balance up to the provided block number. @@ -115,9 +115,10 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum rpc.BlockNumb return nil, err } - var out types.QueryResBalance + var out *big.Int e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return (*hexutil.Big)(out.Balance), nil + + return (*hexutil.Big)(out), nil } // GetStorageAt returns the contract storage at the given address, block number, and key. @@ -128,22 +129,22 @@ func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum return nil, err } - var out types.QueryResStorage + var out []byte e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return out.Value[:], nil + return out, nil } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum rpc.BlockNumber) (hexutil.Uint64, error) { +func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum rpc.BlockNumber) (*hexutil.Uint64, error) { ctx := e.cliCtx.WithHeight(blockNum.Int64()) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/nonce/%s", types.ModuleName, address), nil) if err != nil { - return 0, err + return nil, err } - var out types.QueryResNonce - e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return hexutil.Uint64(out.Nonce), nil + var out *hexutil.Uint64 + e.cliCtx.Codec.MustUnmarshalJSON(res, out) + return out, nil } // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash. @@ -185,9 +186,9 @@ func (e *PublicEthAPI) GetCode(address common.Address, blockNumber rpc.BlockNumb return nil, err } - var out types.QueryResCode + var out []byte e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return out.Code, nil + return out, nil } // Sign signs the provided data using the private key of address via Geth's signature standard. diff --git a/rpc/tester/tester_test.go b/rpc/tester/tester_test.go index f9bdfbef..785b7b25 100644 --- a/rpc/tester/tester_test.go +++ b/rpc/tester/tester_test.go @@ -10,18 +10,19 @@ package tester import ( "bytes" "encoding/json" + "errors" "fmt" - "github.com/cosmos/ethermint/version" - "github.com/cosmos/ethermint/x/evm/types" - "io/ioutil" "math/big" "net/http" "testing" + + "github.com/cosmos/ethermint/version" + "github.com/ethereum/go-ethereum/common/hexutil" ) const ( - host = "127.0.0.1" - port = 1317 + host = "localhost" + port = 8545 addrA = "0xc94770007dda54cF92009BFF0dE90c06F603a09f" addrAStoreKey = 0 ) @@ -35,6 +36,18 @@ type Request struct { Id int `json:"id"` } +type RPCError struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data,omitempty"` +} + +type Response struct { + Error *RPCError `json:"error"` + Id int `json:"id"` + Result json.RawMessage `json:"result,omitempty"` +} + func createRequest(method string, params []string) Request { return Request{ Version: "2.0", @@ -44,86 +57,133 @@ func createRequest(method string, params []string) Request { } } -func call(t *testing.T, method string, params []string, resp interface{}) { +func call(method string, params []string) (*Response, error) { req, err := json.Marshal(createRequest(method, params)) if err != nil { - t.Error(err) + return nil, err } res, err := http.Post(addr, "application/json", bytes.NewBuffer(req)) if err != nil { - t.Error(err) - } - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Error(err) + return nil, err } - err = json.Unmarshal(body, resp) + decoder := json.NewDecoder(res.Body) + var rpcRes *Response + err = decoder.Decode(&rpcRes) if err != nil { - t.Error(err) + return nil, err } + + if rpcRes.Error != nil { + return nil, errors.New(rpcRes.Error.Message) + } + + err = res.Body.Close() + if err != nil { + return nil, err + } + + return rpcRes, nil } func TestEth_protocolVersion(t *testing.T) { - expectedRes := version.ProtocolVersion + expectedRes := hexutil.Uint(version.ProtocolVersion) - res := &types.QueryResProtocolVersion{} - call(t, "eth_protocolVersion", []string{}, res) + rpcRes, err := call("eth_protocolVersion", []string{}) + if err != nil { + t.Fatal(err) + } - t.Logf("Got protocol version: %s\n", res.Version) + var res hexutil.Uint + err = res.UnmarshalJSON(rpcRes.Result) - if res.Version != expectedRes { - t.Errorf("expected: %s got: %s\n", expectedRes, res) + if err != nil { + t.Fatal(err) + } + + t.Logf("Got protocol version: %s\n", res.String()) + + if res != expectedRes { + t.Fatalf("expected: %s got: %s\n", expectedRes.String(), rpcRes.Result) } } func TestEth_blockNumber(t *testing.T) { - res := &types.QueryResBlockNumber{} - call(t, "eth_blockNumber", []string{}, res) - - t.Logf("Got block number: %s\n", res.Number.String()) - - // -1 if x < y, 0 if x == y; where x is res, y is 0 - if res.Number.Cmp(big.NewInt(0)) < 1 { - t.Errorf("Invalid block number got: %v", res) + rpcRes, err := call("eth_blockNumber", []string{}) + if err != nil { + t.Fatal(err) } + var res hexutil.Uint64 + err = res.UnmarshalJSON(rpcRes.Result) + + if err != nil { + t.Fatal(err) + } + + t.Logf("Got block number: %s\n", res.String()) + } func TestEth_GetBalance(t *testing.T) { - //expectedRes := types.QueryResBalance{Balance:} - res := &types.QueryResBalance{} - call(t, "eth_getBalance", []string{addrA, "latest"}, res) + rpcRes, err := call("eth_getBalance", []string{addrA, "0x0"}) + if err != nil { + t.Fatal(err) + return + } - t.Logf("Got balance %s for %s\n", res.Balance.String(), addrA) + var res hexutil.Big + err = res.UnmarshalJSON(rpcRes.Result) + if err != nil { + t.Fatal(err) + } + + t.Logf("Got balance %s for %s\n", res.String(), addrA) // 0 if x == y; where x is res, y is 0 - if res.Balance.ToInt().Cmp(big.NewInt(0)) != 0 { - t.Errorf("expected balance: %d, got: %s", 0, res.Balance.String()) + if res.ToInt().Cmp(big.NewInt(0)) != 0 { + t.Errorf("expected balance: %d, got: %s", 0, res.String()) } + } func TestEth_GetStorageAt(t *testing.T) { - expectedRes := types.QueryResStorage{Value: []byte{}} - res := &types.QueryResStorage{} - call(t, "eth_getStorageAt", []string{addrA, string(addrAStoreKey), "latest"}, res) + expectedRes := hexutil.Bytes{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + rpcRes, err := call("eth_getStorageAt", []string{addrA, string(addrAStoreKey), "0x0"}) + if err != nil { + t.Fatal(err) + } - t.Logf("Got value [%X] for %s with key %X\n", res.Value, addrA, addrAStoreKey) + var storage hexutil.Bytes + err = storage.UnmarshalJSON(rpcRes.Result) - if !bytes.Equal(res.Value, expectedRes.Value) { - t.Errorf("expected: %X got: %X", expectedRes.Value, res.Value) + if err != nil { + t.Fatal(err) + } + + t.Logf("Got value [%X] for %s with key %X\n", storage, addrA, addrAStoreKey) + + if !bytes.Equal(storage, expectedRes) { + t.Errorf("expected: %d (%d bytes) got: %d (%d bytes)", expectedRes, len(expectedRes), storage, len(storage)) } } func TestEth_GetCode(t *testing.T) { - expectedRes := types.QueryResCode{Code: []byte{}} - res := &types.QueryResCode{} - call(t, "eth_getCode", []string{addrA, "latest"}, res) + expectedRes := hexutil.Bytes{} + rpcRes, err := call("eth_getCode", []string{addrA, "0x0"}) + if err != nil { + t.Error(err) + } - t.Logf("Got code [%X] for %s\n", res.Code, addrA) - if !bytes.Equal(expectedRes.Code, res.Code) { - t.Errorf("expected: %X got: %X", expectedRes.Code, res.Code) + var code hexutil.Bytes + err = code.UnmarshalJSON(rpcRes.Result) + + if err != nil { + t.Fatal(err) + } + + t.Logf("Got code [%X] for %s\n", code, addrA) + if !bytes.Equal(expectedRes, code) { + t.Errorf("expected: %X got: %X", expectedRes, code) } } diff --git a/version/version.go b/version/version.go index 015a5b96..f973068f 100644 --- a/version/version.go +++ b/version/version.go @@ -15,7 +15,7 @@ const AppName = "Ethermint" const Version = "0.0.0" // ProtocolVersion is the supported Ethereum protocol version (e.g., Homestead, Olympic, etc.) -const ProtocolVersion = "63" +const ProtocolVersion uint = 63 // GitCommit contains the git SHA1 short hash set by build flags. var GitCommit = "" diff --git a/x/evm/client/cli/query.go b/x/evm/client/cli/query.go index 21c19722..a94ac94c 100644 --- a/x/evm/client/cli/query.go +++ b/x/evm/client/cli/query.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/ethermint/x/evm/types" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/spf13/cobra" ) @@ -42,7 +43,7 @@ func GetCmdGetBlockNumber(queryRoute string, cdc *codec.Codec) *cobra.Command { return nil } - var out types.QueryResBlockNumber + var out *hexutil.Big cdc.MustUnmarshalJSON(res, &out) return cliCtx.PrintOutput(out) }, @@ -67,7 +68,7 @@ func GetCmdGetStorageAt(queryRoute string, cdc *codec.Codec) *cobra.Command { fmt.Printf("could not resolve: %s\n", err) return nil } - var out types.QueryResStorage + var out hexutil.Bytes cdc.MustUnmarshalJSON(res, &out) return cliCtx.PrintOutput(out) }, @@ -91,9 +92,9 @@ func GetCmdGetCode(queryRoute string, cdc *codec.Codec) *cobra.Command { fmt.Printf("could not resolve: %s\n", err) return nil } - var out types.QueryResCode + var out []byte cdc.MustUnmarshalJSON(res, &out) - return cliCtx.PrintOutput(out) + return cliCtx.PrintOutput(hexutil.Bytes(out)) }, } } @@ -115,7 +116,7 @@ func GetCmdGetNonce(queryRoute string, cdc *codec.Codec) *cobra.Command { fmt.Printf("could not resolve: %s\n", err) return nil } - var out types.QueryResNonce + var out hexutil.Uint64 cdc.MustUnmarshalJSON(res, &out) return cliCtx.PrintOutput(out) }, diff --git a/x/evm/querier.go b/x/evm/querier.go index c12f8159..639ffb00 100644 --- a/x/evm/querier.go +++ b/x/evm/querier.go @@ -1,12 +1,9 @@ package evm import ( - "math/big" - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/ethermint/version" - "github.com/cosmos/ethermint/x/evm/types" ethcmn "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" abci "github.com/tendermint/tendermint/abci/types" @@ -47,7 +44,8 @@ func NewQuerier(keeper Keeper) sdk.Querier { func queryProtocolVersion(keeper Keeper) ([]byte, sdk.Error) { vers := version.ProtocolVersion - res, err := codec.MarshalJSONIndent(keeper.cdc, vers) + bigRes := hexutil.Uint(vers) + res, err := codec.MarshalJSONIndent(keeper.cdc, bigRes) if err != nil { panic("could not marshal result to JSON") } @@ -58,16 +56,9 @@ func queryProtocolVersion(keeper Keeper) ([]byte, sdk.Error) { func queryBalance(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) { addr := ethcmn.BytesToAddress([]byte(path[1])) balance := keeper.GetBalance(ctx, addr) - hBalance := &hexutil.Big{} - err := hBalance.UnmarshalText(balance.Bytes()) + res, err := codec.MarshalJSONIndent(keeper.cdc, balance) if err != nil { - panic("could not marshal big.Int to hexutil.Big") - } - - bRes := types.QueryResBalance{Balance: hBalance} - res, err := codec.MarshalJSONIndent(keeper.cdc, bRes) - if err != nil { - panic("could not marshal result to JSON") + panic("could not marshal result to JSON: ") } return res, nil @@ -75,10 +66,12 @@ func queryBalance(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Er func queryBlockNumber(ctx sdk.Context, keeper Keeper) ([]byte, sdk.Error) { num := ctx.BlockHeight() - bnRes := types.QueryResBlockNumber{Number: big.NewInt(num)} - res, err := codec.MarshalJSONIndent(keeper.cdc, bnRes) + hexUint := hexutil.Uint64(num) + + res, err := codec.MarshalJSONIndent(keeper.cdc, hexUint) + if err != nil { - panic("could not marshal result to JSON") + panic("could not marshal result to JSON: " + err.Error()) } return res, nil @@ -88,10 +81,10 @@ func queryStorage(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Er addr := ethcmn.BytesToAddress([]byte(path[1])) key := ethcmn.BytesToHash([]byte(path[2])) val := keeper.GetState(ctx, addr, key) - bRes := types.QueryResStorage{Value: val.Bytes()} - res, err := codec.MarshalJSONIndent(keeper.cdc, bRes) + bRes := hexutil.Bytes(val.Bytes()) + res, err := codec.MarshalJSONIndent(keeper.cdc, &bRes) if err != nil { - panic("could not marshal result to JSON") + panic("could not marshal result to JSON: " + err.Error()) } return res, nil } @@ -99,10 +92,9 @@ func queryStorage(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Er func queryCode(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) { addr := ethcmn.BytesToAddress([]byte(path[1])) code := keeper.GetCode(ctx, addr) - cRes := types.QueryResCode{Code: code} - res, err := codec.MarshalJSONIndent(keeper.cdc, cRes) + res, err := codec.MarshalJSONIndent(keeper.cdc, code) if err != nil { - panic("could not marshal result to JSON") + panic("could not marshal result to JSON: " + err.Error()) } return res, nil @@ -111,10 +103,10 @@ func queryCode(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error func queryNonce(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) { addr := ethcmn.BytesToAddress([]byte(path[1])) nonce := keeper.GetNonce(ctx, addr) - nRes := types.QueryResNonce{Nonce: nonce} + nRes := hexutil.Uint64(nonce) res, err := codec.MarshalJSONIndent(keeper.cdc, nRes) if err != nil { - panic("could not marshal result to JSON") + panic("could not marshal result to JSON: " + err.Error()) } return res, nil diff --git a/x/evm/types/querier.go b/x/evm/types/querier.go deleted file mode 100644 index c2765870..00000000 --- a/x/evm/types/querier.go +++ /dev/null @@ -1,61 +0,0 @@ -package types - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// QueryResProtocolVersion is response type for protocol version query -type QueryResProtocolVersion struct { - Version string `json:"result"` -} - -func (q QueryResProtocolVersion) String() string { - return q.Version -} - -// QueryResBalance is response type for balance query -type QueryResBalance struct { - Balance *hexutil.Big `json:"result"` -} - -func (q QueryResBalance) String() string { - return q.Balance.String() -} - -// QueryResBlockNumber is response type for block number query -type QueryResBlockNumber struct { - Number *big.Int `json:"result"` -} - -func (q QueryResBlockNumber) String() string { - return q.Number.String() -} - -// QueryResStorage is response type for storage query -type QueryResStorage struct { - Value []byte `json:"value"` -} - -func (q QueryResStorage) String() string { - return string(q.Value) -} - -// QueryResCode is response type for code query -type QueryResCode struct { - Code []byte -} - -func (q QueryResCode) String() string { - return string(q.Code) -} - -// QueryResNonce is response type for Nonce query -type QueryResNonce struct { - Nonce uint64 `json:"result"` -} - -func (q QueryResNonce) String() string { - return string(q.Nonce) -}