forked from cerc-io/laconicd-deprecated
additions
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
rpctypes "github.com/cosmos/ethermint/ethereum/rpc/types"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
|
||||
rpctypes "github.com/cosmos/ethermint/rpc/types"
|
||||
"github.com/InjectiveLabs/sdk-go/ethereum/rpc"
|
||||
"github.com/InjectiveLabs/sdk-go/wrappers"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
@@ -23,6 +30,8 @@ func GetQueryCmd() *cobra.Command {
|
||||
cmd.AddCommand(
|
||||
GetStorageCmd(),
|
||||
GetCodeCmd(),
|
||||
GetErc20Balance(),
|
||||
GetAccount(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
@@ -103,3 +112,88 @@ func GetCodeCmd() *cobra.Command {
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetErc20Balance queries the erc20 balance of an address
|
||||
func GetErc20Balance() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "erc20balance [contract] [address]",
|
||||
Short: "Gets erc20 balance of an account",
|
||||
Long: "Gets erc20 balance of an account.",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
|
||||
contract := args[0]
|
||||
address := args[1]
|
||||
|
||||
erc20ABI, err := abi.JSON(strings.NewReader(wrappers.ERC20ABI))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
input, err := erc20ABI.Pack("balanceOf", common.HexToAddress(address))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := &types.QueryStaticCallRequest{
|
||||
Address: contract,
|
||||
Input: input,
|
||||
}
|
||||
|
||||
res, err := queryClient.StaticCall(rpc.ContextWithHeight(clientCtx.Height), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret := big.NewInt(0)
|
||||
err = erc20ABI.UnpackIntoInterface(&ret, "balanceOf", res.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintString(ret.String())
|
||||
},
|
||||
}
|
||||
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetAccount queries the account by address
|
||||
func GetAccount() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "account [address]",
|
||||
Short: "Get an account by address",
|
||||
Long: "Get an account by address",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
address := args[0]
|
||||
|
||||
req := &types.QueryAccountRequest{
|
||||
Address: address,
|
||||
}
|
||||
|
||||
res, err := queryClient.Account(rpc.ContextWithHeight(clientCtx.Height), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -45,3 +45,19 @@ func formatKeyToHash(key string) string {
|
||||
|
||||
return ethkey.Hex()
|
||||
}
|
||||
|
||||
func cosmosAddressFromArg(addr string) (sdk.AccAddress, error) {
|
||||
if strings.HasPrefix(addr, sdk.GetConfig().GetBech32AccountAddrPrefix()) {
|
||||
// Check to see if address is Cosmos bech32 formatted
|
||||
toAddr, err := sdk.AccAddressFromBech32(addr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid bech32 formatted address")
|
||||
}
|
||||
return toAddr, nil
|
||||
}
|
||||
|
||||
// Strip 0x prefix if exists
|
||||
addr = strings.TrimPrefix(addr, "0x")
|
||||
|
||||
return sdk.AccAddressFromHex(addr)
|
||||
}
|
||||
|
||||
@@ -61,3 +61,24 @@ func TestCosmosToEthereumTypes(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hexString, ethDecoded)
|
||||
}
|
||||
|
||||
func TestAddressToCosmosAddress(t *testing.T) {
|
||||
baseAddr, err := sdk.AccAddressFromHex("6A98D72760f7bbA69d62Ed6F48278451251948E7")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test cosmos string back to address
|
||||
cosmosFormatted, err := cosmosAddressFromArg(baseAddr.String())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, baseAddr, cosmosFormatted)
|
||||
|
||||
// Test account address from Ethereum address
|
||||
ethAddr := common.BytesToAddress(baseAddr.Bytes())
|
||||
ethFormatted, err := cosmosAddressFromArg(ethAddr.Hex())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, baseAddr, ethFormatted)
|
||||
|
||||
// Test encoding without the 0x prefix
|
||||
ethFormatted, err = cosmosAddressFromArg(ethAddr.Hex()[2:])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, baseAddr, ethFormatted)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/types/rest"
|
||||
authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
||||
|
||||
rpctypes "github.com/cosmos/ethermint/rpc/types"
|
||||
rpctypes "github.com/cosmos/ethermint/ethereum/rpc/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
@@ -81,7 +81,7 @@ func getEthTransactionByHash(clientCtx client.Context, hashHex string) ([]byte,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockHash := common.BytesToHash(block.Block.Hash())
|
||||
blockHash := common.BytesToHash(block.Block.Header.Hash())
|
||||
|
||||
ethTx, err := rpctypes.RawTxToEthTx(clientCtx, tx.Tx)
|
||||
if err != nil {
|
||||
|
||||
+1
-3
@@ -5,14 +5,12 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/keeper"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
// InitGenesis initializes genesis state based on exported genesis
|
||||
|
||||
+54
-6
File diff suppressed because one or more lines are too long
+46
-53
@@ -2,53 +2,23 @@ package evm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"runtime/debug"
|
||||
|
||||
log "github.com/xlab/suplog"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cosmos/ethermint/x/evm/keeper"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/telemetry"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
// NewHandler returns a handler for Ethermint type messages.
|
||||
func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
defer telemetry.MeasureSince(time.Now(), "evm", "state_transition")
|
||||
func NewHandler(k *keeper.Keeper) sdk.Handler {
|
||||
return func(ctx sdk.Context, msg sdk.Msg) (result *sdk.Result, err error) {
|
||||
defer Recover(&err)
|
||||
|
||||
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
||||
snapshotStateDB := k.CommitStateDB.Copy()
|
||||
|
||||
// The "recover" code here is used to solve the problem of dirty data
|
||||
// in CommitStateDB due to insufficient gas.
|
||||
|
||||
// The following is a detailed description:
|
||||
// If the gas is insufficient during the execution of the "handler",
|
||||
// panic will be thrown from the function "ConsumeGas" and finally
|
||||
// caught by the function "runTx" from Cosmos. The function "runTx"
|
||||
// will think that the execution of Msg has failed and the modified
|
||||
// data in the Store will not take effect.
|
||||
|
||||
// Stacktrace:runTx->runMsgs->handler->...->gaskv.Store.Set->ConsumeGas
|
||||
|
||||
// The problem is that when the modified data in the Store does not take
|
||||
// effect, the data in the modified CommitStateDB is not rolled back,
|
||||
// they take effect, and dirty data is generated.
|
||||
// Therefore, the code here specifically deals with this situation.
|
||||
// See https://github.com/cosmos/ethermint/issues/668 for more information.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// We first used "k.CommitStateDB = snapshotStateDB" to roll back
|
||||
// CommitStateDB, but this can only change the CommitStateDB in the
|
||||
// current Keeper object, but the Keeper object will be destroyed
|
||||
// soon, it is not a global variable, so the content pointed to by
|
||||
// the CommitStateDB pointer can be modified to take effect.
|
||||
types.CopyCommitStateDB(snapshotStateDB, k.CommitStateDB)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
switch msg := msg.(type) {
|
||||
@@ -56,11 +26,8 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
// execute state transition
|
||||
res, err := k.EthereumTx(sdk.WrapSDKContext(ctx), msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := sdk.WrapServiceResult(ctx, res, err)
|
||||
if err != nil {
|
||||
return sdk.WrapServiceResult(ctx, res, err)
|
||||
} else if result, err = sdk.WrapServiceResult(ctx, res, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -69,22 +36,48 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
if res.ContractAddress != "" {
|
||||
recipientLog = fmt.Sprintf("contract address %s", res.ContractAddress)
|
||||
} else {
|
||||
recipientLog = fmt.Sprintf("recipient address %s", msg.Data.Recipient)
|
||||
var recipient string
|
||||
if to := msg.To(); to != nil {
|
||||
recipient = to.Hex()
|
||||
}
|
||||
|
||||
recipientLog = fmt.Sprintf("recipient address %s", recipient)
|
||||
}
|
||||
|
||||
sender := ethcmn.BytesToAddress(msg.GetFrom().Bytes())
|
||||
|
||||
log := fmt.Sprintf(
|
||||
"executed EVM state transition; sender address %s; %s", sender, recipientLog,
|
||||
)
|
||||
|
||||
k.Logger(ctx).Info(log)
|
||||
result.Log = log
|
||||
if res.Reverted {
|
||||
result.Log = "transaction reverted"
|
||||
log := fmt.Sprintf(
|
||||
"reverted EVM state transition; sender address %s; %s", sender.Hex(), recipientLog,
|
||||
)
|
||||
k.Logger(ctx).Info(log)
|
||||
} else {
|
||||
log := fmt.Sprintf(
|
||||
"executed EVM state transition; sender address %s; %s", sender.Hex(), recipientLog,
|
||||
)
|
||||
result.Log = log
|
||||
k.Logger(ctx).Info(log)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
||||
default:
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)
|
||||
err := sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Recover(err *error) {
|
||||
if r := recover(); r != nil {
|
||||
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r)
|
||||
|
||||
if e, ok := r.(error); ok {
|
||||
log.WithError(e).Errorln("evm msg handler panicked with an error")
|
||||
log.Debugln(string(debug.Stack()))
|
||||
} else {
|
||||
log.Errorln(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-40
@@ -33,7 +33,7 @@ type EvmTestSuite struct {
|
||||
|
||||
ctx sdk.Context
|
||||
handler sdk.Handler
|
||||
app *app.EthermintApp
|
||||
app *app.InjectiveApp
|
||||
codec codec.BinaryMarshaler
|
||||
|
||||
privKey *ethsecp256k1.PrivKey
|
||||
@@ -45,8 +45,8 @@ func (suite *EvmTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(checkTx)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
|
||||
suite.handler = evm.NewHandler(*suite.app.EvmKeeper)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "888", Time: time.Now().UTC()})
|
||||
suite.handler = evm.NewHandler(suite.app.EvmKeeper)
|
||||
suite.codec = suite.app.AppCodec()
|
||||
|
||||
privKey, err := ethsecp256k1.GenerateKey()
|
||||
@@ -78,7 +78,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
"passed",
|
||||
func() {
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, suite.from, big.NewInt(100))
|
||||
tx = types.NewMsgEthereumTx(0, &suite.from, big.NewInt(0), 0, big.NewInt(10000), nil)
|
||||
tx = types.NewMsgEthereumTx(0, &suite.from, big.NewInt(100), 0, big.NewInt(10000), nil)
|
||||
|
||||
// parse context chain ID to big.Int
|
||||
chainID, err := ethermint.ParseChainID(suite.ctx.ChainID())
|
||||
@@ -176,7 +176,7 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
|
||||
|
||||
bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029")
|
||||
tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
err = tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
err = tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
@@ -195,34 +195,7 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
|
||||
logs, err := suite.app.EvmKeeper.GetLogs(suite.ctx, ethcmn.BytesToHash(hash))
|
||||
suite.Require().NoError(err, "failed to get logs")
|
||||
|
||||
suite.Require().Equal(len(logs), len(txResponse.TxLogs.Logs))
|
||||
|
||||
for i, logI := range logs {
|
||||
for j, logJ := range txResponse.TxLogs.Logs {
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
suite.Require().Equal(uint64(logI.Index), logJ.Index)
|
||||
suite.Require().Equal(logI.Data, logJ.Data)
|
||||
suite.Require().Equal(logI.Address.String(), logJ.Address)
|
||||
suite.Require().Equal(logI.BlockHash.String(), logJ.BlockHash)
|
||||
suite.Require().Equal(logI.BlockNumber, logJ.BlockNumber)
|
||||
suite.Require().Equal(logI.Removed, logJ.Removed)
|
||||
suite.Require().Equal(logI.TxHash.String(), logJ.TxHash)
|
||||
suite.Require().Equal(uint64(logI.TxIndex), logJ.TxIndex)
|
||||
|
||||
suite.Require().Equal(len(logI.Topics), len(logJ.Topics))
|
||||
|
||||
for i2, topicI := range logI.Topics {
|
||||
for j2, topicJ := range logJ.Topics {
|
||||
if i2 != j2 {
|
||||
continue
|
||||
}
|
||||
suite.Require().Equal(topicI.String(), topicJ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
suite.Require().Equal(logs, txResponse.TxLogs.Logs)
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestQueryTxLogs() {
|
||||
@@ -235,7 +208,7 @@ func (suite *EvmTestSuite) TestQueryTxLogs() {
|
||||
// send contract deployment transaction with an event in the constructor
|
||||
bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029")
|
||||
tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
err = tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
err = tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
@@ -321,7 +294,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
|
||||
bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
|
||||
tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
@@ -338,7 +311,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424"
|
||||
bytecode = common.FromHex(storeAddr)
|
||||
tx = types.NewMsgEthereumTx(2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
result, err = suite.handler(suite.ctx, tx)
|
||||
@@ -350,7 +323,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
// query - getOwner
|
||||
bytecode = common.FromHex("0x893d20e8")
|
||||
tx = types.NewMsgEthereumTx(2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
result, err = suite.handler(suite.ctx, tx)
|
||||
@@ -375,7 +348,7 @@ func (suite *EvmTestSuite) TestSendTransaction() {
|
||||
|
||||
// send simple value transfer with gasLimit=21000
|
||||
tx := types.NewMsgEthereumTx(1, ðcmn.Address{0x1}, big.NewInt(1), gasLimit, gasPrice, nil)
|
||||
err = tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
err = tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
@@ -448,7 +421,7 @@ func (suite *EvmTestSuite) TestOutOfGasWhenDeployContract() {
|
||||
|
||||
bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
|
||||
tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
snapshotCommitStateDBJson, err := json.Marshal(suite.app.EvmKeeper.CommitStateDB)
|
||||
@@ -478,7 +451,7 @@ func (suite *EvmTestSuite) TestErrorWhenDeployContract() {
|
||||
bytecode := common.FromHex("0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424")
|
||||
|
||||
tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode)
|
||||
tx.Sign(big.NewInt(3), priv.ToECDSA())
|
||||
tx.Sign(big.NewInt(888), priv.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
snapshotCommitStateDBJson, err := json.Marshal(suite.app.EvmKeeper.CommitStateDB)
|
||||
|
||||
+12
-8
@@ -3,29 +3,29 @@ package keeper
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/cosmos/ethermint/metrics"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
// BeginBlock sets the block height -> header hash map for the previous block height
|
||||
// BeginBlock sets the block hash -> block height map for the previous block height
|
||||
// and resets the Bloom filter and the transaction count to 0.
|
||||
func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
|
||||
if req.Header.LastBlockId.GetHash() == nil || req.Header.GetHeight() < 1 {
|
||||
if req.Header.Height < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// Gas costs are handled within msg handler so costs should be ignored
|
||||
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
// Set the hash -> height and height -> hash mapping.
|
||||
currentHash := req.Hash
|
||||
height := req.Header.GetHeight()
|
||||
k.SetBlockHash(ctx, req.Hash, req.Header.Height)
|
||||
k.SetBlockHeightToHash(ctx, req.Hash, req.Header.Height)
|
||||
|
||||
k.SetHeightHash(ctx, uint64(height), common.BytesToHash(hash))
|
||||
// special setter for csdb
|
||||
k.SetHeightHash(ctx, uint64(req.Header.Height), common.BytesToHash(req.Hash))
|
||||
|
||||
// reset counters that are used on CommitStateDB.Prepare
|
||||
k.Bloom = big.NewInt(0)
|
||||
@@ -37,6 +37,10 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
|
||||
// the store. The EVM end block logic doesn't update the validator set, thus it returns
|
||||
// an empty slice.
|
||||
func (k Keeper) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
// Gas costs are handled within msg handler so costs should be ignored
|
||||
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestBeginBlock() {
|
||||
// update the counters
|
||||
suite.app.EvmKeeper.Bloom.SetInt64(10)
|
||||
suite.app.EvmKeeper.TxCount = 10
|
||||
|
||||
suite.app.EvmKeeper.BeginBlock(suite.ctx, abci.RequestBeginBlock{})
|
||||
suite.Require().NotZero(suite.app.EvmKeeper.Bloom.Int64())
|
||||
suite.Require().NotZero(suite.app.EvmKeeper.TxCount)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestEndBlock() {
|
||||
// update the counters
|
||||
suite.app.EvmKeeper.Bloom.SetInt64(10)
|
||||
|
||||
// set gas limit to 1 to ensure no gas is consumed during the operation
|
||||
initialConsumed := suite.ctx.GasMeter().GasConsumed()
|
||||
|
||||
_ = suite.app.EvmKeeper.EndBlock(suite.ctx, abci.RequestEndBlock{Height: 100})
|
||||
|
||||
suite.Require().Equal(int64(initialConsumed), int64(suite.ctx.GasMeter().GasConsumed()))
|
||||
|
||||
bloom, found := suite.app.EvmKeeper.GetBlockBloom(suite.ctx, 100)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(int64(10), bloom.Big().Int64())
|
||||
|
||||
}
|
||||
+263
-32
@@ -2,14 +2,17 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cosmos/ethermint/metrics"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
@@ -17,12 +20,18 @@ import (
|
||||
var _ types.QueryServer = Keeper{}
|
||||
|
||||
// Account implements the Query/Account gRPC method
|
||||
func (q Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*types.QueryAccountResponse, error) {
|
||||
func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*types.QueryAccountResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
if types.IsZeroAddress(req.Address) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
@@ -30,9 +39,10 @@ func (q Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
so := q.GetOrNewStateObject(ctx, ethcmn.HexToAddress(req.Address))
|
||||
so := k.GetOrNewStateObject(ctx, ethcmn.HexToAddress(req.Address))
|
||||
balance, err := ethermint.MarshalBigInt(so.Balance())
|
||||
if err != nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -43,13 +53,18 @@ func (q Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Balance implements the Query/Balance gRPC method
|
||||
func (q Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) {
|
||||
func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRequest) (*types.QueryCosmosAccountResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
if types.IsZeroAddress(req.Address) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
@@ -58,9 +73,48 @@ func (q Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
balanceInt := q.GetBalance(ctx, ethcmn.HexToAddress(req.Address))
|
||||
ethStr := req.Address
|
||||
ethAddr := ethcmn.FromHex(ethStr)
|
||||
|
||||
ethToCosmosAddr := sdk.AccAddress(ethAddr[:]).String()
|
||||
cosmosToEthAddr, _ := sdk.AccAddressFromBech32(ethToCosmosAddr)
|
||||
|
||||
acc := k.accountKeeper.GetAccount(ctx, cosmosToEthAddr)
|
||||
res := types.QueryCosmosAccountResponse{
|
||||
CosmosAddress: cosmosToEthAddr.String(),
|
||||
}
|
||||
if acc != nil {
|
||||
res.Sequence = acc.GetSequence()
|
||||
res.AccountNumber = acc.GetAccountNumber()
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// Balance implements the Query/Balance gRPC method
|
||||
func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsZeroAddress(req.Address) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
balanceInt := k.GetBalance(ctx, ethcmn.HexToAddress(req.Address))
|
||||
balance, err := ethermint.MarshalBigInt(balanceInt)
|
||||
if err != nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.Internal,
|
||||
"failed to marshal big.Int to string",
|
||||
@@ -73,31 +127,30 @@ func (q Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ
|
||||
}
|
||||
|
||||
// Storage implements the Query/Storage gRPC method
|
||||
func (q Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) {
|
||||
func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
if types.IsZeroAddress(req.Address) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
if len(req.Key) == 0 {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
address := ethcmn.HexToAddress(req.Address)
|
||||
key := ethcmn.HexToHash(req.Key)
|
||||
|
||||
state := q.GetState(ctx, address, key)
|
||||
state := k.GetState(ctx, address, key)
|
||||
|
||||
return &types.QueryStorageResponse{
|
||||
Value: state.String(),
|
||||
@@ -105,12 +158,18 @@ func (q Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*typ
|
||||
}
|
||||
|
||||
// Code implements the Query/Code gRPC method
|
||||
func (q Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.QueryCodeResponse, error) {
|
||||
func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.QueryCodeResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
if types.IsZeroAddress(req.Address) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
@@ -120,7 +179,7 @@ func (q Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
address := ethcmn.HexToAddress(req.Address)
|
||||
code := q.GetCode(ctx, address)
|
||||
code := k.GetCode(ctx, address)
|
||||
|
||||
return &types.QueryCodeResponse{
|
||||
Code: code,
|
||||
@@ -128,12 +187,18 @@ func (q Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que
|
||||
}
|
||||
|
||||
// TxLogs implements the Query/TxLogs gRPC method
|
||||
func (q Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types.QueryTxLogsResponse, error) {
|
||||
func (k Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types.QueryTxLogsResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsEmptyHash(req.Hash) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
@@ -143,8 +208,9 @@ func (q Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
hash := ethcmn.HexToHash(req.Hash)
|
||||
logs, err := q.GetLogs(ctx, hash)
|
||||
logs, err := k.GetLogs(ctx, hash)
|
||||
if err != nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.Internal,
|
||||
err.Error(),
|
||||
@@ -156,13 +222,19 @@ func (q Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BlockLogs implements the Query/BlockLogs gRPC method
|
||||
func (q Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (*types.QueryBlockLogsResponse, error) {
|
||||
// TxReceipt implements the Query/TxReceipt gRPC method
|
||||
func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) (*types.QueryTxReceiptResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsEmptyHash(req.Hash) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
@@ -171,7 +243,90 @@ func (q Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
txLogs := q.GetAllTxLogs(ctx)
|
||||
hash := ethcmn.HexToHash(req.Hash)
|
||||
receipt, found := k.GetTxReceiptFromHash(ctx, hash)
|
||||
if !found {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.NotFound, types.ErrTxReceiptNotFound.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
return &types.QueryTxReceiptResponse{
|
||||
Receipt: receipt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TxReceiptsByBlockHeight implements the Query/TxReceiptsByBlockHeight gRPC method
|
||||
func (k Keeper) TxReceiptsByBlockHeight(c context.Context, req *types.QueryTxReceiptsByBlockHeightRequest) (*types.QueryTxReceiptsByBlockHeightResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
receipts := k.GetTxReceiptsByBlockHeight(ctx, req.Height)
|
||||
return &types.QueryTxReceiptsByBlockHeightResponse{
|
||||
Receipts: receipts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TxReceiptsByBlockHash implements the Query/TxReceiptsByBlockHash gRPC method
|
||||
func (k Keeper) TxReceiptsByBlockHash(c context.Context, req *types.QueryTxReceiptsByBlockHashRequest) (*types.QueryTxReceiptsByBlockHashResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsEmptyHash(req.Hash) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
hash := ethcmn.HexToHash(req.Hash)
|
||||
receipts := k.GetTxReceiptsByBlockHash(ctx, hash)
|
||||
|
||||
return &types.QueryTxReceiptsByBlockHashResponse{
|
||||
Receipts: receipts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BlockLogs implements the Query/BlockLogs gRPC method
|
||||
func (k Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (*types.QueryBlockLogsResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsEmptyHash(req.Hash) {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
txLogs := k.GetAllTxLogs(ctx)
|
||||
|
||||
return &types.QueryBlockLogsResponse{
|
||||
TxLogs: txLogs,
|
||||
@@ -179,14 +334,28 @@ func (q Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (
|
||||
}
|
||||
|
||||
// BlockBloom implements the Query/BlockBloom gRPC method
|
||||
func (q Keeper) BlockBloom(c context.Context, _ *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) {
|
||||
func (k Keeper) BlockBloom(c context.Context, req *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
// use block height provided through the gRPC header
|
||||
bloom, found := q.GetBlockBloom(ctx, ctx.BlockHeight())
|
||||
height := ctx.BlockHeight()
|
||||
if setHeight := req.Height; setHeight > 0 {
|
||||
height = setHeight
|
||||
}
|
||||
|
||||
bloom, found := k.GetBlockBloom(ctx, height)
|
||||
if !found {
|
||||
return nil, status.Errorf(
|
||||
codes.NotFound, "%s: height %d", types.ErrBloomNotFound.Error(), ctx.BlockHeight(),
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(
|
||||
codes.NotFound, types.ErrBloomNotFound.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -196,11 +365,73 @@ func (q Keeper) BlockBloom(c context.Context, _ *types.QueryBlockBloomRequest) (
|
||||
}
|
||||
|
||||
// Params implements the Query/Params gRPC method
|
||||
func (q Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
|
||||
func (k Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
if req == nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
params := q.GetParams(ctx)
|
||||
params := k.GetParams(ctx)
|
||||
|
||||
return &types.QueryParamsResponse{
|
||||
Params: params,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StaticCall implements Query/StaticCall gRPCP method
|
||||
func (k Keeper) StaticCall(c context.Context, req *types.QueryStaticCallRequest) (*types.QueryStaticCallResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
// parse the chainID from a string to a base-10 integer
|
||||
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
|
||||
ethHash := ethcmn.BytesToHash(txHash)
|
||||
|
||||
var recipient *ethcmn.Address
|
||||
if len(req.Address) > 0 {
|
||||
addr := ethcmn.HexToAddress(req.Address)
|
||||
recipient = &addr
|
||||
}
|
||||
|
||||
so := k.GetOrNewStateObject(ctx, *recipient)
|
||||
sender := ethcmn.HexToAddress("0xaDd00275E3d9d213654Ce5223f0FADE8b106b707")
|
||||
|
||||
st := &types.StateTransition{
|
||||
AccountNonce: so.Nonce(),
|
||||
Price: new(big.Int).SetBytes(big.NewInt(0).Bytes()),
|
||||
GasLimit: 100000000,
|
||||
Recipient: recipient,
|
||||
Amount: new(big.Int).SetBytes(big.NewInt(0).Bytes()),
|
||||
Payload: req.Input,
|
||||
Csdb: k.CommitStateDB.WithContext(ctx),
|
||||
ChainID: chainIDEpoch,
|
||||
TxHash: ðHash,
|
||||
Sender: sender,
|
||||
Simulate: ctx.IsCheckTx(),
|
||||
}
|
||||
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return nil, types.ErrChainConfigNotFound
|
||||
}
|
||||
|
||||
ret, err := st.StaticCall(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.QueryStaticCallResponse{Data: ret}, nil
|
||||
}
|
||||
|
||||
@@ -1,499 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryAccount() {
|
||||
var (
|
||||
req *types.QueryAccountRequest
|
||||
expAccount *types.QueryAccountResponse
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"zero address",
|
||||
func() {
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0))
|
||||
expAccount = &types.QueryAccountResponse{
|
||||
Balance: "0",
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
Nonce: 0,
|
||||
}
|
||||
req = &types.QueryAccountRequest{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(100))
|
||||
expAccount = &types.QueryAccountResponse{
|
||||
Balance: "100",
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
Nonce: 0,
|
||||
}
|
||||
req = &types.QueryAccountRequest{
|
||||
Address: suite.address.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
res, err := suite.queryClient.Account(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expAccount, res)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryBalance() {
|
||||
var (
|
||||
req *types.QueryBalanceRequest
|
||||
expBalance string
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"zero address",
|
||||
func() {
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0))
|
||||
expBalance = "0"
|
||||
req = &types.QueryBalanceRequest{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(100))
|
||||
expBalance = "100"
|
||||
req = &types.QueryBalanceRequest{
|
||||
Address: suite.address.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
res, err := suite.queryClient.Balance(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expBalance, res.Balance)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryStorage() {
|
||||
var (
|
||||
req *types.QueryStorageRequest
|
||||
expValue string
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"zero address",
|
||||
func() {
|
||||
req = &types.QueryStorageRequest{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{"empty hash",
|
||||
func() {
|
||||
req = &types.QueryStorageRequest{
|
||||
Address: suite.address.String(),
|
||||
Key: ethcmn.Hash{}.String(),
|
||||
}
|
||||
exp := &types.QueryStorageResponse{Value: "0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
expValue = exp.Value
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
key := ethcmn.BytesToHash([]byte("key"))
|
||||
value := ethcmn.BytesToHash([]byte("value"))
|
||||
expValue = value.String()
|
||||
suite.app.EvmKeeper.SetState(suite.ctx, suite.address, key, value)
|
||||
req = &types.QueryStorageRequest{
|
||||
Address: suite.address.String(),
|
||||
Key: key.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
res, err := suite.queryClient.Storage(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expValue, res.Value)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryCode() {
|
||||
var (
|
||||
req *types.QueryCodeRequest
|
||||
expCode []byte
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"zero address",
|
||||
func() {
|
||||
req = &types.QueryCodeRequest{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
}
|
||||
exp := &types.QueryCodeResponse{}
|
||||
expCode = exp.Code
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
expCode = []byte("code")
|
||||
suite.app.EvmKeeper.SetCode(suite.ctx, suite.address, expCode)
|
||||
|
||||
req = &types.QueryCodeRequest{
|
||||
Address: suite.address.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
res, err := suite.queryClient.Code(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expCode, res.Code)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryTxLogs() {
|
||||
var (
|
||||
req *types.QueryTxLogsRequest
|
||||
expLogs []*types.Log
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"empty hash",
|
||||
func() {
|
||||
req = &types.QueryTxLogsRequest{
|
||||
Hash: ethcmn.Hash{}.String(),
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{"logs not found",
|
||||
func() {
|
||||
hash := ethcmn.BytesToHash([]byte("hash"))
|
||||
req = &types.QueryTxLogsRequest{
|
||||
Hash: hash.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
hash := ethcmn.BytesToHash([]byte("tx_hash"))
|
||||
|
||||
expLogs = []*types.Log{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: hash.String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
}
|
||||
|
||||
suite.app.EvmKeeper.SetLogs(suite.ctx, hash, types.LogsToEthereum(expLogs))
|
||||
|
||||
req = &types.QueryTxLogsRequest{
|
||||
Hash: hash.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
res, err := suite.queryClient.TxLogs(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expLogs, res.Logs)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryBlockLogs() {
|
||||
var (
|
||||
req *types.QueryBlockLogsRequest
|
||||
expLogs []types.TransactionLogs
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"empty hash",
|
||||
func() {
|
||||
req = &types.QueryBlockLogsRequest{
|
||||
Hash: ethcmn.Hash{}.String(),
|
||||
}
|
||||
},
|
||||
false,
|
||||
},
|
||||
{"logs not found",
|
||||
func() {
|
||||
hash := ethcmn.BytesToHash([]byte("hash"))
|
||||
req = &types.QueryBlockLogsRequest{
|
||||
Hash: hash.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
|
||||
hash := ethcmn.BytesToHash([]byte("block_hash"))
|
||||
expLogs = []types.TransactionLogs{
|
||||
{
|
||||
Hash: ethcmn.BytesToHash([]byte("tx_hash_0")).String(),
|
||||
Logs: []*types.Log{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.BytesToHash([]byte("tx_hash_0")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Hash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(),
|
||||
Logs: []*types.Log{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic_1")).String()},
|
||||
Data: []byte("data_1"),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash([]byte("tx_hash_0")), types.LogsToEthereum(expLogs[0].Logs))
|
||||
suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash([]byte("tx_hash_1")), types.LogsToEthereum(expLogs[1].Logs))
|
||||
|
||||
req = &types.QueryBlockLogsRequest{
|
||||
Hash: hash.String(),
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
res, err := suite.queryClient.BlockLogs(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expLogs, res.TxLogs)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryBlockBloom() {
|
||||
var (
|
||||
req *types.QueryBlockBloomRequest
|
||||
expBloom []byte
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"bloom bytes not found for height",
|
||||
func() {},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
req = &types.QueryBlockBloomRequest{}
|
||||
bloom := ethtypes.BytesToBloom([]byte("bloom"))
|
||||
expBloom = bloom.Bytes()
|
||||
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 1, bloom)
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", suite.ctx.BlockHeight()))
|
||||
res, err := suite.queryClient.BlockBloom(ctx, req)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(expBloom, res.Bloom)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryParams() {
|
||||
ctx := sdk.WrapSDKContext(suite.ctx)
|
||||
expParams := types.DefaultParams()
|
||||
|
||||
res, err := suite.queryClient.Params(ctx, &types.QueryParamsRequest{})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(expParams, res.Params)
|
||||
}
|
||||
@@ -4,10 +4,8 @@ import (
|
||||
"math/big"
|
||||
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
@@ -27,7 +25,7 @@ func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), ethermint.NewPhotonCoinInt64(1))
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), ethermint.NewInjectiveCoinInt64(1))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
@@ -40,7 +38,7 @@ func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), ethermint.NewPhotonCoinInt64(1))
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), ethermint.NewInjectiveCoinInt64(1))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
|
||||
+235
-28
@@ -1,20 +1,17 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
"github.com/cosmos/ethermint/metrics"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// Keeper wraps the CommitStateDB, allowing us to pass in SDK context while adhering
|
||||
@@ -27,11 +24,12 @@ type Keeper struct {
|
||||
// - storing Account's Code
|
||||
// - storing transaction Logs
|
||||
// - storing block height -> bloom filter map. Needed for the Web3 API.
|
||||
// - storing block hash -> block height map. Needed for the Web3 API.
|
||||
// - storing block hash -> block height map. Needed for the Web3 API. TODO: remove
|
||||
storeKey sdk.StoreKey
|
||||
// Account Keeper for fetching accounts
|
||||
|
||||
accountKeeper types.AccountKeeper
|
||||
bankKeeper types.BankKeeper
|
||||
|
||||
// Ethermint concrete implementation on the EVM StateDB interface
|
||||
CommitStateDB *types.CommitStateDB
|
||||
// Transaction counter in a block. Used on StateSB's Prepare function.
|
||||
@@ -39,6 +37,12 @@ type Keeper struct {
|
||||
// on the KVStore or adding it as a field on the EVM genesis state.
|
||||
TxCount int
|
||||
Bloom *big.Int
|
||||
|
||||
// LogsCache keeps mapping of contract address -> eth logs emitted
|
||||
// during EVM execution in the current block.
|
||||
LogsCache map[common.Address][]*ethtypes.Log
|
||||
|
||||
svcTags metrics.Tags
|
||||
}
|
||||
|
||||
// NewKeeper generates new evm module keeper
|
||||
@@ -53,6 +57,10 @@ func NewKeeper(
|
||||
|
||||
// NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations
|
||||
return &Keeper{
|
||||
svcTags: metrics.Tags{
|
||||
"svc": "evm_k",
|
||||
},
|
||||
|
||||
cdc: cdc,
|
||||
accountKeeper: ak,
|
||||
bankKeeper: bankKeeper,
|
||||
@@ -60,19 +68,116 @@ func NewKeeper(
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak, bankKeeper),
|
||||
TxCount: 0,
|
||||
Bloom: big.NewInt(0),
|
||||
LogsCache: map[common.Address][]*ethtypes.Log{},
|
||||
}
|
||||
}
|
||||
|
||||
// Logger returns a module-specific logger.
|
||||
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
|
||||
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
|
||||
return ctx.Logger().With("module", types.ModuleName)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Epoch Height -> hash mapping functions
|
||||
// Required by EVM context's GetHashFunc
|
||||
// Block bloom bits mapping functions
|
||||
// Required by Web3 API.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// GetBlockBloom gets bloombits from block height
|
||||
func (k Keeper) GetBlockBloom(ctx sdk.Context, height int64) (ethtypes.Bloom, bool) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
key := types.BloomKey(height)
|
||||
has := store.Has(key)
|
||||
if !has {
|
||||
return ethtypes.Bloom{}, true // sometimes bloom not found, fix this
|
||||
}
|
||||
|
||||
bz := store.Get(key)
|
||||
return ethtypes.BytesToBloom(bz), true
|
||||
}
|
||||
|
||||
// SetBlockBloom sets the mapping from block height to bloom bits
|
||||
func (k Keeper) SetBlockBloom(ctx sdk.Context, height int64, bloom ethtypes.Bloom) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
key := types.BloomKey(height)
|
||||
store.Set(key, bloom.Bytes())
|
||||
}
|
||||
|
||||
// GetBlockHash gets block height from block consensus hash
|
||||
func (k Keeper) GetBlockHashFromHeight(ctx sdk.Context, height int64) ([]byte, bool) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := store.Get(types.KeyBlockHeightHash(uint64(height)))
|
||||
if len(bz) == 0 {
|
||||
return common.Hash{}.Bytes(), false
|
||||
}
|
||||
|
||||
return common.BytesToHash(bz).Bytes(), true
|
||||
}
|
||||
|
||||
// SetBlockHash sets the mapping from block consensus hash to block height
|
||||
func (k Keeper) SetBlockHash(ctx sdk.Context, hash []byte, height int64) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := sdk.Uint64ToBigEndian(uint64(height))
|
||||
store.Set(types.KeyBlockHash(common.BytesToHash(hash)), bz)
|
||||
}
|
||||
|
||||
// GetBlockHash gets block height from block consensus hash
|
||||
func (k Keeper) GetBlockHeightByHash(ctx sdk.Context, hash common.Hash) (int64, bool) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := store.Get(types.KeyBlockHash(hash))
|
||||
if len(bz) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
height := sdk.BigEndianToUint64(bz)
|
||||
return int64(height), true
|
||||
}
|
||||
|
||||
// SetBlockHash sets the mapping from block consensus hash to block height
|
||||
func (k Keeper) SetBlockHeightToHash(ctx sdk.Context, hash []byte, height int64) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Set(types.KeyBlockHeightHash(uint64(height)), hash)
|
||||
}
|
||||
|
||||
// SetTxReceiptToHash sets the mapping from tx hash to tx receipt
|
||||
func (k Keeper) SetTxReceiptToHash(ctx sdk.Context, hash common.Hash, receipt *types.TxReceipt) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
data := k.cdc.MustMarshalBinaryBare(receipt)
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Set(types.KeyHashTxReceipt(hash), data)
|
||||
}
|
||||
|
||||
// GetHeightHash returns the block header hash associated with a given block height and chain epoch number.
|
||||
func (k Keeper) GetHeightHash(ctx sdk.Context, height uint64) common.Hash {
|
||||
return k.CommitStateDB.WithContext(ctx).GetHeightHash(height)
|
||||
@@ -83,31 +188,121 @@ func (k Keeper) SetHeightHash(ctx sdk.Context, height uint64, hash common.Hash)
|
||||
k.CommitStateDB.WithContext(ctx).SetHeightHash(height, hash)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Block bloom bits mapping functions
|
||||
// Required by Web3 API.
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetTxReceiptFromHash gets tx receipt by tx hash.
|
||||
func (k Keeper) GetTxReceiptFromHash(ctx sdk.Context, hash common.Hash) (*types.TxReceipt, bool) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
// GetBlockBloom gets bloombits from block height
|
||||
func (k Keeper) GetBlockBloom(ctx sdk.Context, height int64) (ethtypes.Bloom, bool) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixBloom)
|
||||
has := store.Has(types.BloomKey(height))
|
||||
if !has {
|
||||
return ethtypes.Bloom{}, false
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
data := store.Get(types.KeyHashTxReceipt(hash))
|
||||
if data == nil || len(data) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
bz := store.Get(types.BloomKey(height))
|
||||
return ethtypes.BytesToBloom(bz), true
|
||||
var receipt types.TxReceipt
|
||||
k.cdc.MustUnmarshalBinaryBare(data, &receipt)
|
||||
|
||||
return &receipt, true
|
||||
}
|
||||
|
||||
// SetBlockBloom sets the mapping from block height to bloom bits
|
||||
func (k Keeper) SetBlockBloom(ctx sdk.Context, height int64, bloom ethtypes.Bloom) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixBloom)
|
||||
store.Set(types.BloomKey(height), bloom.Bytes())
|
||||
// AddTxHashToBlock stores tx hash in the list of tx for the block.
|
||||
func (k Keeper) AddTxHashToBlock(ctx sdk.Context, blockHeight int64, txHash common.Hash) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
key := types.KeyBlockHeightTxs(uint64(blockHeight))
|
||||
|
||||
list := types.BytesList{}
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
data := store.Get(key)
|
||||
if len(data) > 0 {
|
||||
k.cdc.MustUnmarshalBinaryBare(data, &list)
|
||||
}
|
||||
|
||||
list.Bytes = append(list.Bytes, txHash.Bytes())
|
||||
|
||||
data = k.cdc.MustMarshalBinaryBare(&list)
|
||||
store.Set(key, data)
|
||||
}
|
||||
|
||||
// GetTxsFromBlock returns list of tx hash in the block by height.
|
||||
func (k Keeper) GetTxsFromBlock(ctx sdk.Context, blockHeight int64) []common.Hash {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
key := types.KeyBlockHeightTxs(uint64(blockHeight))
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
data := store.Get(key)
|
||||
if len(data) > 0 {
|
||||
list := types.BytesList{}
|
||||
k.cdc.MustUnmarshalBinaryBare(data, &list)
|
||||
|
||||
txs := make([]common.Hash, 0, len(list.Bytes))
|
||||
for _, b := range list.Bytes {
|
||||
txs = append(txs, common.BytesToHash(b))
|
||||
}
|
||||
|
||||
return txs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTxReceiptsByBlockHeight gets tx receipts by block height.
|
||||
func (k Keeper) GetTxReceiptsByBlockHeight(ctx sdk.Context, blockHeight int64) []*types.TxReceipt {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
txs := k.GetTxsFromBlock(ctx, blockHeight)
|
||||
if len(txs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
receipts := make([]*types.TxReceipt, 0, len(txs))
|
||||
|
||||
for idx, txHash := range txs {
|
||||
data := store.Get(types.KeyHashTxReceipt(txHash))
|
||||
if data == nil || len(data) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var receipt types.TxReceipt
|
||||
k.cdc.MustUnmarshalBinaryBare(data, &receipt)
|
||||
receipt.Index = uint64(idx)
|
||||
receipts = append(receipts, &receipt)
|
||||
}
|
||||
|
||||
return receipts
|
||||
}
|
||||
|
||||
// GetTxReceiptsByBlockHash gets tx receipts by block hash.
|
||||
func (k Keeper) GetTxReceiptsByBlockHash(ctx sdk.Context, hash common.Hash) []*types.TxReceipt {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
blockHeight, ok := k.GetBlockHeightByHash(ctx, hash)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return k.GetTxReceiptsByBlockHeight(ctx, blockHeight)
|
||||
}
|
||||
|
||||
// GetAllTxLogs return all the transaction logs from the store.
|
||||
func (k Keeper) GetAllTxLogs(ctx sdk.Context) []types.TransactionLogs {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, types.KeyPrefixLogs)
|
||||
defer iterator.Close()
|
||||
@@ -125,6 +320,10 @@ func (k Keeper) GetAllTxLogs(ctx sdk.Context) []types.TransactionLogs {
|
||||
|
||||
// GetAccountStorage return state storage associated with an account
|
||||
func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) (types.Storage, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
storage := types.Storage{}
|
||||
|
||||
err := k.ForEachStorage(ctx, address, func(key, value common.Hash) bool {
|
||||
@@ -140,6 +339,10 @@ func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) (type
|
||||
|
||||
// GetChainConfig gets block height from block consensus hash
|
||||
func (k Keeper) GetChainConfig(ctx sdk.Context) (types.ChainConfig, bool) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := store.Get(types.KeyPrefixChainConfig)
|
||||
if len(bz) == 0 {
|
||||
@@ -153,6 +356,10 @@ func (k Keeper) GetChainConfig(ctx sdk.Context) (types.ChainConfig, bool) {
|
||||
|
||||
// SetChainConfig sets the mapping from block consensus hash to block height
|
||||
func (k Keeper) SetChainConfig(ctx sdk.Context, config types.ChainConfig) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := k.cdc.MustMarshalBinaryBare(&config)
|
||||
store.Set(types.KeyPrefixChainConfig, bz)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
@@ -32,24 +31,20 @@ var (
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
ctx sdk.Context
|
||||
app *app.EthermintApp
|
||||
queryClient types.QueryClient
|
||||
address ethcmn.Address
|
||||
ctx sdk.Context
|
||||
querier sdk.Querier
|
||||
app *app.InjectiveApp
|
||||
address ethcmn.Address
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(checkTx)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
|
||||
suite.address = ethcmn.HexToAddress(addrHex)
|
||||
|
||||
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
|
||||
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
|
||||
suite.queryClient = types.NewQueryClient(queryHelper)
|
||||
|
||||
balance := ethermint.NewPhotonCoin(sdk.ZeroInt())
|
||||
balance := ethermint.NewInjectiveCoin(sdk.ZeroInt())
|
||||
acc := ðermint.EthAccount{
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
@@ -69,13 +64,11 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
|
||||
Address: suite.address,
|
||||
Data: []byte("log"),
|
||||
BlockNumber: 10,
|
||||
Topics: []ethcmn.Hash{},
|
||||
}
|
||||
log2 := ðtypes.Log{
|
||||
Address: suite.address,
|
||||
Data: []byte("log2"),
|
||||
BlockNumber: 11,
|
||||
Topics: []ethcmn.Hash{},
|
||||
}
|
||||
expLogs := []*ethtypes.Log{log}
|
||||
|
||||
@@ -90,7 +83,6 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
|
||||
|
||||
// add another log under the zero hash
|
||||
suite.app.EvmKeeper.AddLog(suite.ctx, log2)
|
||||
log2.Index = 0
|
||||
logs = suite.app.EvmKeeper.AllLogs(suite.ctx)
|
||||
suite.Require().Equal(expLogs, logs)
|
||||
|
||||
@@ -99,19 +91,17 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
|
||||
Address: suite.address,
|
||||
Data: []byte("log3"),
|
||||
BlockNumber: 10,
|
||||
Topics: []ethcmn.Hash{},
|
||||
}
|
||||
suite.app.EvmKeeper.AddLog(suite.ctx, log3)
|
||||
log3.Index = 0
|
||||
|
||||
txLogs := suite.app.EvmKeeper.GetAllTxLogs(suite.ctx)
|
||||
suite.Require().Equal(2, len(txLogs))
|
||||
|
||||
suite.Require().Equal(ethcmn.Hash{}.String(), txLogs[0].Hash)
|
||||
suite.Require().Equal([]*ethtypes.Log{log2, log3}, txLogs[0].EthLogs())
|
||||
suite.Require().Equal([]*ethtypes.Log{log2, log3}, txLogs[0].Logs)
|
||||
|
||||
suite.Require().Equal(ethHash.String(), txLogs[1].Hash)
|
||||
suite.Require().Equal([]*ethtypes.Log{log}, txLogs[1].EthLogs())
|
||||
suite.Require().Equal([]*ethtypes.Log{log}, txLogs[1].Logs)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestDBStorage() {
|
||||
|
||||
+288
-36
@@ -2,57 +2,68 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/xlab/suplog"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/telemetry"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/ethermint/metrics"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var _ types.MsgServer = Keeper{}
|
||||
var _ types.MsgServer = &Keeper{}
|
||||
|
||||
func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
// EthereumTx implements the Msg/EthereumTx gRPC method.
|
||||
func (k Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// parse the chainID from a string to a base-10 integer
|
||||
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
|
||||
if err != nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify signature and retrieve sender address
|
||||
sender, err := msg.VerifySig(chainIDEpoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var homesteadErr error
|
||||
sender, eip155Err := msg.VerifySig(chainIDEpoch)
|
||||
if eip155Err != nil {
|
||||
sender, homesteadErr = msg.VerifySigHomestead()
|
||||
if homesteadErr != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"eip155_err": eip155Err.Error(),
|
||||
"homestead_err": homesteadErr.Error(),
|
||||
}).Warningln("failed to verify signatures with EIP155 and Homestead signers")
|
||||
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, errors.New("no valid signatures")
|
||||
}
|
||||
}
|
||||
|
||||
txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
|
||||
ethHash := ethcmn.BytesToHash(txHash)
|
||||
|
||||
var recipient *ethcmn.Address
|
||||
|
||||
labels := []metrics.Label{telemetry.NewLabel("operation", "create")}
|
||||
|
||||
if msg.Data.Recipient != nil {
|
||||
addr := ethcmn.HexToAddress(msg.Data.Recipient.Address)
|
||||
if len(msg.Data.Recipient) > 0 {
|
||||
addr := ethcmn.BytesToAddress(msg.Data.Recipient)
|
||||
recipient = &addr
|
||||
labels = []metrics.Label{telemetry.NewLabel("operation", "call")}
|
||||
}
|
||||
|
||||
st := types.StateTransition{
|
||||
st := &types.StateTransition{
|
||||
AccountNonce: msg.Data.AccountNonce,
|
||||
Price: msg.Data.Price.BigInt(),
|
||||
Price: new(big.Int).SetBytes(msg.Data.Price),
|
||||
GasLimit: msg.Data.GasLimit,
|
||||
Recipient: recipient,
|
||||
Amount: msg.Data.Amount.BigInt(),
|
||||
Amount: new(big.Int).SetBytes(msg.Data.Amount),
|
||||
Payload: msg.Data.Payload,
|
||||
Csdb: k.CommitStateDB.WithContext(ctx),
|
||||
ChainID: chainIDEpoch,
|
||||
@@ -66,18 +77,47 @@ func (k Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*ty
|
||||
// other nodes, causing a consensus error
|
||||
if !st.Simulate {
|
||||
// Prepare db for logs
|
||||
blockHash := types.HashFromContext(ctx)
|
||||
k.Prepare(ctx, ethHash, blockHash, k.TxCount)
|
||||
hash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
|
||||
k.Prepare(ctx, ethHash, ethcmn.BytesToHash(hash), k.TxCount)
|
||||
k.TxCount++
|
||||
}
|
||||
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
if !found {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, types.ErrChainConfigNotFound
|
||||
}
|
||||
|
||||
executionResult, err := st.TransitionDb(ctx, config)
|
||||
if err != nil {
|
||||
if err.Error() == "execution reverted" && executionResult != nil {
|
||||
// keep the execution result for revert reason
|
||||
executionResult.Response.Reverted = true
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
|
||||
if !st.Simulate {
|
||||
blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
|
||||
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
|
||||
Hash: ethHash.Bytes(),
|
||||
From: sender.Bytes(),
|
||||
Data: msg.Data,
|
||||
BlockHeight: uint64(ctx.BlockHeight()),
|
||||
BlockHash: blockHash,
|
||||
Result: &types.TxResult{
|
||||
ContractAddress: executionResult.Response.ContractAddress,
|
||||
Bloom: executionResult.Response.Bloom,
|
||||
TxLogs: executionResult.Response.TxLogs,
|
||||
Ret: executionResult.Response.Ret,
|
||||
Reverted: executionResult.Response.Reverted,
|
||||
GasUsed: executionResult.GasInfo.GasConsumed,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return executionResult.Response, nil
|
||||
}
|
||||
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -86,28 +126,42 @@ func (k Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*ty
|
||||
k.Bloom.Or(k.Bloom, executionResult.Bloom)
|
||||
|
||||
// update transaction logs in KVStore
|
||||
err = k.SetLogs(ctx, ethcmn.BytesToHash(txHash), executionResult.Logs)
|
||||
err = k.SetLogs(ctx, ethHash, executionResult.Logs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// add metrics for the transaction
|
||||
defer func() {
|
||||
if st.Amount.IsInt64() {
|
||||
telemetry.SetGaugeWithLabels(
|
||||
[]string{"tx", "msg", "ethereum"},
|
||||
float32(st.Amount.Int64()),
|
||||
labels,
|
||||
)
|
||||
blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
|
||||
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
|
||||
Hash: ethHash.Bytes(),
|
||||
From: sender.Bytes(),
|
||||
Data: msg.Data,
|
||||
Index: uint64(st.Csdb.TxIndex()),
|
||||
BlockHeight: uint64(ctx.BlockHeight()),
|
||||
BlockHash: blockHash,
|
||||
Result: &types.TxResult{
|
||||
ContractAddress: executionResult.Response.ContractAddress,
|
||||
Bloom: executionResult.Response.Bloom,
|
||||
TxLogs: executionResult.Response.TxLogs,
|
||||
Ret: executionResult.Response.Ret,
|
||||
Reverted: executionResult.Response.Reverted,
|
||||
GasUsed: executionResult.GasInfo.GasConsumed,
|
||||
},
|
||||
})
|
||||
|
||||
k.AddTxHashToBlock(ctx, ctx.BlockHeight(), ethHash)
|
||||
|
||||
for _, ethLog := range executionResult.Logs {
|
||||
k.LogsCache[ethLog.Address] = append(k.LogsCache[ethLog.Address], ethLog)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// emit events
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(sdk.AttributeKeyAmount, st.Amount.String()),
|
||||
sdk.NewAttribute(types.AttributeKeyTxHash, ethcmn.BytesToHash(txHash).Hex()),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
@@ -116,11 +170,209 @@ func (k Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*ty
|
||||
),
|
||||
})
|
||||
|
||||
if msg.Data.Recipient != nil {
|
||||
if len(msg.Data.Recipient) > 0 {
|
||||
ethAddr := ethcmn.BytesToAddress(msg.Data.Recipient)
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(types.AttributeKeyRecipient, msg.Data.Recipient.Address),
|
||||
sdk.NewAttribute(types.AttributeKeyRecipient, ethAddr.Hex()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return executionResult.Response, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) SendInternalEthereumTx(
|
||||
ctx sdk.Context,
|
||||
payload []byte,
|
||||
senderAddress common.Address,
|
||||
recipientAddress common.Address,
|
||||
) (*types.MsgEthereumTxResponse, error) {
|
||||
|
||||
accAddress := sdk.AccAddress(senderAddress.Bytes())
|
||||
|
||||
acc := k.accountKeeper.GetAccount(ctx, accAddress)
|
||||
if acc == nil {
|
||||
acc = k.accountKeeper.NewAccountWithAddress(ctx, accAddress)
|
||||
k.accountKeeper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
ethAccount, ok := acc.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
return nil, errors.New("could not cast account to EthAccount")
|
||||
}
|
||||
|
||||
if err := ethAccount.SetSequence(ethAccount.GetSequence() + 1); err != nil {
|
||||
return nil, errors.New("failed to set acc sequence")
|
||||
}
|
||||
|
||||
k.accountKeeper.SetAccount(ctx, ethAccount)
|
||||
|
||||
res, err := k.InternalEthereumTx(sdk.WrapSDKContext(ctx), senderAddress, &types.TxData{
|
||||
AccountNonce: ethAccount.GetSequence(),
|
||||
Recipient: recipientAddress.Bytes(),
|
||||
Amount: big.NewInt(0).Bytes(),
|
||||
Price: big.NewInt(0).Bytes(),
|
||||
GasLimit: 10000000, // TODO: don't hardcode, maybe set a limit?
|
||||
Payload: payload,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to execute InternalEthereumTx at contract %s", recipientAddress.Hex())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (k *Keeper) InternalEthereumTx(
|
||||
goCtx context.Context,
|
||||
sender common.Address,
|
||||
tx *types.TxData,
|
||||
) (*types.MsgEthereumTxResponse, error) {
|
||||
metrics.ReportFuncCall(k.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(k.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// parse the chainID from a string to a base-10 integer
|
||||
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
|
||||
if err != nil {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// true Ethereum tx hash based on its data
|
||||
ethHash := (&types.MsgEthereumTx{
|
||||
Data: tx,
|
||||
}).RLPSignBytes(chainIDEpoch)
|
||||
|
||||
var recipient *ethcmn.Address
|
||||
if len(tx.Recipient) > 0 {
|
||||
addr := ethcmn.BytesToAddress(tx.Recipient)
|
||||
recipient = &addr
|
||||
}
|
||||
|
||||
st := &types.StateTransition{
|
||||
AccountNonce: tx.AccountNonce,
|
||||
Price: new(big.Int).SetBytes(tx.Price),
|
||||
GasLimit: tx.GasLimit,
|
||||
Recipient: recipient,
|
||||
Amount: new(big.Int).SetBytes(tx.Amount),
|
||||
Payload: tx.Payload,
|
||||
Csdb: k.CommitStateDB.WithContext(ctx),
|
||||
ChainID: chainIDEpoch,
|
||||
TxHash: ðHash,
|
||||
Sender: sender,
|
||||
Simulate: ctx.IsCheckTx(),
|
||||
}
|
||||
|
||||
// since the txCount is used by the stateDB, and a simulated tx is run only on the node it's submitted to,
|
||||
// then this will cause the txCount/stateDB of the node that ran the simulated tx to be different than the
|
||||
// other nodes, causing a consensus error
|
||||
if !st.Simulate {
|
||||
// Prepare db for logs
|
||||
hash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
|
||||
k.Prepare(ctx, ethHash, ethcmn.BytesToHash(hash), k.TxCount)
|
||||
k.TxCount++
|
||||
}
|
||||
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
if !found {
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, types.ErrChainConfigNotFound
|
||||
}
|
||||
|
||||
executionResult, err := st.TransitionDb(ctx, config)
|
||||
if err != nil {
|
||||
if err.Error() == "execution reverted" && executionResult != nil {
|
||||
// keep the execution result for revert reason
|
||||
executionResult.Response.Reverted = true
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
|
||||
if !st.Simulate {
|
||||
blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
|
||||
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
|
||||
Hash: ethHash.Bytes(),
|
||||
From: sender.Bytes(),
|
||||
Data: tx,
|
||||
BlockHeight: uint64(ctx.BlockHeight()),
|
||||
BlockHash: blockHash,
|
||||
Result: &types.TxResult{
|
||||
ContractAddress: executionResult.Response.ContractAddress,
|
||||
Bloom: executionResult.Response.Bloom,
|
||||
TxLogs: executionResult.Response.TxLogs,
|
||||
Ret: executionResult.Response.Ret,
|
||||
Reverted: executionResult.Response.Reverted,
|
||||
GasUsed: executionResult.GasInfo.GasConsumed,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return executionResult.Response, err
|
||||
}
|
||||
|
||||
metrics.ReportFuncError(k.svcTags)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
|
||||
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
|
||||
Hash: ethHash.Bytes(),
|
||||
From: sender.Bytes(),
|
||||
Data: tx,
|
||||
Index: uint64(st.Csdb.TxIndex()),
|
||||
BlockHeight: uint64(ctx.BlockHeight()),
|
||||
BlockHash: blockHash,
|
||||
Result: &types.TxResult{
|
||||
ContractAddress: executionResult.Response.ContractAddress,
|
||||
Bloom: executionResult.Response.Bloom,
|
||||
TxLogs: executionResult.Response.TxLogs,
|
||||
Ret: executionResult.Response.Ret,
|
||||
Reverted: executionResult.Response.Reverted,
|
||||
GasUsed: executionResult.GasInfo.GasConsumed,
|
||||
},
|
||||
})
|
||||
|
||||
k.AddTxHashToBlock(ctx, ctx.BlockHeight(), ethHash)
|
||||
|
||||
if !st.Simulate {
|
||||
// update block bloom filter
|
||||
k.Bloom.Or(k.Bloom, executionResult.Bloom)
|
||||
|
||||
// update transaction logs in KVStore
|
||||
err = k.SetLogs(ctx, ethHash, executionResult.Logs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, ethLog := range executionResult.Logs {
|
||||
k.LogsCache[ethLog.Address] = append(k.LogsCache[ethLog.Address], ethLog)
|
||||
}
|
||||
}
|
||||
|
||||
// emit events
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(sdk.AttributeKeyAmount, st.Amount.String()),
|
||||
sdk.NewAttribute(types.AttributeKeyTxHash, ethHash.Hex()),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
sdk.NewAttribute(sdk.AttributeKeySender, sender.String()),
|
||||
),
|
||||
})
|
||||
|
||||
if len(tx.Recipient) > 0 {
|
||||
ethAddr := ethcmn.BytesToAddress(tx.Recipient)
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(types.AttributeKeyRecipient, ethAddr.Hex()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
func (suite *KeeperTestSuite) TestParams() {
|
||||
params := suite.app.EvmKeeper.GetParams(suite.ctx)
|
||||
suite.Require().Equal(types.DefaultParams(), params)
|
||||
params.EvmDenom = "ara"
|
||||
params.EvmDenom = "inj"
|
||||
suite.app.EvmKeeper.SetParams(suite.ctx, params)
|
||||
newParams := suite.app.EvmKeeper.GetParams(suite.ctx)
|
||||
suite.Require().Equal(newParams, params)
|
||||
|
||||
@@ -49,6 +49,11 @@ func (k *Keeper) SetCode(ctx sdk.Context, addr ethcmn.Address, code []byte) {
|
||||
|
||||
// SetLogs calls CommitStateDB.SetLogs using the passed in context
|
||||
func (k *Keeper) SetLogs(ctx sdk.Context, hash ethcmn.Hash, logs []*ethtypes.Log) error {
|
||||
// TODO:@albert
|
||||
// since SetLogs is only called for non-simulation mode, GasEstimation is quite not correct
|
||||
// I suggest using ctx.ConsumeGas(XXX) where XXX is max of gas consume for set logs.
|
||||
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
return k.CommitStateDB.WithContext(ctx).SetLogs(hash, logs)
|
||||
}
|
||||
|
||||
@@ -225,8 +230,8 @@ func (k *Keeper) Reset(ctx sdk.Context, root ethcmn.Hash) error {
|
||||
}
|
||||
|
||||
// Prepare calls CommitStateDB.Prepare using the passed in context
|
||||
func (k *Keeper) Prepare(ctx sdk.Context, thash ethcmn.Hash, txi int) {
|
||||
k.CommitStateDB.WithContext(ctx).Prepare(thash, txi)
|
||||
func (k *Keeper) Prepare(ctx sdk.Context, thash, bhash ethcmn.Hash, txi int) {
|
||||
k.CommitStateDB.WithContext(ctx).Prepare(thash, bhash, txi)
|
||||
}
|
||||
|
||||
// CreateAccount calls CommitStateDB.CreateAccount using the passed in context
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
func (suite *KeeperTestSuite) TestBloomFilter() {
|
||||
// Prepare db for logs
|
||||
tHash := ethcmn.BytesToHash([]byte{0x1})
|
||||
suite.app.EvmKeeper.Prepare(suite.ctx, tHash, 0)
|
||||
suite.app.EvmKeeper.Prepare(suite.ctx, tHash, ethcmn.Hash{}, 0)
|
||||
contractAddress := ethcmn.BigToAddress(big.NewInt(1))
|
||||
log := ethtypes.Log{Address: contractAddress, Topics: []ethcmn.Hash{}}
|
||||
|
||||
@@ -230,7 +230,6 @@ func (suite *KeeperTestSuite) TestStateDB_Logs() {
|
||||
suite.Require().Empty(dbLogs, tc.name)
|
||||
|
||||
suite.app.EvmKeeper.AddLog(suite.ctx, tc.log)
|
||||
tc.log.Index = 0 // reset index
|
||||
suite.Require().Equal(logs, suite.app.EvmKeeper.AllLogs(suite.ctx), tc.name)
|
||||
|
||||
//resets state but checking to see if storekey still persists.
|
||||
@@ -360,8 +359,7 @@ func (suite *KeeperTestSuite) TestSuiteDB_Prepare() {
|
||||
bhash := ethcmn.BytesToHash([]byte("bhash"))
|
||||
txi := 1
|
||||
|
||||
suite.app.EvmKeeper.Prepare(suite.ctx, thash, txi)
|
||||
suite.app.EvmKeeper.CommitStateDB.SetBlockHash(bhash)
|
||||
suite.app.EvmKeeper.Prepare(suite.ctx, thash, bhash, txi)
|
||||
|
||||
suite.Require().Equal(txi, suite.app.EvmKeeper.TxIndex(suite.ctx))
|
||||
suite.Require().Equal(bhash, suite.app.EvmKeeper.BlockHash(suite.ctx))
|
||||
|
||||
+15
-12
@@ -57,17 +57,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, _ client.TxEncodi
|
||||
|
||||
// RegisterRESTRoutes performs a no-op as the EVM module doesn't expose REST
|
||||
// endpoints
|
||||
func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {
|
||||
func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {
|
||||
}
|
||||
|
||||
// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the evm module.
|
||||
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
|
||||
if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil {
|
||||
func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) {
|
||||
if err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(c)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTxCmd returns nil as the evm module doesn't support transactions through the CLI.
|
||||
// GetTxCmd returns the root tx command for the evm module.
|
||||
func (AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||
return nil
|
||||
}
|
||||
@@ -82,7 +81,7 @@ func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry)
|
||||
types.RegisterInterfaces(registry)
|
||||
}
|
||||
|
||||
// ____________________________________________________________________________
|
||||
//____________________________________________________________________________
|
||||
|
||||
// AppModule implements an application module for the evm module.
|
||||
type AppModule struct {
|
||||
@@ -107,20 +106,23 @@ func (AppModule) Name() string {
|
||||
return types.ModuleName
|
||||
}
|
||||
|
||||
// RegisterInvariants interface for registering invariants
|
||||
// RegisterInvariants interface for registering invariants. Performs a no-op
|
||||
// as the evm module doesn't expose invariants.
|
||||
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
|
||||
keeper.RegisterInvariants(ir, *am.keeper)
|
||||
// Invariats lead to performance degradation
|
||||
//
|
||||
// keeper.RegisterInvariants(ir, *am.keeper)
|
||||
}
|
||||
|
||||
// RegisterServices registers the evm module Msg and gRPC services.
|
||||
// RegisterQueryService registers a GRPC query service to respond to the
|
||||
// module-specific GRPC queries.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
|
||||
}
|
||||
|
||||
// Route returns the message routing key for the evm module.
|
||||
func (am AppModule) Route() sdk.Route {
|
||||
return sdk.NewRoute(types.RouterKey, NewHandler(*am.keeper))
|
||||
return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper))
|
||||
}
|
||||
|
||||
// QuerierRoute returns the evm module's querier route name.
|
||||
@@ -149,7 +151,8 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data j
|
||||
var genesisState types.GenesisState
|
||||
|
||||
cdc.MustUnmarshalJSON(data, &genesisState)
|
||||
return InitGenesis(ctx, *am.keeper, am.ak, am.bk, genesisState)
|
||||
InitGenesis(ctx, *am.keeper, am.ak, am.bk, genesisState)
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
// ExportGenesis returns the exported genesis state as raw bytes for the evm
|
||||
|
||||
@@ -28,12 +28,13 @@ func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
|
||||
PetersburgBlock: getBlockValue(cc.PetersburgBlock),
|
||||
IstanbulBlock: getBlockValue(cc.IstanbulBlock),
|
||||
MuirGlacierBlock: getBlockValue(cc.MuirGlacierBlock),
|
||||
YoloV2Block: getBlockValue(cc.YoloV2Block),
|
||||
EWASMBlock: getBlockValue(cc.EWASMBlock),
|
||||
//TODO(xlab): after upgrading ethereum to newer version, this should be set to YoloV2Block
|
||||
YoloV2Block: getBlockValue(cc.YoloV2Block),
|
||||
EWASMBlock: getBlockValue(cc.EWASMBlock),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultChainConfig returns default evm parameters.
|
||||
// DefaultChainConfig returns default evm parameters. Th
|
||||
func DefaultChainConfig() ChainConfig {
|
||||
return ChainConfig{
|
||||
HomesteadBlock: sdk.ZeroInt(),
|
||||
@@ -46,8 +47,8 @@ func DefaultChainConfig() ChainConfig {
|
||||
ByzantiumBlock: sdk.ZeroInt(),
|
||||
ConstantinopleBlock: sdk.ZeroInt(),
|
||||
PetersburgBlock: sdk.ZeroInt(),
|
||||
IstanbulBlock: sdk.ZeroInt(),
|
||||
MuirGlacierBlock: sdk.ZeroInt(),
|
||||
IstanbulBlock: sdk.NewInt(-1),
|
||||
MuirGlacierBlock: sdk.NewInt(-1),
|
||||
YoloV2Block: sdk.NewInt(-1),
|
||||
EWASMBlock: sdk.NewInt(-1),
|
||||
}
|
||||
@@ -125,13 +126,3 @@ func validateBlock(block sdk.Int) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsIstanbul returns whether the Istanbul version is enabled.
|
||||
func (cc ChainConfig) IsIstanbul() bool {
|
||||
return getBlockValue(cc.IstanbulBlock) != nil
|
||||
}
|
||||
|
||||
// IsHomestead returns whether the Homestead version is enabled.
|
||||
func (cc ChainConfig) IsHomestead() bool {
|
||||
return getBlockValue(cc.HomesteadBlock) != nil
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ func TestChainConfigValidate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestChainConfig_String(t *testing.T) {
|
||||
configStr := `homestead_block:"0" dao_fork_block:"0" dao_fork_support:true eip150_block:"0" eip150_hash:"0x0000000000000000000000000000000000000000000000000000000000000000" eip155_block:"0" eip158_block:"0" byzantium_block:"0" constantinople_block:"0" petersburg_block:"0" istanbul_block:"-1" muir_glacier_block:"-1" yolo_v2_block:"-1" ewasm_block:"-1" `
|
||||
config := DefaultChainConfig()
|
||||
configStr := `homestead_block:"0" dao_fork_block:"0" dao_fork_support:true eip150_block:"0" eip150_hash:"0x0000000000000000000000000000000000000000000000000000000000000000" eip155_block:"0" eip158_block:"0" byzantium_block:"0" constantinople_block:"0" petersburg_block:"0" istanbul_block:"0" muir_glacier_block:"0" yolo_v2_block:"-1" ewasm_block:"-1" `
|
||||
require.Equal(t, configStr, config.String())
|
||||
}
|
||||
|
||||
+16
-11
@@ -4,28 +4,33 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
)
|
||||
|
||||
type (
|
||||
ExtensionOptionsEthereumTxI interface{}
|
||||
ExtensionOptionsWeb3TxI interface{}
|
||||
)
|
||||
|
||||
// RegisterInterfaces registers the client interfaces to protobuf Any.
|
||||
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||
registry.RegisterImplementations(
|
||||
(*sdk.Tx)(nil),
|
||||
&MsgEthereumTx{},
|
||||
)
|
||||
registry.RegisterImplementations(
|
||||
(*sdk.Msg)(nil),
|
||||
&MsgEthereumTx{},
|
||||
)
|
||||
|
||||
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||
registry.RegisterInterface("injective.evm.v1beta1.ExtensionOptionsEthereumTx", (*ExtensionOptionsEthereumTxI)(nil))
|
||||
registry.RegisterImplementations(
|
||||
(*ExtensionOptionsEthereumTxI)(nil),
|
||||
&ExtensionOptionsEthereumTx{},
|
||||
)
|
||||
|
||||
registry.RegisterInterface("injective.evm.v1beta1.ExtensionOptionsWeb3Tx", (*ExtensionOptionsWeb3TxI)(nil))
|
||||
registry.RegisterImplementations(
|
||||
(*ExtensionOptionsWeb3TxI)(nil),
|
||||
&ExtensionOptionsWeb3Tx{},
|
||||
)
|
||||
}
|
||||
|
||||
var (
|
||||
// ModuleCdc references the global evm module codec. Note, the codec should
|
||||
// ONLY be used in certain instances of tests and for JSON encoding.
|
||||
//
|
||||
// The actual codec used for serialization should be provided to x/evm and
|
||||
// defined at the application level.
|
||||
ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
|
||||
)
|
||||
|
||||
+14
-2
@@ -25,9 +25,21 @@ var (
|
||||
// ErrBloomNotFound returns an error if the block bloom cannot be found on the store.
|
||||
ErrBloomNotFound = sdkerrors.Register(ModuleName, 7, "block bloom not found")
|
||||
|
||||
// ErrInvalidValue returns an error resulting from an invalid value.
|
||||
ErrInvalidValue = sdkerrors.Register(ModuleName, 8, "invalid value")
|
||||
|
||||
// ErrInvalidChainID returns an error resulting from an invalid chain ID.
|
||||
ErrInvalidChainID = sdkerrors.Register(ModuleName, 9, "invalid chain ID")
|
||||
|
||||
// ErrVMExecution returns an error resulting from an error in EVM execution.
|
||||
ErrVMExecution = sdkerrors.Register(ModuleName, 10, "error while executing evm transaction")
|
||||
|
||||
// ErrTxReceiptNotFound returns an error if the transaction receipt could not be found
|
||||
ErrTxReceiptNotFound = sdkerrors.Register(ModuleName, 11, "transaction receipt not found")
|
||||
|
||||
// ErrCreateDisabled returns an error if the EnableCreate parameter is false.
|
||||
ErrCreateDisabled = sdkerrors.Register(ModuleName, 8, "EVM Create operation is disabled")
|
||||
ErrCreateDisabled = sdkerrors.Register(ModuleName, 12, "EVM Create operation is disabled")
|
||||
|
||||
// ErrCallDisabled returns an error if the EnableCall parameter is false.
|
||||
ErrCallDisabled = sdkerrors.Register(ModuleName, 9, "EVM Call operation is disabled")
|
||||
ErrCallDisabled = sdkerrors.Register(ModuleName, 13, "EVM Call operation is disabled")
|
||||
)
|
||||
|
||||
@@ -6,5 +6,6 @@ const (
|
||||
|
||||
AttributeKeyContractAddress = "contract"
|
||||
AttributeKeyRecipient = "recipient"
|
||||
AttributeKeyTxHash = "txHash"
|
||||
AttributeValueCategory = ModuleName
|
||||
)
|
||||
|
||||
+1614
-97
File diff suppressed because it is too large
Load Diff
@@ -4,13 +4,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// Validate performs a basic validation of a GenesisAccount fields.
|
||||
func (ga GenesisAccount) Validate() error {
|
||||
if ethermint.IsZeroAddress(ga.Address) {
|
||||
if IsZeroAddress(ga.Address) {
|
||||
return fmt.Errorf("address cannot be the zero address %s", ga.Address)
|
||||
}
|
||||
if len(ethcmn.Hex2Bytes(ga.Code)) == 0 {
|
||||
|
||||
+37
-42
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: ethermint/evm/v1alpha1/genesis.proto
|
||||
// source: injective/evm/v1beta1/genesis.proto
|
||||
|
||||
package types
|
||||
|
||||
@@ -38,7 +38,7 @@ func (m *GenesisState) Reset() { *m = GenesisState{} }
|
||||
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenesisState) ProtoMessage() {}
|
||||
func (*GenesisState) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8205a12b97b89a87, []int{0}
|
||||
return fileDescriptor_edebcfd612cffc8a, []int{0}
|
||||
}
|
||||
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -111,7 +111,7 @@ func (m *GenesisAccount) Reset() { *m = GenesisAccount{} }
|
||||
func (m *GenesisAccount) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenesisAccount) ProtoMessage() {}
|
||||
func (*GenesisAccount) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8205a12b97b89a87, []int{1}
|
||||
return fileDescriptor_edebcfd612cffc8a, []int{1}
|
||||
}
|
||||
func (m *GenesisAccount) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -162,42 +162,43 @@ func (m *GenesisAccount) GetStorage() Storage {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*GenesisState)(nil), "ethermint.evm.v1alpha1.GenesisState")
|
||||
proto.RegisterType((*GenesisAccount)(nil), "ethermint.evm.v1alpha1.GenesisAccount")
|
||||
proto.RegisterType((*GenesisState)(nil), "injective.evm.v1beta1.GenesisState")
|
||||
proto.RegisterType((*GenesisAccount)(nil), "injective.evm.v1beta1.GenesisAccount")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("ethermint/evm/v1alpha1/genesis.proto", fileDescriptor_8205a12b97b89a87)
|
||||
proto.RegisterFile("injective/evm/v1beta1/genesis.proto", fileDescriptor_edebcfd612cffc8a)
|
||||
}
|
||||
|
||||
var fileDescriptor_8205a12b97b89a87 = []byte{
|
||||
// 405 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xb1, 0x8e, 0xda, 0x30,
|
||||
0x18, 0xc7, 0x13, 0x40, 0x04, 0x0c, 0x2a, 0x92, 0x5b, 0xb5, 0x11, 0x55, 0x03, 0x4a, 0xab, 0xc2,
|
||||
0x94, 0x08, 0xba, 0x55, 0x5d, 0x08, 0x43, 0x19, 0x3a, 0x54, 0xa1, 0x53, 0x3b, 0x20, 0x63, 0x5c,
|
||||
0x27, 0x12, 0x89, 0xa3, 0xd8, 0x20, 0x78, 0x83, 0x1b, 0xef, 0x39, 0xee, 0x49, 0x18, 0x19, 0x99,
|
||||
0xb8, 0x13, 0xbc, 0xc1, 0x3d, 0xc1, 0x29, 0x4e, 0x02, 0x77, 0xd2, 0x65, 0x73, 0xa4, 0xdf, 0xff,
|
||||
0xe7, 0x7f, 0x3e, 0x7f, 0xe0, 0x0b, 0x11, 0x1e, 0x89, 0x03, 0x3f, 0x14, 0x36, 0x59, 0x07, 0xf6,
|
||||
0x7a, 0x80, 0x96, 0x91, 0x87, 0x06, 0x36, 0x25, 0x21, 0xe1, 0x3e, 0xb7, 0xa2, 0x98, 0x09, 0x06,
|
||||
0xdf, 0x5f, 0x28, 0x8b, 0xac, 0x03, 0x2b, 0xa7, 0xda, 0xef, 0x28, 0xa3, 0x4c, 0x22, 0x76, 0x72,
|
||||
0x4a, 0xe9, 0x76, 0xb7, 0xc0, 0x99, 0x44, 0x25, 0x61, 0x1e, 0x4a, 0xa0, 0xf9, 0x33, 0xbd, 0x61,
|
||||
0x2a, 0x90, 0x20, 0x70, 0x02, 0x6a, 0x08, 0x63, 0xb6, 0x0a, 0x05, 0xd7, 0xd5, 0x6e, 0xb9, 0xdf,
|
||||
0x18, 0x7e, 0xb5, 0x5e, 0xbf, 0xd3, 0xca, 0x72, 0xa3, 0x14, 0x77, 0x2a, 0xbb, 0x63, 0x47, 0x71,
|
||||
0x2f, 0x69, 0x88, 0x41, 0x13, 0x7b, 0xc8, 0x0f, 0x67, 0x98, 0x85, 0xff, 0x7d, 0xaa, 0x97, 0xba,
|
||||
0x6a, 0xbf, 0x31, 0xfc, 0x5c, 0x64, 0x1b, 0x27, 0xec, 0x58, 0xa2, 0xce, 0xc7, 0x44, 0xf5, 0x78,
|
||||
0xec, 0xbc, 0xdd, 0xa2, 0x60, 0xf9, 0xdd, 0x7c, 0xae, 0x31, 0xdd, 0x06, 0xbe, 0x92, 0xf0, 0x07,
|
||||
0xa8, 0x46, 0x28, 0x46, 0x01, 0xd7, 0xcb, 0x52, 0x6f, 0x14, 0xe9, 0x7f, 0x4b, 0x2a, 0x2b, 0x99,
|
||||
0x65, 0xe0, 0x3f, 0x50, 0x13, 0x1b, 0x3e, 0x5b, 0x32, 0xca, 0xf5, 0x8a, 0xfc, 0xd9, 0x5e, 0x51,
|
||||
0xfe, 0x4f, 0x8c, 0x42, 0x8e, 0xb0, 0xf0, 0x59, 0xf8, 0x8b, 0x51, 0xee, 0x7c, 0xc8, 0x2a, 0xb6,
|
||||
0xd2, 0x8a, 0xb9, 0xc6, 0x74, 0x35, 0xb1, 0xe1, 0x09, 0x61, 0xde, 0xa8, 0xe0, 0xcd, 0xcb, 0x11,
|
||||
0x41, 0x1d, 0x68, 0x68, 0xb1, 0x88, 0x09, 0x4f, 0x66, 0xab, 0xf6, 0xeb, 0x6e, 0xfe, 0x09, 0x21,
|
||||
0xa8, 0x60, 0xb6, 0x20, 0x72, 0x48, 0x75, 0x57, 0x9e, 0xe1, 0x04, 0x68, 0x5c, 0xb0, 0x18, 0x51,
|
||||
0xa2, 0x97, 0x65, 0xb9, 0x4f, 0x45, 0xe5, 0xe4, 0xd3, 0x39, 0xad, 0xa4, 0xd2, 0xdd, 0x7d, 0x47,
|
||||
0x9b, 0xa6, 0x29, 0x37, 0x8f, 0x3b, 0xa3, 0xdd, 0xc9, 0x50, 0xf7, 0x27, 0x43, 0x7d, 0x38, 0x19,
|
||||
0xea, 0xed, 0xd9, 0x50, 0xf6, 0x67, 0x43, 0x39, 0x9c, 0x0d, 0xe5, 0x6f, 0x8f, 0xfa, 0xc2, 0x5b,
|
||||
0xcd, 0x2d, 0xcc, 0x02, 0x1b, 0x33, 0x1e, 0x30, 0x6e, 0x5f, 0x77, 0x66, 0x23, 0xb7, 0x46, 0x6c,
|
||||
0x23, 0xc2, 0xe7, 0x55, 0xb9, 0x2f, 0xdf, 0x9e, 0x02, 0x00, 0x00, 0xff, 0xff, 0xf3, 0x74, 0xbc,
|
||||
0x46, 0xa7, 0x02, 0x00, 0x00,
|
||||
var fileDescriptor_edebcfd612cffc8a = []byte{
|
||||
// 420 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x8e, 0xd2, 0x40,
|
||||
0x18, 0xc7, 0xdb, 0x85, 0x6c, 0x77, 0x87, 0x8d, 0x9b, 0x8c, 0x1a, 0x1b, 0xd4, 0x96, 0xd4, 0x68,
|
||||
0xb8, 0xd8, 0x06, 0xbc, 0xe9, 0xc9, 0x72, 0x20, 0x24, 0x1c, 0x4c, 0xf1, 0xc4, 0x85, 0x4c, 0xa7,
|
||||
0xe3, 0x50, 0x43, 0x3b, 0xa4, 0x33, 0x34, 0xf0, 0x04, 0x5e, 0x7d, 0x0e, 0x9f, 0x84, 0x23, 0x07,
|
||||
0x0f, 0x9e, 0xd0, 0xc0, 0x1b, 0xf8, 0x04, 0x66, 0xa6, 0x2d, 0xb2, 0x09, 0xbd, 0xcd, 0x24, 0xbf,
|
||||
0xff, 0x6f, 0xfe, 0xfd, 0xfa, 0x81, 0x57, 0x71, 0xfa, 0x95, 0x60, 0x11, 0xe7, 0xc4, 0x23, 0x79,
|
||||
0xe2, 0xe5, 0xbd, 0x90, 0x08, 0xd4, 0xf3, 0x28, 0x49, 0x09, 0x8f, 0xb9, 0xbb, 0xcc, 0x98, 0x60,
|
||||
0xf0, 0xe9, 0x09, 0x72, 0x49, 0x9e, 0xb8, 0x25, 0xd4, 0x7e, 0x42, 0x19, 0x65, 0x8a, 0xf0, 0xe4,
|
||||
0xa9, 0x80, 0xdb, 0xf6, 0x65, 0xa3, 0x0c, 0x2a, 0xc0, 0xf9, 0x79, 0x05, 0xee, 0x86, 0x85, 0x7f,
|
||||
0x22, 0x90, 0x20, 0x70, 0x08, 0x6e, 0x10, 0xc6, 0x6c, 0x95, 0x0a, 0x6e, 0xea, 0x9d, 0x46, 0xb7,
|
||||
0xd5, 0x7f, 0xed, 0x5e, 0x7c, 0xd1, 0x2d, 0x63, 0x1f, 0x0b, 0xda, 0x6f, 0x6e, 0xf7, 0xb6, 0x16,
|
||||
0x9c, 0xc2, 0x30, 0x04, 0x77, 0x78, 0x8e, 0xe2, 0x74, 0x86, 0x59, 0xfa, 0x25, 0xa6, 0xe6, 0x55,
|
||||
0x47, 0xef, 0xb6, 0xfa, 0x4e, 0x8d, 0x6c, 0x20, 0xd1, 0x81, 0x22, 0xfd, 0xe7, 0xd2, 0xf4, 0x77,
|
||||
0x6f, 0x3f, 0xde, 0xa0, 0x64, 0xf1, 0xde, 0x39, 0xb7, 0x38, 0x41, 0x0b, 0xff, 0x27, 0xe1, 0x07,
|
||||
0x70, 0xbd, 0x44, 0x19, 0x4a, 0xb8, 0xd9, 0x50, 0xf6, 0x97, 0x35, 0xf6, 0x4f, 0x0a, 0x2a, 0x2b,
|
||||
0x96, 0x11, 0x38, 0x05, 0x37, 0x62, 0xcd, 0x67, 0x0b, 0x46, 0xb9, 0xd9, 0x54, 0x5f, 0xfa, 0xa6,
|
||||
0x26, 0xfe, 0x39, 0x43, 0x29, 0x47, 0x58, 0xc4, 0x2c, 0x1d, 0x33, 0xca, 0xfd, 0x67, 0x65, 0xc1,
|
||||
0xfb, 0xa2, 0x60, 0x65, 0x71, 0x02, 0x43, 0xac, 0xb9, 0x24, 0x9c, 0x6f, 0x3a, 0x78, 0xf4, 0x70,
|
||||
0x3e, 0xd0, 0x04, 0x06, 0x8a, 0xa2, 0x8c, 0x70, 0x39, 0x57, 0xbd, 0x7b, 0x1b, 0x54, 0x57, 0x08,
|
||||
0x41, 0x13, 0xb3, 0x88, 0xa8, 0x09, 0xdd, 0x06, 0xea, 0x0c, 0x87, 0xc0, 0xe0, 0x82, 0x65, 0x88,
|
||||
0x12, 0xb3, 0xa1, 0xba, 0xbd, 0xa8, 0xe9, 0xa6, 0xfe, 0x9a, 0x7f, 0x2f, 0x1b, 0xfd, 0xf8, 0x6d,
|
||||
0x1b, 0x93, 0x22, 0x14, 0x54, 0x69, 0x1f, 0x6f, 0x0f, 0x96, 0xbe, 0x3b, 0x58, 0xfa, 0x9f, 0x83,
|
||||
0xa5, 0x7f, 0x3f, 0x5a, 0xda, 0xee, 0x68, 0x69, 0xbf, 0x8e, 0x96, 0x36, 0x1d, 0xd1, 0x58, 0xcc,
|
||||
0x57, 0xa1, 0x8b, 0x59, 0xe2, 0x8d, 0x2a, 0xf7, 0x18, 0x85, 0xdc, 0x3b, 0xbd, 0xf4, 0x16, 0xb3,
|
||||
0x8c, 0x9c, 0x5f, 0xe5, 0xec, 0xbd, 0x84, 0x45, 0xab, 0x05, 0xe1, 0x6a, 0xa3, 0xc4, 0x66, 0x49,
|
||||
0x78, 0x78, 0xad, 0x96, 0xe9, 0xdd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xed, 0x3b, 0xae, 0x70,
|
||||
0xc1, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
|
||||
@@ -556,10 +557,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -707,10 +705,7 @@ func (m *GenesisAccount) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
@@ -42,6 +43,7 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
"valid genesis account",
|
||||
GenesisAccount{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
NewState(suite.hash, suite.hash),
|
||||
@@ -53,6 +55,23 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
"empty account address bytes",
|
||||
GenesisAccount{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
Balance: sdk.OneInt(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty account balance",
|
||||
GenesisAccount{
|
||||
Address: suite.address,
|
||||
Balance: sdk.Int{},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"negative account balance",
|
||||
GenesisAccount{
|
||||
Address: suite.address,
|
||||
Balance: sdk.NewInt(-1),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -60,6 +79,7 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
"empty code bytes",
|
||||
GenesisAccount{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: "",
|
||||
},
|
||||
false,
|
||||
@@ -78,6 +98,7 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
}
|
||||
|
||||
func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
genState *GenesisState
|
||||
@@ -94,6 +115,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
{Key: suite.hash.String()},
|
||||
@@ -145,6 +167,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
NewState(suite.hash, suite.hash),
|
||||
@@ -152,6 +175,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
NewState(suite.hash, suite.hash),
|
||||
@@ -167,6 +191,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
{Key: suite.hash.String()},
|
||||
@@ -216,6 +241,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address,
|
||||
Balance: sdk.OneInt(),
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
{Key: suite.hash.String()},
|
||||
|
||||
@@ -5,14 +5,14 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmdb "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
@@ -26,9 +26,10 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
ethermintcodec "github.com/cosmos/ethermint/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
ethcodec "github.com/cosmos/ethermint/codec"
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
)
|
||||
|
||||
func newTestCodec() (codec.BinaryMarshaler, *codec.LegacyAmino) {
|
||||
@@ -38,7 +39,7 @@ func newTestCodec() (codec.BinaryMarshaler, *codec.LegacyAmino) {
|
||||
|
||||
sdk.RegisterLegacyAminoCodec(amino)
|
||||
|
||||
ethermintcodec.RegisterInterfaces(interfaceRegistry)
|
||||
ethcodec.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
return cdc, amino
|
||||
}
|
||||
@@ -61,7 +62,7 @@ func (suite *JournalTestSuite) SetupTest() {
|
||||
suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
suite.journal = newJournal()
|
||||
|
||||
balance := ethermint.NewPhotonCoin(sdk.NewInt(100))
|
||||
balance := ethermint.NewInjectiveCoin(sdk.NewInt(100))
|
||||
acc := ðermint.EthAccount{
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
|
||||
+32
-17
@@ -21,26 +21,21 @@ const (
|
||||
|
||||
// KVStore key prefixes
|
||||
var (
|
||||
KeyPrefixBloom = []byte{0x01}
|
||||
KeyPrefixLogs = []byte{0x02}
|
||||
KeyPrefixCode = []byte{0x03}
|
||||
KeyPrefixStorage = []byte{0x04}
|
||||
KeyPrefixChainConfig = []byte{0x05}
|
||||
KeyPrefixHeightHash = []byte{0x06}
|
||||
KeyPrefixBlockHash = []byte{0x01}
|
||||
KeyPrefixBloom = []byte{0x02}
|
||||
KeyPrefixLogs = []byte{0x03}
|
||||
KeyPrefixCode = []byte{0x04}
|
||||
KeyPrefixStorage = []byte{0x05}
|
||||
KeyPrefixChainConfig = []byte{0x06}
|
||||
KeyPrefixBlockHeightHash = []byte{0x07}
|
||||
KeyPrefixHashTxReceipt = []byte{0x08}
|
||||
KeyPrefixBlockHeightTxs = []byte{0x09}
|
||||
)
|
||||
|
||||
// HeightHashKey returns the key for the given chain epoch and height.
|
||||
// The key will be composed in the following order:
|
||||
// key = prefix + bytes(height)
|
||||
// This ordering facilitates the iteration by height for the EVM GetHashFn
|
||||
// queries.
|
||||
func HeightHashKey(height uint64) []byte {
|
||||
return sdk.Uint64ToBigEndian(height)
|
||||
}
|
||||
|
||||
// BloomKey defines the store key for a block Bloom
|
||||
func BloomKey(height int64) []byte {
|
||||
return sdk.Uint64ToBigEndian(uint64(height))
|
||||
heightBytes := sdk.Uint64ToBigEndian(uint64(height))
|
||||
return append(KeyPrefixBloom, heightBytes...)
|
||||
}
|
||||
|
||||
// AddressStoragePrefix returns a prefix to iterate over a given account storage.
|
||||
@@ -53,4 +48,24 @@ func StateKey(address ethcmn.Address, key []byte) []byte {
|
||||
return append(AddressStoragePrefix(address), key...)
|
||||
}
|
||||
|
||||
// TODO: fix Logs key and append block hash
|
||||
// KeyBlockHash returns a key for accessing block hash data.
|
||||
func KeyBlockHash(hash ethcmn.Hash) []byte {
|
||||
return append(KeyPrefixBlockHash, hash.Bytes()...)
|
||||
}
|
||||
|
||||
// KeyBlockHash returns a key for accessing block hash data.
|
||||
func KeyBlockHeightHash(height uint64) []byte {
|
||||
heightBytes := sdk.Uint64ToBigEndian(height)
|
||||
return append(KeyPrefixBlockHeightHash, heightBytes...)
|
||||
}
|
||||
|
||||
// KeyHashTxReceipt returns a key for accessing tx receipt data by hash.
|
||||
func KeyHashTxReceipt(hash ethcmn.Hash) []byte {
|
||||
return append(KeyPrefixHashTxReceipt, hash.Bytes()...)
|
||||
}
|
||||
|
||||
// KeyBlockHeightTxs returns a key for accessing tx hash list by block height.
|
||||
func KeyBlockHeightTxs(height uint64) []byte {
|
||||
heightBytes := sdk.Uint64ToBigEndian(height)
|
||||
return append(KeyPrefixBlockHeightTxs, heightBytes...)
|
||||
}
|
||||
|
||||
+13
-4
@@ -1,10 +1,12 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
log "github.com/xlab/suplog"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
@@ -32,7 +34,7 @@ func NewTransactionLogsFromEth(hash ethcmn.Hash, ethlogs []*ethtypes.Log) Transa
|
||||
|
||||
// Validate performs a basic validation of a GenesisAccount fields.
|
||||
func (tx TransactionLogs) Validate() error {
|
||||
if ethermint.IsEmptyHash(tx.Hash) {
|
||||
if bytes.Equal(ethcmn.Hex2Bytes(tx.Hash), ethcmn.Hash{}.Bytes()) {
|
||||
return fmt.Errorf("hash cannot be the empty %s", tx.Hash)
|
||||
}
|
||||
|
||||
@@ -57,7 +59,7 @@ func (tx TransactionLogs) EthLogs() []*ethtypes.Log {
|
||||
|
||||
// Validate performs a basic validation of an ethereum Log fields.
|
||||
func (log *Log) Validate() error {
|
||||
if ethermint.IsZeroAddress(log.Address) {
|
||||
if IsZeroAddress(log.Address) {
|
||||
return fmt.Errorf("log address cannot be empty %s", log.Address)
|
||||
}
|
||||
if IsEmptyHash(log.BlockHash) {
|
||||
@@ -66,7 +68,7 @@ func (log *Log) Validate() error {
|
||||
if log.BlockNumber == 0 {
|
||||
return errors.New("block number cannot be zero")
|
||||
}
|
||||
if ethermint.IsEmptyHash(log.TxHash) {
|
||||
if IsEmptyHash(log.TxHash) {
|
||||
return fmt.Errorf("tx hash cannot be the empty %s", log.TxHash)
|
||||
}
|
||||
return nil
|
||||
@@ -86,6 +88,7 @@ func (log *Log) ToEthereum() *ethtypes.Log {
|
||||
BlockNumber: log.BlockNumber,
|
||||
TxHash: ethcmn.HexToHash(log.TxHash),
|
||||
TxIndex: uint(log.TxIndex),
|
||||
Index: uint(log.Index),
|
||||
BlockHash: ethcmn.HexToHash(log.BlockHash),
|
||||
Removed: log.Removed,
|
||||
}
|
||||
@@ -95,6 +98,12 @@ func (log *Log) ToEthereum() *ethtypes.Log {
|
||||
func LogsToEthereum(logs []*Log) []*ethtypes.Log {
|
||||
ethLogs := make([]*ethtypes.Log, len(logs))
|
||||
for i := range logs {
|
||||
err := logs[i].Validate()
|
||||
if err != nil {
|
||||
log.WithError(err).Errorln("failed log validation", logs[i].String())
|
||||
continue
|
||||
}
|
||||
|
||||
ethLogs[i] = logs[i].ToEthereum()
|
||||
}
|
||||
return ethLogs
|
||||
|
||||
+41
-26
@@ -1,10 +1,21 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
func TestTransactionLogsValidate(t *testing.T) {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
addr := ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey).String()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
txLogs TransactionLogs
|
||||
@@ -13,16 +24,16 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
{
|
||||
"valid log",
|
||||
TransactionLogs{
|
||||
Hash: suite.hash.String(),
|
||||
Hash: ethcmn.BytesToHash([]byte("tx_hash")).String(),
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []string{suite.hash.String()},
|
||||
Address: addr,
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash.String(),
|
||||
TxHash: ethcmn.BytesToHash([]byte("tx_hash")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash.String(),
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -40,24 +51,24 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
{
|
||||
"invalid log",
|
||||
TransactionLogs{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*Log{nil},
|
||||
Hash: ethcmn.BytesToHash([]byte("tx_hash")).String(),
|
||||
Logs: []*Log{{}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"hash mismatch log",
|
||||
TransactionLogs{
|
||||
Hash: suite.hash.String(),
|
||||
Hash: ethcmn.BytesToHash([]byte("tx_hash")).String(),
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []string{suite.hash.String()},
|
||||
Address: addr,
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.BytesToHash([]byte("other_hash")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash.String(),
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -71,14 +82,18 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
tc := tc
|
||||
err := tc.txLogs.Validate()
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, tc.name)
|
||||
require.NoError(t, err, tc.name)
|
||||
} else {
|
||||
suite.Require().Error(err, tc.name)
|
||||
require.Error(t, err, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
func TestValidateLog(t *testing.T) {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
addr := ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey).String()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
log *Log
|
||||
@@ -87,13 +102,13 @@ func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
{
|
||||
"valid log",
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
Topics: []string{suite.hash.String()},
|
||||
Address: addr,
|
||||
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash.String(),
|
||||
TxHash: ethcmn.BytesToHash([]byte("tx_hash")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash.String(),
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -112,7 +127,7 @@ func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
{
|
||||
"empty block hash",
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
Address: addr,
|
||||
BlockHash: ethcmn.Hash{}.String(),
|
||||
},
|
||||
false,
|
||||
@@ -120,8 +135,8 @@ func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
{
|
||||
"zero block number",
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
BlockHash: suite.hash.String(),
|
||||
Address: addr,
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
BlockNumber: 0,
|
||||
},
|
||||
false,
|
||||
@@ -129,8 +144,8 @@ func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
{
|
||||
"empty tx hash",
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
BlockHash: suite.hash.String(),
|
||||
Address: addr,
|
||||
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.Hash{}.String(),
|
||||
},
|
||||
@@ -142,9 +157,9 @@ func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
tc := tc
|
||||
err := tc.log.Validate()
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, tc.name)
|
||||
require.NoError(t, err, tc.name)
|
||||
} else {
|
||||
suite.Require().Error(err, tc.name)
|
||||
require.Error(t, err, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+76
-106
@@ -2,13 +2,10 @@ package types
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
@@ -27,7 +24,7 @@ var big8 = big.NewInt(8)
|
||||
|
||||
// message type and route constants
|
||||
const (
|
||||
// TypeMsgEthereumTx defines the type string of an Ethereum transaction
|
||||
// TypeMsgEthereumTx defines the type string of an Ethereum tranasction
|
||||
TypeMsgEthereumTx = "ethereum"
|
||||
)
|
||||
|
||||
@@ -55,28 +52,28 @@ func newMsgEthereumTx(
|
||||
payload = ethcmn.CopyBytes(payload)
|
||||
}
|
||||
|
||||
var recipient *Recipient
|
||||
var toBz []byte
|
||||
if to != nil {
|
||||
recipient = &Recipient{Address: to.String()}
|
||||
toBz = to.Bytes()
|
||||
}
|
||||
|
||||
txData := &TxData{
|
||||
AccountNonce: nonce,
|
||||
Recipient: recipient,
|
||||
Recipient: toBz,
|
||||
Payload: payload,
|
||||
GasLimit: gasLimit,
|
||||
Amount: sdk.ZeroInt(),
|
||||
Price: sdk.ZeroInt(),
|
||||
Amount: []byte{},
|
||||
Price: []byte{},
|
||||
V: []byte{},
|
||||
R: []byte{},
|
||||
S: []byte{},
|
||||
}
|
||||
|
||||
if amount != nil {
|
||||
txData.Amount = sdk.NewIntFromBigInt(amount)
|
||||
txData.Amount = amount.Bytes()
|
||||
}
|
||||
if gasPrice != nil {
|
||||
txData.Price = sdk.NewIntFromBigInt(gasPrice)
|
||||
txData.Price = gasPrice.Bytes()
|
||||
}
|
||||
|
||||
return &MsgEthereumTx{Data: txData}
|
||||
@@ -91,17 +88,19 @@ func (msg MsgEthereumTx) Type() string { return TypeMsgEthereumTx }
|
||||
// ValidateBasic implements the sdk.Msg interface. It performs basic validation
|
||||
// checks of a Transaction. If returns an error if validation fails.
|
||||
func (msg MsgEthereumTx) ValidateBasic() error {
|
||||
if msg.Data.Price.IsZero() {
|
||||
return sdkerrors.Wrapf(ethermint.ErrInvalidValue, "gas price cannot be 0")
|
||||
}
|
||||
gasPrice := new(big.Int).SetBytes(msg.Data.Price)
|
||||
// if gasPrice.Sign() == 0 {
|
||||
// return sdkerrors.Wrapf(ErrInvalidValue, "gas price cannot be 0")
|
||||
// }
|
||||
|
||||
if msg.Data.Price.IsNegative() {
|
||||
return sdkerrors.Wrapf(ethermint.ErrInvalidValue, "gas price cannot be negative %s", msg.Data.Price)
|
||||
if gasPrice.Sign() == -1 {
|
||||
return sdkerrors.Wrapf(ErrInvalidValue, "gas price cannot be negative %s", gasPrice)
|
||||
}
|
||||
|
||||
// Amount can be 0
|
||||
if msg.Data.Amount.IsNegative() {
|
||||
return sdkerrors.Wrapf(ethermint.ErrInvalidValue, "amount cannot be negative %s", msg.Data.Amount)
|
||||
amount := new(big.Int).SetBytes(msg.Data.Amount)
|
||||
if amount.Sign() == -1 {
|
||||
return sdkerrors.Wrapf(ErrInvalidValue, "amount cannot be negative %s", amount)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -110,11 +109,11 @@ func (msg MsgEthereumTx) ValidateBasic() error {
|
||||
// To returns the recipient address of the transaction. It returns nil if the
|
||||
// transaction is a contract creation.
|
||||
func (msg MsgEthereumTx) To() *ethcmn.Address {
|
||||
if msg.Data.Recipient == nil {
|
||||
if len(msg.Data.Recipient) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
recipient := ethcmn.HexToAddress(msg.Data.Recipient.Address)
|
||||
recipient := ethcmn.BytesToAddress(msg.Data.Recipient)
|
||||
return &recipient
|
||||
}
|
||||
|
||||
@@ -149,52 +148,33 @@ func (msg MsgEthereumTx) GetSignBytes() []byte {
|
||||
func (msg MsgEthereumTx) RLPSignBytes(chainID *big.Int) ethcmn.Hash {
|
||||
return rlpHash([]interface{}{
|
||||
msg.Data.AccountNonce,
|
||||
msg.Data.Price.BigInt(),
|
||||
new(big.Int).SetBytes(msg.Data.Price),
|
||||
msg.Data.GasLimit,
|
||||
msg.To(),
|
||||
msg.Data.Amount.BigInt(),
|
||||
msg.Data.Payload,
|
||||
new(big.Int).SetBytes(msg.Data.Amount),
|
||||
new(big.Int).SetBytes(msg.Data.Payload),
|
||||
chainID,
|
||||
uint(0),
|
||||
uint(0),
|
||||
})
|
||||
}
|
||||
|
||||
// RLPSignHomesteadBytes returns the RLP hash of an Ethereum transaction message with a
|
||||
// a Homestead layout without chainID.
|
||||
func (msg MsgEthereumTx) RLPSignHomesteadBytes() ethcmn.Hash {
|
||||
return rlpHash([]interface{}{
|
||||
msg.Data.AccountNonce,
|
||||
msg.Data.Price,
|
||||
msg.Data.GasLimit,
|
||||
msg.To(),
|
||||
msg.Data.Amount,
|
||||
msg.Data.Payload,
|
||||
})
|
||||
}
|
||||
|
||||
// EncodeRLP implements the rlp.Encoder interface.
|
||||
func (msg *MsgEthereumTx) EncodeRLP(w io.Writer) error {
|
||||
var hash ethcmn.Hash
|
||||
if len(msg.Data.Hash) > 0 {
|
||||
hash = ethcmn.HexToHash(msg.Data.Hash)
|
||||
}
|
||||
|
||||
data := struct {
|
||||
AccountNonce uint64
|
||||
Price *big.Int `json:"gasPrice"`
|
||||
GasLimit uint64 `json:"gas"`
|
||||
Recipient *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation
|
||||
Amount *big.Int `json:"value"`
|
||||
Payload []byte `json:"input"`
|
||||
|
||||
// signature values
|
||||
V *big.Int `json:"v"`
|
||||
R *big.Int `json:"r"`
|
||||
S *big.Int `json:"s"`
|
||||
|
||||
// hash is only used when marshaling to JSON
|
||||
Hash *ethcmn.Hash `json:"hash" rlp:"-"`
|
||||
}{
|
||||
AccountNonce: msg.Data.AccountNonce,
|
||||
Price: msg.Data.Price.BigInt(),
|
||||
GasLimit: msg.Data.GasLimit,
|
||||
Recipient: msg.To(),
|
||||
Amount: msg.Data.Amount.BigInt(),
|
||||
Payload: msg.Data.Payload,
|
||||
V: new(big.Int).SetBytes(msg.Data.V),
|
||||
R: new(big.Int).SetBytes(msg.Data.R),
|
||||
S: new(big.Int).SetBytes(msg.Data.S),
|
||||
Hash: &hash,
|
||||
}
|
||||
return rlp.Encode(w, data)
|
||||
return rlp.Encode(w, &msg.Data)
|
||||
}
|
||||
|
||||
// DecodeRLP implements the rlp.Decoder interface.
|
||||
@@ -205,50 +185,10 @@ func (msg *MsgEthereumTx) DecodeRLP(s *rlp.Stream) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var data struct {
|
||||
AccountNonce uint64
|
||||
Price *big.Int `json:"gasPrice"`
|
||||
GasLimit uint64 `json:"gas"`
|
||||
Recipient *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation
|
||||
Amount *big.Int `json:"value"`
|
||||
Payload []byte `json:"input"`
|
||||
|
||||
// signature values
|
||||
V *big.Int `json:"v"`
|
||||
R *big.Int `json:"r"`
|
||||
S *big.Int `json:"s"`
|
||||
|
||||
// hash is only used when marshaling to JSON
|
||||
Hash *ethcmn.Hash `json:"hash" rlp:"-"`
|
||||
}
|
||||
|
||||
if err := s.Decode(&data); err != nil {
|
||||
if err := s.Decode(&msg.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hash string
|
||||
if data.Hash != nil {
|
||||
hash = data.Hash.String()
|
||||
}
|
||||
|
||||
var recipient *Recipient
|
||||
if data.Recipient != nil {
|
||||
recipient = &Recipient{Address: data.Recipient.String()}
|
||||
}
|
||||
|
||||
msg.Data = &TxData{
|
||||
AccountNonce: data.AccountNonce,
|
||||
Price: sdk.NewIntFromBigInt(data.Price),
|
||||
GasLimit: data.GasLimit,
|
||||
Recipient: recipient,
|
||||
Amount: sdk.NewIntFromBigInt(data.Amount),
|
||||
Payload: data.Payload,
|
||||
V: data.V.Bytes(),
|
||||
R: data.R.Bytes(),
|
||||
S: data.S.Bytes(),
|
||||
Hash: hash,
|
||||
}
|
||||
|
||||
msg.Size_ = float64(ethcmn.StorageSize(rlp.ListSize(size)))
|
||||
return nil
|
||||
}
|
||||
@@ -292,23 +232,27 @@ func (msg *MsgEthereumTx) Sign(chainID *big.Int, priv *ecdsa.PrivateKey) error {
|
||||
// VerifySig attempts to verify a Transaction's signature for a given chainID.
|
||||
// A derived address is returned upon success or an error if recovery fails.
|
||||
func (msg *MsgEthereumTx) VerifySig(chainID *big.Int) (ethcmn.Address, error) {
|
||||
v, r, s := msg.RawSignatureValues()
|
||||
signer := ethtypes.NewEIP155Signer(chainID)
|
||||
|
||||
if msg.From != nil {
|
||||
if msg.From.Signer == nil {
|
||||
return msg.VerifySigHomestead()
|
||||
}
|
||||
|
||||
// If the signer used to derive from in a previous call is not the same as
|
||||
// used current, invalidate the cache.
|
||||
fromSigner := ethtypes.NewEIP155Signer(new(big.Int).SetBytes(msg.From.Signer.chainId))
|
||||
if signer.Equal(fromSigner) {
|
||||
return ethcmn.HexToAddress(msg.From.Address), nil
|
||||
return ethcmn.BytesToAddress(msg.From.Address), nil
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow recovery for transactions with an unprotected chainID
|
||||
if chainID.Sign() == 0 {
|
||||
return ethcmn.Address{}, errors.New("chainID cannot be zero")
|
||||
return msg.VerifySigHomestead()
|
||||
}
|
||||
|
||||
v, r, s := msg.RawSignatureValues()
|
||||
chainIDMul := new(big.Int).Mul(chainID, big.NewInt(2))
|
||||
V := new(big.Int).Sub(v, chainIDMul)
|
||||
V.Sub(V, big8)
|
||||
@@ -324,8 +268,35 @@ func (msg *MsgEthereumTx) VerifySig(chainID *big.Int) (ethcmn.Address, error) {
|
||||
chainId: chainID.Bytes(),
|
||||
chainIdMul: new(big.Int).Mul(chainID, big.NewInt(2)).Bytes(),
|
||||
},
|
||||
Address: sender.String(),
|
||||
Address: sender.Bytes(),
|
||||
}
|
||||
|
||||
return sender, nil
|
||||
}
|
||||
|
||||
// VerifySigHomestead attempts to verify a Transaction's signature in legacy way (no EIP155).
|
||||
// A derived address is returned upon success or an error if recovery fails.
|
||||
func (msg *MsgEthereumTx) VerifySigHomestead() (ethcmn.Address, error) {
|
||||
// signer := ethtypes.HomesteadSigner{}
|
||||
if msg.From != nil {
|
||||
// If the signer used to derive from in a previous call is not the same as
|
||||
// used current, invalidate the cache.
|
||||
if msg.From.Signer == nil {
|
||||
return ethcmn.BytesToAddress(msg.From.Address), nil
|
||||
}
|
||||
}
|
||||
|
||||
v, r, s := msg.RawSignatureValues()
|
||||
sigHash := msg.RLPSignHomesteadBytes()
|
||||
sender, err := recoverEthSig(r, s, v, sigHash)
|
||||
if err != nil {
|
||||
return ethcmn.Address{}, err
|
||||
}
|
||||
|
||||
msg.From = &SigCache{
|
||||
Address: sender.Bytes(),
|
||||
}
|
||||
|
||||
return sender, nil
|
||||
}
|
||||
|
||||
@@ -336,21 +307,20 @@ func (msg MsgEthereumTx) GetGas() uint64 {
|
||||
|
||||
// Fee returns gasprice * gaslimit.
|
||||
func (msg MsgEthereumTx) Fee() *big.Int {
|
||||
gasPrice := msg.Data.Price.BigInt()
|
||||
gasPrice := new(big.Int).SetBytes(msg.Data.Price)
|
||||
gasLimit := new(big.Int).SetUint64(msg.Data.GasLimit)
|
||||
return new(big.Int).Mul(gasPrice, gasLimit)
|
||||
}
|
||||
|
||||
// ChainID returns which chain id this transaction was signed for (if at all)
|
||||
func (msg *MsgEthereumTx) ChainID() *big.Int {
|
||||
v := new(big.Int).SetBytes(msg.Data.V)
|
||||
return deriveChainID(v)
|
||||
return deriveChainID(new(big.Int).SetBytes(msg.Data.V))
|
||||
}
|
||||
|
||||
// Cost returns amount + gasprice * gaslimit.
|
||||
func (msg MsgEthereumTx) Cost() *big.Int {
|
||||
total := msg.Fee()
|
||||
total.Add(total, msg.Data.Amount.BigInt())
|
||||
total.Add(total, new(big.Int).SetBytes(msg.Data.Amount))
|
||||
return total
|
||||
}
|
||||
|
||||
@@ -369,7 +339,7 @@ func (msg *MsgEthereumTx) GetFrom() sdk.AccAddress {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sdk.AccAddress(ethcmn.HexToAddress(msg.From.Address).Bytes())
|
||||
return sdk.AccAddress(msg.From.Address)
|
||||
}
|
||||
|
||||
// deriveChainID derives the chain id from the given v parameter
|
||||
|
||||
+4
-16
@@ -16,23 +16,12 @@ import (
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
// GenerateEthAddress generates an Ethereum address.
|
||||
func GenerateEthAddress() ethcmn.Address {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ethcmn.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
}
|
||||
|
||||
func TestMsgEthereumTx(t *testing.T) {
|
||||
addr := GenerateEthAddress()
|
||||
|
||||
msg := NewMsgEthereumTx(0, &addr, nil, 100000, nil, []byte("test"))
|
||||
require.NotNil(t, msg)
|
||||
require.NotNil(t, msg.Data.Recipient)
|
||||
require.Equal(t, msg.Data.Recipient.Address, addr.String())
|
||||
require.EqualValues(t, msg.Data.Recipient, addr.Bytes())
|
||||
require.Equal(t, msg.Route(), RouterKey)
|
||||
require.Equal(t, msg.Type(), TypeMsgEthereumTx)
|
||||
require.NotNil(t, msg.To())
|
||||
@@ -42,7 +31,7 @@ func TestMsgEthereumTx(t *testing.T) {
|
||||
|
||||
msg = NewMsgEthereumTxContract(0, nil, 100000, nil, []byte("test"))
|
||||
require.NotNil(t, msg)
|
||||
require.Empty(t, msg.Data.Recipient)
|
||||
require.Nil(t, msg.Data.Recipient)
|
||||
require.Nil(t, msg.To())
|
||||
}
|
||||
|
||||
@@ -62,11 +51,10 @@ func TestMsgEthereumTxValidation(t *testing.T) {
|
||||
for i, tc := range testCases {
|
||||
msg := NewMsgEthereumTx(0, nil, tc.amount, 0, tc.gasPrice, nil)
|
||||
|
||||
err := msg.ValidateBasic()
|
||||
if tc.expectPass {
|
||||
require.NoError(t, err, "valid test %d failed: %s", i, tc.msg)
|
||||
require.Nil(t, msg.ValidateBasic(), "valid test %d failed: %s", i, tc.msg)
|
||||
} else {
|
||||
require.Error(t, err, "invalid test %d passed: %s", i, tc.msg)
|
||||
require.NotNil(t, msg.ValidateBasic(), "invalid test %d passed: %s", i, tc.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,7 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
)
|
||||
|
||||
var _ paramtypes.ParamSet = &Params{}
|
||||
@@ -41,7 +38,7 @@ func NewParams(evmDenom string, enableCreate, enableCall bool, extraEIPs ...int6
|
||||
// DefaultParams returns default evm parameters
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
EvmDenom: ethermint.AttoPhoton,
|
||||
EvmDenom: "inj",
|
||||
EnableCreate: true,
|
||||
EnableCall: true,
|
||||
ExtraEIPs: []int64(nil), // TODO: define default values
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestParamsValidate(t *testing.T) {
|
||||
|
||||
func TestParamsValidatePriv(t *testing.T) {
|
||||
require.Error(t, validateEVMDenom(false))
|
||||
require.NoError(t, validateEVMDenom("aphoton"))
|
||||
require.NoError(t, validateEVMDenom("inj"))
|
||||
require.Error(t, validateBool(""))
|
||||
require.NoError(t, validateBool(true))
|
||||
require.Error(t, validateEIPs(""))
|
||||
@@ -61,5 +61,5 @@ func TestParamsValidatePriv(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParams_String(t *testing.T) {
|
||||
require.Equal(t, "evm_denom: aphoton\nenable_create: true\nenable_call: true\nextra_eips: []\n", DefaultParams().String())
|
||||
require.Equal(t, "evm_denom: inj\nenable_create: true\nenable_call: true\nextra_eips: []\n", DefaultParams().String())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package types
|
||||
|
||||
// Constants to match up protocol versions and messages
|
||||
const (
|
||||
eth65 = 65
|
||||
|
||||
// ProtocolVersion is the latest supported version of the eth protocol.
|
||||
ProtocolVersion = eth65
|
||||
)
|
||||
@@ -1,26 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestQueryETHLogs_String(t *testing.T) {
|
||||
const expectedQueryETHLogsStr = `{0x0000000000000000000000000000000000000000 [] [1 2 3 4] 9 0x0000000000000000000000000000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000000000000000000000000000 0 false}
|
||||
{0x0000000000000000000000000000000000000000 [] [5 6 7 8] 10 0x0000000000000000000000000000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000000000000000000000000000 0 false}
|
||||
`
|
||||
logs := []*ethtypes.Log{
|
||||
{
|
||||
Data: []byte{1, 2, 3, 4},
|
||||
BlockNumber: 9,
|
||||
},
|
||||
{
|
||||
Data: []byte{5, 6, 7, 8},
|
||||
BlockNumber: 10,
|
||||
},
|
||||
}
|
||||
|
||||
require.True(t, strings.EqualFold(expectedQueryETHLogsStr, QueryETHLogs{logs}.String()))
|
||||
}
|
||||
+2196
-164
File diff suppressed because it is too large
Load Diff
+499
-9
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: ethermint/evm/v1alpha1/query.proto
|
||||
// source: injective/evm/v1beta1/query.proto
|
||||
|
||||
/*
|
||||
Package types is a reverse proxy.
|
||||
@@ -85,6 +85,60 @@ func local_request_Query_Account_0(ctx context.Context, marshaler runtime.Marsha
|
||||
|
||||
}
|
||||
|
||||
func request_Query_CosmosAccount_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryCosmosAccountRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["address"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
|
||||
}
|
||||
|
||||
protoReq.Address, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
|
||||
}
|
||||
|
||||
msg, err := client.CosmosAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_CosmosAccount_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryCosmosAccountRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["address"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address")
|
||||
}
|
||||
|
||||
protoReq.Address, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err)
|
||||
}
|
||||
|
||||
msg, err := server.CosmosAccount(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryBalanceRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@@ -323,6 +377,168 @@ func local_request_Query_TxLogs_0(ctx context.Context, marshaler runtime.Marshal
|
||||
|
||||
}
|
||||
|
||||
func request_Query_TxReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxReceiptRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["hash"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash")
|
||||
}
|
||||
|
||||
protoReq.Hash, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err)
|
||||
}
|
||||
|
||||
msg, err := client.TxReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_TxReceipt_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxReceiptRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["hash"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash")
|
||||
}
|
||||
|
||||
protoReq.Hash, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err)
|
||||
}
|
||||
|
||||
msg, err := server.TxReceipt(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_TxReceiptsByBlockHeight_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxReceiptsByBlockHeightRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["height"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height")
|
||||
}
|
||||
|
||||
protoReq.Height, err = runtime.Int64(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err)
|
||||
}
|
||||
|
||||
msg, err := client.TxReceiptsByBlockHeight(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_TxReceiptsByBlockHeight_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxReceiptsByBlockHeightRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["height"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height")
|
||||
}
|
||||
|
||||
protoReq.Height, err = runtime.Int64(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err)
|
||||
}
|
||||
|
||||
msg, err := server.TxReceiptsByBlockHeight(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_TxReceiptsByBlockHash_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxReceiptsByBlockHashRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["hash"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash")
|
||||
}
|
||||
|
||||
protoReq.Hash, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err)
|
||||
}
|
||||
|
||||
msg, err := client.TxReceiptsByBlockHash(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_TxReceiptsByBlockHash_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxReceiptsByBlockHashRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["hash"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash")
|
||||
}
|
||||
|
||||
protoReq.Hash, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err)
|
||||
}
|
||||
|
||||
msg, err := server.TxReceiptsByBlockHash(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_BlockLogs_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryBlockLogsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@@ -377,10 +593,21 @@ func local_request_Query_BlockLogs_0(ctx context.Context, marshaler runtime.Mars
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Query_BlockBloom_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Query_BlockBloom_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryBlockBloomRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_BlockBloom_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.BlockBloom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
@@ -390,6 +617,13 @@ func local_request_Query_BlockBloom_0(ctx context.Context, marshaler runtime.Mar
|
||||
var protoReq QueryBlockBloomRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_BlockBloom_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.BlockBloom(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
@@ -413,6 +647,42 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Query_StaticCall_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Query_StaticCall_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryStaticCallRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_StaticCall_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.StaticCall(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_StaticCall_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryStaticCallRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_StaticCall_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.StaticCall(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
|
||||
// UnaryRPC :call QueryServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@@ -439,6 +709,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_CosmosAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_CosmosAccount_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_CosmosAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -519,6 +809,66 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxReceipt_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_TxReceipt_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_TxReceipt_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxReceiptsByBlockHeight_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_TxReceiptsByBlockHeight_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_TxReceiptsByBlockHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxReceiptsByBlockHash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_TxReceiptsByBlockHash_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_TxReceiptsByBlockHash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_BlockLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -579,6 +929,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_StaticCall_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_StaticCall_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_StaticCall_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -640,6 +1010,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_CosmosAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_CosmosAccount_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_CosmosAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -720,6 +1110,66 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxReceipt_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_TxReceipt_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_TxReceipt_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxReceiptsByBlockHeight_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_TxReceiptsByBlockHeight_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_TxReceiptsByBlockHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxReceiptsByBlockHash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_TxReceiptsByBlockHash_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_TxReceiptsByBlockHash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_BlockLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -780,30 +1230,62 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_StaticCall_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_StaticCall_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_StaticCall_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "account", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "account", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_Balance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "balances", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_CosmosAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "cosmos_account", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_Storage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"ethermint", "evm", "v1alpha1", "storage", "address", "key"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_Balance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "balances", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_Code_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "codes", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_Storage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"injective", "evm", "v1beta1", "storage", "address", "key"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_TxLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "tx_logs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_Code_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "codes", "address"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_BlockLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "block_logs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_TxLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "tx_logs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_BlockBloom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "evm", "v1alpha1", "block_bloom"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_TxReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "tx_receipt", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "evm", "v1alpha1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
pattern_Query_TxReceiptsByBlockHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "tx_receipts_block", "height"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_TxReceiptsByBlockHash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "tx_receipts_block_hash", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_BlockLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"injective", "evm", "v1beta1", "block_logs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_BlockBloom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"injective", "evm", "v1beta1", "block_bloom"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"injective", "evm", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_StaticCall_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"injective", "evm", "v1beta1", "static_call"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Query_Account_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_CosmosAccount_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Balance_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Storage_0 = runtime.ForwardResponseMessage
|
||||
@@ -812,9 +1294,17 @@ var (
|
||||
|
||||
forward_Query_TxLogs_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_TxReceipt_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_TxReceiptsByBlockHeight_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_TxReceiptsByBlockHash_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_BlockLogs_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_BlockBloom_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Params_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_StaticCall_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
+10
-11
@@ -10,7 +10,7 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethstate "github.com/ethereum/go-ethereum/core/state"
|
||||
@@ -53,7 +53,7 @@ type StateObject interface {
|
||||
// Account values can be accessed and modified through the object.
|
||||
// Finally, call CommitTrie to write the modified storage trie into a database.
|
||||
type stateObject struct {
|
||||
code ethermint.Code // contract bytecode, which gets set when code is loaded
|
||||
code types.Code // contract bytecode, which gets set when code is loaded
|
||||
// State objects are used by the consensus core and VM which are
|
||||
// unable to deal with database-level errors. Any error that occurs
|
||||
// during a database read is memoized here and will eventually be returned
|
||||
@@ -64,7 +64,7 @@ type stateObject struct {
|
||||
// DB error
|
||||
dbErr error
|
||||
stateDB *CommitStateDB
|
||||
account *ethermint.EthAccount
|
||||
account *types.EthAccount
|
||||
// balance represents the amount of the EVM denom token that an account holds
|
||||
balance sdk.Int
|
||||
|
||||
@@ -83,21 +83,21 @@ type stateObject struct {
|
||||
}
|
||||
|
||||
func newStateObject(db *CommitStateDB, accProto authtypes.AccountI, balance sdk.Int) *stateObject {
|
||||
ethermintAccount, ok := accProto.(*ethermint.EthAccount)
|
||||
ethAccount, ok := accProto.(*types.EthAccount)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("invalid account type for state object: %T", accProto))
|
||||
}
|
||||
|
||||
// set empty code hash
|
||||
if ethermintAccount.CodeHash == nil {
|
||||
ethermintAccount.CodeHash = emptyCodeHash
|
||||
if ethAccount.CodeHash == nil {
|
||||
ethAccount.CodeHash = emptyCodeHash
|
||||
}
|
||||
|
||||
return &stateObject{
|
||||
stateDB: db,
|
||||
account: ethermintAccount,
|
||||
account: ethAccount,
|
||||
balance: balance,
|
||||
address: ethermintAccount.EthAddress(),
|
||||
address: ethAccount.EthAddress(),
|
||||
originStorage: Storage{},
|
||||
dirtyStorage: Storage{},
|
||||
keyToOriginStorageIndex: make(map[ethcmn.Hash]int),
|
||||
@@ -250,9 +250,8 @@ func (so *stateObject) commitState() {
|
||||
|
||||
key := ethcmn.HexToHash(state.Key)
|
||||
value := ethcmn.HexToHash(state.Value)
|
||||
|
||||
// delete empty values from the store
|
||||
if ethermint.IsEmptyHash(state.Value) {
|
||||
if IsEmptyHash(state.Value) {
|
||||
store.Delete(key.Bytes())
|
||||
}
|
||||
|
||||
@@ -264,7 +263,7 @@ func (so *stateObject) commitState() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ethermint.IsEmptyHash(state.Value) {
|
||||
if IsEmptyHash(state.Value) {
|
||||
delete(so.keyToOriginStorageIndex, key)
|
||||
continue
|
||||
}
|
||||
|
||||
+142
-33
@@ -1,18 +1,22 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/xlab/suplog"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/ethermint/metrics"
|
||||
)
|
||||
|
||||
// StateTransition defines data to transitionDB in evm
|
||||
@@ -30,6 +34,18 @@ type StateTransition struct {
|
||||
TxHash *common.Hash
|
||||
Sender common.Address
|
||||
Simulate bool // i.e CheckTx execution
|
||||
Debug bool // enable EVM debugging
|
||||
|
||||
once sync.Once
|
||||
svcTags metrics.Tags
|
||||
}
|
||||
|
||||
func (st *StateTransition) initOnce() {
|
||||
st.once.Do(func() {
|
||||
st.svcTags = metrics.Tags{
|
||||
"svc": "evm_state",
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// GasInfo returns the gas limit, gas consumed and gas refunded from the EVM transition
|
||||
@@ -49,16 +65,16 @@ type ExecutionResult struct {
|
||||
}
|
||||
|
||||
// GetHashFn implements vm.GetHashFunc for Ethermint. It handles 3 cases:
|
||||
// 1. The requested height matches the current height (and thus same epoch number)
|
||||
// 1. The requested height matches the current height from context (and thus same epoch number)
|
||||
// 2. The requested height is from an previous height from the same chain epoch
|
||||
// 3. The requested height is from a height greater than the latest one
|
||||
func GetHashFn(ctx sdk.Context, csdb *CommitStateDB) vm.GetHashFunc {
|
||||
return func(height uint64) common.Hash {
|
||||
switch {
|
||||
case ctx.BlockHeight() == int64(height):
|
||||
// Case 1: The requested height matches the one from the CommitStateDB so we can retrieve the block
|
||||
// hash directly from the CommitStateDB.
|
||||
return csdb.bhash
|
||||
// Case 1: The requested height matches the one from the context so we can retrieve the header
|
||||
// hash directly from the context.
|
||||
return HashFromContext(ctx)
|
||||
|
||||
case ctx.BlockHeight() > int64(height):
|
||||
// Case 2: if the chain is not the current height we need to retrieve the hash from the store for the
|
||||
@@ -72,7 +88,7 @@ func GetHashFn(ctx sdk.Context, csdb *CommitStateDB) vm.GetHashFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func (st StateTransition) newEVM(
|
||||
func (st *StateTransition) newEVM(
|
||||
ctx sdk.Context,
|
||||
csdb *CommitStateDB,
|
||||
gasLimit uint64,
|
||||
@@ -80,13 +96,14 @@ func (st StateTransition) newEVM(
|
||||
config ChainConfig,
|
||||
extraEIPs []int64,
|
||||
) *vm.EVM {
|
||||
// Create context for evm
|
||||
st.initOnce()
|
||||
|
||||
// Create context for evm
|
||||
blockCtx := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetHash: GetHashFn(ctx, csdb),
|
||||
Coinbase: common.Address{}, // there's no beneficiary since we're not mining
|
||||
Coinbase: common.Address{}, // there's no benefitiary since we're not mining
|
||||
BlockNumber: big.NewInt(ctx.BlockHeight()),
|
||||
Time: big.NewInt(ctx.BlockHeader().Time.Unix()),
|
||||
Difficulty: big.NewInt(0), // unused. Only required in PoW context
|
||||
@@ -106,18 +123,35 @@ func (st StateTransition) newEVM(
|
||||
vmConfig := vm.Config{
|
||||
ExtraEips: eips,
|
||||
}
|
||||
|
||||
if st.Debug {
|
||||
vmConfig.Tracer = vm.NewJSONLogger(&vm.LogConfig{
|
||||
Debug: true,
|
||||
}, os.Stderr)
|
||||
|
||||
vmConfig.Debug = true
|
||||
}
|
||||
|
||||
return vm.NewEVM(blockCtx, txCtx, csdb, config.EthereumConfig(st.ChainID), vmConfig)
|
||||
}
|
||||
|
||||
// TransitionDb will transition the state by applying the current transaction and
|
||||
// returning the evm execution result.
|
||||
// NOTE: State transition checks are run during AnteHandler execution.
|
||||
func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*ExecutionResult, error) {
|
||||
func (st *StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (resp *ExecutionResult, err error) {
|
||||
st.initOnce()
|
||||
|
||||
metrics.ReportFuncCall(st.svcTags)
|
||||
doneFn := metrics.ReportFuncTiming(st.svcTags)
|
||||
defer doneFn()
|
||||
|
||||
contractCreation := st.Recipient == nil
|
||||
|
||||
cost, err := core.IntrinsicGas(st.Payload, contractCreation, config.IsHomestead(), config.IsIstanbul())
|
||||
cost, err := core.IntrinsicGas(st.Payload, contractCreation, true, false)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(err, "invalid intrinsic gas for transaction")
|
||||
metrics.ReportFuncError(st.svcTags)
|
||||
err = sdkerrors.Wrap(err, "invalid intrinsic gas for transaction")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This gas limit the the transaction gas limit with intrinsic gas subtracted
|
||||
@@ -149,8 +183,10 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
params := csdb.GetParams()
|
||||
|
||||
gasPrice := ctx.MinGasPrices().AmountOf(params.EvmDenom)
|
||||
//gasPrice := sdk.ZeroDec()
|
||||
if gasPrice.IsNil() {
|
||||
return nil, errors.New("gas price cannot be nil")
|
||||
metrics.ReportFuncError(st.svcTags)
|
||||
return nil, errors.New("min gas price cannot be nil")
|
||||
}
|
||||
|
||||
evm := st.newEVM(ctx, csdb, gasLimit, gasPrice.BigInt(), config, params.ExtraEIPs)
|
||||
@@ -176,6 +212,24 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
|
||||
ret, contractAddress, leftOverGas, err = evm.Create(senderRef, st.Payload, gasLimit, st.Amount)
|
||||
|
||||
if err != nil {
|
||||
log.WithField("simulate?", st.Simulate).
|
||||
WithField("AccountNonce", st.AccountNonce).
|
||||
WithField("contract", contractAddress.String()).
|
||||
WithError(err).Warningln("evm contract creation failed")
|
||||
}
|
||||
|
||||
gasConsumed := gasLimit - leftOverGas
|
||||
resp = &ExecutionResult{
|
||||
Response: &MsgEthereumTxResponse{
|
||||
Ret: ret,
|
||||
},
|
||||
GasInfo: GasInfo{
|
||||
GasConsumed: gasConsumed,
|
||||
GasLimit: gasLimit,
|
||||
GasRefunded: leftOverGas,
|
||||
},
|
||||
}
|
||||
default:
|
||||
if !params.EnableCall {
|
||||
return nil, ErrCallDisabled
|
||||
@@ -183,15 +237,36 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
|
||||
// Increment the nonce for the next transaction (just for evm state transition)
|
||||
csdb.SetNonce(st.Sender, csdb.GetNonce(st.Sender)+1)
|
||||
ret, leftOverGas, err = evm.Call(senderRef, *st.Recipient, st.Payload, gasLimit, st.Amount)
|
||||
}
|
||||
|
||||
gasConsumed := gasLimit - leftOverGas
|
||||
ret, leftOverGas, err = evm.Call(senderRef, *st.Recipient, st.Payload, gasLimit, st.Amount)
|
||||
|
||||
// fmt.Println("EVM CALL!!!", senderRef.Address().Hex(), (*st.Recipient).Hex(), gasLimit)
|
||||
// fmt.Println("EVM CALL RESULT", common.ToHex(ret), leftOverGas, err)
|
||||
|
||||
if err != nil {
|
||||
log.WithField("recipient", st.Recipient.String()).
|
||||
WithError(err).Debugln("evm call failed")
|
||||
}
|
||||
|
||||
gasConsumed := gasLimit - leftOverGas
|
||||
resp = &ExecutionResult{
|
||||
Response: &MsgEthereumTxResponse{
|
||||
Ret: ret,
|
||||
},
|
||||
GasInfo: GasInfo{
|
||||
GasConsumed: gasConsumed,
|
||||
GasLimit: gasLimit,
|
||||
GasRefunded: leftOverGas,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// Consume gas before returning
|
||||
ctx.GasMeter().ConsumeGas(gasConsumed, "evm execution consumption")
|
||||
return nil, err
|
||||
metrics.EVMRevertedTx(st.svcTags)
|
||||
metrics.EVMGasConsumed(resp.GasInfo.GasConsumed)
|
||||
ctx.GasMeter().ConsumeGas(resp.GasInfo.GasConsumed, "evm execution consumption")
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Resets nonce to value pre state transition
|
||||
@@ -208,6 +283,8 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
if st.TxHash != nil && !st.Simulate {
|
||||
logs, err = csdb.GetLogs(*st.TxHash)
|
||||
if err != nil {
|
||||
metrics.ReportFuncError(st.svcTags)
|
||||
err = errors.Wrap(err, "failed to get logs")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -219,38 +296,70 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
// Finalise state if not a simulated transaction
|
||||
// TODO: change to depend on config
|
||||
if err := csdb.Finalise(true); err != nil {
|
||||
metrics.ReportFuncError(st.svcTags)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
res := &MsgEthereumTxResponse{
|
||||
resp.Logs = logs
|
||||
resp.Bloom = bloomInt
|
||||
resp.Response = &MsgEthereumTxResponse{
|
||||
Bloom: bloomFilter.Bytes(),
|
||||
TxLogs: NewTransactionLogsFromEth(*st.TxHash, logs),
|
||||
Ret: ret,
|
||||
}
|
||||
|
||||
if contractCreation {
|
||||
res.ContractAddress = contractAddress.String()
|
||||
}
|
||||
|
||||
executionResult := &ExecutionResult{
|
||||
Logs: logs,
|
||||
Bloom: bloomInt,
|
||||
Response: res,
|
||||
GasInfo: GasInfo{
|
||||
GasConsumed: gasConsumed,
|
||||
GasLimit: gasLimit,
|
||||
GasRefunded: leftOverGas,
|
||||
},
|
||||
resp.Response.ContractAddress = contractAddress.String()
|
||||
}
|
||||
|
||||
// TODO: Refund unused gas here, if intended in future
|
||||
|
||||
// Consume gas from evm execution
|
||||
// Out of gas check does not need to be done here since it is done within the EVM execution
|
||||
ctx.WithGasMeter(currentGasMeter).GasMeter().ConsumeGas(gasConsumed, "EVM execution consumption")
|
||||
metrics.EVMGasConsumed(resp.GasInfo.GasConsumed)
|
||||
// TODO: @albert, @maxim, decide if can take this out, since InternalEthereumTx may want to continue execution afterwards
|
||||
// which will use gas.
|
||||
_ = currentGasMeter
|
||||
//ctx.WithGasMeter(currentGasMeter).GasMeter().ConsumeGas(resp.GasInfo.GasConsumed, "EVM execution consumption")
|
||||
|
||||
return executionResult, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// StaticCall executes the contract associated with the addr with the given input
|
||||
// as parameters while disallowing any modifications to the state during the call.
|
||||
// Opcodes that attempt to perform such modifications will result in exceptions
|
||||
// instead of performing the modifications.
|
||||
func (st *StateTransition) StaticCall(ctx sdk.Context, config ChainConfig) ([]byte, error) {
|
||||
st.initOnce()
|
||||
|
||||
// This gas limit the the transaction gas limit with intrinsic gas subtracted
|
||||
gasLimit := st.GasLimit - ctx.GasMeter().GasConsumed()
|
||||
csdb := st.Csdb.WithContext(ctx)
|
||||
|
||||
// This gas meter is set up to consume gas from gaskv during evm execution and be ignored
|
||||
evmGasMeter := sdk.NewInfiniteGasMeter()
|
||||
csdb.WithContext(ctx.WithGasMeter(evmGasMeter))
|
||||
|
||||
// Clear cache of accounts to handle changes outside of the EVM
|
||||
csdb.UpdateAccounts()
|
||||
|
||||
params := csdb.GetParams()
|
||||
|
||||
gasPrice := ctx.MinGasPrices().AmountOf(params.EvmDenom)
|
||||
if gasPrice.IsNil() {
|
||||
return []byte{}, errors.New("min gas price cannot be nil")
|
||||
}
|
||||
|
||||
evm := st.newEVM(ctx, csdb, gasLimit, gasPrice.BigInt(), config, params.ExtraEIPs)
|
||||
senderRef := vm.AccountRef(st.Sender)
|
||||
|
||||
ret, _, err := evm.StaticCall(senderRef, *st.Recipient, st.Payload, gasLimit)
|
||||
|
||||
// fmt.Println("EVM STATIC CALL!!!", senderRef.Address().Hex(), (*st.Recipient).Hex(), st.Payload, gasLimit)
|
||||
// fmt.Println("EVM STATIC CALL RESULT", common.ToHex(ret), leftOverGas, err)
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// HashFromContext returns the Ethereum Header hash from the context's Tendermint
|
||||
|
||||
@@ -3,127 +3,21 @@ package types_test
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
"github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
tmversion "github.com/tendermint/tendermint/version"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
func (suite *StateDBTestSuite) TestGetHashFn() {
|
||||
testCase := []struct {
|
||||
name string
|
||||
height uint64
|
||||
malleate func()
|
||||
expEmptyHash bool
|
||||
}{
|
||||
// {
|
||||
// "valid hash, case 1",
|
||||
// 1,
|
||||
// func() {
|
||||
// suite.ctx = suite.ctx.WithBlockHeader(
|
||||
// tmproto.Header{
|
||||
// ChainID: "ethermint-1",
|
||||
// Height: 1,
|
||||
// ValidatorsHash: []byte("val_hash"),
|
||||
// Version: version.Consensus{
|
||||
// Block: tmversion.BlockProtocol,
|
||||
// },
|
||||
// },
|
||||
// )
|
||||
// },
|
||||
// false,
|
||||
// },
|
||||
{
|
||||
"case 1, nil tendermint hash",
|
||||
1,
|
||||
func() {},
|
||||
true,
|
||||
},
|
||||
// {
|
||||
// "valid hash, case 2",
|
||||
// 1,
|
||||
// func() {
|
||||
// suite.ctx = suite.ctx.WithBlockHeader(
|
||||
// tmproto.Header{
|
||||
// ChainID: "ethermint-1",
|
||||
// Height: 100,
|
||||
// ValidatorsHash: []byte("val_hash"),
|
||||
// Version: version.Consensus{
|
||||
// Block: tmversion.BlockProtocol,
|
||||
// },
|
||||
// },
|
||||
// )
|
||||
// hash := types.HashFromContext(suite.ctx)
|
||||
// suite.stateDB.WithContext(suite.ctx).SetHeightHash(1, hash)
|
||||
// },
|
||||
// false,
|
||||
// },
|
||||
{
|
||||
"height not found, case 2",
|
||||
1,
|
||||
func() {
|
||||
suite.ctx = suite.ctx.WithBlockHeader(
|
||||
tmproto.Header{
|
||||
ChainID: "ethermint-1",
|
||||
Height: 100,
|
||||
ValidatorsHash: []byte("val_hash"),
|
||||
Version: version.Consensus{
|
||||
Block: tmversion.BlockProtocol,
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"empty hash, case 3",
|
||||
1000,
|
||||
func() {
|
||||
suite.ctx = suite.ctx.WithBlockHeader(
|
||||
tmproto.Header{
|
||||
ChainID: "ethermint-1",
|
||||
Height: 100,
|
||||
ValidatorsHash: []byte("val_hash"),
|
||||
Version: version.Consensus{
|
||||
Block: tmversion.BlockProtocol,
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCase {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
|
||||
tc.malleate()
|
||||
|
||||
hash := types.GetHashFn(suite.ctx, suite.stateDB)(tc.height)
|
||||
if tc.expEmptyHash {
|
||||
suite.Require().Equal(common.Hash{}.String(), hash.String())
|
||||
} else {
|
||||
suite.Require().NotEqual(common.Hash{}.String(), hash.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *StateDBTestSuite) TestTransitionDb() {
|
||||
suite.stateDB.SetNonce(suite.address, 123)
|
||||
|
||||
addr := sdk.AccAddress(suite.address.Bytes())
|
||||
balance := ethermint.NewPhotonCoin(sdk.NewInt(5000))
|
||||
balance := ethermint.NewInjectiveCoin(sdk.NewInt(5000))
|
||||
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, addr)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, addr, balance)
|
||||
@@ -228,54 +122,11 @@ func (suite *StateDBTestSuite) TestTransitionDb() {
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"call disabled",
|
||||
func() {
|
||||
params := types.NewParams(ethermint.AttoPhoton, true, false)
|
||||
suite.stateDB.SetParams(params)
|
||||
},
|
||||
types.StateTransition{
|
||||
AccountNonce: 123,
|
||||
Price: big.NewInt(10),
|
||||
GasLimit: 11,
|
||||
Recipient: &recipient,
|
||||
Amount: big.NewInt(50),
|
||||
Payload: []byte("data"),
|
||||
ChainID: big.NewInt(1),
|
||||
Csdb: suite.stateDB,
|
||||
TxHash: ðcmn.Hash{},
|
||||
Sender: suite.address,
|
||||
Simulate: suite.ctx.IsCheckTx(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"create disabled",
|
||||
func() {
|
||||
params := types.NewParams(ethermint.AttoPhoton, false, true)
|
||||
suite.stateDB.SetParams(params)
|
||||
},
|
||||
types.StateTransition{
|
||||
AccountNonce: 123,
|
||||
Price: big.NewInt(10),
|
||||
GasLimit: 11,
|
||||
Recipient: nil,
|
||||
Amount: big.NewInt(50),
|
||||
Payload: []byte("data"),
|
||||
ChainID: big.NewInt(1),
|
||||
Csdb: suite.stateDB,
|
||||
TxHash: ðcmn.Hash{},
|
||||
Sender: suite.address,
|
||||
Simulate: suite.ctx.IsCheckTx(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil gas price",
|
||||
func() {
|
||||
suite.stateDB.SetParams(types.DefaultParams())
|
||||
invalidGas := sdk.DecCoins{
|
||||
{Denom: ethermint.AttoPhoton},
|
||||
{Denom: ethermint.InjectiveCoin},
|
||||
}
|
||||
suite.ctx = suite.ctx.WithMinGasPrices(invalidGas)
|
||||
},
|
||||
|
||||
+40
-31
@@ -122,8 +122,8 @@ func (csdb *CommitStateDB) WithContext(ctx sdk.Context) *CommitStateDB {
|
||||
|
||||
// SetHeightHash sets the block header hash associated with a given height.
|
||||
func (csdb *CommitStateDB) SetHeightHash(height uint64, hash ethcmn.Hash) {
|
||||
store := prefix.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixHeightHash)
|
||||
key := HeightHashKey(height)
|
||||
store := prefix.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixBlockHeightHash)
|
||||
key := KeyBlockHeightHash(height)
|
||||
store.Set(key, hash.Bytes())
|
||||
}
|
||||
|
||||
@@ -135,38 +135,49 @@ func (csdb *CommitStateDB) SetParams(params Params) {
|
||||
// SetBalance sets the balance of an account.
|
||||
func (csdb *CommitStateDB) SetBalance(addr ethcmn.Address, amount *big.Int) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
so.SetBalance(amount)
|
||||
|
||||
if so != nil {
|
||||
so.SetBalance(amount)
|
||||
}
|
||||
}
|
||||
|
||||
// AddBalance adds amount to the account associated with addr.
|
||||
func (csdb *CommitStateDB) AddBalance(addr ethcmn.Address, amount *big.Int) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
so.AddBalance(amount)
|
||||
if so != nil {
|
||||
so.AddBalance(amount)
|
||||
}
|
||||
}
|
||||
|
||||
// SubBalance subtracts amount from the account associated with addr.
|
||||
func (csdb *CommitStateDB) SubBalance(addr ethcmn.Address, amount *big.Int) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
so.SubBalance(amount)
|
||||
if so != nil {
|
||||
so.SubBalance(amount)
|
||||
}
|
||||
}
|
||||
|
||||
// SetNonce sets the nonce (sequence number) of an account.
|
||||
func (csdb *CommitStateDB) SetNonce(addr ethcmn.Address, nonce uint64) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
so.SetNonce(nonce)
|
||||
if so != nil {
|
||||
so.SetNonce(nonce)
|
||||
}
|
||||
}
|
||||
|
||||
// SetState sets the storage state with a key, value pair for an account.
|
||||
func (csdb *CommitStateDB) SetState(addr ethcmn.Address, key, value ethcmn.Hash) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
so.SetState(nil, key, value)
|
||||
if so != nil {
|
||||
so.SetState(nil, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// SetCode sets the code for a given account.
|
||||
func (csdb *CommitStateDB) SetCode(addr ethcmn.Address, code []byte) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
so.SetCode(ethcrypto.Keccak256Hash(code), code)
|
||||
if so != nil {
|
||||
so.SetCode(ethcrypto.Keccak256Hash(code), code)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -289,8 +300,8 @@ func (csdb *CommitStateDB) SlotInAccessList(addr ethcmn.Address, slot ethcmn.Has
|
||||
|
||||
// GetHeightHash returns the block header hash associated with a given block height and chain epoch number.
|
||||
func (csdb *CommitStateDB) GetHeightHash(height uint64) ethcmn.Hash {
|
||||
store := prefix.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixHeightHash)
|
||||
key := HeightHashKey(height)
|
||||
store := prefix.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixBlockHeightHash)
|
||||
key := KeyBlockHeightHash(height)
|
||||
bz := store.Get(key)
|
||||
if len(bz) == 0 {
|
||||
return ethcmn.Hash{}
|
||||
@@ -300,16 +311,8 @@ func (csdb *CommitStateDB) GetHeightHash(height uint64) ethcmn.Hash {
|
||||
}
|
||||
|
||||
// GetParams returns the total set of evm parameters.
|
||||
// It will check if every param exists in the Subspace's KVStore before querying by the key,
|
||||
// the default value of that param will be returned if not exist.
|
||||
func (csdb *CommitStateDB) GetParams() (params Params) {
|
||||
ps := ¶ms
|
||||
for _, pair := range ps.ParamSetPairs() {
|
||||
if csdb.paramSpace.Has(csdb.ctx, pair.Key) {
|
||||
csdb.paramSpace.Get(csdb.ctx, pair.Key, pair.Value)
|
||||
}
|
||||
}
|
||||
|
||||
csdb.paramSpace.GetParamSet(csdb.ctx, ¶ms)
|
||||
return params
|
||||
}
|
||||
|
||||
@@ -344,10 +347,6 @@ func (csdb *CommitStateDB) BlockHash() ethcmn.Hash {
|
||||
return csdb.bhash
|
||||
}
|
||||
|
||||
func (csdb *CommitStateDB) SetBlockHash(hash ethcmn.Hash) {
|
||||
csdb.bhash = hash
|
||||
}
|
||||
|
||||
// GetCode returns the code for a given account.
|
||||
func (csdb *CommitStateDB) GetCode(addr ethcmn.Address) []byte {
|
||||
so := csdb.getStateObject(addr)
|
||||
@@ -417,7 +416,12 @@ func (csdb *CommitStateDB) GetLogs(hash ethcmn.Hash) ([]*ethtypes.Log, error) {
|
||||
return []*ethtypes.Log{}, err
|
||||
}
|
||||
|
||||
return txLogs.EthLogs(), nil
|
||||
allLogs := []*ethtypes.Log{}
|
||||
for _, txLog := range txLogs.Logs {
|
||||
allLogs = append(allLogs, txLog.ToEthereum())
|
||||
}
|
||||
|
||||
return allLogs, nil
|
||||
}
|
||||
|
||||
// AllLogs returns all the current logs in the state.
|
||||
@@ -430,7 +434,10 @@ func (csdb *CommitStateDB) AllLogs() []*ethtypes.Log {
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var txLogs TransactionLogs
|
||||
ModuleCdc.MustUnmarshalBinaryBare(iterator.Value(), &txLogs)
|
||||
allLogs = append(allLogs, txLogs.EthLogs()...)
|
||||
|
||||
for _, txLog := range txLogs.Logs {
|
||||
allLogs = append(allLogs, txLog.ToEthereum())
|
||||
}
|
||||
}
|
||||
|
||||
return allLogs
|
||||
@@ -705,7 +712,7 @@ func (csdb *CommitStateDB) UpdateAccounts() {
|
||||
for _, stateEntry := range csdb.stateObjects {
|
||||
address := sdk.AccAddress(stateEntry.address.Bytes())
|
||||
currAccount := csdb.accountKeeper.GetAccount(csdb.ctx, address)
|
||||
ethermintAcc, ok := currAccount.(*ethermint.EthAccount)
|
||||
ethAcc, ok := currAccount.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -717,8 +724,8 @@ func (csdb *CommitStateDB) UpdateAccounts() {
|
||||
stateEntry.stateObject.balance = balance.Amount
|
||||
}
|
||||
|
||||
if stateEntry.stateObject.Nonce() != ethermintAcc.GetSequence() {
|
||||
stateEntry.stateObject.account = ethermintAcc
|
||||
if stateEntry.stateObject.Nonce() != ethAcc.GetSequence() {
|
||||
stateEntry.stateObject.account = ethAcc
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,8 +745,9 @@ func (csdb *CommitStateDB) clearJournalAndRefund() {
|
||||
|
||||
// Prepare sets the current transaction hash and index and block hash which is
|
||||
// used when the EVM emits new state logs.
|
||||
func (csdb *CommitStateDB) Prepare(thash ethcmn.Hash, txi int) {
|
||||
func (csdb *CommitStateDB) Prepare(thash, bhash ethcmn.Hash, txi int) {
|
||||
csdb.thash = thash
|
||||
csdb.bhash = bhash
|
||||
csdb.txIndex = txi
|
||||
}
|
||||
|
||||
@@ -867,7 +875,8 @@ func (csdb *CommitStateDB) ForEachStorage(addr ethcmn.Address, cb func(key, valu
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOrNewStateObject retrieves a state object or create a new state object if nil.
|
||||
// GetOrNewStateObject retrieves a state object or create a new state object if
|
||||
// nil.
|
||||
func (csdb *CommitStateDB) GetOrNewStateObject(addr ethcmn.Address) StateObject {
|
||||
so := csdb.getStateObject(addr)
|
||||
if so == nil || so.deleted {
|
||||
|
||||
+18
-34
@@ -26,7 +26,7 @@ type StateDBTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
ctx sdk.Context
|
||||
app *app.EthermintApp
|
||||
app *app.InjectiveApp
|
||||
stateDB *types.CommitStateDB
|
||||
address ethcmn.Address
|
||||
stateObject types.StateObject
|
||||
@@ -40,7 +40,7 @@ func (suite *StateDBTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(checkTx)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-1"})
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1})
|
||||
suite.stateDB = suite.app.EvmKeeper.CommitStateDB.WithContext(suite.ctx)
|
||||
|
||||
privkey, err := ethsecp256k1.GenerateKey()
|
||||
@@ -48,7 +48,7 @@ func (suite *StateDBTestSuite) SetupTest() {
|
||||
|
||||
suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
|
||||
balance := ethermint.NewPhotonCoin(sdk.ZeroInt())
|
||||
balance := ethermint.NewInjectiveCoin(sdk.ZeroInt())
|
||||
acc := ðermint.EthAccount{
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
@@ -64,32 +64,18 @@ func (suite *StateDBTestSuite) SetupTest() {
|
||||
func (suite *StateDBTestSuite) TestParams() {
|
||||
params := suite.stateDB.GetParams()
|
||||
suite.Require().Equal(types.DefaultParams(), params)
|
||||
params.EvmDenom = "ara"
|
||||
params.EvmDenom = "inj"
|
||||
suite.stateDB.SetParams(params)
|
||||
newParams := suite.stateDB.GetParams()
|
||||
suite.Require().Equal(newParams, params)
|
||||
}
|
||||
|
||||
func (suite *StateDBTestSuite) TestGetHeightHash() {
|
||||
hash := suite.stateDB.GetHeightHash(0)
|
||||
suite.Require().Equal(ethcmn.Hash{}.String(), hash.String())
|
||||
|
||||
expHash := ethcmn.BytesToHash([]byte("hash"))
|
||||
suite.stateDB.SetHeightHash(10, expHash)
|
||||
|
||||
hash = suite.stateDB.GetHeightHash(10)
|
||||
suite.Require().Equal(expHash.String(), hash.String())
|
||||
}
|
||||
|
||||
func (suite *StateDBTestSuite) TestBloomFilter() {
|
||||
// Prepare db for logs
|
||||
tHash := ethcmn.BytesToHash([]byte{0x1})
|
||||
suite.stateDB.Prepare(tHash, 0)
|
||||
suite.stateDB.Prepare(tHash, ethcmn.Hash{}, 0)
|
||||
contractAddress := ethcmn.BigToAddress(big.NewInt(1))
|
||||
log := ethtypes.Log{
|
||||
Address: contractAddress,
|
||||
Topics: []ethcmn.Hash{},
|
||||
}
|
||||
log := ethtypes.Log{Address: contractAddress}
|
||||
|
||||
testCase := []struct {
|
||||
name string
|
||||
@@ -130,8 +116,8 @@ func (suite *StateDBTestSuite) TestBloomFilter() {
|
||||
}
|
||||
} else {
|
||||
// get logs bloom from the log
|
||||
bloomBytes := ethtypes.LogsBloom(logs)
|
||||
bloomFilter := ethtypes.BytesToBloom(bloomBytes)
|
||||
bloomInt := ethtypes.LogsBloom(logs)
|
||||
bloomFilter := ethtypes.BytesToBloom(bloomInt)
|
||||
suite.Require().True(ethtypes.BloomLookup(bloomFilter, contractAddress), tc.name)
|
||||
suite.Require().False(ethtypes.BloomLookup(bloomFilter, ethcmn.BigToAddress(big.NewInt(2))), tc.name)
|
||||
}
|
||||
@@ -306,7 +292,6 @@ func (suite *StateDBTestSuite) TestStateDB_Logs() {
|
||||
suite.Require().Empty(dbLogs, tc.name)
|
||||
|
||||
suite.stateDB.AddLog(&tc.log)
|
||||
tc.log.Index = 0 // reset index
|
||||
suite.Require().Equal(logs, suite.stateDB.AllLogs(), tc.name)
|
||||
|
||||
//resets state but checking to see if storekey still persists.
|
||||
@@ -433,8 +418,7 @@ func (suite *StateDBTestSuite) TestSuiteDB_Prepare() {
|
||||
bhash := ethcmn.BytesToHash([]byte("bhash"))
|
||||
txi := 1
|
||||
|
||||
suite.stateDB.Prepare(thash, txi)
|
||||
suite.stateDB.SetBlockHash(bhash)
|
||||
suite.stateDB.Prepare(thash, bhash, txi)
|
||||
|
||||
suite.Require().Equal(txi, suite.stateDB.TxIndex())
|
||||
suite.Require().Equal(bhash, suite.stateDB.BlockHash())
|
||||
@@ -675,7 +659,7 @@ func (suite *StateDBTestSuite) TestCommitStateDB_ForEachStorage() {
|
||||
name string
|
||||
malleate func()
|
||||
callback func(key, value ethcmn.Hash) (stop bool)
|
||||
expValues []string
|
||||
expValues []ethcmn.Hash
|
||||
}{
|
||||
{
|
||||
"aggregate state",
|
||||
@@ -688,12 +672,12 @@ func (suite *StateDBTestSuite) TestCommitStateDB_ForEachStorage() {
|
||||
storage = append(storage, types.NewState(key, value))
|
||||
return false
|
||||
},
|
||||
[]string{
|
||||
ethcmn.BytesToHash([]byte("value0")).String(),
|
||||
ethcmn.BytesToHash([]byte("value1")).String(),
|
||||
ethcmn.BytesToHash([]byte("value2")).String(),
|
||||
ethcmn.BytesToHash([]byte("value3")).String(),
|
||||
ethcmn.BytesToHash([]byte("value4")).String(),
|
||||
[]ethcmn.Hash{
|
||||
ethcmn.BytesToHash([]byte("value0")),
|
||||
ethcmn.BytesToHash([]byte("value1")),
|
||||
ethcmn.BytesToHash([]byte("value2")),
|
||||
ethcmn.BytesToHash([]byte("value3")),
|
||||
ethcmn.BytesToHash([]byte("value4")),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -709,8 +693,8 @@ func (suite *StateDBTestSuite) TestCommitStateDB_ForEachStorage() {
|
||||
}
|
||||
return false
|
||||
},
|
||||
[]string{
|
||||
ethcmn.BytesToHash([]byte("filtervalue")).String(),
|
||||
[]ethcmn.Hash{
|
||||
ethcmn.BytesToHash([]byte("filtervalue")),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
@@ -51,7 +50,7 @@ func (s Storage) Copy() Storage {
|
||||
|
||||
// Validate performs a basic validation of the State fields.
|
||||
func (s State) Validate() error {
|
||||
if ethermint.IsEmptyHash(s.Key) {
|
||||
if bytes.Equal(ethcmn.Hex2Bytes(s.Key), ethcmn.Hash{}.Bytes()) {
|
||||
return sdkerrors.Wrap(ErrInvalidState, "state key hash cannot be empty")
|
||||
}
|
||||
// NOTE: state value can be empty
|
||||
|
||||
@@ -80,7 +80,6 @@ func TestStorageCopy(t *testing.T) {
|
||||
|
||||
func TestStorageString(t *testing.T) {
|
||||
storage := Storage{NewState(ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value")))}
|
||||
str := `key:"0x00000000000000000000000000000000000000000000000000000000006b6579" value:"0x00000000000000000000000000000000000000000000000000000076616c7565"
|
||||
`
|
||||
str := "key:\"0x00000000000000000000000000000000000000000000000000000000006b6579\" value:\"0x00000000000000000000000000000000000000000000000000000076616c7565\"\n"
|
||||
require.Equal(t, str, storage.String())
|
||||
}
|
||||
|
||||
+320
-802
File diff suppressed because it is too large
Load Diff
+38
-6
@@ -5,10 +5,13 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
log "github.com/xlab/suplog"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@@ -44,13 +47,42 @@ func EncodeTxResponse(res *MsgEthereumTxResponse) ([]byte, error) {
|
||||
}
|
||||
|
||||
// DecodeTxResponse decodes an protobuf-encoded byte slice into TxResponse
|
||||
func DecodeTxResponse(data []byte) (MsgEthereumTxResponse, error) {
|
||||
var txResponse MsgEthereumTxResponse
|
||||
err := proto.Unmarshal(data, &txResponse)
|
||||
if err != nil {
|
||||
return MsgEthereumTxResponse{}, err
|
||||
func DecodeTxResponse(in []byte) (*MsgEthereumTxResponse, error) {
|
||||
var txMsgData sdk.TxMsgData
|
||||
if err := proto.Unmarshal(in, &txMsgData); err != nil {
|
||||
log.WithError(err).Errorln("failed to unmarshal TxMsgData")
|
||||
return nil, err
|
||||
}
|
||||
return txResponse, nil
|
||||
|
||||
dataList := txMsgData.GetData()
|
||||
if len(dataList) == 0 {
|
||||
return &MsgEthereumTxResponse{}, nil
|
||||
}
|
||||
|
||||
var res MsgEthereumTxResponse
|
||||
|
||||
err := proto.Unmarshal(dataList[0].GetData(), &res)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "proto.Unmarshal failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// EncodeTransactionLogs encodes TransactionLogs slice into a protobuf-encoded byte slice.
|
||||
func EncodeTransactionLogs(res *TransactionLogs) ([]byte, error) {
|
||||
return proto.Marshal(res)
|
||||
}
|
||||
|
||||
// DecodeTxResponse decodes an protobuf-encoded byte slice into TransactionLogs
|
||||
func DecodeTransactionLogs(data []byte) (TransactionLogs, error) {
|
||||
var logs TransactionLogs
|
||||
err := proto.Unmarshal(data, &logs)
|
||||
if err != nil {
|
||||
return TransactionLogs{}, err
|
||||
}
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
+13
-32
@@ -1,15 +1,27 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
// GenerateEthAddress generates an Ethereum address.
|
||||
func GenerateEthAddress() ethcmn.Address {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey)
|
||||
}
|
||||
|
||||
func TestEvmDataEncoding(t *testing.T) {
|
||||
addr := "0x5dE8a020088a2D6d0a23c204FFbeD02790466B49"
|
||||
bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
||||
@@ -39,34 +51,3 @@ func TestEvmDataEncoding(t *testing.T) {
|
||||
require.Equal(t, data.TxLogs, res.TxLogs)
|
||||
require.Equal(t, ret, res.Ret)
|
||||
}
|
||||
|
||||
func TestResultData_String(t *testing.T) {
|
||||
const expectedResultDataStr = `ResultData:
|
||||
ContractAddress: 0x5dE8a020088a2D6d0a23c204FFbeD02790466B49
|
||||
Bloom: 259
|
||||
Ret: [5 8]
|
||||
TxHash: 0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
Logs:
|
||||
{0x0000000000000000000000000000000000000000 [] [1 2 3 4] 17 0x0000000000000000000000000000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000000000000000000000000000 0 false}
|
||||
{0x0000000000000000000000000000000000000000 [] [5 6 7 8] 18 0x0000000000000000000000000000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000000000000000000000000000 0 false}`
|
||||
addr := ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49")
|
||||
bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
||||
ret := []byte{0x5, 0x8}
|
||||
|
||||
data := ResultData{
|
||||
ContractAddress: addr,
|
||||
Bloom: bloom,
|
||||
Logs: []*ethtypes.Log{
|
||||
{
|
||||
Data: []byte{1, 2, 3, 4},
|
||||
BlockNumber: 17,
|
||||
},
|
||||
{
|
||||
Data: []byte{5, 6, 7, 8},
|
||||
BlockNumber: 18,
|
||||
}},
|
||||
Ret: ret,
|
||||
}
|
||||
|
||||
require.True(t, strings.EqualFold(expectedResultDataStr, data.String()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user