diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 35e4fa12..90abcbbc 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -8,6 +8,7 @@ import ( emintcrypto "github.com/cosmos/ethermint/crypto" emintkeys "github.com/cosmos/ethermint/keys" "github.com/cosmos/ethermint/rpc/args" + "github.com/cosmos/ethermint/utils" "github.com/cosmos/ethermint/version" "github.com/cosmos/ethermint/x/evm/types" @@ -120,50 +121,53 @@ func (e *PublicEthAPI) BlockNumber() (hexutil.Uint64, error) { return hexutil.Uint64(0), err } - var qRes uint64 - e.cliCtx.Codec.MustUnmarshalJSON(res, &qRes) - - return hexutil.Uint64(qRes), nil + var out types.QueryResBlockNumber + e.cliCtx.Codec.MustUnmarshalJSON(res, &out) + return hexutil.Uint64(out.Number), nil } // GetBalance returns the provided account's balance up to the provided block number. func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) (*hexutil.Big, error) { ctx := e.cliCtx.WithHeight(blockNum.Int64()) - res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", types.ModuleName, address), nil) + res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", types.ModuleName, address.Hex()), nil) if err != nil { return nil, err } - var out *big.Int + var out types.QueryResBalance e.cliCtx.Codec.MustUnmarshalJSON(res, &out) + val, err := utils.UnmarshalBigInt(out.Balance) + if err != nil { + return nil, err + } - return (*hexutil.Big)(out), nil + return (*hexutil.Big)(val), nil } // GetStorageAt returns the contract storage at the given address, block number, and key. func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum BlockNumber) (hexutil.Bytes, error) { ctx := e.cliCtx.WithHeight(blockNum.Int64()) - res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/storage/%s/%s", types.ModuleName, address, key), nil) + res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/storage/%s/%s", types.ModuleName, address.Hex(), key), nil) if err != nil { return nil, err } - var out []byte + var out types.QueryResStorage e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return out, nil + return out.Value, 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 BlockNumber) (*hexutil.Uint64, error) { ctx := e.cliCtx.WithHeight(blockNum.Int64()) - res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/nonce/%s", types.ModuleName, address), nil) + res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/nonce/%s", types.ModuleName, address.Hex()), nil) if err != nil { return nil, err } - var out *hexutil.Uint64 - e.cliCtx.Codec.MustUnmarshalJSON(res, out) - return out, nil + var out types.QueryResNonce + e.cliCtx.Codec.MustUnmarshalJSON(res, &out) + return (*hexutil.Uint64)(&out.Nonce), nil } // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash. @@ -200,14 +204,14 @@ func (e *PublicEthAPI) GetUncleCountByBlockNumber(blockNum BlockNumber) hexutil. // GetCode returns the contract code at the given address and block number. func (e *PublicEthAPI) GetCode(address common.Address, blockNumber BlockNumber) (hexutil.Bytes, error) { ctx := e.cliCtx.WithHeight(blockNumber.Int64()) - res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/code/%s", types.ModuleName, address), nil) + res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/code/%s", types.ModuleName, address.Hex()), nil) if err != nil { return nil, err } - var out []byte + var out types.QueryResCode e.cliCtx.Codec.MustUnmarshalJSON(res, &out) - return out, nil + return out.Code, 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 785b7b25..d492d985 100644 --- a/rpc/tester/tester_test.go +++ b/rpc/tester/tester_test.go @@ -33,7 +33,7 @@ type Request struct { Version string `json:"jsonrpc"` Method string `json:"method"` Params []string `json:"params"` - Id int `json:"id"` + ID int `json:"id"` } type RPCError struct { @@ -44,7 +44,7 @@ type RPCError struct { type Response struct { Error *RPCError `json:"error"` - Id int `json:"id"` + ID int `json:"id"` Result json.RawMessage `json:"result,omitempty"` } @@ -53,7 +53,7 @@ func createRequest(method string, params []string) Request { Version: "2.0", Method: method, Params: params, - Id: 1, + ID: 1, } } diff --git a/utils/int.go b/utils/int.go new file mode 100644 index 00000000..6c820045 --- /dev/null +++ b/utils/int.go @@ -0,0 +1,19 @@ +package utils + +import "math/big" + +// MarshalBigInt marshalls big int into text string for consistent encoding +func MarshalBigInt(i *big.Int) string { + bz, err := i.MarshalText() + if err != nil { + panic(err) + } + return string(bz) +} + +// UnmarshalBigInt unmarshalls string from *big.Int +func UnmarshalBigInt(s string) (*big.Int, error) { + ret := new(big.Int) + err := ret.UnmarshalText([]byte(s)) + return ret, err +} diff --git a/version/version.go b/version/version.go index f973068f..b969a7fd 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 uint = 63 +const ProtocolVersion = 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 a94ac94c..21c19722 100644 --- a/x/evm/client/cli/query.go +++ b/x/evm/client/cli/query.go @@ -7,7 +7,6 @@ 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" ) @@ -43,7 +42,7 @@ func GetCmdGetBlockNumber(queryRoute string, cdc *codec.Codec) *cobra.Command { return nil } - var out *hexutil.Big + var out types.QueryResBlockNumber cdc.MustUnmarshalJSON(res, &out) return cliCtx.PrintOutput(out) }, @@ -68,7 +67,7 @@ func GetCmdGetStorageAt(queryRoute string, cdc *codec.Codec) *cobra.Command { fmt.Printf("could not resolve: %s\n", err) return nil } - var out hexutil.Bytes + var out types.QueryResStorage cdc.MustUnmarshalJSON(res, &out) return cliCtx.PrintOutput(out) }, @@ -92,9 +91,9 @@ func GetCmdGetCode(queryRoute string, cdc *codec.Codec) *cobra.Command { fmt.Printf("could not resolve: %s\n", err) return nil } - var out []byte + var out types.QueryResCode cdc.MustUnmarshalJSON(res, &out) - return cliCtx.PrintOutput(hexutil.Bytes(out)) + return cliCtx.PrintOutput(out) }, } } @@ -116,7 +115,7 @@ func GetCmdGetNonce(queryRoute string, cdc *codec.Codec) *cobra.Command { fmt.Printf("could not resolve: %s\n", err) return nil } - var out hexutil.Uint64 + var out types.QueryResNonce cdc.MustUnmarshalJSON(res, &out) return cliCtx.PrintOutput(out) }, diff --git a/x/evm/querier.go b/x/evm/querier.go index 639ffb00..a983938c 100644 --- a/x/evm/querier.go +++ b/x/evm/querier.go @@ -3,7 +3,9 @@ package evm import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ethermint/utils" "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" @@ -44,8 +46,7 @@ func NewQuerier(keeper Keeper) sdk.Querier { func queryProtocolVersion(keeper Keeper) ([]byte, sdk.Error) { vers := version.ProtocolVersion - bigRes := hexutil.Uint(vers) - res, err := codec.MarshalJSONIndent(keeper.cdc, bigRes) + res, err := codec.MarshalJSONIndent(keeper.cdc, hexutil.Uint(vers)) if err != nil { panic("could not marshal result to JSON") } @@ -54,11 +55,13 @@ 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])) + addr := ethcmn.HexToAddress(path[1]) balance := keeper.GetBalance(ctx, addr) - res, err := codec.MarshalJSONIndent(keeper.cdc, balance) + + bRes := types.QueryResBalance{Balance: utils.MarshalBigInt(balance)} + 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 @@ -66,10 +69,8 @@ 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() - hexUint := hexutil.Uint64(num) - - res, err := codec.MarshalJSONIndent(keeper.cdc, hexUint) - + bnRes := types.QueryResBlockNumber{Number: num} + res, err := codec.MarshalJSONIndent(keeper.cdc, bnRes) if err != nil { panic("could not marshal result to JSON: " + err.Error()) } @@ -78,11 +79,11 @@ func queryBlockNumber(ctx sdk.Context, keeper Keeper) ([]byte, sdk.Error) { } func queryStorage(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) { - addr := ethcmn.BytesToAddress([]byte(path[1])) - key := ethcmn.BytesToHash([]byte(path[2])) + addr := ethcmn.HexToAddress(path[1]) + key := ethcmn.HexToHash(path[2]) val := keeper.GetState(ctx, addr, key) - bRes := hexutil.Bytes(val.Bytes()) - res, err := codec.MarshalJSONIndent(keeper.cdc, &bRes) + bRes := types.QueryResStorage{Value: val.Bytes()} + res, err := codec.MarshalJSONIndent(keeper.cdc, bRes) if err != nil { panic("could not marshal result to JSON: " + err.Error()) } @@ -90,9 +91,10 @@ 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])) + addr := ethcmn.HexToAddress(path[1]) code := keeper.GetCode(ctx, addr) - res, err := codec.MarshalJSONIndent(keeper.cdc, code) + cRes := types.QueryResCode{Code: code} + res, err := codec.MarshalJSONIndent(keeper.cdc, cRes) if err != nil { panic("could not marshal result to JSON: " + err.Error()) } @@ -101,9 +103,9 @@ 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])) + addr := ethcmn.HexToAddress(path[1]) nonce := keeper.GetNonce(ctx, addr) - nRes := hexutil.Uint64(nonce) + nRes := types.QueryResNonce{Nonce: nonce} res, err := codec.MarshalJSONIndent(keeper.cdc, nRes) if err != nil { panic("could not marshal result to JSON: " + err.Error()) diff --git a/x/evm/types/msg_encoding.go b/x/evm/types/msg_encoding.go index 86218d28..5e62e434 100644 --- a/x/evm/types/msg_encoding.go +++ b/x/evm/types/msg_encoding.go @@ -1,9 +1,8 @@ package types import ( - "math/big" - "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/ethermint/utils" ethcmn "github.com/ethereum/go-ethereum/common" ) @@ -19,7 +18,7 @@ func RegisterAmino(cdc *codec.Codec) { cdc.RegisterConcrete(EncodableTxData{}, "ethermint/EncodedMessage", nil) } -// TxData implements the Ethereum transaction data structure. It is used +// EncodableTxData implements the Ethereum transaction data structure. It is used // solely as intended in Ethereum abiding by the protocol. type EncodableTxData struct { AccountNonce uint64 `json:"nonce"` @@ -47,33 +46,19 @@ func unmarshalAmino(td *EncodableTxData, text string) (err error) { return cdc.UnmarshalBinaryBare([]byte(text), td) } -func marshalBigInt(i *big.Int) string { - bz, err := i.MarshalText() - if err != nil { - panic(err) - } - return string(bz) -} - -func unmarshalBigInt(s string) (*big.Int, error) { - ret := new(big.Int) - err := ret.UnmarshalText([]byte(s)) - return ret, err -} - // MarshalAmino defines custom encoding scheme for TxData func (td TxData) MarshalAmino() (string, error) { e := EncodableTxData{ AccountNonce: td.AccountNonce, - Price: marshalBigInt(td.Price), + Price: utils.MarshalBigInt(td.Price), GasLimit: td.GasLimit, Recipient: td.Recipient, - Amount: marshalBigInt(td.Amount), + Amount: utils.MarshalBigInt(td.Amount), Payload: td.Payload, - V: marshalBigInt(td.V), - R: marshalBigInt(td.R), - S: marshalBigInt(td.S), + V: utils.MarshalBigInt(td.V), + R: utils.MarshalBigInt(td.R), + S: utils.MarshalBigInt(td.S), Hash: td.Hash, } @@ -95,7 +80,7 @@ func (td *TxData) UnmarshalAmino(text string) (err error) { td.Payload = e.Payload td.Hash = e.Hash - price, err := unmarshalBigInt(e.Price) + price, err := utils.UnmarshalBigInt(e.Price) if err != nil { return } @@ -105,7 +90,7 @@ func (td *TxData) UnmarshalAmino(text string) (err error) { td.Price = price } - amt, err := unmarshalBigInt(e.Amount) + amt, err := utils.UnmarshalBigInt(e.Amount) if err != nil { return } @@ -115,7 +100,7 @@ func (td *TxData) UnmarshalAmino(text string) (err error) { td.Amount = amt } - v, err := unmarshalBigInt(e.V) + v, err := utils.UnmarshalBigInt(e.V) if err != nil { return } @@ -125,7 +110,7 @@ func (td *TxData) UnmarshalAmino(text string) (err error) { td.V = v } - r, err := unmarshalBigInt(e.R) + r, err := utils.UnmarshalBigInt(e.R) if err != nil { return } @@ -135,7 +120,7 @@ func (td *TxData) UnmarshalAmino(text string) (err error) { td.R = r } - s, err := unmarshalBigInt(e.S) + s, err := utils.UnmarshalBigInt(e.S) if err != nil { return } diff --git a/x/evm/types/msg_test.go b/x/evm/types/msg_test.go index c2f3ecad..4577f114 100644 --- a/x/evm/types/msg_test.go +++ b/x/evm/types/msg_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/cosmos/ethermint/crypto" + "github.com/cosmos/ethermint/utils" ethcmn "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/require" @@ -140,8 +141,8 @@ func TestMsgEthereumTxAmino(t *testing.T) { func TestMarshalAndUnmarshalInt(t *testing.T) { i := big.NewInt(3) - m := marshalBigInt(i) - i2, err := unmarshalBigInt(m) + m := utils.MarshalBigInt(i) + i2, err := utils.UnmarshalBigInt(m) require.NoError(t, err) require.Equal(t, i, i2) @@ -152,15 +153,15 @@ func TestMarshalAndUnmarshalData(t *testing.T) { hash := ethcmn.BigToHash(big.NewInt(2)) e := EncodableTxData{ AccountNonce: 2, - Price: marshalBigInt(big.NewInt(3)), + Price: utils.MarshalBigInt(big.NewInt(3)), GasLimit: 1, Recipient: &addr, - Amount: marshalBigInt(big.NewInt(4)), + Amount: utils.MarshalBigInt(big.NewInt(4)), Payload: []byte("test"), - V: marshalBigInt(big.NewInt(5)), - R: marshalBigInt(big.NewInt(6)), - S: marshalBigInt(big.NewInt(7)), + V: utils.MarshalBigInt(big.NewInt(5)), + R: utils.MarshalBigInt(big.NewInt(6)), + S: utils.MarshalBigInt(big.NewInt(7)), Hash: &hash, } diff --git a/x/evm/types/querier.go b/x/evm/types/querier.go new file mode 100644 index 00000000..9a8972bb --- /dev/null +++ b/x/evm/types/querier.go @@ -0,0 +1,55 @@ +package types + +// QueryResProtocolVersion is response type for protocol version query +type QueryResProtocolVersion struct { + Version string `json:"version"` +} + +func (q QueryResProtocolVersion) String() string { + return q.Version +} + +// QueryResBalance is response type for balance query +type QueryResBalance struct { + Balance string `json:"balance"` +} + +func (q QueryResBalance) String() string { + return q.Balance +} + +// QueryResBlockNumber is response type for block number query +type QueryResBlockNumber struct { + Number int64 `json:"blockNumber"` +} + +func (q QueryResBlockNumber) String() string { + return string(q.Number) +} + +// 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:"nonce"` +} + +func (q QueryResNonce) String() string { + return string(q.Nonce) +}